blob: d4744dde790331fc0173ab6e183d6267ca7afeda [file] [log] [blame]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001from test.test_support import TestFailed, verbose, verify, vereq
Thomas Wouters477c8d52006-05-27 19:21:47 +00002import test.test_support
Barry Warsaw07a0eec1996-12-12 23:34:06 +00003import struct
Thomas Wouters477c8d52006-05-27 19:21:47 +00004import array
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00005import warnings
Barry Warsaw07a0eec1996-12-12 23:34:06 +00006
Tim Peters17e17d42001-06-13 22:45:27 +00007import sys
8ISBIGENDIAN = sys.byteorder == "big"
9del sys
10verify((struct.pack('=i', 1)[0] == chr(0)) == ISBIGENDIAN,
11 "bigendian determination appears wrong")
12
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000013try:
14 import _struct
15except ImportError:
16 PY_STRUCT_RANGE_CHECKING = 0
17 PY_STRUCT_OVERFLOW_MASKING = 1
Thomas Wouters0e3f5912006-08-11 14:57:12 +000018 PY_STRUCT_FLOAT_COERCE = 2
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000019else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000020 PY_STRUCT_RANGE_CHECKING = getattr(_struct, '_PY_STRUCT_RANGE_CHECKING', 0)
21 PY_STRUCT_OVERFLOW_MASKING = getattr(_struct, '_PY_STRUCT_OVERFLOW_MASKING', 0)
22 PY_STRUCT_FLOAT_COERCE = getattr(_struct, '_PY_STRUCT_FLOAT_COERCE', 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +000023
Tim Peters17e17d42001-06-13 22:45:27 +000024def string_reverse(s):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000025 return "".join(reversed(s))
Tim Peters17e17d42001-06-13 22:45:27 +000026
27def bigendian_to_native(value):
28 if ISBIGENDIAN:
29 return value
30 else:
31 return string_reverse(value)
32
Barry Warsaw07a0eec1996-12-12 23:34:06 +000033def simple_err(func, *args):
34 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000035 func(*args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000036 except struct.error:
Guido van Rossum41360a41998-03-26 19:42:58 +000037 pass
Barry Warsaw07a0eec1996-12-12 23:34:06 +000038 else:
Guido van Rossum41360a41998-03-26 19:42:58 +000039 raise TestFailed, "%s%s did not raise struct.error" % (
40 func.__name__, args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000041
Tim Peters7a3bfc32001-06-12 01:22:22 +000042def any_err(func, *args):
43 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000044 func(*args)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000045 except (struct.error, TypeError):
Tim Peters7a3bfc32001-06-12 01:22:22 +000046 pass
47 else:
48 raise TestFailed, "%s%s did not raise error" % (
49 func.__name__, args)
Tim Peters7a3bfc32001-06-12 01:22:22 +000050
Thomas Wouters0e3f5912006-08-11 14:57:12 +000051def with_warning_restore(func):
52 def _with_warning_restore(*args, **kw):
Thomas Wouters902d6eb2007-01-09 23:18:33 +000053 with test.test_support.guard_warnings_filter():
54 # Grrr, we need this function to warn every time. Without removing
55 # the warningregistry, running test_tarfile then test_struct would fail
56 # on 64-bit platforms.
57 globals = func.func_globals
58 if '__warningregistry__' in globals:
59 del globals['__warningregistry__']
60 warnings.filterwarnings("error", r"""^struct.*""", DeprecationWarning)
61 warnings.filterwarnings("error", r""".*format requires.*""",
62 DeprecationWarning)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000063 return func(*args, **kw)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000064 return _with_warning_restore
65
66def deprecated_err(func, *args):
67 try:
68 func(*args)
69 except (struct.error, TypeError):
70 pass
71 except DeprecationWarning:
72 if not PY_STRUCT_OVERFLOW_MASKING:
73 raise TestFailed, "%s%s expected to raise struct.error" % (
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000074 func.__name__, args)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000075 else:
76 raise TestFailed, "%s%s did not raise error" % (
77 func.__name__, args)
78deprecated_err = with_warning_restore(deprecated_err)
79
Tim Peters17e17d42001-06-13 22:45:27 +000080
Tim Peters7b9542a2001-06-10 23:40:19 +000081simple_err(struct.calcsize, 'Z')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000082
83sz = struct.calcsize('i')
Fred Drake132dce22000-12-12 23:11:42 +000084if sz * 3 != struct.calcsize('iii'):
Guido van Rossum2a378501996-12-31 17:25:47 +000085 raise TestFailed, 'inconsistent sizes'
Barry Warsaw07a0eec1996-12-12 23:34:06 +000086
Guido van Rossum04ebf5c1997-01-03 19:00:37 +000087fmt = 'cbxxxxxxhhhhiillffd'
88fmt3 = '3c3b18x12h6i6l6f3d'
89sz = struct.calcsize(fmt)
90sz3 = struct.calcsize(fmt3)
Fred Drake132dce22000-12-12 23:11:42 +000091if sz * 3 != sz3:
Walter Dörwald70a6b492004-02-12 17:35:32 +000092 raise TestFailed, 'inconsistent sizes (3*%r -> 3*%d = %d, %r -> %d)' % (
93 fmt, sz, 3*sz, fmt3, sz3)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000094
95simple_err(struct.pack, 'iii', 3)
96simple_err(struct.pack, 'i', 3, 3, 3)
97simple_err(struct.pack, 'i', 'foo')
Armin Rigo9f904392004-09-27 19:27:51 +000098simple_err(struct.pack, 'P', 'foo')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000099simple_err(struct.unpack, 'd', 'flap')
100s = struct.pack('ii', 1, 2)
101simple_err(struct.unpack, 'iii', s)
102simple_err(struct.unpack, 'i', s)
103
104c = 'a'
Guido van Rossum2a378501996-12-31 17:25:47 +0000105b = 1
Barry Warsaw07a0eec1996-12-12 23:34:06 +0000106h = 255
107i = 65535
108l = 65536
109f = 3.1415
110d = 3.1415
111
Guido van Rossum420c11c1997-01-03 00:09:46 +0000112for prefix in ('', '@', '<', '>', '=', '!'):
113 for format in ('xcbhilfd', 'xcBHILfd'):
Guido van Rossum41360a41998-03-26 19:42:58 +0000114 format = prefix + format
115 if verbose:
116 print "trying:", format
117 s = struct.pack(format, c, b, h, i, l, f, d)
118 cp, bp, hp, ip, lp, fp, dp = struct.unpack(format, s)
Fred Drake132dce22000-12-12 23:11:42 +0000119 if (cp != c or bp != b or hp != h or ip != i or lp != l or
120 int(100 * fp) != int(100 * f) or int(100 * dp) != int(100 * d)):
Guido van Rossum41360a41998-03-26 19:42:58 +0000121 # ^^^ calculate only to two decimal places
122 raise TestFailed, "unpack/pack not transitive (%s, %s)" % (
123 str(format), str((cp, bp, hp, ip, lp, fp, dp)))
Guido van Rossum2a378501996-12-31 17:25:47 +0000124
Guido van Rossum420c11c1997-01-03 00:09:46 +0000125# Test some of the new features in detail
Guido van Rossum2a378501996-12-31 17:25:47 +0000126
127# (format, argument, big-endian result, little-endian result, asymmetric)
128tests = [
129 ('c', 'a', 'a', 'a', 0),
130 ('xc', 'a', '\0a', '\0a', 0),
131 ('cx', 'a', 'a\0', 'a\0', 0),
132 ('s', 'a', 'a', 'a', 0),
133 ('0s', 'helloworld', '', '', 1),
134 ('1s', 'helloworld', 'h', 'h', 1),
135 ('9s', 'helloworld', 'helloworl', 'helloworl', 1),
136 ('10s', 'helloworld', 'helloworld', 'helloworld', 0),
137 ('11s', 'helloworld', 'helloworld\0', 'helloworld\0', 1),
138 ('20s', 'helloworld', 'helloworld'+10*'\0', 'helloworld'+10*'\0', 1),
139 ('b', 7, '\7', '\7', 0),
140 ('b', -7, '\371', '\371', 0),
141 ('B', 7, '\7', '\7', 0),
142 ('B', 249, '\371', '\371', 0),
143 ('h', 700, '\002\274', '\274\002', 0),
144 ('h', -700, '\375D', 'D\375', 0),
145 ('H', 700, '\002\274', '\274\002', 0),
146 ('H', 0x10000-700, '\375D', 'D\375', 0),
147 ('i', 70000000, '\004,\035\200', '\200\035,\004', 0),
148 ('i', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
149 ('I', 70000000L, '\004,\035\200', '\200\035,\004', 0),
150 ('I', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
151 ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
152 ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
153 ('L', 70000000L, '\004,\035\200', '\200\035,\004', 0),
154 ('L', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
Guido van Rossum420c11c1997-01-03 00:09:46 +0000155 ('f', 2.0, '@\000\000\000', '\000\000\000@', 0),
156 ('d', 2.0, '@\000\000\000\000\000\000\000',
157 '\000\000\000\000\000\000\000@', 0),
158 ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0),
159 ('d', -2.0, '\300\000\000\000\000\000\000\000',
160 '\000\000\000\000\000\000\000\300', 0),
Guido van Rossum2a378501996-12-31 17:25:47 +0000161]
162
Guido van Rossum2a378501996-12-31 17:25:47 +0000163for fmt, arg, big, lil, asy in tests:
164 if verbose:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000165 print "%r %r %r %r" % (fmt, arg, big, lil)
Guido van Rossum2a378501996-12-31 17:25:47 +0000166 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
Tim Peters17e17d42001-06-13 22:45:27 +0000167 ('='+fmt, ISBIGENDIAN and big or lil)]:
Guido van Rossum41360a41998-03-26 19:42:58 +0000168 res = struct.pack(xfmt, arg)
169 if res != exp:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000170 raise TestFailed, "pack(%r, %r) -> %r # expected %r" % (
171 fmt, arg, res, exp)
Guido van Rossum41360a41998-03-26 19:42:58 +0000172 n = struct.calcsize(xfmt)
173 if n != len(res):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000174 raise TestFailed, "calcsize(%r) -> %d # expected %d" % (
175 xfmt, n, len(res))
Guido van Rossum41360a41998-03-26 19:42:58 +0000176 rev = struct.unpack(xfmt, res)[0]
177 if rev != arg and not asy:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000178 raise TestFailed, "unpack(%r, %r) -> (%r,) # expected (%r,)" % (
179 fmt, res, rev, arg)
Tim Peters7b9542a2001-06-10 23:40:19 +0000180
Tim Peters7a3bfc32001-06-12 01:22:22 +0000181###########################################################################
Tim Peters17e17d42001-06-13 22:45:27 +0000182# Simple native q/Q tests.
Tim Peters7b9542a2001-06-10 23:40:19 +0000183
184has_native_qQ = 1
185try:
186 struct.pack("q", 5)
187except struct.error:
188 has_native_qQ = 0
189
190if verbose:
191 print "Platform has native q/Q?", has_native_qQ and "Yes." or "No."
192
Tim Peters7a3bfc32001-06-12 01:22:22 +0000193any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless
Tim Peters7b9542a2001-06-10 23:40:19 +0000194simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless
195simple_err(struct.pack, "Q", "a") # ditto, but 'Q'
196
Tim Peters7a3bfc32001-06-12 01:22:22 +0000197def test_native_qQ():
Tim Peters7b9542a2001-06-10 23:40:19 +0000198 bytes = struct.calcsize('q')
199 # The expected values here are in big-endian format, primarily because
200 # I'm on a little-endian machine and so this is the clearest way (for
201 # me) to force the code to get exercised.
202 for format, input, expected in (
203 ('q', -1, '\xff' * bytes),
204 ('q', 0, '\x00' * bytes),
205 ('Q', 0, '\x00' * bytes),
206 ('q', 1L, '\x00' * (bytes-1) + '\x01'),
207 ('Q', (1L << (8*bytes))-1, '\xff' * bytes),
208 ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))):
209 got = struct.pack(format, input)
Tim Petersc533edc2001-06-10 23:52:59 +0000210 native_expected = bigendian_to_native(expected)
211 verify(got == native_expected,
Tim Peters7b9542a2001-06-10 23:40:19 +0000212 "%r-pack of %r gave %r, not %r" %
Tim Petersc533edc2001-06-10 23:52:59 +0000213 (format, input, got, native_expected))
Tim Peters7b9542a2001-06-10 23:40:19 +0000214 retrieved = struct.unpack(format, got)[0]
215 verify(retrieved == input,
216 "%r-unpack of %r gave %r, not %r" %
217 (format, got, retrieved, input))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000218
219if has_native_qQ:
220 test_native_qQ()
221
Tim Peters17e17d42001-06-13 22:45:27 +0000222###########################################################################
223# Standard integer tests (bBhHiIlLqQ).
Tim Peters7a3bfc32001-06-12 01:22:22 +0000224
225import binascii
Tim Peters7a3bfc32001-06-12 01:22:22 +0000226
Tim Peters17e17d42001-06-13 22:45:27 +0000227class IntTester:
Tim Peters7a3bfc32001-06-12 01:22:22 +0000228
Tim Peters17e17d42001-06-13 22:45:27 +0000229 # XXX Most std integer modes fail to test for out-of-range.
Tim Peters3eec38a2001-06-18 22:27:39 +0000230 # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
231 # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
232 # reported by Mark Favas).
233 BUGGY_RANGE_CHECK = "bBhHiIlL"
Tim Peters7a3bfc32001-06-12 01:22:22 +0000234
Tim Peters17e17d42001-06-13 22:45:27 +0000235 def __init__(self, formatpair, bytesize):
236 assert len(formatpair) == 2
237 self.formatpair = formatpair
238 for direction in "<>!=":
239 for code in formatpair:
240 format = direction + code
241 verify(struct.calcsize(format) == bytesize)
242 self.bytesize = bytesize
243 self.bitsize = bytesize * 8
244 self.signed_code, self.unsigned_code = formatpair
245 self.unsigned_min = 0
246 self.unsigned_max = 2L**self.bitsize - 1
247 self.signed_min = -(2L**(self.bitsize-1))
248 self.signed_max = 2L**(self.bitsize-1) - 1
Tim Peters7a3bfc32001-06-12 01:22:22 +0000249
Tim Peters17e17d42001-06-13 22:45:27 +0000250 def test_one(self, x, pack=struct.pack,
251 unpack=struct.unpack,
252 unhexlify=binascii.unhexlify):
253 if verbose:
254 print "trying std", self.formatpair, "on", x, "==", hex(x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000255
Tim Peters17e17d42001-06-13 22:45:27 +0000256 # Try signed.
257 code = self.signed_code
258 if self.signed_min <= x <= self.signed_max:
259 # Try big-endian.
260 expected = long(x)
261 if x < 0:
262 expected += 1L << self.bitsize
263 assert expected > 0
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000264 expected = hex(expected)[2:] # chop "0x"
Tim Peters17e17d42001-06-13 22:45:27 +0000265 if len(expected) & 1:
266 expected = "0" + expected
267 expected = unhexlify(expected)
268 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000269
Tim Peters17e17d42001-06-13 22:45:27 +0000270 # Pack work?
271 format = ">" + code
272 got = pack(format, x)
273 verify(got == expected,
274 "'%s'-pack of %r gave %r, not %r" %
275 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000276
Tim Peters17e17d42001-06-13 22:45:27 +0000277 # Unpack work?
278 retrieved = unpack(format, got)[0]
279 verify(x == retrieved,
280 "'%s'-unpack of %r gave %r, not %r" %
281 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000282
Tim Peters17e17d42001-06-13 22:45:27 +0000283 # Adding any byte should cause a "too big" error.
284 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000285
Tim Peters17e17d42001-06-13 22:45:27 +0000286 # Try little-endian.
287 format = "<" + code
288 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000289
Tim Peters17e17d42001-06-13 22:45:27 +0000290 # Pack work?
291 got = pack(format, x)
292 verify(got == expected,
293 "'%s'-pack of %r gave %r, not %r" %
294 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000295
Tim Peters17e17d42001-06-13 22:45:27 +0000296 # Unpack work?
297 retrieved = unpack(format, got)[0]
298 verify(x == retrieved,
299 "'%s'-unpack of %r gave %r, not %r" %
300 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000301
Tim Peters17e17d42001-06-13 22:45:27 +0000302 # Adding any byte should cause a "too big" error.
303 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000304
Tim Peters17e17d42001-06-13 22:45:27 +0000305 else:
306 # x is out of range -- verify pack realizes that.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000307 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000308 if verbose:
309 print "Skipping buggy range check for code", code
310 else:
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000311 deprecated_err(pack, ">" + code, x)
312 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000313
Tim Peters17e17d42001-06-13 22:45:27 +0000314 # Much the same for unsigned.
315 code = self.unsigned_code
316 if self.unsigned_min <= x <= self.unsigned_max:
317 # Try big-endian.
318 format = ">" + code
319 expected = long(x)
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000320 expected = hex(expected)[2:] # chop "0x"
Tim Peters17e17d42001-06-13 22:45:27 +0000321 if len(expected) & 1:
322 expected = "0" + expected
323 expected = unhexlify(expected)
324 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000325
Tim Peters17e17d42001-06-13 22:45:27 +0000326 # Pack work?
327 got = pack(format, x)
328 verify(got == expected,
329 "'%s'-pack of %r gave %r, not %r" %
330 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000331
Tim Peters17e17d42001-06-13 22:45:27 +0000332 # Unpack work?
333 retrieved = unpack(format, got)[0]
334 verify(x == retrieved,
335 "'%s'-unpack of %r gave %r, not %r" %
336 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000337
Tim Peters17e17d42001-06-13 22:45:27 +0000338 # Adding any byte should cause a "too big" error.
339 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000340
Tim Peters17e17d42001-06-13 22:45:27 +0000341 # Try little-endian.
342 format = "<" + code
343 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000344
Tim Peters17e17d42001-06-13 22:45:27 +0000345 # Pack work?
346 got = pack(format, x)
347 verify(got == expected,
348 "'%s'-pack of %r gave %r, not %r" %
349 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000350
Tim Peters17e17d42001-06-13 22:45:27 +0000351 # Unpack work?
352 retrieved = unpack(format, got)[0]
353 verify(x == retrieved,
354 "'%s'-unpack of %r gave %r, not %r" %
355 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000356
Tim Peters17e17d42001-06-13 22:45:27 +0000357 # Adding any byte should cause a "too big" error.
358 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000359
Tim Peters17e17d42001-06-13 22:45:27 +0000360 else:
361 # x is out of range -- verify pack realizes that.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000362 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000363 if verbose:
364 print "Skipping buggy range check for code", code
365 else:
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000366 deprecated_err(pack, ">" + code, x)
367 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000368
Tim Peters17e17d42001-06-13 22:45:27 +0000369 def run(self):
370 from random import randrange
371
372 # Create all interesting powers of 2.
373 values = []
374 for exp in range(self.bitsize + 3):
375 values.append(1L << exp)
376
377 # Add some random values.
378 for i in range(self.bitsize):
379 val = 0L
380 for j in range(self.bytesize):
381 val = (val << 8) | randrange(256)
382 values.append(val)
383
384 # Try all those, and their negations, and +-1 from them. Note
385 # that this tests all power-of-2 boundaries in range, and a few out
386 # of range, plus +-(2**n +- 1).
387 for base in values:
388 for val in -base, base:
389 for incr in -1, 0, 1:
390 x = val + incr
391 try:
392 x = int(x)
393 except OverflowError:
394 pass
395 self.test_one(x)
396
397 # Some error cases.
398 for direction in "<>":
399 for code in self.formatpair:
400 for badobject in "a string", 3+42j, randrange:
401 any_err(struct.pack, direction + code, badobject)
402
403for args in [("bB", 1),
404 ("hH", 2),
405 ("iI", 4),
406 ("lL", 4),
407 ("qQ", 8)]:
408 t = IntTester(*args)
409 t.run()
Tim Peters0891ac02001-09-15 02:35:15 +0000410
411
412###########################################################################
413# The p ("Pascal string") code.
414
415def test_p_code():
416 for code, input, expected, expectedback in [
417 ('p','abc', '\x00', ''),
418 ('1p', 'abc', '\x00', ''),
419 ('2p', 'abc', '\x01a', 'a'),
420 ('3p', 'abc', '\x02ab', 'ab'),
421 ('4p', 'abc', '\x03abc', 'abc'),
422 ('5p', 'abc', '\x03abc\x00', 'abc'),
423 ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
424 ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
425 got = struct.pack(code, input)
426 if got != expected:
427 raise TestFailed("pack(%r, %r) == %r but expected %r" %
428 (code, input, got, expected))
429 (got,) = struct.unpack(code, got)
430 if got != expectedback:
431 raise TestFailed("unpack(%r, %r) == %r but expected %r" %
432 (code, input, got, expectedback))
433
434test_p_code()
Tim Petersd50ade62003-03-20 18:32:13 +0000435
436
437###########################################################################
438# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
439# from the low-order discarded bits could propagate into the exponent
440# field, causing the result to be wrong by a factor of 2.
441
442def test_705836():
443 import math
444
445 for base in range(1, 33):
446 # smaller <- largest representable float less than base.
447 delta = 0.5
448 while base - delta / 2.0 != base:
449 delta /= 2.0
450 smaller = base - delta
451 # Packing this rounds away a solid string of trailing 1 bits.
452 packed = struct.pack("<f", smaller)
453 unpacked = struct.unpack("<f", packed)[0]
454 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
455 # 16, respectively.
456 verify(base == unpacked)
457 bigpacked = struct.pack(">f", smaller)
458 verify(bigpacked == string_reverse(packed),
459 ">f pack should be byte-reversal of <f pack")
460 unpacked = struct.unpack(">f", bigpacked)[0]
461 verify(base == unpacked)
462
463 # Largest finite IEEE single.
464 big = (1 << 24) - 1
465 big = math.ldexp(big, 127 - 23)
466 packed = struct.pack(">f", big)
467 unpacked = struct.unpack(">f", packed)[0]
468 verify(big == unpacked)
469
470 # The same, but tack on a 1 bit so it rounds up to infinity.
471 big = (1 << 25) - 1
472 big = math.ldexp(big, 127 - 24)
473 try:
474 packed = struct.pack(">f", big)
475 except OverflowError:
476 pass
477 else:
478 TestFailed("expected OverflowError")
479
480test_705836()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000481
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000482###########################################################################
483# SF bug 1229380. No struct.pack exception for some out of range integers
484
Thomas Wouters477c8d52006-05-27 19:21:47 +0000485def test_1229380():
486 import sys
487 for endian in ('', '>', '<'):
488 for cls in (int, long):
489 for fmt in ('B', 'H', 'I', 'L'):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000490 deprecated_err(struct.pack, endian + fmt, cls(-1))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000491
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000492 deprecated_err(struct.pack, endian + 'B', cls(300))
493 deprecated_err(struct.pack, endian + 'H', cls(70000))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000494
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000495 deprecated_err(struct.pack, endian + 'I', sys.maxint * 4L)
496 deprecated_err(struct.pack, endian + 'L', sys.maxint * 4L)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000497
498if PY_STRUCT_RANGE_CHECKING:
499 test_1229380()
500
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000501###########################################################################
502# SF bug 1530559. struct.pack raises TypeError where it used to convert.
503
504def check_float_coerce(format, number):
505 if PY_STRUCT_FLOAT_COERCE == 2:
506 # Test for pre-2.5 struct module
507 packed = struct.pack(format, number)
508 floored = struct.unpack(format, packed)[0]
509 if floored != int(number):
510 raise TestFailed("did not correcly coerce float to int")
511 return
512 try:
513 func(*args)
514 except (struct.error, TypeError):
515 if PY_STRUCT_FLOAT_COERCE:
516 raise TestFailed("expected DeprecationWarning for float coerce")
517 except DeprecationWarning:
518 if not PY_STRUCT_FLOAT_COERCE:
519 raise TestFailed("expected to raise struct.error for float coerce")
520 else:
521 raise TestFailed("did not raise error for float coerce")
522
523check_float_coerce = with_warning_restore(deprecated_err)
524
525def test_1530559():
526 for endian in ('', '>', '<'):
527 for fmt in ('B', 'H', 'I', 'L', 'b', 'h', 'i', 'l'):
528 check_float_coerce(endian + fmt, 1.0)
529 check_float_coerce(endian + fmt, 1.5)
530
531test_1530559()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000532
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000533###########################################################################
534# Packing and unpacking to/from buffers.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000535
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000536# Copied and modified from unittest.
537def assertRaises(excClass, callableObj, *args, **kwargs):
538 try:
539 callableObj(*args, **kwargs)
540 except excClass:
541 return
542 else:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000543 raise TestFailed("%s not raised." % excClass)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000544
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000545def test_unpack_from():
546 test_string = 'abcd01234'
547 fmt = '4s'
548 s = struct.Struct(fmt)
549 for cls in (str, buffer):
550 data = cls(test_string)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000551 vereq(s.unpack_from(data), ('abcd',))
552 vereq(s.unpack_from(data, 2), ('cd01',))
553 vereq(s.unpack_from(data, 4), ('0123',))
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000554 for i in xrange(6):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000555 vereq(s.unpack_from(data, i), (data[i:i+4],))
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000556 for i in xrange(6, len(test_string) + 1):
557 simple_err(s.unpack_from, data, i)
558 for cls in (str, buffer):
559 data = cls(test_string)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000560 vereq(struct.unpack_from(fmt, data), ('abcd',))
561 vereq(struct.unpack_from(fmt, data, 2), ('cd01',))
562 vereq(struct.unpack_from(fmt, data, 4), ('0123',))
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000563 for i in xrange(6):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000564 vereq(struct.unpack_from(fmt, data, i), (data[i:i+4],))
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000565 for i in xrange(6, len(test_string) + 1):
566 simple_err(struct.unpack_from, fmt, data, i)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000567
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000568def test_pack_into():
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000569 test_string = 'Reykjavik rocks, eow!'
570 writable_buf = array.array('c', ' '*100)
571 fmt = '21s'
572 s = struct.Struct(fmt)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000573
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000574 # Test without offset
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000575 s.pack_into(writable_buf, 0, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000576 from_buf = writable_buf.tostring()[:len(test_string)]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000577 vereq(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000578
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000579 # Test with offset.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000580 s.pack_into(writable_buf, 10, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000581 from_buf = writable_buf.tostring()[:len(test_string)+10]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000582 vereq(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000583
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000584 # Go beyond boundaries.
585 small_buf = array.array('c', ' '*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000586 assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
587 assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000588
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000589def test_pack_into_fn():
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000590 test_string = 'Reykjavik rocks, eow!'
591 writable_buf = array.array('c', ' '*100)
592 fmt = '21s'
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000593 pack_into = lambda *args: struct.pack_into(fmt, *args)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000594
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000595 # Test without offset.
596 pack_into(writable_buf, 0, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000597 from_buf = writable_buf.tostring()[:len(test_string)]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000598 vereq(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000599
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000600 # Test with offset.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000601 pack_into(writable_buf, 10, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000602 from_buf = writable_buf.tostring()[:len(test_string)+10]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000603 vereq(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000604
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000605 # Go beyond boundaries.
606 small_buf = array.array('c', ' '*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000607 assertRaises(struct.error, pack_into, small_buf, 0, test_string)
608 assertRaises(struct.error, pack_into, small_buf, 2, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000609
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000610
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000611# Test methods to pack and unpack from buffers rather than strings.
612test_unpack_from()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000613test_pack_into()
614test_pack_into_fn()