[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/_test/tests/inc/parser/ -> lexer.test.php (source)

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