|
1 | 1 | '''
|
2 | 2 | Tests for mutation based fields
|
3 |
| -
|
4 |
| -.. todo:: BlockDuplicates, MutableField |
5 | 3 | '''
|
6 | 4 |
|
7 | 5 | from common import BaseTestCase, metaTest
|
8 | 6 | from kitty.core import KittyException
|
9 | 7 | from kitty.model.low_level.mutated_field import BitFlip, ByteFlip
|
10 | 8 | from kitty.model.low_level.mutated_field import BitFlips, ByteFlips
|
11 | 9 | from kitty.model.low_level.mutated_field import BlockRemove, BlockDuplicate, BlockSet
|
| 10 | +from kitty.model.low_level.mutated_field import BlockDuplicates, MutableField |
12 | 11 | from struct import pack
|
13 | 12 |
|
14 | 13 |
|
@@ -520,3 +519,160 @@ def testNumDups10(self):
|
520 | 519 | def testExceptionIfNumDupsNotPositive(self):
|
521 | 520 | with self.assertRaises(KittyException):
|
522 | 521 | BlockDuplicate(b'\x00\x00\x00', 2, num_dups=-1)
|
| 522 | + |
| 523 | + |
| 524 | +class BlockDuplicatesTests(BaseTestCase): |
| 525 | + |
| 526 | + __meta__ = False |
| 527 | + |
| 528 | + def setUp(self): |
| 529 | + super(BlockDuplicatesTests, self).setUp(BlockDuplicates) |
| 530 | + self._uut_name = 'uut' |
| 531 | + self._default_uut_value = '\x11\x22\x33\x44' |
| 532 | + self._default_block_size = 2 |
| 533 | + self._default_num_dups_range = (2, 5, 10, 50, 100) |
| 534 | + |
| 535 | + def _get_field(self, value=-1, block_size=None, num_dups_range=None, fuzzable=True): |
| 536 | + if value == -1: |
| 537 | + value = self._default_uut_value |
| 538 | + if block_size is None: |
| 539 | + block_size = self._default_block_size |
| 540 | + if num_dups_range is None: |
| 541 | + num_dups_range = self._default_num_dups_range |
| 542 | + return BlockDuplicates(value, block_size, num_dups_range, fuzzable, name=self._uut_name) |
| 543 | + |
| 544 | + def _get_all_mutations(self, field, reset=True): |
| 545 | + res = [] |
| 546 | + while field.mutate(): |
| 547 | + res.append(field.render()) |
| 548 | + if reset: |
| 549 | + field.reset() |
| 550 | + return res |
| 551 | + |
| 552 | + def _base_check(self, field): |
| 553 | + num_mutations = field.num_mutations() |
| 554 | + mutations = self._get_all_mutations(field) |
| 555 | + self.assertEqual(num_mutations, len(mutations)) |
| 556 | + mutations = self._get_all_mutations(field) |
| 557 | + self.assertEqual(num_mutations, len(mutations)) |
| 558 | + |
| 559 | + def testBase(self): |
| 560 | + self._base_check(self._get_field()) |
| 561 | + |
| 562 | + def testNoMutationsWhenNotFuzzable(self): |
| 563 | + uut = self._get_field(fuzzable=False) |
| 564 | + uut_num_mutations = uut.num_mutations() |
| 565 | + uut_mutations = self._get_all_mutations(uut) |
| 566 | + self.assertEqual(0, uut_num_mutations) |
| 567 | + self.assertEqual(uut_num_mutations, len(uut_mutations)) |
| 568 | + |
| 569 | + def testExceptionIfBlockSizeIsNegative(self): |
| 570 | + with self.assertRaises(KittyException): |
| 571 | + self._get_field(value='\x11\x22\x33\x44', block_size=-1) |
| 572 | + |
| 573 | + def testExceptionIfBlockSizeIsZero(self): |
| 574 | + with self.assertRaises(KittyException): |
| 575 | + self._get_field(value='\x11\x22\x33\x44', block_size=0) |
| 576 | + |
| 577 | + def testExceptionIfBlockSizeBiggerThanValue(self): |
| 578 | + with self.assertRaises(KittyException): |
| 579 | + self._get_field(value='\x11\x22\x33\x44', block_size=5) |
| 580 | + |
| 581 | + def testExceptionNumDupsRangeNegativeValues(self): |
| 582 | + with self.assertRaises(KittyException): |
| 583 | + self._get_field(num_dups_range=(-1,)) |
| 584 | + |
| 585 | + |
| 586 | +class MutableFieldTests(BaseTestCase): |
| 587 | + |
| 588 | + def setUp(self): |
| 589 | + super(MutableFieldTests, self).setUp(MutableField) |
| 590 | + self._uut_name = 'uut' |
| 591 | + |
| 592 | + def _get_field(self, value, fuzzable=True): |
| 593 | + return MutableField(value=value, fuzzable=fuzzable, name=self._uut_name) |
| 594 | + |
| 595 | + def _get_all_mutations(self, field, reset=True): |
| 596 | + res = [] |
| 597 | + while field.mutate(): |
| 598 | + res.append(field.render()) |
| 599 | + if reset: |
| 600 | + field.reset() |
| 601 | + return res |
| 602 | + |
| 603 | + def _base_check(self, field): |
| 604 | + num_mutations = field.num_mutations() |
| 605 | + mutations = self._get_all_mutations(field) |
| 606 | + self.assertEqual(num_mutations, len(mutations)) |
| 607 | + mutations = self._get_all_mutations(field) |
| 608 | + self.assertEqual(num_mutations, len(mutations)) |
| 609 | + |
| 610 | + def testBasePayloadShort(self): |
| 611 | + self._base_check(self._get_field('012')) |
| 612 | + |
| 613 | + def testBasePayloadOver4bytes(self): |
| 614 | + self._base_check(self._get_field('01234')) |
| 615 | + |
| 616 | + def testBasePayloadOver8bytes(self): |
| 617 | + self._base_check(self._get_field('0123456789')) |
| 618 | + |
| 619 | + def testBasePayloadOver16bytes(self): |
| 620 | + self._base_check(self._get_field('0123456789abcdefghijklmno')) |
| 621 | + |
| 622 | + def testNoMutationsWhenNotFuzzable(self): |
| 623 | + uut = self._get_field(value='0123456789', fuzzable=False) |
| 624 | + uut_num_mutations = uut.num_mutations() |
| 625 | + uut_mutations = self._get_all_mutations(uut) |
| 626 | + self.assertEqual(0, uut_num_mutations) |
| 627 | + self.assertEqual(uut_num_mutations, len(uut_mutations)) |
| 628 | + |
| 629 | + # |
| 630 | + # This set of tests looks at the internal fields of the |
| 631 | + # MutableField. Kinda dirty, but this should be checked |
| 632 | + # |
| 633 | + def testInternalFieldsShortPayload(self): |
| 634 | + uut = self._get_field('012') |
| 635 | + fields = uut._fields |
| 636 | + field_types = [type(f) for f in fields] |
| 637 | + expected_field_types = [ |
| 638 | + ByteFlips, BitFlips |
| 639 | + ] |
| 640 | + self.assertEqual(field_types, expected_field_types) |
| 641 | + self.assertEqual(len(fields[0]._fields), 2) |
| 642 | + |
| 643 | + def testInternalFieldsPayloadOver4Bytes(self): |
| 644 | + uut = self._get_field('01234') |
| 645 | + fields = uut._fields |
| 646 | + field_types = [type(f) for f in fields] |
| 647 | + expected_field_types = [ |
| 648 | + ByteFlips, BitFlips, |
| 649 | + BlockRemove, BlockDuplicate, BlockSet, |
| 650 | + ] |
| 651 | + self.assertEqual(field_types, expected_field_types) |
| 652 | + self.assertEqual(len(fields[0]._fields), 3) |
| 653 | + |
| 654 | + def testInternalFieldsPayloadOver8Bytes(self): |
| 655 | + uut = self._get_field('012345678') |
| 656 | + fields = uut._fields |
| 657 | + field_types = [type(f) for f in fields] |
| 658 | + expected_field_types = [ |
| 659 | + ByteFlips, BitFlips, |
| 660 | + BlockRemove, BlockDuplicate, BlockSet, |
| 661 | + BlockRemove, BlockDuplicates, BlockSet, |
| 662 | + ] |
| 663 | + self.assertEqual(field_types, expected_field_types) |
| 664 | + self.assertEqual(len(fields[0]._fields), 3) |
| 665 | + |
| 666 | + def testInternalFieldsPayloadOver16Bytes(self): |
| 667 | + uut = self._get_field('0123456789abcdefgh') |
| 668 | + fields = uut._fields |
| 669 | + field_types = [type(f) for f in fields] |
| 670 | + expected_field_types = [ |
| 671 | + ByteFlips, BitFlips, |
| 672 | + BlockRemove, BlockDuplicate, BlockSet, |
| 673 | + BlockRemove, BlockDuplicates, BlockSet, |
| 674 | + BlockRemove, BlockDuplicates, BlockSet, |
| 675 | + ] |
| 676 | + self.assertEqual(field_types, expected_field_types) |
| 677 | + self.assertEqual(len(fields[0]._fields), 3) |
| 678 | + |
0 commit comments