test_pack_failures: The old and new code is not exactly the same about
[samba.git] / source / 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 = [('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'),
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', [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'),
55
56              # strings are sequences in Python, there's no getting away
57              # from it
58              ('ffff', 'evil', 'e\0v\0i\0l\0'),
59              ('BBBB', 'evil',                   
60               '\x01\0\0\0e'
61               '\x01\0\0\0v'
62               '\x01\0\0\0i'
63               '\x01\0\0\0l'),
64
65              ('', [], ''),
66
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),
75              ]
76
77     def test_symmetric(self):
78         """Cookbook of symmetric pack/unpack tests
79         """
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))
87         
88     
89     def test_pack(self):
90         """Cookbook of expected pack values
91
92         These can't be used for the symmetric test because the unpacked value is
93         not "canonical".
94         """
95         cases = [('w', (42,), '\x2a\0'),
96                  ('p', [None], '\0\0\0\0'),
97                  ('p', ['true'], '\x01\0\0\0'),
98                  ]
99
100         for packer in both_packers:
101             for format, values, expected in cases:
102                 self.assertEquals(packer(format, values), expected)
103
104     def test_unpack_extra(self):
105         # Test leftover data
106         for unpacker in both_unpackers:
107             for format, values, packed in self.symm_cases:
108                 out, rest = unpacker(format, packed + 'hello sailor!')
109                 self.assertEquals(rest, 'hello sailor!')
110                 self.assertEquals(list(values), list(out))
111         
112
113     def test_unpack(self):
114         """Cookbook of tricky unpack tests"""
115         cases = [
116                  # Apparently I couldn't think of any tests that weren't
117                  # symmetric :-/
118                  ]
119         for unpacker in both_unpackers:
120             for format, values, expected in cases:
121                 out, rest = unpacker(format, expected)
122                 self.assertEquals(rest, '')
123                 self.assertEquals(list(values), list(out))
124
125
126     def test_pack_failures(self):
127         """Expected errors for incorrect packing"""
128         cases = [('w', []),
129                  ('w', ()),
130                  ('w', {}),
131                  ('ww', [2]),
132                  ('w', 2),
133                  ('', [1, 2, 3]),
134                  ('w', None),
135                  ('wwwwwwwwwwww', []),
136                  ('w', [2, 3]),
137                  ('w', [0x60A15EC5L]),
138                  ('w', [None]),
139                  ('w', xrange(10000)),
140                  ('d', []),
141                  ('d', [0L]),
142                  ('p', []),
143                  ('f', [2]),
144                  ('P', [None]),
145                  ('P', ()),
146                  ('f', [hex]),
147                  ('fw', ['hello']),
148                  ('f', [u'hello']),
149                  ('B', [2]),
150                  (None, [2, 3, 4]),
151                  (ord('f'), [20]),
152                  (['w', 'w'], [2, 2]),
153                  ('Q', [2]),
154                  ('fQ', ['2', 3]),
155                  ('fQ', ['2']),
156                  (2, [2]),
157                  ({}, {})]
158         for packer in both_packers:
159             for format, values in cases:
160                 try:
161                     packer(format, values)
162                 except StandardError:
163                     pass
164                 else:
165                     raise AssertionError("didn't get exception: format %s, values %s, packer %s"
166                                          % (`format`, `values`, `packer`))
167
168
169     def test_unpack_failures(self):
170         """Expected errors for incorrect unpacking"""
171         cases = [('$', '', ValueError),
172                  ('Q', '', ValueError),
173                  ('Q$', '', ValueError),
174                  ('f', '', IndexError),
175                  ('d', '', IndexError),
176                  ('d', '2', IndexError),
177                  ('d', '22', IndexError),
178                  ('d', '222', IndexError),
179                  ('w', '', IndexError),
180                  ('w', '2', IndexError),
181                  ('f', 'hello', IndexError),
182                  ('f', '', IndexError),
183                  ('p', '\x01\0', IndexError),
184                  ('B', '\xff\0\0\0hello', IndexError),
185                  ('B', '\xff\0', IndexError),
186                  ('B', '\x01\0\0\0', IndexError),
187                  ('B', '\x05\0\0\0hell', IndexError),
188                  ('B', '\xff\xff\xff\xff', ValueError),
189                  ('B', 'foobar', IndexError),
190                  ('BB', '\x01\0\0\0a\x01', IndexError),
191                  ]
192
193         for unpacker in both_unpackers:
194             for format, values, throwable_class in cases:
195                 def do_unpack():
196                     unpacker(format, values)
197             self.assertRaises(throwable_class, do_unpack)
198
199         
200
201 if __name__ == '__main__':
202     unittest.main()
203