Index: Lib/test/test_struct.py
===================================================================
--- Lib/test/test_struct.py (revision 87813)
+++ Lib/test/test_struct.py (working copy)
@@ -29,7 +29,37 @@
else:
return string_reverse(value)
+def sizeof(fmt):
+ return struct.calcsize(fmt)
+
+def alignof(code):
+ return sizeof('b' + code) - sizeof(code)
+
class StructTest(unittest.TestCase):
+ def assertStructEquivalence(self, fmt1, fmt2, tup1, tup2):
+ flat = struct.Struct(fmt1)
+ flat_bytes = flat.pack(*tup1)
+ nested = struct.Struct(fmt2)
+ nested_bytes = nested.pack(*tup2)
+ self.assertEqual(flat_bytes, nested_bytes)
+ self.assertEqual(tup1, flat.unpack(flat_bytes))
+ self.assertEqual(tup2, nested.unpack(nested_bytes))
+
+ def assertBadPack(self, fmt, tup):
+ self.assertRaises(struct.error, struct.pack, fmt, *tup)
+
+ def assertBadUnpack(self, fmt, byte_str):
+ self.assertRaises(struct.error, struct.unpack, fmt, byte_str)
+
+ def assertBadFormat(self, fmt):
+ self.assertRaises(struct.error, struct.calcsize, fmt)
+
+ def assertEqualSizes(self, fmt1, fmt2):
+ self.assertEqual(sizeof(fmt1), sizeof(fmt2))
+
+ def assertUnequalSizes(self, fmt1, fmt2):
+ self.assertNotEqual(sizeof(fmt1), sizeof(fmt2))
+
def test_isbigendian(self):
self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN)
@@ -556,6 +586,161 @@
s = struct.Struct('i')
s.__init__('ii')
+ def test_struct_equivalence(self):
+ def empty_tuples(depth):
+ tup = ()
+ for i in range(0, depth):
+ tup = (tup,)
+ return tup
+
+ self.assertStructEquivalence('', 'T{}', (), empty_tuples(1))
+ self.assertStructEquivalence('', 'T{' * 61 + '}' * 61,
+ (), empty_tuples(61))
+ self.assertStructEquivalence('ii ', 'T{ii} ', (1, 2), ((1, 2),))
+ self.assertStructEquivalence('iii', 'T{ii} i', (1, 2, 3), ((1, 2),3))
+ self.assertStructEquivalence('HB2B', '\t\tT{\n\tH\n\n\nB 2B}',
+ (1, 2, 3, 4), ((1, 2, 3, 4),))
+ self.assertStructEquivalence('i2i', 'T{ i 2i }',
+ (1, 2, 3), ((1, 2, 3),))
+ self.assertStructEquivalence('iiiHHiBiHBiHi',
+ '\t T{\n\nii T {i HH }\ni T { BiH B i } } T\t{ H }i\t',
+ (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13),
+ ((1, 2, (3, 4, 5), 6, (7, 8, 9, 10, 11)), (12,), 13))
+ self.assertStructEquivalence('ii', 'T { i T { i } }',
+ (187, 42), ((187, (42,)),))
+ self.assertStructEquivalence('iHBB',
+ """i
+ T{
+ H
+ B
+ B
+ }
+ """,
+ (1, 2, 3, 4),
+ (1, (2, 3, 4)))
+ self.assertStructEquivalence('iHBBBB',
+ """i
+ T{
+ H
+ T {}
+ B
+ T {
+ }
+ B
+ T { BB }
+ }
+ """,
+ (1, 2, 3, 4, 5, 6),
+ (1, (2, (), 3, (), 4, (5, 6))))
+ self.assertStructEquivalence('2T{bb}', 'T{bb}T{bb}',
+ ((1, 2), (3, 4)), ((1, 2), (3, 4)))
+ self.assertStructEquivalence('2i3i', '5i',
+ (1, 2, 3, 4, 5), (1, 2, 3, 4, 5))
+
+ def test_bad_pack(self):
+ self.assertBadPack('T{}', ())
+ self.assertBadPack('T{ T{} }', ())
+ self.assertBadPack('T{T{T{}}}', (1,))
+ self.assertBadPack('T{i}', ((),))
+ self.assertBadPack('T{i}', (1,))
+ self.assertBadPack('h T { b }', ((2,), 1))
+ self.assertBadPack('T { h } T { h }', (1, 2))
+ self.assertBadPack('T { T { h } }', ((1,),))
+ self.assertBadPack('T { h }', (('fizzbuzz',),))
+ self.assertBadPack('T { i T { i } }', (('foo', (42,)),))
+ self.assertBadPack('bb', ((1,), (2,)))
+
+ def test_bad_unpack(self):
+ self.assertBadUnpack('T{i}', b'fizzbuzz')
+ self.assertBadUnpack('i T{ h T{b} }', b'\x00' * 100)
+ self.assertBadUnpack('T{ b T{T{T{T{bbb}}} 10s }}', b'\x00')
+
+ def test_bad_structs(self):
+ self.assertBadFormat('T{')
+ self.assertBadFormat('\nT\t\t{')
+ self.assertBadFormat('T')
+ self.assertBadFormat('T { T { }')
+ self.assertBadFormat('T\n{\nT{\n}\n\n')
+ self.assertBadFormat('((()))')
+ self.assertBadFormat('T<{}')
+ self.assertBadFormat('12&&&afa7sasdf7asdfl><>aaa')
+ self.assertBadFormat('{}')
+ self.assertBadFormat('T{}TTTTT')
+ self.assertBadFormat('1+2*200')
+ self.assertBadFormat('def foo(): return 187')
+ self.assertBadFormat('t{b}')
+ self.assertBadFormat('<<<<<<<<<<<')
+ self.assertBadFormat('.......................')
+ self.assertBadFormat('<i<i')
+ self.assertBadFormat('<i>i')
+ self.assertBadFormat('>i<i')
+ self.assertBadFormat('>i>i')
+ self.assertBadFormat('<H T { >i }')
+ self.assertBadFormat('<H > T { i }')
+ self.assertBadFormat('}}}}')
+ self.assertBadFormat('}this is bogus!!!!')
+
+
+ def test_struct_alignment(self):
+ largest_code_struct = 'T{%s}' % ''.join(integer_codes)
+ largest_code = max(integer_codes, key=alignof)
+ largest_code_size = sizeof(largest_code)
+ largest_code_alignment = alignof(largest_code)
+ all_codes_size = sizeof(''.join(integer_codes))
+
+ for code in integer_codes:
+ code_size = sizeof(code)
+ struct_str = code + largest_code_struct
+ padding_size = max(code_size, largest_code_alignment)
+ self.assertEquals(sizeof(struct_str),
+ padding_size + all_codes_size)
+
pv
2011年02月12日 19:31:43
The tests for alignment handling is not fully comp
+ def test_no_padding(self):
+ all_codes_size = struct.calcsize('=' + ''.join(integer_codes))
+
+ for code in integer_codes:
+ for order in ['<', '>', '=']:
+ code_size = sizeof(order + code)
+ struct_str = '%s%sT{%s}' % (order, code, ''.join(integer_codes))
+ self.assertEquals(sizeof(struct_str),
+ code_size + all_codes_size)
+
+ def test_equal_sizes(self):
+ self.assertEqualSizes('b', 'T{b}')
+ self.assertEqualSizes('bT{bbb}bbT{T{b}}', 'T{bbbbbbb}')
+ self.assertEqualSizes('=hibihibi', '=hiT{bi}hiT{bi}')
+ self.assertEqualSizes('T{T{T{T{}}}}', '')
+ self.assertEqualSizes('121T{}', '')
+ self.assertEqualSizes('=bhi', '=T{bT{hT{i}}}')
+ self.assertEqualSizes('=T{T{T{bb}}}hhT{T{T{b}}}', '=bbhhb')
+ self.assertEqualSizes('xxxxT{T{x}}xxxx', 'xxxxxxxxx')
+ self.assertEqualSizes('bl', 'll')
+ self.assertEqualSizes('bi', 'ii')
+ self.assertEqualSizes('bh', 'hh')
+ self.assertEqualSizes('100b', 'b' * 100)
+ self.assertEqualSizes('13T{bT{hi}}', 'T{bT{hi}}' * 13)
+ self.assertEqualSizes('20T{ 13T{b} }', '260b')
+ self.assertEqualSizes('20T{ 13T{4T{b}} 10T{60T{b}} }', '13040b')
+
+ def test_unequal_sizes(self):
+ self.assertUnequalSizes('', 'x')
+ self.assertUnequalSizes('bi', '=bi')
+ self.assertUnequalSizes('iT{b}', 'bT{i}')
+ self.assertUnequalSizes('20T{ 13T{4T{b}} 10T{60T{b}} }', '130b')
+
+ def test_del(self):
+ s = struct.Struct('T{ T { h T{i} T{d} } b}')
+ del s
+ with self.assertRaises(NameError) as exc:
+ s.pack( ((1,), 2))
+
+ def test_max_nesting_depth(self):
+ self.assertBadFormat('T{' * 65 + '}' * 65)
+ self.assertBadFormat('T{' * 187 + '}' * 187)
+ self.assertBadFormat('T{' * 500 + '}' * 500)
+ self.assertEqualSizes('T{' * 64 + '}' * 64, '')
+ self.assertEqualSizes('T{' * 64 + '}' * 64 + 'T{' * 64 + '}' * 64, '')
+
def test_main():
run_unittest(StructTest)