1#!/usr/bin/env python3 2# Copyright 2014 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6 7import sys 8import unittest 9import make_dafsa 10 11 12class ParseGperfTest(unittest.TestCase): 13 def testMalformedKey(self): 14 """Tests exception is thrown at bad format.""" 15 infile1 = [ '%%', '', '%%' ] 16 self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile1, 17 False) 18 19 infile2 = [ '%%', 'apa,1', '%%' ] 20 self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile2, 21 False) 22 23 infile3 = [ '%%', 'apa, 1', '%%' ] 24 self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile3, 25 False) 26 27 def testBadValues(self): 28 """Tests exception is thrown when value is out of range.""" 29 infile1 = [ '%%', 'a, -1', '%%' ] 30 self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile1, 31 False) 32 33 infile2 = [ '%%', 'a, x', '%%' ] 34 self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile2, 35 False) 36 37 infile5 = [ '%%', 'a, 12', '%%' ] 38 self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile5, 39 False) 40 41 def testValues(self): 42 """Tests legal values are accepted.""" 43 infile1 = [ '%%', 'a, 0', '%%' ] 44 words1 = [ 'a0' ] 45 self.assertEqual(make_dafsa.parse_gperf(infile1, False), words1) 46 47 infile2 = [ '%%', 'a, 1', '%%' ] 48 words2 = [ 'a1' ] 49 self.assertEqual(make_dafsa.parse_gperf(infile2, False), words2) 50 51 infile3 = [ '%%', 'a, 2', '%%' ] 52 words3 = [ 'a2' ] 53 self.assertEqual(make_dafsa.parse_gperf(infile3, False), words3) 54 55 infile4 = [ '%%', 'a, 3', '%%' ] 56 words4 = [ 'a3' ] 57 self.assertEqual(make_dafsa.parse_gperf(infile4, False), words4) 58 59 infile5 = [ '%%', 'a, 4', '%%' ] 60 words5 = [ 'a4' ] 61 self.assertEqual(make_dafsa.parse_gperf(infile5, False), words5) 62 63 infile6 = [ '%%', 'a, 6', '%%' ] 64 words6 = [ 'a6' ] 65 self.assertEqual(make_dafsa.parse_gperf(infile6, False), words6) 66 67 infile7 = ['%%', '%%'] 68 words7 = [] 69 self.assertEqual(make_dafsa.parse_gperf(infile7, False), words7) 70 71 def testOneWord(self): 72 """Tests a single key can be parsed.""" 73 infile = [ '%%', 'apa, 1', '%%' ] 74 words = [ 'apa1' ] 75 self.assertEqual(make_dafsa.parse_gperf(infile, False), words) 76 77 def testTwoWords(self): 78 """Tests a sequence of keys can be parsed.""" 79 infile = [ '%%', 'apa, 1', 'bepa.com, 2', '%%' ] 80 words = [ 'apa1', 'bepa.com2' ] 81 self.assertEqual(make_dafsa.parse_gperf(infile, False), words) 82 83 def testReverse(self): 84 infile = [ '%%', 'foo.com, 0', 'foo.bar.com, 1', '%%' ] 85 words = [ 'moc.oof0', 'moc.rab.oof1' ] 86 self.assertEqual(make_dafsa.parse_gperf(infile, True), words) 87 88class ToDafsaTest(unittest.TestCase): 89 def testEmptyInput(self): 90 """Tests exception is thrown at empty input.""" 91 words = () 92 self.assertRaises(make_dafsa.InputError, make_dafsa.to_dafsa, words) 93 94 def testNonASCII(self): 95 """Tests exception is thrown if illegal characters are used.""" 96 words1 = ( chr(0x1F) + 'a1', ) 97 self.assertRaises(make_dafsa.InputError, make_dafsa.to_dafsa, words1) 98 99 words2 = ( 'a' + chr(0x1F) + '1', ) 100 self.assertRaises(make_dafsa.InputError, make_dafsa.to_dafsa, words2) 101 102 words3 = ( chr(0x80) + 'a1', ) 103 self.assertRaises(make_dafsa.InputError, make_dafsa.to_dafsa, words3) 104 105 words4 = ( 'a' + chr(0x80) + '1', ) 106 self.assertRaises(make_dafsa.InputError, make_dafsa.to_dafsa, words4) 107 108 def testChar(self): 109 """Tests a DAFSA can be created from a single character domain name.""" 110 words = [ 'a0' ] 111 node2 = ( chr(0), [ None ] ) 112 node1 = ( 'a', [ node2 ] ) 113 source = [ node1 ] 114 self.assertEqual(make_dafsa.to_dafsa(words), source) 115 116 def testChars(self): 117 """Tests a DAFSA can be created from a multi character domain name.""" 118 words = [ 'ab0' ] 119 node3 = ( chr(0), [ None ] ) 120 node2 = ( 'b', [ node3 ] ) 121 node1 = ( 'a', [ node2 ] ) 122 source = [ node1 ] 123 self.assertEqual(make_dafsa.to_dafsa(words), source) 124 125 def testWords(self): 126 """Tests a DAFSA can be created from a sequence of domain names.""" 127 words = [ 'a0', 'b1' ] 128 node4 = ( chr(1), [ None ] ) 129 node3 = ( 'b', [ node4 ] ) 130 node2 = ( chr(0), [ None ] ) 131 node1 = ( 'a', [ node2 ] ) 132 source = [ node1, node3 ] 133 self.assertEqual(make_dafsa.to_dafsa(words), source) 134 135 136class ToWordsTest(unittest.TestCase): 137 def testSink(self): 138 """Tests the sink is exapnded to a list with an empty string.""" 139 node1 = None 140 words = [ '' ] 141 self.assertEqual(make_dafsa.to_words(node1), words) 142 143 def testSingleNode(self): 144 """Tests a single node is expanded to a list with the label string.""" 145 146 # 'ab' -> [ 'ab' ] 147 148 node1 = ( 'ab', [ None ] ) 149 words = [ 'ab' ] 150 self.assertEqual(make_dafsa.to_words(node1), words) 151 152 def testChain(self): 153 """Tests a sequence of nodes are preoperly expanded.""" 154 155 # 'ab' -> 'cd' => [ 'abcd' ] 156 157 node2 = ( 'cd', [ None ] ) 158 node1 = ( 'ab', [ node2 ] ) 159 words = [ 'abcd' ] 160 self.assertEqual(make_dafsa.to_words(node1), words) 161 162 def testInnerTerminator(self): 163 """Tests a sequence with an inner terminator is expanded to two strings.""" 164 165 # 'a' -> 'b' 166 # \ => [ 'ab', 'a' ] 167 # {sink} 168 169 node2 = ( 'b', [ None ] ) 170 node1 = ( 'a', [ node2, None ] ) 171 words = [ 'ab', 'a' ] 172 self.assertEqual(make_dafsa.to_words(node1), words) 173 174 def testDiamond(self): 175 """Tests a diamond can be expanded to a word list.""" 176 177 # 'cd' 178 # / \ 179 # 'ab' 'gh' 180 # \ / 181 # 'ef' 182 183 node4 = ( 'gh', [ None ] ) 184 node3 = ( 'ef', [ node4 ] ) 185 node2 = ( 'cd', [ node4 ] ) 186 node1 = ( 'ab', [ node2, node3 ] ) 187 words = [ 'abcdgh', 'abefgh' ] 188 self.assertEqual(make_dafsa.to_words(node1), words) 189 190 191class JoinLabelsTest(unittest.TestCase): 192 def testLabel(self): 193 """Tests a single label passes unchanged.""" 194 195 # 'a' => 'a' 196 197 node1 = ( 'a', [ None ] ) 198 source = [ node1 ] 199 self.assertEqual(make_dafsa.join_labels(source), source) 200 201 def testInnerTerminator(self): 202 """Tests a sequence with an inner terminator passes unchanged.""" 203 204 # 'a' -> 'b' 'a' -> 'b' 205 # \ => \ 206 # {sink} {sink} 207 208 node2 = ( 'b', [ None ] ) 209 node1 = ( 'a', [ node2, None ] ) 210 source = [ node1 ] 211 self.assertEqual(make_dafsa.join_labels(source), source) 212 213 def testLabels(self): 214 """Tests a sequence of labels can be joined.""" 215 216 # 'a' -> 'b' => 'ab' 217 218 node2 = ( 'b', [ None ] ) 219 node1 = ( 'a', [ node2 ] ) 220 source1 = [ node1 ] 221 node3 = ( 'ab', [ None ] ) 222 source2 = [ node3 ] 223 self.assertEqual(make_dafsa.join_labels(source1), source2) 224 225 def testCompositeLabels(self): 226 """Tests a sequence of multi character labels can be joined.""" 227 228 # 'ab' -> 'cd' => 'abcd' 229 230 node2 = ( 'cd', [ None ] ) 231 node1 = ( 'ab', [ node2 ] ) 232 source1 = [ node1 ] 233 node3 = ( 'abcd', [ None ] ) 234 source2 = [ node3 ] 235 self.assertEqual(make_dafsa.join_labels(source1), source2) 236 237 def testAtomicTrie(self): 238 """Tests a trie formed DAFSA with atomic labels passes unchanged.""" 239 240 # 'b' 'b' 241 # / / 242 # 'a' => 'a' 243 # \ \ 244 # 'c' 'c' 245 246 node3 = ( 'c', [ None ] ) 247 node2 = ( 'b', [ None ] ) 248 node1 = ( 'a', [ node2, node3 ] ) 249 source = [ node1 ] 250 self.assertEqual(make_dafsa.join_labels(source), source) 251 252 def testReverseAtomicTrie(self): 253 """Tests a reverse trie formed DAFSA with atomic labels passes unchanged.""" 254 255 # 'a' 'a' 256 # \ \ 257 # 'c' => 'c' 258 # / / 259 # 'b' 'b' 260 261 node3 = ( 'c', [ None ] ) 262 node2 = ( 'b', [ node3 ] ) 263 node1 = ( 'a', [ node3 ] ) 264 source = [ node1, node2 ] 265 self.assertEqual(make_dafsa.join_labels(source), source) 266 267 def testChainedTrie(self): 268 """Tests a trie formed DAFSA with chained labels can be joined.""" 269 270 # 'c' -> 'd' 'cd' 271 # / / 272 # 'a' -> 'b' => 'ab' 273 # \ \ 274 # 'e' -> 'f' 'ef' 275 276 node6 = ( 'f', [ None ] ) 277 node5 = ( 'e', [ node6 ] ) 278 node4 = ( 'd', [ None ] ) 279 node3 = ( 'c', [ node4 ] ) 280 node2 = ( 'b', [ node3, node5 ] ) 281 node1 = ( 'a', [ node2 ] ) 282 source1 = [ node1 ] 283 node9 = ( 'ef', [ None ] ) 284 node8 = ( 'cd', [ None ] ) 285 node7 = ( 'ab', [ node8, node9 ] ) 286 source2 = [ node7 ] 287 self.assertEqual(make_dafsa.join_labels(source1), source2) 288 289 def testReverseChainedTrie(self): 290 """Tests a reverse trie formed DAFSA with chained labels can be joined.""" 291 292 # 'a' -> 'b' 'ab' 293 # \ \ 294 # 'e' -> 'f' => 'ef' 295 # / / 296 # 'c' -> 'd' 'cd' 297 298 node6 = ( 'f', [ None ] ) 299 node5 = ( 'e', [ node6 ] ) 300 node4 = ( 'd', [ node5 ] ) 301 node3 = ( 'c', [ node4 ] ) 302 node2 = ( 'b', [ node5 ] ) 303 node1 = ( 'a', [ node2 ] ) 304 source1 = [ node1, node3 ] 305 node9 = ( 'ef', [ None ] ) 306 node8 = ( 'cd', [ node9 ] ) 307 node7 = ( 'ab', [ node9 ] ) 308 source2 = [ node7, node8 ] 309 self.assertEqual(make_dafsa.join_labels(source1), source2) 310 311 312class JoinSuffixesTest(unittest.TestCase): 313 def testSingleLabel(self): 314 """Tests a single label passes unchanged.""" 315 316 # 'a' => 'a' 317 318 node1 = ( 'a', [ None ] ) 319 source = [ node1 ] 320 self.assertEqual(make_dafsa.join_suffixes(source), source) 321 322 def testInnerTerminator(self): 323 """Tests a sequence with an inner terminator passes unchanged.""" 324 325 # 'a' -> 'b' 'a' -> 'b' 326 # \ => \ 327 # {sink} {sink} 328 329 node2 = ( 'b', [ None ] ) 330 node1 = ( 'a', [ node2, None ] ) 331 source = [ node1 ] 332 self.assertEqual(make_dafsa.join_suffixes(source), source) 333 334 def testDistinctTrie(self): 335 """Tests a trie formed DAFSA with distinct labels passes unchanged.""" 336 337 # 'b' 'b' 338 # / / 339 # 'a' => 'a' 340 # \ \ 341 # 'c' 'c' 342 343 node3 = ( 'c', [ None ] ) 344 node2 = ( 'b', [ None ] ) 345 node1 = ( 'a', [ node2, node3 ] ) 346 source = [ node1 ] 347 self.assertEqual(make_dafsa.join_suffixes(source), source) 348 349 def testReverseDistinctTrie(self): 350 """Tests a reverse trie formed DAFSA with distinct labels passes unchanged. 351 """ 352 353 # 'a' 'a' 354 # \ \ 355 # 'c' => 'c' 356 # / / 357 # 'b' 'b' 358 359 node3 = ( 'c', [ None ] ) 360 node2 = ( 'b', [ node3 ] ) 361 node1 = ( 'a', [ node3 ] ) 362 source = [ node1, node2 ] 363 self.assertEqual(make_dafsa.join_suffixes(source), source) 364 365 def testJoinTwoHeads(self): 366 """Tests two heads can be joined even if there is something else between.""" 367 368 # 'a' ------'a' 369 # / 370 # 'b' => 'b' / 371 # / 372 # 'a' --- 373 # 374 # The picture above should shows that the new version should have just one 375 # instance of the node with label 'a'. 376 377 node3 = ( 'a', [ None ] ) 378 node2 = ( 'b', [ None ] ) 379 node1 = ( 'a', [ None ] ) 380 source1 = [ node1, node2, node3 ] 381 source2 = make_dafsa.join_suffixes(source1) 382 383 # Both versions should expand to the same content. 384 self.assertEqual(source1, source2) 385 # But the new version should have just one instance of 'a'. 386 self.assertIs(source2[0], source2[2]) 387 388 def testJoinTails(self): 389 """Tests tails can be joined.""" 390 391 # 'a' -> 'c' 'a' 392 # \ 393 # => 'c' 394 # / 395 # 'b' -> 'c' 'b' 396 397 node4 = ( 'c', [ None ] ) 398 node3 = ( 'b', [ node4 ] ) 399 node2 = ( 'c', [ None ] ) 400 node1 = ( 'a', [ node2 ] ) 401 source1 = [ node1, node3 ] 402 source2 = make_dafsa.join_suffixes(source1) 403 404 # Both versions should expand to the same content. 405 self.assertEqual(source1, source2) 406 # But the new version should have just one tail. 407 self.assertIs(source2[0][1][0], source2[1][1][0]) 408 409 def testMakeRecursiveTrie(self): 410 """Tests recursive suffix join.""" 411 412 # 'a' -> 'e' -> 'g' 'a' 413 # \ 414 # 'e' 415 # / \ 416 # 'b' -> 'e' -> 'g' 'b' \ 417 # \ 418 # => 'g' 419 # / 420 # 'c' -> 'f' -> 'g' 'c' / 421 # \ / 422 # 'f' 423 # / 424 # 'd' -> 'f' -> 'g' 'd' 425 426 node7 = ( 'g', [ None ] ) 427 node6 = ( 'f', [ node7 ] ) 428 node5 = ( 'e', [ node7 ] ) 429 node4 = ( 'd', [ node6 ] ) 430 node3 = ( 'c', [ node6 ] ) 431 node2 = ( 'b', [ node5 ] ) 432 node1 = ( 'a', [ node5 ] ) 433 source1 = [ node1, node2, node3, node4 ] 434 source2 = make_dafsa.join_suffixes(source1) 435 436 # Both versions should expand to the same content. 437 self.assertEqual(source1, source2) 438 # But the new version should have just one 'e'. 439 self.assertIs(source2[0][1][0], source2[1][1][0]) 440 # And one 'f'. 441 self.assertIs(source2[2][1][0], source2[3][1][0]) 442 # And one 'g'. 443 self.assertIs(source2[0][1][0][1][0], source2[2][1][0][1][0]) 444 445 def testMakeDiamond(self): 446 """Test we can join suffixes of a trie.""" 447 448 # 'b' -> 'd' 'b' 449 # / / \ 450 # 'a' => 'a' 'd' 451 # \ \ / 452 # 'c' -> 'd' 'c' 453 454 node5 = ( 'd', [ None ] ) 455 node4 = ( 'c', [ node5 ] ) 456 node3 = ( 'd', [ None ] ) 457 node2 = ( 'b', [ node3 ] ) 458 node1 = ( 'a', [ node2, node4 ] ) 459 source1 = [ node1 ] 460 source2 = make_dafsa.join_suffixes(source1) 461 462 # Both versions should expand to the same content. 463 self.assertEqual(source1, source2) 464 # But the new version should have just one 'd'. 465 self.assertIs(source2[0][1][0][1][0], source2[0][1][1][1][0]) 466 467 def testJoinOneChild(self): 468 """Tests that we can join some children but not all.""" 469 470 # 'c' ----'c' 471 # / / / 472 # 'a' 'a' / 473 # \ \ / 474 # 'd' 'd'/ 475 # => / 476 # 'c' / 477 # / / 478 # 'b' 'b' 479 # \ \ 480 # 'e' 'e' 481 482 node6 = ( 'e', [ None ] ) 483 node5 = ( 'c', [ None ] ) 484 node4 = ( 'b', [ node5, node6 ] ) 485 node3 = ( 'd', [ None ] ) 486 node2 = ( 'c', [ None ] ) 487 node1 = ( 'a', [ node2, node3 ] ) 488 source1 = [ node1, node4 ] 489 source2 = make_dafsa.join_suffixes(source1) 490 491 # Both versions should expand to the same content. 492 self.assertEqual(source1, source2) 493 # But the new version should have just one 'c'. 494 self.assertIs(source2[0][1][0], source2[1][1][0]) 495 496 497class ReverseTest(unittest.TestCase): 498 def testAtomicLabel(self): 499 """Tests an atomic label passes unchanged.""" 500 501 # 'a' => 'a' 502 503 node1 = ( 'a', [ None ] ) 504 source = [ node1 ] 505 self.assertEqual(make_dafsa.reverse(source), source) 506 507 def testLabel(self): 508 """Tests that labels are reversed.""" 509 510 # 'ab' => 'ba' 511 512 node1 = ( 'ab', [ None ] ) 513 source1 = [ node1 ] 514 node2 = ( 'ba', [ None ] ) 515 source2 = [ node2 ] 516 self.assertEqual(make_dafsa.reverse(source1), source2) 517 518 def testChain(self): 519 """Tests that edges are reversed.""" 520 521 # 'a' -> 'b' => 'b' -> 'a' 522 523 node2 = ( 'b', [ None ] ) 524 node1 = ( 'a', [ node2 ] ) 525 source1 = [ node1 ] 526 node4 = ( 'a', [ None ] ) 527 node3 = ( 'b', [ node4 ] ) 528 source2 = [ node3 ] 529 self.assertEqual(make_dafsa.reverse(source1), source2) 530 531 def testInnerTerminator(self): 532 """Tests a sequence with an inner terminator can be reversed.""" 533 534 # 'a' -> 'b' 'b' -> 'a' 535 # \ => / 536 # {sink} ------ 537 538 node2 = ( 'b', [ None ] ) 539 node1 = ( 'a', [ node2, None ] ) 540 source1 = [ node1 ] 541 node4 = ( 'a', [ None ] ) 542 node3 = ( 'b', [ node4 ] ) 543 source2 = [ node3, node4 ] 544 self.assertEqual(make_dafsa.reverse(source1), source2) 545 546 def testAtomicTrie(self): 547 """Tests a trie formed DAFSA can be reversed.""" 548 549 # 'b' 'b' 550 # / \ 551 # 'a' => 'a' 552 # \ / 553 # 'c' 'c' 554 555 node3 = ( 'c', [ None ] ) 556 node2 = ( 'b', [ None ] ) 557 node1 = ( 'a', [ node2, node3 ] ) 558 source1 = [ node1 ] 559 node6 = ( 'a', [ None ] ) 560 node5 = ( 'c', [ node6 ] ) 561 node4 = ( 'b', [ node6 ] ) 562 source2 = [ node4, node5 ] 563 self.assertEqual(make_dafsa.reverse(source1), source2) 564 565 def testReverseAtomicTrie(self): 566 """Tests a reverse trie formed DAFSA can be reversed.""" 567 568 # 'a' 'a' 569 # \ / 570 # 'c' => 'c' 571 # / \ 572 # 'b' 'b' 573 574 node3 = ( 'c', [ None ] ) 575 node2 = ( 'b', [ node3 ] ) 576 node1 = ( 'a', [ node3 ] ) 577 source1 = [ node1, node2 ] 578 node6 = ( 'b', [ None ] ) 579 node5 = ( 'a', [ None ] ) 580 node4 = ( 'c', [ node5, node6 ] ) 581 source2 = [ node4 ] 582 self.assertEqual(make_dafsa.reverse(source1), source2) 583 584 def testDiamond(self): 585 """Tests we can reverse both edges and nodes in a diamond.""" 586 587 # 'cd' 'dc' 588 # / \ / \ 589 # 'ab' 'gh' => 'hg' 'ba' 590 # \ / \ / 591 # 'ef' 'fe' 592 593 node4 = ( 'gh', [ None ] ) 594 node3 = ( 'ef', [ node4 ] ) 595 node2 = ( 'cd', [ node4 ] ) 596 node1 = ( 'ab', [ node2, node3 ] ) 597 source1 = [ node1 ] 598 node8 = ( 'ba', [ None ] ) 599 node7 = ( 'fe', [ node8 ] ) 600 node6 = ( 'dc', [ node8 ] ) 601 node5 = ( 'hg', [ node6, node7 ] ) 602 source2 = [ node5 ] 603 self.assertEqual(make_dafsa.reverse(source1), source2) 604 605 606class TopSortTest(unittest.TestCase): 607 def testEmpty(self): 608 """Tests a DAFSA with no interior nodes can be sorted.""" 609 610 # {} => [ ] 611 612 source = [None] 613 nodes = [] 614 self.assertEqual(make_dafsa.top_sort(source), nodes) 615 616 def testNode(self): 617 """Tests a DAFSA with one node can be sorted.""" 618 619 # 'a' => [ 'a' ] 620 621 node1 = ( 'a', [ None ] ) 622 source = [ node1 ] 623 nodes = [ node1 ] 624 self.assertEqual(make_dafsa.top_sort(source), nodes) 625 626 def testDiamond(self): 627 """Tests nodes in a diamond can be sorted.""" 628 629 # 'b' 630 # / \ 631 # 'a' 'd' 632 # \ / 633 # 'c' 634 635 node4 = ( 'd', [ None ] ) 636 node3 = ( 'c', [ node4 ] ) 637 node2 = ( 'b', [ node4 ] ) 638 node1 = ( 'a', [ node2, node3 ] ) 639 source = [ node1 ] 640 nodes = make_dafsa.top_sort(source) 641 self.assertLess(nodes.index(node1), nodes.index(node2)) 642 self.assertLess(nodes.index(node2), nodes.index(node4)) 643 self.assertLess(nodes.index(node3), nodes.index(node4)) 644 645 646class EncodePrefixTest(unittest.TestCase): 647 def testChar(self): 648 """Tests to encode a single character prefix.""" 649 label = 'a' 650 bytes = [ ord('a') ] 651 self.assertEqual(make_dafsa.encode_prefix(label), bytes) 652 653 def testChars(self): 654 """Tests to encode a multi character prefix.""" 655 label = 'ab' 656 bytes = [ ord('b'), ord('a') ] 657 self.assertEqual(make_dafsa.encode_prefix(label), bytes) 658 659 660class EncodeLabelTest(unittest.TestCase): 661 def testChar(self): 662 """Tests to encode a single character label.""" 663 label = 'a' 664 bytes = [ ord('a') + 0x80 ] 665 self.assertEqual(make_dafsa.encode_label(label), bytes) 666 667 def testChars(self): 668 """Tests to encode a multi character label.""" 669 label = 'ab' 670 bytes = [ ord('b') + 0x80, ord('a') ] 671 self.assertEqual(make_dafsa.encode_label(label), bytes) 672 673 674class EncodeLinksTest(unittest.TestCase): 675 def testEndLabel(self): 676 """Tests to encode link to the sink.""" 677 children = [ None ] 678 offsets = {} 679 bytes = 0 680 output = [] 681 self.assertEqual(make_dafsa.encode_links(children, offsets, bytes), 682 output) 683 684 def testOneByteOffset(self): 685 """Tests to encode a single one byte offset.""" 686 node = ( '', [ None ] ) 687 children = [ node ] 688 offsets = { id(node) : 2 } 689 bytes = 5 690 output = [ 132 ] 691 self.assertEqual(make_dafsa.encode_links(children, offsets, bytes), 692 output) 693 694 def testOneByteOffsets(self): 695 """Tests to encode a sequence of one byte offsets.""" 696 node1 = ( '', [ None ] ) 697 node2 = ( '', [ None ] ) 698 children = [ node1, node2 ] 699 offsets = { id(node1) : 2, id(node2) : 1 } 700 bytes = 5 701 output = [ 129, 5 ] 702 self.assertEqual(make_dafsa.encode_links(children, offsets, bytes), 703 output) 704 705 def testTwoBytesOffset(self): 706 """Tests to encode a single two byte offset.""" 707 node = ( '', [ None ] ) 708 children = [ node ] 709 offsets = { id(node) : 2 } 710 bytes = 1005 711 output = [ 237, 195] 712 self.assertEqual(make_dafsa.encode_links(children, offsets, bytes), 713 output) 714 715 def testTwoBytesOffsets(self): 716 """Tests to encode a sequence of two byte offsets.""" 717 node1 = ( '', [ None ] ) 718 node2 = ( '', [ None ] ) 719 node3 = ( '', [ None ] ) 720 children = [ node1, node2, node3 ] 721 offsets = { id(node1) : 1002, id(node2) : 2, id(node3) : 2002 } 722 bytes = 3005 723 output = [ 232, 195, 232, 67, 241, 67 ] 724 self.assertEqual(make_dafsa.encode_links(children, offsets, bytes), 725 output) 726 727 def testThreeBytesOffset(self): 728 """Tests to encode a single three byte offset.""" 729 node = ( '', [ None ] ) 730 children = [ node ] 731 offsets = { id(node) : 2 } 732 bytes = 100005 733 output = [ 166, 134, 225 ] 734 self.assertEqual(make_dafsa.encode_links(children, offsets, bytes), 735 output) 736 737 def testThreeBytesOffsets(self): 738 """Tests to encode a sequence of three byte offsets.""" 739 node1 = ( '', [ None ] ) 740 node2 = ( '', [ None ] ) 741 node3 = ( '', [ None ] ) 742 children = [ node1, node2, node3 ] 743 offsets = { id(node1) : 100002, id(node2) : 2, id(node3) : 200002 } 744 bytes = 300005 745 output = [ 160, 134, 225, 160, 134, 97, 172, 134, 97 ] 746 self.assertEqual(make_dafsa.encode_links(children, offsets, bytes), 747 output) 748 749 def testOneTwoThreeBytesOffsets(self): 750 """Tests to encode offsets of different sizes.""" 751 node1 = ( '', [ None ] ) 752 node2 = ( '', [ None ] ) 753 node3 = ( '', [ None ] ) 754 children = [ node1, node2, node3 ] 755 offsets = { id(node1) : 10003, id(node2) : 10002, id(node3) : 100002 } 756 bytes = 300005 757 output = [ 129, 143, 95, 97, 74, 13, 99 ] 758 self.assertEqual(make_dafsa.encode_links(children, offsets, bytes), 759 output) 760 761 762class ExamplesTest(unittest.TestCase): 763 def testExample1(self): 764 """Tests Example 1 from make_dafsa.py.""" 765 infile = [ '%%', 'aa, 1', 'a, 2', '%%' ] 766 bytes = [ 0x81, 0xE1, 0x02, 0x81, 0x82, 0x61, 0x81 ] 767 outfile = make_dafsa.to_cxx(bytes) 768 self.assertEqual(make_dafsa.words_to_cxx(make_dafsa.parse_gperf( 769 infile, False)), outfile) 770 771 def testExample2(self): 772 """Tests Example 2 from make_dafsa.py.""" 773 infile = [ '%%', 'aa, 1', 'bbb, 2', 'baa, 1', '%%' ] 774 bytes = [ 0x02, 0x83, 0xE2, 0x02, 0x83, 0x61, 0x61, 0x81, 0x62, 0x62, 775 0x82 ] 776 outfile = make_dafsa.to_cxx(bytes) 777 self.assertEqual(make_dafsa.words_to_cxx(make_dafsa.parse_gperf( 778 infile, False)), outfile) 779 780 781if __name__ == '__main__': 782 unittest.main() 783