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"""
129 for unpacker in both_unpackers:
130 for packer in both_packers:
131 for format, values in cases:
132 bin = packer(format, values)
133 out, rest = unpacker(format, bin)
134 self.assertEquals(list(out), list(values))
135 self.assertEquals(rest, '')
138 def test_unpack(self):
139 """Cookbook of tricky unpack tests"""
141 # Apparently I couldn't think of any tests that weren't
144 for unpacker in both_unpackers:
145 for format, values, expected in cases:
146 out, rest = unpacker(format, expected)
147 self.assertEquals(rest, '')
148 self.assertEquals(list(values), list(out))
151 def test_pack_failures(self):
152 """Expected errors for incorrect packing"""
159 ('wwwwwwwwwwww', []),
160 # ('w', [0x60A15EC5L]),
174 (['w', 'w'], [2, 2]),
180 for packer in both_packers:
181 for format, values in cases:
183 packer(format, values)
184 except StandardError:
187 raise AssertionError("didn't get exception: format %s, values %s, packer %s"
188 % (`format`, `values`, `packer`))
191 def test_unpack_failures(self):
192 """Expected errors for incorrect unpacking"""
193 cases = [('$', '', ValueError),
194 ('Q', '', ValueError),
195 ('Q$', '', ValueError),
196 ('f', '', IndexError),
197 ('d', '', IndexError),
198 ('d', '2', IndexError),
199 ('d', '22', IndexError),
200 ('d', '222', IndexError),
201 ('w', '', IndexError),
202 ('w', '2', IndexError),
203 ('f', 'hello', IndexError),
204 ('f', '', IndexError),
205 ('p', '\x01\0', IndexError),
206 ('B', '\xff\0\0\0hello', IndexError),
207 ('B', '\xff\0', IndexError),
208 ('B', '\x01\0\0\0', IndexError),
209 ('B', '\x05\0\0\0hell', IndexError),
210 ('B', '\xff\xff\xff\xff', ValueError),
211 ('B', 'foobar', IndexError),
212 ('BB', '\x01\0\0\0a\x01', IndexError),
215 for unpacker in both_unpackers:
216 for format, values, throwable_class in cases:
218 unpacker(format, values)
219 self.assertRaises(throwable_class, do_unpack)
223 if __name__ == '__main__':