1 #! /usr/bin/env python2.2
3 __doc__ = """test case for samba.tdbkpack functions
5 tdbpack provides a means of pickling values into binary formats
6 compatible with that used by the samba tdbpack()/tdbunpack()
9 Numbers are always stored in little-endian format; strings are stored
10 in either DOS or Unix codepage as appropriate.
12 The format for any particular element is encoded as a short ASCII
13 string, with one character per field."""
15 # Copyright (C) 2002 Hewlett-Packard.
17 __author__ = 'Martin Pool <mbp@sourcefrog.net>'
23 both_unpackers = (samba.tdbpack.unpack, oldtdbutil.unpack)
24 both_packers = (samba.tdbpack.pack, oldtdbutil.pack)
26 class PackTests(unittest.TestCase):
27 symm_cases = [('B', ['hello' * 51], '\xff\0\0\0' + 'hello' * 51),
28 ('w', [42], '\x2a\0'),
29 ('www', [42, 2, 69], '\x2a\0\x02\0\x45\0'),
30 ('wd', [42, 256], '\x2a\0\0\x01\0\0'),
32 ('w', [255], '\xff\0'),
33 ('w', [256], '\0\x01'),
34 ('w', [0xdead], '\xad\xde'),
35 ('w', [0xffff], '\xff\xff'),
36 ('p', [0], '\0\0\0\0'),
37 ('p', [1], '\x01\0\0\0'),
38 ('d', [0x01020304], '\x04\x03\x02\x01'),
39 ('d', [0x7fffffff], '\xff\xff\xff\x7f'),
40 ('d', [0x80000000], '\x00\x00\x00\x80'),
41 ('d', [-1], '\xff\xff\xff\xff'),
42 ('d', [-255], '\x01\xff\xff\xff'),
43 ('d', [-256], '\x00\xff\xff\xff'),
44 ('ddd', [1, 10, 50], '\x01\0\0\0\x0a\0\0\0\x32\0\0\0'),
45 ('ff', ['hello', 'world'], 'hello\0world\0'),
46 ('fP', ['hello', 'world'], 'hello\0world\0'),
47 ('PP', ['hello', 'world'], 'hello\0world\0'),
48 ('B', [''], '\0\0\0\0'),
49 ('B', ['hello'], '\x05\0\0\0hello'),
50 ('BB', ['hello\0world', 'now'],
51 '\x0b\0\0\0hello\0world\x03\0\0\0now'),
52 ('pd', [1, 10], '\x01\0\0\0\x0a\0\0\0'),
53 ('BBB', ['hello', '', 'world'],
54 '\x05\0\0\0hello\0\0\0\0\x05\0\0\0world'),
56 # strings are sequences in Python, there's no getting away
58 ('ffff', 'evil', 'e\0v\0i\0l\0'),
67 # exercise some long strings
68 ('PP', ['hello' * 255, 'world' * 255],
69 'hello' * 255 + '\0' + 'world' * 255 + '\0'),
70 ('PP', ['hello' * 40000, 'world' * 50000],
71 'hello' * 40000 + '\0' + 'world' * 50000 + '\0'),
72 ('B', ['hello' * 51], '\xff\0\0\0' + 'hello' * 51),
73 ('BB', ['hello' * 40000, 'world' * 50000],
74 '\x40\x0d\x03\0' + 'hello' * 40000 + '\x90\xd0\x03\x00' + 'world' * 50000),
77 def test_symmetric(self):
78 """Cookbook of symmetric pack/unpack tests
80 for packer in both_packers:
81 for unpacker in both_unpackers:
82 for format, values, expected in self.symm_cases:
83 self.assertEquals(packer(format, values), expected)
84 out, rest = unpacker(format, expected)
85 self.assertEquals(rest, '')
86 self.assertEquals(list(values), list(out))
89 """Test large pack/unpack strings"""
90 large_cases = [('w' * 1000, xrange(1000)), ]
91 for packer in both_packers:
92 for unpacker in both_unpackers:
93 for format, values in large_cases:
94 packed = packer(format, values)
95 out, rest = unpacker(format, packed)
96 self.assertEquals(rest, '')
97 self.assertEquals(list(values), list(out))
101 """Cookbook of expected pack values
103 These can't be used for the symmetric test because the unpacked value is
106 cases = [('w', (42,), '\x2a\0'),
107 ('p', [None], '\0\0\0\0'),
108 ('p', ['true'], '\x01\0\0\0'),
111 for packer in both_packers:
112 for format, values, expected in cases:
113 self.assertEquals(packer(format, values), expected)
115 def test_unpack_extra(self):
117 for unpacker in both_unpackers:
118 for format, values, packed in self.symm_cases:
119 out, rest = unpacker(format, packed + 'hello sailor!')
120 self.assertEquals(rest, 'hello sailor!')
121 self.assertEquals(list(values), list(out))
124 def test_pack_extra(self):
125 """Leftover values when packing"""
127 ('d', [10, 20], [10]),
128 ('d', [10, 'hello'], [10]),
129 ('ff', ['hello', 'world', 'sailor'], ['hello', 'world']),
131 for unpacker in both_unpackers:
132 for packer in both_packers:
133 for format, values, chopped in cases:
134 bin = packer(format, values)
135 out, rest = unpacker(format, bin)
136 self.assertEquals(list(out), list(chopped))
137 self.assertEquals(rest, '')
140 def test_unpack(self):
141 """Cookbook of tricky unpack tests"""
143 # Apparently I couldn't think of any tests that weren't
146 for unpacker in both_unpackers:
147 for format, values, expected in cases:
148 out, rest = unpacker(format, expected)
149 self.assertEquals(rest, '')
150 self.assertEquals(list(values), list(out))
153 def test_pack_failures(self):
154 """Expected errors for incorrect packing"""
161 ('wwwwwwwwwwww', []),
162 # ('w', [0x60A15EC5L]),
175 # old code doesn't distinguish string from seq-of-char
176 # (['w', 'w'], [2, 2]),
177 # old code just ignores invalid characters
182 # old code doesn't typecheck format
185 for packer in both_packers:
186 for format, values in cases:
188 packer(format, values)
189 except StandardError:
192 raise AssertionError("didn't get exception: format %s, values %s, packer %s"
193 % (`format`, `values`, `packer`))
196 def test_unpack_failures(self):
197 """Expected errors for incorrect unpacking"""
198 cases = [('$', '', ValueError),
199 ('Q', '', ValueError),
200 ('Q$', '', ValueError),
201 ('f', '', IndexError),
202 ('d', '', IndexError),
203 ('d', '2', IndexError),
204 ('d', '22', IndexError),
205 ('d', '222', IndexError),
206 ('w', '', IndexError),
207 ('w', '2', IndexError),
208 ('f', 'hello', IndexError),
209 ('f', '', IndexError),
210 ('p', '\x01\0', IndexError),
211 ('B', '\xff\0\0\0hello', IndexError),
212 ('B', '\xff\0', IndexError),
213 ('B', '\x01\0\0\0', IndexError),
214 ('B', '\x05\0\0\0hell', IndexError),
215 ('B', '\xff\xff\xff\xff', ValueError),
216 ('B', 'foobar', IndexError),
217 ('BB', '\x01\0\0\0a\x01', IndexError),
220 for unpacker in both_unpackers:
221 for format, values, throwable_class in cases:
223 unpacker(format, values)
224 self.assertRaises(throwable_class, do_unpack)
228 if __name__ == '__main__':