File size: 4,640 Bytes
543c8e8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | """Small independent byte fixtures for the E02 inspector's validation boundaries."""
import struct
import unittest
from inspect_mb3dat import InvalidDAT, inspect
from analyze_converter import cases, dat, i32, methods, vecs, TRIPLE
class DATInspectorTests(unittest.TestCase):
def test_two_distinct_header_layouts(self):
for version, size in [(201501280, 21), (201512200, 23)]:
data = dat(version)
self.assertEqual(len(data), size)
result = inspect(data)
self.assertEqual(result['version'], version)
self.assertEqual(result['consumed_bytes'], size)
self.assertEqual(result['brushes'], [])
def test_origin_and_direction_vectors(self):
d = inspect(dat(201512200, b'\0\1' + vecs(TRIPLE), 1))
p = d['brushes'][0]['planes'][0]
self.assertEqual(p['offset'], 21)
self.assertEqual(p['p0'], [1, 2, 3])
self.assertEqual(p['u'], [4, 5, 6])
self.assertEqual(p['v'], [7, 8, 9])
def test_sparse_strings_and_binary_duplicate(self):
body = b'\0\1\0first\0\0last\0\xff' + vecs(TRIPLE)
d = inspect(dat(201512200, body, 1, tables=b'\1name\0\0'))
self.assertEqual(d['string_properties'], ['name'])
self.assertEqual(d['brushes'][0]['planes'][0]['strings'], {'0': 'last'})
def test_uv_wire_order_is_not_text_tuple_order(self):
body = b'\0\1\0' + struct.pack('<10f', *range(1, 11)) + b'\xff' + vecs(TRIPLE)
d = inspect(dat(201512200, body, 1, tables=b'\0\1uv\0'))
self.assertEqual(d['brushes'][0]['planes'][0]['uv']['0'], list(range(1, 11)))
def test_width_three_uses_four_bytes(self):
data = dat(201512200, tables=i32(0) + i32(0), widths=30)
self.assertEqual(inspect(data)['consumed_bytes'], 29)
def test_legacy_signed_16_count_is_rejected(self):
with self.assertRaisesRegex(InvalidDAT, 'invalid/excessive count -32768'):
inspect(dat(201501280, b'\1\0\x80', 1))
def test_computed_contour(self):
body = b'\0\1' + vecs(TRIPLE) + b'\1' + vecs([(9, 8, 7)])
d = inspect(dat(201512200, body, 1, computed=True))
self.assertEqual(d['brushes'][0]['planes'][0]['polygon'], [[9, 8, 7]])
def test_patch_implicit_grid_size(self):
body = b'\0\3\3\2\2' + vecs([(1, 2, 3)] * 9) + vecs([(4, 5, 6)] * 9) + vecs([(0, 1, 0)] * 9)
d = inspect(dat(201512200, patch_records=body, patch_count=1, computed=True))
self.assertEqual(len(d['patches'][0]['points']), 9)
self.assertEqual(d['patches'][0]['normals'][8], [0, 1, 0])
def test_all_prefix_truncations_rejected(self):
data = dat(201512200, b'\0\1' + vecs(TRIPLE), 1)
for length in range(len(data)):
with self.subTest(length=length), self.assertRaises(InvalidDAT):
inspect(data[:length])
def test_unterminated_string_and_bad_index_rejected(self):
with self.assertRaisesRegex(InvalidDAT, 'unterminated'):
inspect(b'Mb3World' + i32(201512200) + b'\0\1no-terminator')
with self.assertRaisesRegex(InvalidDAT, 'index 1 out of range'):
inspect(dat(201512200, b'\0\1\1bad\0\xff' + vecs(TRIPLE), 1, tables=b'\1p\0\0'))
def test_allocation_limit_and_count_overflow(self):
with self.assertRaises(InvalidDAT):
inspect(dat(201512200, brush_count=2**31 - 1))
with self.assertRaises(InvalidDAT):
inspect(dat(201512200, patch_records=b'\x0a' + i32(65536) * 4, patch_count=1))
def test_trailing_bytes_reported(self):
self.assertEqual(inspect(dat(201512200) + b'extra')['trailing_bytes'], 5)
def test_wrong_magic_and_unknown_version(self):
for data in [b'NOTWORLD' + dat(201512200)[8:], b'Mb3World' + i32(1) + b'\0' * 20]:
with self.assertRaises(InvalidDAT):
inspect(data)
class ResearchHarnessTests(unittest.TestCase):
def test_unique_case_names_and_chained_inputs(self):
for version in [201501280, 201512200]:
seen = set()
for case in cases(version):
self.assertNotIn(case['name'], seen)
if 'from_case' in case:
self.assertIn(case['from_case'], seen)
seen.add(case['name'])
def test_il_anchor_index(self):
il = '.method public static void Sample () cil managed\n{\n// Method begins at RVA 0x2050\n// Code size: 7 (0x7)\n} // end of method Example::Sample\n'
self.assertEqual(methods(il), [{'name': 'Example::Sample', 'rva': '0x2050', 'il_bytes': 7, 'il_line': 1}])
if __name__ == '__main__':
unittest.main()
|