Add more test cases that now work.
[samba.git] / source3 / python / examples / tdbpack / test_tdbpack.py
1 #! /usr/bin/env python2.2
2
3 __doc__ = """test case for samba.tdbkpack functions
4
5 tdbpack provides a means of pickling values into binary formats
6 compatible with that used by the samba tdbpack()/tdbunpack()
7 functions.
8
9 Numbers are always stored in little-endian format; strings are stored
10 in either DOS or Unix codepage as appropriate.
11
12 The format for any particular element is encoded as a short ASCII
13 string, with one character per field."""
14
15 # Copyright (C) 2002 Hewlett-Packard.
16
17 __author__ = 'Martin Pool <mbp@sourcefrog.net>'
18
19 import unittest
20 import oldtdbutil
21 import samba.tdbpack
22
23 both_unpackers = (samba.tdbpack.unpack, oldtdbutil.unpack)
24 both_packers = (samba.tdbpack.pack, oldtdbutil.pack)
25     
26 class PackTests(unittest.TestCase):
27     symm_cases = [
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'),
31              ('w', [0], '\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', [0x80000000L], '\x00\x00\x00\x80'),
41              ('d', [0x80000069L], '\x69\x00\x00\x80'),
42 #              ('d', [-1], '\xff\xff\xff\xff'),
43 #              ('d', [-255], '\x01\xff\xff\xff'),
44 #              ('d', [-256], '\x00\xff\xff\xff'),
45 #              ('ddd', [1, 10, 50], '\x01\0\0\0\x0a\0\0\0\x32\0\0\0'),
46 #              ('ff', ['hello', 'world'], 'hello\0world\0'),
47 #              ('fP', ['hello', 'world'], 'hello\0world\0'),
48 #              ('PP', ['hello', 'world'], 'hello\0world\0'),
49 #              ('B', [0, ''], '\0\0\0\0'),
50 #              ('B', [5, 'hello'], '\x05\0\0\0hello'),
51 # #             ('B', [10, 'hello'], '\x0a\0\0\0hello'),
52 # #             ('B', [2, 'hello'], '\x0a\0\0\0hello'),
53 #              ('BB', [11, 'hello\0world', 3, 'now'],
54 #               '\x0b\0\0\0hello\0world\x03\0\0\0now'),
55 #              ('pd', [1, 10], '\x01\0\0\0\x0a\0\0\0'),
56 #              ('BBB', [5, 'hello', 0, '', 5, 'world'],
57 #               '\x05\0\0\0hello\0\0\0\0\x05\0\0\0world'),
58
59              # strings are sequences in Python, there's no getting away
60              # from it
61 #             ('ffff', 'evil', 'e\0v\0i\0l\0'),
62 #              ('BBBB', 'evil',                   
63 #               '\x01\0\0\0e'
64 #               '\x01\0\0\0v'
65 #               '\x01\0\0\0i'
66 #               '\x01\0\0\0l'),
67
68 #              ('', [], ''),
69
70 #              # exercise some long strings
71 #              ('PP', ['hello' * 255, 'world' * 255],
72 #               'hello' * 255 + '\0' + 'world' * 255 + '\0'),
73 #              ('PP', ['hello' * 40000, 'world' * 50000],
74 #               'hello' * 40000 + '\0' + 'world' * 50000 + '\0'),
75 #              ('B', [(5*51), 'hello' * 51], '\xff\0\0\0' + 'hello' * 51),
76 #              ('BB', [(5 * 40000), 'hello' * 40000,
77 #                      (5 * 50000), 'world' * 50000],
78 #               '\x40\x0d\x03\0' + 'hello' * 40000 + '\x90\xd0\x03\x00' + 'world' * 50000),
79              ]
80
81     def test_symmetric(self):
82         """Cookbook of symmetric pack/unpack tests
83         """
84         for packer in both_packers:
85             for unpacker in both_unpackers:
86                 for format, values, expected in self.symm_cases:
87                     out_packed = packer(format, values)
88                     self.assertEquals(out_packed, expected)
89                     out, rest = unpacker(format, expected)
90                     self.assertEquals(rest, '')
91                     self.assertEquals(list(values), list(out))
92
93     def test_large(self):
94         """Test large pack/unpack strings"""
95         large_cases = [('w' * 1000, xrange(1000)), ]
96         for packer in both_packers:
97             for unpacker in both_unpackers:
98                 for format, values in large_cases:
99                     packed = packer(format, values)
100                     out, rest = unpacker(format, packed)
101                     self.assertEquals(rest, '')
102                     self.assertEquals(list(values), list(out))
103
104                     
105     def test_pack(self):
106         """Cookbook of expected pack values
107
108         These can't be used for the symmetric test because the unpacked value is
109         not "canonical".
110         """
111         cases = [('w', (42,), '\x2a\0'),
112                  ('p', [None], '\0\0\0\0'),
113                  ('p', ['true'], '\x01\0\0\0'),
114                  ]
115
116         for packer in both_packers:
117             for format, values, expected in cases:
118                 self.assertEquals(packer(format, values), expected)
119
120     def test_unpack_extra(self):
121         # Test leftover data
122         for unpacker in both_unpackers:
123             for format, values, packed in self.symm_cases:
124                 out, rest = unpacker(format, packed + 'hello sailor!')
125                 self.assertEquals(rest, 'hello sailor!')
126                 self.assertEquals(list(values), list(out))
127
128
129     def test_pack_extra(self):
130         """Leftover values when packing"""
131         cases = [
132             ('d', [10, 20], [10]),
133             ('d', [10, 'hello'], [10]),
134             ('ff', ['hello', 'world', 'sailor'], ['hello', 'world']),
135             ]
136         for unpacker in both_unpackers:
137             for packer in both_packers:
138                 for format, values, chopped in cases:
139                     bin = packer(format, values)
140                     out, rest = unpacker(format, bin)
141                     self.assertEquals(list(out), list(chopped))
142                     self.assertEquals(rest, '')
143
144
145     def test_unpack(self):
146         """Cookbook of tricky unpack tests"""
147         cases = [
148                  # Apparently I couldn't think of any tests that weren't
149                  # symmetric :-/
150                  ]
151         for unpacker in both_unpackers:
152             for format, values, expected in cases:
153                 out, rest = unpacker(format, expected)
154                 self.assertEquals(rest, '')
155                 self.assertEquals(list(values), list(out))
156
157
158     def test_pack_failures(self):
159         """Expected errors for incorrect packing"""
160         cases = [('w', []),
161 #                 ('w', ()),
162 #                 ('w', {}),
163                  ('ww', [2]),
164                  ('w', 2),
165 #                  ('w', None),
166                  ('wwwwwwwwwwww', []),
167 #                 ('w', [0x60A15EC5L]),
168 #                 ('w', [None]),
169                  ('d', []),
170                  ('p', []),
171                  ('f', [2]),
172                  ('P', [None]),
173                  ('P', ()),
174                  ('f', [hex]),
175                  ('fw', ['hello']),
176 #                  ('f', [u'hello']),
177                  ('B', [2]),
178                  (None, [2, 3, 4]),
179                  (ord('f'), [20]),
180                  # old code doesn't distinguish string from seq-of-char
181 #                 (['w', 'w'], [2, 2]),
182                  # old code just ignores invalid characters
183 #                 ('Q', [2]),
184 #                 ('fQ', ['2', 3]),
185 #                 ('fQ', ['2']),
186                  (2, [2]),
187                  # old code doesn't typecheck format
188 #                 ({}, {})
189                  ]
190         for packer in both_packers:
191             for format, values in cases:
192                 try:
193                     packer(format, values)
194                 except StandardError:
195                     pass
196                 else:
197                     raise AssertionError("didn't get exception: format %s, values %s, packer %s"
198                                          % (`format`, `values`, `packer`))
199
200
201     def test_unpack_failures(self):
202         """Expected errors for incorrect unpacking"""
203         cases = [
204 # This ought to be illegal, but the old code doesn't prohibit it
205 #                ('$', '', ValueError),
206 #                ('Q', '', ValueError),
207 #                ('Q$', '', ValueError),
208                  ('f', '', IndexError),
209                  ('d', '', IndexError),
210 # This is an illegal packing, but the old code doesn't trap                 
211 #                 ('d', '2', IndexError),
212 #                 ('d', '22', IndexError),
213 #                 ('d', '222', IndexError),
214 #                 ('p', '\x01\0', IndexError),
215 #                ('w', '2', IndexError),
216 #                ('B', '\xff\0\0\0hello', IndexError),
217 #                  ('B', '\xff\0', IndexError),
218                  ('w', '', IndexError),
219                  ('f', 'hello', IndexError),
220                  ('f', '', IndexError),
221 #                ('B', '\x01\0\0\0', IndexError),
222 #                 ('B', '\x05\0\0\0hell', IndexError),
223                  ('B', '\xff\xff\xff\xff', ValueError),
224 #                 ('B', 'foobar', IndexError),
225 #                 ('BB', '\x01\0\0\0a\x01', IndexError),
226                  ]
227
228         for unpacker in both_unpackers:
229             for format, values, throwable_class in cases:
230                 try:
231                     unpacker(format, values)
232                 except StandardError:
233                     pass
234                 else:
235                     raise AssertionError("didn't get exception: format %s, values %s, unpacker %s"
236                                          % (`format`, `values`, `unpacker`))
237
238         
239
240 if __name__ == '__main__':
241     unittest.main()
242