blob: aa458e625b606da13147cc413b10c0ef7fa7fd1d [file] [log] [blame]
Tim Peters852eae12006-06-05 20:48:49 +00001from test.test_support import TestFailed, verbose, verify, vereq
Martin Blais2856e5f2006-05-26 12:03:27 +00002import test.test_support
Barry Warsaw07a0eec1996-12-12 23:34:06 +00003import struct
Martin Blais2856e5f2006-05-26 12:03:27 +00004import array
Bob Ippolito2fd39772006-05-29 22:55:48 +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
Bob Ippolito2fd39772006-05-29 22:55:48 +000013try:
14 import _struct
15except ImportError:
16 PY_STRUCT_RANGE_CHECKING = 0
Bob Ippolito4182a752006-05-30 17:37:54 +000017 PY_STRUCT_OVERFLOW_MASKING = 1
Bob Ippolito2fd39772006-05-29 22:55:48 +000018else:
Tim Peters852eae12006-06-05 20:48:49 +000019 PY_STRUCT_RANGE_CHECKING = _struct._PY_STRUCT_RANGE_CHECKING
20 PY_STRUCT_OVERFLOW_MASKING = _struct._PY_STRUCT_OVERFLOW_MASKING
Bob Ippolitoe27337b2006-05-26 13:15:44 +000021
Tim Peters17e17d42001-06-13 22:45:27 +000022def string_reverse(s):
Tim Peters852eae12006-06-05 20:48:49 +000023 return "".join(reversed(s))
Tim Peters17e17d42001-06-13 22:45:27 +000024
25def bigendian_to_native(value):
26 if ISBIGENDIAN:
27 return value
28 else:
29 return string_reverse(value)
30
Barry Warsaw07a0eec1996-12-12 23:34:06 +000031def simple_err(func, *args):
32 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000033 func(*args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000034 except struct.error:
Guido van Rossum41360a41998-03-26 19:42:58 +000035 pass
Barry Warsaw07a0eec1996-12-12 23:34:06 +000036 else:
Guido van Rossum41360a41998-03-26 19:42:58 +000037 raise TestFailed, "%s%s did not raise struct.error" % (
38 func.__name__, args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000039
Tim Peters7a3bfc32001-06-12 01:22:22 +000040def any_err(func, *args):
41 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000042 func(*args)
Bob Ippolito2fd39772006-05-29 22:55:48 +000043 except (struct.error, TypeError):
Tim Peters7a3bfc32001-06-12 01:22:22 +000044 pass
45 else:
46 raise TestFailed, "%s%s did not raise error" % (
47 func.__name__, args)
Tim Peters7a3bfc32001-06-12 01:22:22 +000048
Bob Ippolito2fd39772006-05-29 22:55:48 +000049def deprecated_err(func, *args):
Tim Petersaba19bc2006-05-30 02:25:25 +000050 # The `warnings` module doesn't have an advertised way to restore
51 # its filter list. Cheat.
52 save_warnings_filters = warnings.filters[:]
Neal Norwitz9f16dd02006-05-31 09:02:44 +000053 # Grrr, we need this function to warn every time. Without removing
54 # the warningregistry, running test_tarfile then test_struct would fail
55 # on 64-bit platforms.
56 globals = func.func_globals
57 if '__warningregistry__' in globals:
58 del globals['__warningregistry__']
Bob Ippolito2fd39772006-05-29 22:55:48 +000059 warnings.filterwarnings("error", r"""^struct.*""", DeprecationWarning)
Tim Petersaba19bc2006-05-30 02:25:25 +000060 warnings.filterwarnings("error", r""".*format requires.*""",
61 DeprecationWarning)
Bob Ippolito2fd39772006-05-29 22:55:48 +000062 try:
63 try:
64 func(*args)
65 except (struct.error, TypeError):
66 pass
67 except DeprecationWarning:
Bob Ippolito4182a752006-05-30 17:37:54 +000068 if not PY_STRUCT_OVERFLOW_MASKING:
Bob Ippolito2fd39772006-05-29 22:55:48 +000069 raise TestFailed, "%s%s expected to raise struct.error" % (
70 func.__name__, args)
71 else:
72 raise TestFailed, "%s%s did not raise error" % (
73 func.__name__, args)
74 finally:
Tim Petersaba19bc2006-05-30 02:25:25 +000075 warnings.filters[:] = save_warnings_filters[:]
Tim Peters17e17d42001-06-13 22:45:27 +000076
Tim Peters7b9542a2001-06-10 23:40:19 +000077simple_err(struct.calcsize, 'Z')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000078
79sz = struct.calcsize('i')
Fred Drake132dce22000-12-12 23:11:42 +000080if sz * 3 != struct.calcsize('iii'):
Guido van Rossum2a378501996-12-31 17:25:47 +000081 raise TestFailed, 'inconsistent sizes'
Barry Warsaw07a0eec1996-12-12 23:34:06 +000082
Guido van Rossum04ebf5c1997-01-03 19:00:37 +000083fmt = 'cbxxxxxxhhhhiillffd'
84fmt3 = '3c3b18x12h6i6l6f3d'
85sz = struct.calcsize(fmt)
86sz3 = struct.calcsize(fmt3)
Fred Drake132dce22000-12-12 23:11:42 +000087if sz * 3 != sz3:
Walter Dörwald70a6b492004-02-12 17:35:32 +000088 raise TestFailed, 'inconsistent sizes (3*%r -> 3*%d = %d, %r -> %d)' % (
89 fmt, sz, 3*sz, fmt3, sz3)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000090
91simple_err(struct.pack, 'iii', 3)
92simple_err(struct.pack, 'i', 3, 3, 3)
93simple_err(struct.pack, 'i', 'foo')
Armin Rigo9f904392004-09-27 19:27:51 +000094simple_err(struct.pack, 'P', 'foo')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000095simple_err(struct.unpack, 'd', 'flap')
96s = struct.pack('ii', 1, 2)
97simple_err(struct.unpack, 'iii', s)
98simple_err(struct.unpack, 'i', s)
99
100c = 'a'
Guido van Rossum2a378501996-12-31 17:25:47 +0000101b = 1
Barry Warsaw07a0eec1996-12-12 23:34:06 +0000102h = 255
103i = 65535
104l = 65536
105f = 3.1415
106d = 3.1415
107
Guido van Rossum420c11c1997-01-03 00:09:46 +0000108for prefix in ('', '@', '<', '>', '=', '!'):
109 for format in ('xcbhilfd', 'xcBHILfd'):
Guido van Rossum41360a41998-03-26 19:42:58 +0000110 format = prefix + format
111 if verbose:
112 print "trying:", format
113 s = struct.pack(format, c, b, h, i, l, f, d)
114 cp, bp, hp, ip, lp, fp, dp = struct.unpack(format, s)
Fred Drake132dce22000-12-12 23:11:42 +0000115 if (cp != c or bp != b or hp != h or ip != i or lp != l or
116 int(100 * fp) != int(100 * f) or int(100 * dp) != int(100 * d)):
Guido van Rossum41360a41998-03-26 19:42:58 +0000117 # ^^^ calculate only to two decimal places
118 raise TestFailed, "unpack/pack not transitive (%s, %s)" % (
119 str(format), str((cp, bp, hp, ip, lp, fp, dp)))
Guido van Rossum2a378501996-12-31 17:25:47 +0000120
Guido van Rossum420c11c1997-01-03 00:09:46 +0000121# Test some of the new features in detail
Guido van Rossum2a378501996-12-31 17:25:47 +0000122
123# (format, argument, big-endian result, little-endian result, asymmetric)
124tests = [
125 ('c', 'a', 'a', 'a', 0),
126 ('xc', 'a', '\0a', '\0a', 0),
127 ('cx', 'a', 'a\0', 'a\0', 0),
128 ('s', 'a', 'a', 'a', 0),
129 ('0s', 'helloworld', '', '', 1),
130 ('1s', 'helloworld', 'h', 'h', 1),
131 ('9s', 'helloworld', 'helloworl', 'helloworl', 1),
132 ('10s', 'helloworld', 'helloworld', 'helloworld', 0),
133 ('11s', 'helloworld', 'helloworld\0', 'helloworld\0', 1),
134 ('20s', 'helloworld', 'helloworld'+10*'\0', 'helloworld'+10*'\0', 1),
135 ('b', 7, '\7', '\7', 0),
136 ('b', -7, '\371', '\371', 0),
137 ('B', 7, '\7', '\7', 0),
138 ('B', 249, '\371', '\371', 0),
139 ('h', 700, '\002\274', '\274\002', 0),
140 ('h', -700, '\375D', 'D\375', 0),
141 ('H', 700, '\002\274', '\274\002', 0),
142 ('H', 0x10000-700, '\375D', 'D\375', 0),
143 ('i', 70000000, '\004,\035\200', '\200\035,\004', 0),
144 ('i', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
145 ('I', 70000000L, '\004,\035\200', '\200\035,\004', 0),
146 ('I', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
147 ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
148 ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
149 ('L', 70000000L, '\004,\035\200', '\200\035,\004', 0),
150 ('L', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
Guido van Rossum420c11c1997-01-03 00:09:46 +0000151 ('f', 2.0, '@\000\000\000', '\000\000\000@', 0),
152 ('d', 2.0, '@\000\000\000\000\000\000\000',
153 '\000\000\000\000\000\000\000@', 0),
154 ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0),
155 ('d', -2.0, '\300\000\000\000\000\000\000\000',
156 '\000\000\000\000\000\000\000\300', 0),
Guido van Rossum2a378501996-12-31 17:25:47 +0000157]
158
Guido van Rossum2a378501996-12-31 17:25:47 +0000159for fmt, arg, big, lil, asy in tests:
160 if verbose:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000161 print "%r %r %r %r" % (fmt, arg, big, lil)
Guido van Rossum2a378501996-12-31 17:25:47 +0000162 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
Tim Peters17e17d42001-06-13 22:45:27 +0000163 ('='+fmt, ISBIGENDIAN and big or lil)]:
Guido van Rossum41360a41998-03-26 19:42:58 +0000164 res = struct.pack(xfmt, arg)
165 if res != exp:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000166 raise TestFailed, "pack(%r, %r) -> %r # expected %r" % (
167 fmt, arg, res, exp)
Guido van Rossum41360a41998-03-26 19:42:58 +0000168 n = struct.calcsize(xfmt)
169 if n != len(res):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000170 raise TestFailed, "calcsize(%r) -> %d # expected %d" % (
171 xfmt, n, len(res))
Guido van Rossum41360a41998-03-26 19:42:58 +0000172 rev = struct.unpack(xfmt, res)[0]
173 if rev != arg and not asy:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000174 raise TestFailed, "unpack(%r, %r) -> (%r,) # expected (%r,)" % (
175 fmt, res, rev, arg)
Tim Peters7b9542a2001-06-10 23:40:19 +0000176
Tim Peters7a3bfc32001-06-12 01:22:22 +0000177###########################################################################
Tim Peters17e17d42001-06-13 22:45:27 +0000178# Simple native q/Q tests.
Tim Peters7b9542a2001-06-10 23:40:19 +0000179
180has_native_qQ = 1
181try:
182 struct.pack("q", 5)
183except struct.error:
184 has_native_qQ = 0
185
186if verbose:
187 print "Platform has native q/Q?", has_native_qQ and "Yes." or "No."
188
Tim Peters7a3bfc32001-06-12 01:22:22 +0000189any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless
Tim Peters7b9542a2001-06-10 23:40:19 +0000190simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless
191simple_err(struct.pack, "Q", "a") # ditto, but 'Q'
192
Tim Peters7a3bfc32001-06-12 01:22:22 +0000193def test_native_qQ():
Tim Peters7b9542a2001-06-10 23:40:19 +0000194 bytes = struct.calcsize('q')
195 # The expected values here are in big-endian format, primarily because
196 # I'm on a little-endian machine and so this is the clearest way (for
197 # me) to force the code to get exercised.
198 for format, input, expected in (
199 ('q', -1, '\xff' * bytes),
200 ('q', 0, '\x00' * bytes),
201 ('Q', 0, '\x00' * bytes),
202 ('q', 1L, '\x00' * (bytes-1) + '\x01'),
203 ('Q', (1L << (8*bytes))-1, '\xff' * bytes),
204 ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))):
205 got = struct.pack(format, input)
Tim Petersc533edc2001-06-10 23:52:59 +0000206 native_expected = bigendian_to_native(expected)
207 verify(got == native_expected,
Tim Peters7b9542a2001-06-10 23:40:19 +0000208 "%r-pack of %r gave %r, not %r" %
Tim Petersc533edc2001-06-10 23:52:59 +0000209 (format, input, got, native_expected))
Tim Peters7b9542a2001-06-10 23:40:19 +0000210 retrieved = struct.unpack(format, got)[0]
211 verify(retrieved == input,
212 "%r-unpack of %r gave %r, not %r" %
213 (format, got, retrieved, input))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000214
215if has_native_qQ:
216 test_native_qQ()
217
Tim Peters17e17d42001-06-13 22:45:27 +0000218###########################################################################
219# Standard integer tests (bBhHiIlLqQ).
Tim Peters7a3bfc32001-06-12 01:22:22 +0000220
221import binascii
Tim Peters7a3bfc32001-06-12 01:22:22 +0000222
Tim Peters17e17d42001-06-13 22:45:27 +0000223class IntTester:
Tim Peters7a3bfc32001-06-12 01:22:22 +0000224
Tim Peters17e17d42001-06-13 22:45:27 +0000225 # XXX Most std integer modes fail to test for out-of-range.
Tim Peters3eec38a2001-06-18 22:27:39 +0000226 # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
227 # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
228 # reported by Mark Favas).
229 BUGGY_RANGE_CHECK = "bBhHiIlL"
Tim Peters7a3bfc32001-06-12 01:22:22 +0000230
Tim Peters17e17d42001-06-13 22:45:27 +0000231 def __init__(self, formatpair, bytesize):
232 assert len(formatpair) == 2
233 self.formatpair = formatpair
234 for direction in "<>!=":
235 for code in formatpair:
236 format = direction + code
237 verify(struct.calcsize(format) == bytesize)
238 self.bytesize = bytesize
239 self.bitsize = bytesize * 8
240 self.signed_code, self.unsigned_code = formatpair
241 self.unsigned_min = 0
242 self.unsigned_max = 2L**self.bitsize - 1
243 self.signed_min = -(2L**(self.bitsize-1))
244 self.signed_max = 2L**(self.bitsize-1) - 1
Tim Peters7a3bfc32001-06-12 01:22:22 +0000245
Tim Peters17e17d42001-06-13 22:45:27 +0000246 def test_one(self, x, pack=struct.pack,
247 unpack=struct.unpack,
248 unhexlify=binascii.unhexlify):
249 if verbose:
250 print "trying std", self.formatpair, "on", x, "==", hex(x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000251
Tim Peters17e17d42001-06-13 22:45:27 +0000252 # Try signed.
253 code = self.signed_code
254 if self.signed_min <= x <= self.signed_max:
255 # Try big-endian.
256 expected = long(x)
257 if x < 0:
258 expected += 1L << self.bitsize
259 assert expected > 0
260 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
261 if len(expected) & 1:
262 expected = "0" + expected
263 expected = unhexlify(expected)
264 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000265
Tim Peters17e17d42001-06-13 22:45:27 +0000266 # Pack work?
267 format = ">" + code
268 got = pack(format, x)
269 verify(got == expected,
270 "'%s'-pack of %r gave %r, not %r" %
271 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000272
Tim Peters17e17d42001-06-13 22:45:27 +0000273 # Unpack work?
274 retrieved = unpack(format, got)[0]
275 verify(x == retrieved,
276 "'%s'-unpack of %r gave %r, not %r" %
277 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000278
Tim Peters17e17d42001-06-13 22:45:27 +0000279 # Adding any byte should cause a "too big" error.
280 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000281
Tim Peters17e17d42001-06-13 22:45:27 +0000282 # Try little-endian.
283 format = "<" + code
284 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000285
Tim Peters17e17d42001-06-13 22:45:27 +0000286 # Pack work?
287 got = pack(format, x)
288 verify(got == expected,
289 "'%s'-pack of %r gave %r, not %r" %
290 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000291
Tim Peters17e17d42001-06-13 22:45:27 +0000292 # Unpack work?
293 retrieved = unpack(format, got)[0]
294 verify(x == retrieved,
295 "'%s'-unpack of %r gave %r, not %r" %
296 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000297
Tim Peters17e17d42001-06-13 22:45:27 +0000298 # Adding any byte should cause a "too big" error.
299 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000300
Tim Peters17e17d42001-06-13 22:45:27 +0000301 else:
302 # x is out of range -- verify pack realizes that.
Bob Ippolitoe27337b2006-05-26 13:15:44 +0000303 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000304 if verbose:
305 print "Skipping buggy range check for code", code
306 else:
Bob Ippolito2fd39772006-05-29 22:55:48 +0000307 deprecated_err(pack, ">" + code, x)
308 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000309
Tim Peters17e17d42001-06-13 22:45:27 +0000310 # Much the same for unsigned.
311 code = self.unsigned_code
312 if self.unsigned_min <= x <= self.unsigned_max:
313 # Try big-endian.
314 format = ">" + code
315 expected = long(x)
316 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
317 if len(expected) & 1:
318 expected = "0" + expected
319 expected = unhexlify(expected)
320 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000321
Tim Peters17e17d42001-06-13 22:45:27 +0000322 # Pack work?
323 got = pack(format, x)
324 verify(got == expected,
325 "'%s'-pack of %r gave %r, not %r" %
326 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000327
Tim Peters17e17d42001-06-13 22:45:27 +0000328 # Unpack work?
329 retrieved = unpack(format, got)[0]
330 verify(x == retrieved,
331 "'%s'-unpack of %r gave %r, not %r" %
332 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000333
Tim Peters17e17d42001-06-13 22:45:27 +0000334 # Adding any byte should cause a "too big" error.
335 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000336
Tim Peters17e17d42001-06-13 22:45:27 +0000337 # Try little-endian.
338 format = "<" + code
339 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000340
Tim Peters17e17d42001-06-13 22:45:27 +0000341 # Pack work?
342 got = pack(format, x)
343 verify(got == expected,
344 "'%s'-pack of %r gave %r, not %r" %
345 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000346
Tim Peters17e17d42001-06-13 22:45:27 +0000347 # Unpack work?
348 retrieved = unpack(format, got)[0]
349 verify(x == retrieved,
350 "'%s'-unpack of %r gave %r, not %r" %
351 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000352
Tim Peters17e17d42001-06-13 22:45:27 +0000353 # Adding any byte should cause a "too big" error.
354 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000355
Tim Peters17e17d42001-06-13 22:45:27 +0000356 else:
357 # x is out of range -- verify pack realizes that.
Bob Ippolitoaa70a172006-05-26 20:25:23 +0000358 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000359 if verbose:
360 print "Skipping buggy range check for code", code
361 else:
Bob Ippolito2fd39772006-05-29 22:55:48 +0000362 deprecated_err(pack, ">" + code, x)
363 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000364
Tim Peters17e17d42001-06-13 22:45:27 +0000365 def run(self):
366 from random import randrange
367
368 # Create all interesting powers of 2.
369 values = []
370 for exp in range(self.bitsize + 3):
371 values.append(1L << exp)
372
373 # Add some random values.
374 for i in range(self.bitsize):
375 val = 0L
376 for j in range(self.bytesize):
377 val = (val << 8) | randrange(256)
378 values.append(val)
379
380 # Try all those, and their negations, and +-1 from them. Note
381 # that this tests all power-of-2 boundaries in range, and a few out
382 # of range, plus +-(2**n +- 1).
383 for base in values:
384 for val in -base, base:
385 for incr in -1, 0, 1:
386 x = val + incr
387 try:
388 x = int(x)
389 except OverflowError:
390 pass
391 self.test_one(x)
392
393 # Some error cases.
394 for direction in "<>":
395 for code in self.formatpair:
396 for badobject in "a string", 3+42j, randrange:
397 any_err(struct.pack, direction + code, badobject)
398
399for args in [("bB", 1),
400 ("hH", 2),
401 ("iI", 4),
402 ("lL", 4),
403 ("qQ", 8)]:
404 t = IntTester(*args)
405 t.run()
Tim Peters0891ac02001-09-15 02:35:15 +0000406
407
408###########################################################################
409# The p ("Pascal string") code.
410
411def test_p_code():
412 for code, input, expected, expectedback in [
413 ('p','abc', '\x00', ''),
414 ('1p', 'abc', '\x00', ''),
415 ('2p', 'abc', '\x01a', 'a'),
416 ('3p', 'abc', '\x02ab', 'ab'),
417 ('4p', 'abc', '\x03abc', 'abc'),
418 ('5p', 'abc', '\x03abc\x00', 'abc'),
419 ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
420 ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
421 got = struct.pack(code, input)
422 if got != expected:
423 raise TestFailed("pack(%r, %r) == %r but expected %r" %
424 (code, input, got, expected))
425 (got,) = struct.unpack(code, got)
426 if got != expectedback:
427 raise TestFailed("unpack(%r, %r) == %r but expected %r" %
428 (code, input, got, expectedback))
429
430test_p_code()
Tim Petersd50ade62003-03-20 18:32:13 +0000431
432
433###########################################################################
434# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
435# from the low-order discarded bits could propagate into the exponent
436# field, causing the result to be wrong by a factor of 2.
437
438def test_705836():
439 import math
440
441 for base in range(1, 33):
442 # smaller <- largest representable float less than base.
443 delta = 0.5
444 while base - delta / 2.0 != base:
445 delta /= 2.0
446 smaller = base - delta
447 # Packing this rounds away a solid string of trailing 1 bits.
448 packed = struct.pack("<f", smaller)
449 unpacked = struct.unpack("<f", packed)[0]
450 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
451 # 16, respectively.
452 verify(base == unpacked)
453 bigpacked = struct.pack(">f", smaller)
454 verify(bigpacked == string_reverse(packed),
455 ">f pack should be byte-reversal of <f pack")
456 unpacked = struct.unpack(">f", bigpacked)[0]
457 verify(base == unpacked)
458
459 # Largest finite IEEE single.
460 big = (1 << 24) - 1
461 big = math.ldexp(big, 127 - 23)
462 packed = struct.pack(">f", big)
463 unpacked = struct.unpack(">f", packed)[0]
464 verify(big == unpacked)
465
466 # The same, but tack on a 1 bit so it rounds up to infinity.
467 big = (1 << 25) - 1
468 big = math.ldexp(big, 127 - 24)
469 try:
470 packed = struct.pack(">f", big)
471 except OverflowError:
472 pass
473 else:
474 TestFailed("expected OverflowError")
475
476test_705836()
Bob Ippolitoeb621272006-05-24 15:32:06 +0000477
Bob Ippolitoeb621272006-05-24 15:32:06 +0000478def test_1229380():
Bob Ippolitoe27337b2006-05-26 13:15:44 +0000479 import sys
Bob Ippolitoeb621272006-05-24 15:32:06 +0000480 for endian in ('', '>', '<'):
481 for cls in (int, long):
482 for fmt in ('B', 'H', 'I', 'L'):
Bob Ippolito2fd39772006-05-29 22:55:48 +0000483 deprecated_err(struct.pack, endian + fmt, cls(-1))
Bob Ippolitoeb621272006-05-24 15:32:06 +0000484
Bob Ippolito2fd39772006-05-29 22:55:48 +0000485 deprecated_err(struct.pack, endian + 'B', cls(300))
486 deprecated_err(struct.pack, endian + 'H', cls(70000))
Bob Ippolitoeb621272006-05-24 15:32:06 +0000487
Bob Ippolito2fd39772006-05-29 22:55:48 +0000488 deprecated_err(struct.pack, endian + 'I', sys.maxint * 4L)
489 deprecated_err(struct.pack, endian + 'L', sys.maxint * 4L)
Bob Ippolitoeb621272006-05-24 15:32:06 +0000490
Bob Ippolitoe27337b2006-05-26 13:15:44 +0000491if PY_STRUCT_RANGE_CHECKING:
Bob Ippolitoeb621272006-05-24 15:32:06 +0000492 test_1229380()
Martin Blais2856e5f2006-05-26 12:03:27 +0000493
Martin Blais2856e5f2006-05-26 12:03:27 +0000494
Martin Blais7f7386c2006-06-02 13:03:43 +0000495###########################################################################
496# Packing and unpacking to/from buffers.
Martin Blais2856e5f2006-05-26 12:03:27 +0000497
Martin Blais7f7386c2006-06-02 13:03:43 +0000498# Copied and modified from unittest.
499def assertRaises(excClass, callableObj, *args, **kwargs):
500 try:
501 callableObj(*args, **kwargs)
502 except excClass:
503 return
504 else:
Tim Peters852eae12006-06-05 20:48:49 +0000505 raise TestFailed("%s not raised." % excClass)
Martin Blais2856e5f2006-05-26 12:03:27 +0000506
Martin Blais7f7386c2006-06-02 13:03:43 +0000507def test_unpack_from():
508 test_string = 'abcd01234'
509 fmt = '4s'
510 s = struct.Struct(fmt)
511 for cls in (str, buffer):
512 data = cls(test_string)
Tim Peters852eae12006-06-05 20:48:49 +0000513 vereq(s.unpack_from(data), ('abcd',))
514 vereq(s.unpack_from(data, 2), ('cd01',))
515 vereq(s.unpack_from(data, 4), ('0123',))
Martin Blais7f7386c2006-06-02 13:03:43 +0000516 for i in xrange(6):
Tim Peters852eae12006-06-05 20:48:49 +0000517 vereq(s.unpack_from(data, i), (data[i:i+4],))
Martin Blais7f7386c2006-06-02 13:03:43 +0000518 for i in xrange(6, len(test_string) + 1):
519 simple_err(s.unpack_from, data, i)
520 for cls in (str, buffer):
521 data = cls(test_string)
Tim Peters852eae12006-06-05 20:48:49 +0000522 vereq(struct.unpack_from(fmt, data), ('abcd',))
523 vereq(struct.unpack_from(fmt, data, 2), ('cd01',))
524 vereq(struct.unpack_from(fmt, data, 4), ('0123',))
Martin Blais7f7386c2006-06-02 13:03:43 +0000525 for i in xrange(6):
Tim Peters852eae12006-06-05 20:48:49 +0000526 vereq(struct.unpack_from(fmt, data, i), (data[i:i+4],))
Martin Blais7f7386c2006-06-02 13:03:43 +0000527 for i in xrange(6, len(test_string) + 1):
528 simple_err(struct.unpack_from, fmt, data, i)
Martin Blais2856e5f2006-05-26 12:03:27 +0000529
Martin Blaisaf2ae722006-06-04 13:49:49 +0000530def test_pack_into():
Martin Blais7f7386c2006-06-02 13:03:43 +0000531 test_string = 'Reykjavik rocks, eow!'
532 writable_buf = array.array('c', ' '*100)
533 fmt = '21s'
534 s = struct.Struct(fmt)
Martin Blais2856e5f2006-05-26 12:03:27 +0000535
Martin Blais7f7386c2006-06-02 13:03:43 +0000536 # Test without offset
Martin Blaisaf2ae722006-06-04 13:49:49 +0000537 s.pack_into(writable_buf, 0, test_string)
Martin Blais7f7386c2006-06-02 13:03:43 +0000538 from_buf = writable_buf.tostring()[:len(test_string)]
Tim Peters852eae12006-06-05 20:48:49 +0000539 vereq(from_buf, test_string)
Martin Blais2856e5f2006-05-26 12:03:27 +0000540
Martin Blais7f7386c2006-06-02 13:03:43 +0000541 # Test with offset.
Martin Blaisaf2ae722006-06-04 13:49:49 +0000542 s.pack_into(writable_buf, 10, test_string)
Martin Blais7f7386c2006-06-02 13:03:43 +0000543 from_buf = writable_buf.tostring()[:len(test_string)+10]
Tim Peters852eae12006-06-05 20:48:49 +0000544 vereq(from_buf, test_string[:10] + test_string)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000545
Martin Blais7f7386c2006-06-02 13:03:43 +0000546 # Go beyond boundaries.
547 small_buf = array.array('c', ' '*10)
Martin Blaisaf2ae722006-06-04 13:49:49 +0000548 assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
549 assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000550
Martin Blaisaf2ae722006-06-04 13:49:49 +0000551def test_pack_into_fn():
Martin Blais7f7386c2006-06-02 13:03:43 +0000552 test_string = 'Reykjavik rocks, eow!'
553 writable_buf = array.array('c', ' '*100)
554 fmt = '21s'
Martin Blaisaf2ae722006-06-04 13:49:49 +0000555 pack_into = lambda *args: struct.pack_into(fmt, *args)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000556
Tim Peters852eae12006-06-05 20:48:49 +0000557 # Test without offset.
Martin Blaisaf2ae722006-06-04 13:49:49 +0000558 pack_into(writable_buf, 0, test_string)
Martin Blais7f7386c2006-06-02 13:03:43 +0000559 from_buf = writable_buf.tostring()[:len(test_string)]
Tim Peters852eae12006-06-05 20:48:49 +0000560 vereq(from_buf, test_string)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000561
Martin Blais7f7386c2006-06-02 13:03:43 +0000562 # Test with offset.
Martin Blaisaf2ae722006-06-04 13:49:49 +0000563 pack_into(writable_buf, 10, test_string)
Martin Blais7f7386c2006-06-02 13:03:43 +0000564 from_buf = writable_buf.tostring()[:len(test_string)+10]
Tim Peters852eae12006-06-05 20:48:49 +0000565 vereq(from_buf, test_string[:10] + test_string)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000566
Martin Blais7f7386c2006-06-02 13:03:43 +0000567 # Go beyond boundaries.
568 small_buf = array.array('c', ' '*10)
Martin Blaisaf2ae722006-06-04 13:49:49 +0000569 assertRaises(struct.error, pack_into, small_buf, 0, test_string)
570 assertRaises(struct.error, pack_into, small_buf, 2, test_string)
Tim Petersfe98f962006-05-26 12:26:21 +0000571
Tim Petersc65a13f2006-06-04 01:22:53 +0000572
Martin Blais7f7386c2006-06-02 13:03:43 +0000573# Test methods to pack and unpack from buffers rather than strings.
574test_unpack_from()
Martin Blaisaf2ae722006-06-04 13:49:49 +0000575test_pack_into()
576test_pack_into_fn()