xref: /dokuwiki/_test/tests/inc/parser/lexer.test.php (revision 564ad40a29ed6fd13280ffa4c2db9a67ff064796)
1<?php
2/**
3* @version $Id: lexer.todo.php,v 1.2 2005/03/25 21:00:22 harryf Exp $
4* @package Doku
5* @subpackage Tests
6*/
7
8/**
9* Includes
10*/
11require_once DOKU_INC . 'inc/parser/lexer.php';
12
13/**
14* @package Doku
15* @subpackage Tests
16*/
17class TestOfLexerParallelRegex extends DokuWikiTest {
18
19    function testNoPatterns() {
20        $regex = new Doku_LexerParallelRegex(false);
21        $this->assertFalse($regex->match("Hello", $match));
22        $this->assertEquals($match, "");
23    }
24    function testNoSubject() {
25        $regex = new Doku_LexerParallelRegex(false);
26        $regex->addPattern(".*");
27        $this->assertTrue($regex->match("", $match));
28        $this->assertEquals($match, "");
29    }
30    function testMatchAll() {
31        $regex = new Doku_LexerParallelRegex(false);
32        $regex->addPattern(".*");
33        $this->assertTrue($regex->match("Hello", $match));
34        $this->assertEquals($match, "Hello");
35    }
36    function testCaseSensitive() {
37        $regex = new Doku_LexerParallelRegex(true);
38        $regex->addPattern("abc");
39        $this->assertTrue($regex->match("abcdef", $match));
40        $this->assertEquals($match, "abc");
41        $this->assertTrue($regex->match("AAABCabcdef", $match));
42        $this->assertEquals($match, "abc");
43    }
44    function testCaseInsensitive() {
45        $regex = new Doku_LexerParallelRegex(false);
46        $regex->addPattern("abc");
47        $this->assertTrue($regex->match("abcdef", $match));
48        $this->assertEquals($match, "abc");
49        $this->assertTrue($regex->match("AAABCabcdef", $match));
50        $this->assertEquals($match, "ABC");
51    }
52    function testMatchMultiple() {
53        $regex = new Doku_LexerParallelRegex(true);
54        $regex->addPattern("abc");
55        $regex->addPattern("ABC");
56        $this->assertTrue($regex->match("abcdef", $match));
57        $this->assertEquals($match, "abc");
58        $this->assertTrue($regex->match("AAABCabcdef", $match));
59        $this->assertEquals($match, "ABC");
60        $this->assertFalse($regex->match("Hello", $match));
61    }
62    function testPatternLabels() {
63        $regex = new Doku_LexerParallelRegex(false);
64        $regex->addPattern("abc", "letter");
65        $regex->addPattern("123", "number");
66        $this->assertEquals($regex->match("abcdef", $match), "letter");
67        $this->assertEquals($match, "abc");
68        $this->assertEquals($regex->match("0123456789", $match), "number");
69        $this->assertEquals($match, "123");
70    }
71    function testMatchMultipleWithLookaheadNot() {
72        $regex = new Doku_LexerParallelRegex(true);
73        $regex->addPattern("abc");
74        $regex->addPattern("ABC");
75        $regex->addPattern("a(?!\n).{1}");
76        $this->assertTrue($regex->match("abcdef", $match));
77        $this->assertEquals($match, "abc");
78        $this->assertTrue($regex->match("AAABCabcdef", $match));
79        $this->assertEquals($match, "ABC");
80        $this->assertTrue($regex->match("a\nab", $match));
81        $this->assertEquals($match, "ab");
82        $this->assertFalse($regex->match("Hello", $match));
83    }
84    function testMatchSetOptionCaseless() {
85        $regex = new Doku_LexerParallelRegex(true);
86        $regex->addPattern("a(?i)b(?i)c");
87        $this->assertTrue($regex->match("aBc", $match));
88        $this->assertEquals($match, "aBc");
89    }
90    function testMatchSetOptionUngreedy() {
91        $regex = new Doku_LexerParallelRegex(true);
92        $regex->addPattern("(?U)\w+");
93        $this->assertTrue($regex->match("aaaaaa", $match));
94        $this->assertEquals($match, "a");
95    }
96    function testMatchLookaheadEqual() {
97        $regex = new Doku_LexerParallelRegex(true);
98        $regex->addPattern("\w(?=c)");
99        $this->assertTrue($regex->match("xbyczd", $match));
100        $this->assertEquals($match, "y");
101    }
102    function testMatchLookaheadNot() {
103        $regex = new Doku_LexerParallelRegex(true);
104        $regex->addPattern("\w(?!b|c)");
105        $this->assertTrue($regex->match("xbyczd", $match));
106        $this->assertEquals($match, "b");
107    }
108    function testMatchLookbehindEqual() {
109        $regex = new Doku_LexerParallelRegex(true);
110        $regex->addPattern("(?<=c)\w");
111        $this->assertTrue($regex->match("xbyczd", $match));
112        $this->assertEquals($match, "z");
113    }
114    function testMatchLookbehindNot() {
115        $regex = new Doku_LexerParallelRegex(true);
116        $regex->addPattern("(?<!\A|x|b)\w");
117        $this->assertTrue($regex->match("xbyczd", $match));
118        $this->assertEquals($match, "c");
119    }
120}
121
122
123class TestOfLexerStateStack extends DokuWikiTest {
124    function testStartState() {
125        $stack = new Doku_LexerStateStack("one");
126        $this->assertEquals($stack->getCurrent(), "one");
127    }
128    function testExhaustion() {
129        $stack = new Doku_LexerStateStack("one");
130        $this->assertFalse($stack->leave());
131    }
132    function testStateMoves() {
133        $stack = new Doku_LexerStateStack("one");
134        $stack->enter("two");
135        $this->assertEquals($stack->getCurrent(), "two");
136        $stack->enter("three");
137        $this->assertEquals($stack->getCurrent(), "three");
138        $this->assertTrue($stack->leave());
139        $this->assertEquals($stack->getCurrent(), "two");
140        $stack->enter("third");
141        $this->assertEquals($stack->getCurrent(), "third");
142        $this->assertTrue($stack->leave());
143        $this->assertTrue($stack->leave());
144        $this->assertEquals($stack->getCurrent(), "one");
145    }
146}
147
148class TestParser {
149    function __construct() {
150    }
151    function accept() {
152    }
153    function a() {
154    }
155    function b() {
156    }
157}
158
159class TestOfLexer extends DokuWikiTest {
160    function testNoPatterns() {
161        $handler = $this->createMock('TestParser');
162        $handler->expects($this->never())->method('accept');
163        $lexer = new Doku_Lexer($handler);
164        $this->assertFalse($lexer->parse("abcdef"));
165    }
166    function testEmptyPage() {
167        $handler = $this->createMock('TestParser');
168        $handler->expects($this->never())->method('accept');
169        $lexer = new Doku_Lexer($handler);
170        $lexer->addPattern("a+");
171        $this->assertTrue($lexer->parse(""));
172    }
173    function testSinglePattern() {
174        $handler = $this->createMock('TestParser');
175        $handler->expects($this->at(0))->method('accept')
176            ->with("aaa", DOKU_LEXER_MATCHED, 0)->will($this->returnValue(true));
177        $handler->expects($this->at(1))->method('accept')
178            ->with("x", DOKU_LEXER_UNMATCHED, 3)->will($this->returnValue(true));
179        $handler->expects($this->at(2))->method('accept')
180            ->with("a", DOKU_LEXER_MATCHED, 4)->will($this->returnValue(true));
181        $handler->expects($this->at(3))->method('accept')
182            ->with("yyy", DOKU_LEXER_UNMATCHED, 5)->will($this->returnValue(true));
183        $handler->expects($this->at(4))->method('accept')
184            ->with("a", DOKU_LEXER_MATCHED, 8)->will($this->returnValue(true));
185        $handler->expects($this->at(5))->method('accept')
186            ->with("x", DOKU_LEXER_UNMATCHED, 9)->will($this->returnValue(true));
187        $handler->expects($this->at(6))->method('accept')
188            ->with("aaa", DOKU_LEXER_MATCHED, 10)->will($this->returnValue(true));
189        $handler->expects($this->at(7))->method('accept')
190            ->with("z", DOKU_LEXER_UNMATCHED, 13)->will($this->returnValue(true));
191
192        $lexer = new Doku_Lexer($handler);
193        $lexer->addPattern("a+");
194        $this->assertTrue($lexer->parse("aaaxayyyaxaaaz"));
195    }
196    function testMultiplePattern() {
197        $handler = $this->createPartialMock('TestParser', array('accept'));
198        $target = array("a", "b", "a", "bb", "x", "b", "a", "xxxxxx", "a", "x");
199        $positions = array(0, 1, 2, 3, 5, 6, 7, 8, 14, 15);
200        for ($i = 0; $i < count($target); $i++) {
201            $handler->expects($this->at($i))->method('accept')
202                ->with($target[$i], $this->anything(), $positions[$i])->will($this->returnValue(true));
203        }
204        $lexer = new Doku_Lexer($handler);
205        $lexer->addPattern("a+");
206        $lexer->addPattern("b+");
207        $this->assertTrue($lexer->parse("ababbxbaxxxxxxax"));
208    }
209}
210
211class TestOfLexerModes extends DokuWikiTest {
212    function testIsolatedPattern() {
213        $handler = $this->createMock('TestParser');
214        $handler->expects($this->at(0))->method('a')
215            ->with("a", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
216        $handler->expects($this->at(1))->method('a')
217            ->with("b", DOKU_LEXER_UNMATCHED,1)->will($this->returnValue(true));
218        $handler->expects($this->at(2))->method('a')
219            ->with("aa", DOKU_LEXER_MATCHED,2)->will($this->returnValue(true));
220        $handler->expects($this->at(3))->method('a')
221            ->with("bxb", DOKU_LEXER_UNMATCHED,4)->will($this->returnValue(true));
222        $handler->expects($this->at(4))->method('a')
223            ->with("aaa", DOKU_LEXER_MATCHED,7)->will($this->returnValue(true));
224        $handler->expects($this->at(5))->method('a')
225            ->with("x", DOKU_LEXER_UNMATCHED,10)->will($this->returnValue(true));
226        $handler->expects($this->at(6))->method('a')
227            ->with("aaaa", DOKU_LEXER_MATCHED,11)->will($this->returnValue(true));
228        $handler->expects($this->at(7))->method('a')
229            ->with("x", DOKU_LEXER_UNMATCHED,15)->will($this->returnValue(true));
230        $lexer = new Doku_Lexer($handler, "a");
231        $lexer->addPattern("a+", "a");
232        $lexer->addPattern("b+", "b");
233        $this->assertTrue($lexer->parse("abaabxbaaaxaaaax"));
234    }
235    function testModeChange() {
236        $handler = $this->createMock('TestParser');
237        $handler->expects($this->at(0))->method('a')
238            ->with("a", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
239        $handler->expects($this->at(1))->method('a')
240            ->with("b", DOKU_LEXER_UNMATCHED,1)->will($this->returnValue(true));
241        $handler->expects($this->at(2))->method('a')
242            ->with("aa", DOKU_LEXER_MATCHED,2)->will($this->returnValue(true));
243        $handler->expects($this->at(3))->method('a')
244            ->with("b", DOKU_LEXER_UNMATCHED,4)->will($this->returnValue(true));
245        $handler->expects($this->at(4))->method('a')
246            ->with("aaa", DOKU_LEXER_MATCHED,5)->will($this->returnValue(true));
247        $handler->expects($this->at(5))->method('b')
248            ->with(":", DOKU_LEXER_ENTER,8)->will($this->returnValue(true));
249        $handler->expects($this->at(6))->method('b')
250            ->with("a", DOKU_LEXER_UNMATCHED,9)->will($this->returnValue(true));
251        $handler->expects($this->at(7))->method('b')
252            ->with("b", DOKU_LEXER_MATCHED, 10)->will($this->returnValue(true));
253        $handler->expects($this->at(8))->method('b')
254            ->with("a", DOKU_LEXER_UNMATCHED,11)->will($this->returnValue(true));
255        $handler->expects($this->at(9))->method('b')
256            ->with("bb", DOKU_LEXER_MATCHED,12)->will($this->returnValue(true));
257        $handler->expects($this->at(10))->method('b')
258            ->with("a", DOKU_LEXER_UNMATCHED,14)->will($this->returnValue(true));
259        $handler->expects($this->at(11))->method('b')
260            ->with("bbb", DOKU_LEXER_MATCHED,15)->will($this->returnValue(true));
261        $handler->expects($this->at(12))->method('b')
262            ->with("a", DOKU_LEXER_UNMATCHED,18)->will($this->returnValue(true));
263
264        $lexer = new Doku_Lexer($handler, "a");
265        $lexer->addPattern("a+", "a");
266        $lexer->addEntryPattern(":", "a", "b");
267        $lexer->addPattern("b+", "b");
268        $this->assertTrue($lexer->parse("abaabaaa:ababbabbba"));
269    }
270    function testNesting() {
271        $handler = $this->createMock('TestParser');
272        $handler->expects($this->at(0))->method('a')
273            ->with("aa", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
274        $handler->expects($this->at(1))->method('a')
275            ->with("b", DOKU_LEXER_UNMATCHED,2)->will($this->returnValue(true));
276        $handler->expects($this->at(2))->method('a')
277            ->with("aa", DOKU_LEXER_MATCHED,3)->will($this->returnValue(true));
278        $handler->expects($this->at(3))->method('a')
279            ->with("b", DOKU_LEXER_UNMATCHED,5)->will($this->returnValue(true));
280        $handler->expects($this->at(4))->method('b')
281            ->with("(", DOKU_LEXER_ENTER,6)->will($this->returnValue(true));
282        $handler->expects($this->at(5))->method('b')
283            ->with("bb", DOKU_LEXER_MATCHED,7)->will($this->returnValue(true));
284        $handler->expects($this->at(6))->method('b')
285            ->with("a", DOKU_LEXER_UNMATCHED,9)->will($this->returnValue(true));
286        $handler->expects($this->at(7))->method('b')
287            ->with("bb", DOKU_LEXER_MATCHED,10)->will($this->returnValue(true));
288        $handler->expects($this->at(8))->method('b')
289            ->with(")", DOKU_LEXER_EXIT,12)->will($this->returnValue(true));
290        $handler->expects($this->at(9))->method('a')
291            ->with("aa", DOKU_LEXER_MATCHED,13)->will($this->returnValue(true));
292        $handler->expects($this->at(10))->method('a')
293            ->with("b", DOKU_LEXER_UNMATCHED,15)->will($this->returnValue(true));
294
295
296        $lexer = new Doku_Lexer($handler, "a");
297        $lexer->addPattern("a+", "a");
298        $lexer->addEntryPattern("(", "a", "b");
299        $lexer->addPattern("b+", "b");
300        $lexer->addExitPattern(")", "b");
301        $this->assertTrue($lexer->parse("aabaab(bbabb)aab"));
302    }
303    function testSingular() {
304        $handler = $this->createMock('TestParser');
305        $handler->expects($this->at(0))->method('a')
306            ->with("aa", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
307        $handler->expects($this->at(1))->method('b')
308            ->with("b", DOKU_LEXER_SPECIAL,2)->will($this->returnValue(true));
309        $handler->expects($this->at(2))->method('a')
310            ->with("aa", DOKU_LEXER_MATCHED,3)->will($this->returnValue(true));
311        $handler->expects($this->at(3))->method('a')
312            ->with("xx", DOKU_LEXER_UNMATCHED,5)->will($this->returnValue(true));
313        $handler->expects($this->at(4))->method('b')
314            ->with("bbb", DOKU_LEXER_SPECIAL,7)->will($this->returnValue(true));
315        $handler->expects($this->at(5))->method('a')
316            ->with("xx", DOKU_LEXER_UNMATCHED,10)->will($this->returnValue(true));
317        $lexer = new Doku_Lexer($handler, "a");
318        $lexer->addPattern("a+", "a");
319        $lexer->addSpecialPattern("b+", "a", "b");
320        $this->assertTrue($lexer->parse("aabaaxxbbbxx"));
321    }
322    function testUnwindTooFar() {
323        $handler = $this->createMock('TestParser');
324        $handler->expects($this->at(0))->method('a')
325            ->with("aa", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
326        $handler->expects($this->at(1))->method('a')
327            ->with(")", DOKU_LEXER_EXIT,2)->will($this->returnValue(true));
328
329        $lexer = new Doku_Lexer($handler, "a");
330        $lexer->addPattern("a+", "a");
331        $lexer->addExitPattern(")", "a");
332        $this->assertFalse($lexer->parse("aa)aa"));
333    }
334}
335
336class TestOfLexerHandlers extends DokuWikiTest {
337    function testModeMapping() {
338        $handler = $this->createMock('TestParser');
339        $handler->expects($this->at(0))->method('a')
340            ->with("aa", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
341        $handler->expects($this->at(1))->method('a')
342            ->with("(", DOKU_LEXER_ENTER,2)->will($this->returnValue(true));
343        $handler->expects($this->at(2))->method('a')
344            ->with("bb", DOKU_LEXER_MATCHED,3)->will($this->returnValue(true));
345        $handler->expects($this->at(3))->method('a')
346            ->with("a", DOKU_LEXER_UNMATCHED,5)->will($this->returnValue(true));
347        $handler->expects($this->at(4))->method('a')
348            ->with("bb", DOKU_LEXER_MATCHED,6)->will($this->returnValue(true));
349        $handler->expects($this->at(5))->method('a')
350            ->with(")", DOKU_LEXER_EXIT,8)->will($this->returnValue(true));
351        $handler->expects($this->at(6))->method('a')
352            ->with("b", DOKU_LEXER_UNMATCHED,9)->will($this->returnValue(true));
353
354        $lexer = new Doku_Lexer($handler, "mode_a");
355        $lexer->addPattern("a+", "mode_a");
356        $lexer->addEntryPattern("(", "mode_a", "mode_b");
357        $lexer->addPattern("b+", "mode_b");
358        $lexer->addExitPattern(")", "mode_b");
359        $lexer->mapHandler("mode_a", "a");
360        $lexer->mapHandler("mode_b", "a");
361        $this->assertTrue($lexer->parse("aa(bbabb)b"));
362    }
363}
364
365class TestParserByteIndex {
366
367    function __construct() {}
368
369    function ignore() {}
370
371    function caught() {}
372}
373
374class TestOfLexerByteIndices extends DokuWikiTest {
375
376    function testIndex() {
377        $doc = "aaa<file>bcd</file>eee";
378
379        $handler = $this->createMock('TestParserByteIndex');
380        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
381        $handler->expects($this->at(1))->method('caught')
382            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
383        $handler->expects($this->at(2))->method('caught')
384            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
385        $handler->expects($this->at(3))->method('caught')
386            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
387        $handler->expects($this->at(4))->method('caught')
388            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
389        $handler->expects($this->at(5))->method('caught')
390            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
391
392        $lexer = new Doku_Lexer($handler, "ignore");
393        $lexer->addEntryPattern("<file>", "ignore", "caught");
394        $lexer->addExitPattern("</file>", "caught");
395        $lexer->addSpecialPattern('b','caught','special');
396        $lexer->mapHandler('special','caught');
397        $lexer->addPattern('c','caught');
398
399        $this->assertTrue($lexer->parse($doc));
400    }
401
402    function testIndexLookaheadEqual() {
403        $doc = "aaa<file>bcd</file>eee";
404
405        $handler = $this->createMock('TestParserByteIndex');
406        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
407        $handler->expects($this->at(1))->method('caught')
408            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
409        $handler->expects($this->at(2))->method('caught')
410            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
411        $handler->expects($this->at(3))->method('caught')
412            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
413        $handler->expects($this->at(4))->method('caught')
414            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
415        $handler->expects($this->at(5))->method('caught')
416            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
417
418        $lexer = new Doku_Lexer($handler, "ignore");
419        $lexer->addEntryPattern('<file>(?=.*</file>)', "ignore", "caught");
420        $lexer->addExitPattern("</file>", "caught");
421        $lexer->addSpecialPattern('b','caught','special');
422        $lexer->mapHandler('special','caught');
423        $lexer->addPattern('c','caught');
424
425        $this->assertTrue($lexer->parse($doc));
426    }
427
428    function testIndexLookaheadNotEqual() {
429        $doc = "aaa<file>bcd</file>eee";
430
431        $handler = $this->createMock('TestParserByteIndex');
432        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
433        $handler->expects($this->at(1))->method('caught')
434            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
435        $handler->expects($this->at(2))->method('caught')
436            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
437        $handler->expects($this->at(3))->method('caught')
438            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
439        $handler->expects($this->at(4))->method('caught')
440            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
441        $handler->expects($this->at(5))->method('caught')
442            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
443
444        $lexer = new Doku_Lexer($handler, "ignore");
445        $lexer->addEntryPattern('<file>(?!foo)', "ignore", "caught");
446        $lexer->addExitPattern("</file>", "caught");
447        $lexer->addSpecialPattern('b','caught','special');
448        $lexer->mapHandler('special','caught');
449        $lexer->addPattern('c','caught');
450
451        $this->assertTrue($lexer->parse($doc));
452    }
453
454    function testIndexLookbehindEqual() {
455        $doc = "aaa<file>bcd</file>eee";
456
457        $handler = $this->createMock('TestParserByteIndex');
458        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
459        $handler->expects($this->at(1))->method('caught')
460            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
461        $handler->expects($this->at(2))->method('caught')
462            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
463        $handler->expects($this->at(3))->method('caught')
464            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
465        $handler->expects($this->at(4))->method('caught')
466            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
467        $handler->expects($this->at(5))->method('caught')
468            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
469
470        $lexer = new Doku_Lexer($handler, "ignore");
471        $lexer->addEntryPattern('<file>', "ignore", "caught");
472        $lexer->addExitPattern("(?<=d)</file>", "caught");
473        $lexer->addSpecialPattern('b','caught','special');
474        $lexer->mapHandler('special','caught');
475        $lexer->addPattern('c','caught');
476
477        $this->assertTrue($lexer->parse($doc));
478    }
479
480    function testIndexLookbehindNotEqual() {
481        $doc = "aaa<file>bcd</file>eee";
482
483        $handler = $this->createMock('TestParserByteIndex');
484        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
485        $handler->expects($this->at(1))->method('caught')
486            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
487        $handler->expects($this->at(2))->method('caught')
488            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
489        $handler->expects($this->at(3))->method('caught')
490            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
491        $handler->expects($this->at(4))->method('caught')
492            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
493        $handler->expects($this->at(5))->method('caught')
494            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
495
496        $lexer = new Doku_Lexer($handler, 'ignore');
497        $lexer->addEntryPattern('<file>', 'ignore', 'caught');
498        $lexer->addExitPattern('(?<!c)</file>', 'caught');
499        $lexer->addSpecialPattern('b','caught','special');
500        $lexer->mapHandler('special','caught');
501        $lexer->addPattern('c','caught');
502
503        $this->assertTrue($lexer->parse($doc));
504    }
505
506    /**
507     * This test is primarily to ensure the correct match is chosen
508     * when there are non-captured elements in the pattern.
509     */
510    function testIndexSelectCorrectMatch() {
511        $doc = "ALL FOOLS ARE FOO";
512        $pattern = '\bFOO\b';
513
514        $handler = $this->createMock('TestParserByteIndex');
515        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
516
517        $matches = array();
518        preg_match('/'.$pattern.'/',$doc,$matches,PREG_OFFSET_CAPTURE);
519
520        $handler->expects($this->once())->method('caught')
521            ->with("FOO", DOKU_LEXER_SPECIAL, $matches[0][1])->will($this->returnValue(true));
522
523        $lexer = new Doku_Lexer($handler, "ignore");
524        $lexer->addSpecialPattern($pattern,'ignore','caught');
525
526        $this->assertTrue($lexer->parse($doc));
527    }
528
529}
530