blob: 05ac760bac337e3d53095b195fed0c7c758fc577 [file] [log] [blame]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001from test.support import TestFailed, verbose, verify, vereq
2import 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
Guido van Rossume625fd52007-05-27 09:19:04 +000010verify((struct.pack('=i', 1)[0] == 0) == ISBIGENDIAN,
Tim Peters17e17d42001-06-13 22:45:27 +000011 "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):
Guido van Rossume625fd52007-05-27 09:19:04 +000025 return s[::-1]
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:
Collin Winter3add4d72007-08-29 23:37:32 +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:
Collin Winter3add4d72007-08-29 23:37:32 +000048 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):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000053 with test.support.catch_warning():
Thomas Wouters902d6eb2007-01-09 23:18:33 +000054 # 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.
Neal Norwitz221085d2007-02-25 20:55:47 +000057 globals = func.__globals__
Thomas Wouters902d6eb2007-01-09 23:18:33 +000058 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:
Collin Winter3add4d72007-08-29 23:37:32 +000073 raise TestFailed("%s%s expected to raise struct.error" % (
74 func.__name__, args))
Thomas Wouters0e3f5912006-08-11 14:57:12 +000075 else:
Collin Winter3add4d72007-08-29 23:37:32 +000076 raise TestFailed("%s%s did not raise error" % (
77 func.__name__, args))
Thomas Wouters0e3f5912006-08-11 14:57:12 +000078deprecated_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'):
Collin Winter3add4d72007-08-29 23:37:32 +000085 raise TestFailed('inconsistent sizes')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000086
Christian Heimesdd15f6c2008-03-16 00:07:10 +000087fmt = 'cbxxxxxxhhhhiillffd?'
88fmt3 = '3c3b18x12h6i6l6f3d3?'
Guido van Rossum04ebf5c1997-01-03 19:00:37 +000089sz = struct.calcsize(fmt)
90sz3 = struct.calcsize(fmt3)
Fred Drake132dce22000-12-12 23:11:42 +000091if sz * 3 != sz3:
Collin Winter3add4d72007-08-29 23:37: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')
Guido van Rossum98297ee2007-11-06 21:34:58 +000099simple_err(struct.unpack, 'd', b'flap')
Barry Warsaw07a0eec1996-12-12 23:34:06 +0000100s = struct.pack('ii', 1, 2)
101simple_err(struct.unpack, 'iii', s)
102simple_err(struct.unpack, 'i', s)
103
Guido van Rossum98297ee2007-11-06 21:34:58 +0000104c = b'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
Thomas Woutersb2137042007-02-01 18:02:27 +0000111t = True
Barry Warsaw07a0eec1996-12-12 23:34:06 +0000112
Guido van Rossum420c11c1997-01-03 00:09:46 +0000113for prefix in ('', '@', '<', '>', '=', '!'):
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000114 for format in ('xcbhilfd?', 'xcBHILfd?'):
Guido van Rossum41360a41998-03-26 19:42:58 +0000115 format = prefix + format
116 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000117 print("trying:", format)
Thomas Woutersb2137042007-02-01 18:02:27 +0000118 s = struct.pack(format, c, b, h, i, l, f, d, t)
119 cp, bp, hp, ip, lp, fp, dp, tp = struct.unpack(format, s)
Fred Drake132dce22000-12-12 23:11:42 +0000120 if (cp != c or bp != b or hp != h or ip != i or lp != l or
Thomas Woutersb2137042007-02-01 18:02:27 +0000121 int(100 * fp) != int(100 * f) or int(100 * dp) != int(100 * d) or
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000122 tp != t):
Guido van Rossum41360a41998-03-26 19:42:58 +0000123 # ^^^ calculate only to two decimal places
Collin Winter3add4d72007-08-29 23:37:32 +0000124 raise TestFailed("unpack/pack not transitive (%s, %s)" % (
125 str(format), str((cp, bp, hp, ip, lp, fp, dp, tp))))
Guido van Rossum2a378501996-12-31 17:25:47 +0000126
Guido van Rossum420c11c1997-01-03 00:09:46 +0000127# Test some of the new features in detail
Guido van Rossum2a378501996-12-31 17:25:47 +0000128
129# (format, argument, big-endian result, little-endian result, asymmetric)
130tests = [
131 ('c', 'a', 'a', 'a', 0),
132 ('xc', 'a', '\0a', '\0a', 0),
133 ('cx', 'a', 'a\0', 'a\0', 0),
134 ('s', 'a', 'a', 'a', 0),
135 ('0s', 'helloworld', '', '', 1),
136 ('1s', 'helloworld', 'h', 'h', 1),
137 ('9s', 'helloworld', 'helloworl', 'helloworl', 1),
138 ('10s', 'helloworld', 'helloworld', 'helloworld', 0),
139 ('11s', 'helloworld', 'helloworld\0', 'helloworld\0', 1),
140 ('20s', 'helloworld', 'helloworld'+10*'\0', 'helloworld'+10*'\0', 1),
141 ('b', 7, '\7', '\7', 0),
142 ('b', -7, '\371', '\371', 0),
143 ('B', 7, '\7', '\7', 0),
144 ('B', 249, '\371', '\371', 0),
145 ('h', 700, '\002\274', '\274\002', 0),
146 ('h', -700, '\375D', 'D\375', 0),
147 ('H', 700, '\002\274', '\274\002', 0),
148 ('H', 0x10000-700, '\375D', 'D\375', 0),
149 ('i', 70000000, '\004,\035\200', '\200\035,\004', 0),
150 ('i', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
Guido van Rossume2a383d2007-01-15 16:59:06 +0000151 ('I', 70000000, '\004,\035\200', '\200\035,\004', 0),
152 ('I', 0x100000000-70000000, '\373\323\342\200', '\200\342\323\373', 0),
Guido van Rossum2a378501996-12-31 17:25:47 +0000153 ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
154 ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
Guido van Rossume2a383d2007-01-15 16:59:06 +0000155 ('L', 70000000, '\004,\035\200', '\200\035,\004', 0),
156 ('L', 0x100000000-70000000, '\373\323\342\200', '\200\342\323\373', 0),
Guido van Rossum420c11c1997-01-03 00:09:46 +0000157 ('f', 2.0, '@\000\000\000', '\000\000\000@', 0),
158 ('d', 2.0, '@\000\000\000\000\000\000\000',
159 '\000\000\000\000\000\000\000@', 0),
160 ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0),
161 ('d', -2.0, '\300\000\000\000\000\000\000\000',
162 '\000\000\000\000\000\000\000\300', 0),
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000163 ('?', 0, '\0', '\0', 0),
164 ('?', 3, '\1', '\1', 1),
165 ('?', True, '\1', '\1', 0),
166 ('?', [], '\0', '\0', 1),
167 ('?', (1,), '\1', '\1', 1),
Guido van Rossum2a378501996-12-31 17:25:47 +0000168]
169
Guido van Rossum2a378501996-12-31 17:25:47 +0000170for fmt, arg, big, lil, asy in tests:
Guido van Rossume625fd52007-05-27 09:19:04 +0000171 big = bytes(big, "latin-1")
172 lil = bytes(lil, "latin-1")
Guido van Rossum2a378501996-12-31 17:25:47 +0000173 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000174 print("%r %r %r %r" % (fmt, arg, big, lil))
Guido van Rossum2a378501996-12-31 17:25:47 +0000175 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
Tim Peters17e17d42001-06-13 22:45:27 +0000176 ('='+fmt, ISBIGENDIAN and big or lil)]:
Guido van Rossum41360a41998-03-26 19:42:58 +0000177 res = struct.pack(xfmt, arg)
178 if res != exp:
Collin Winter3add4d72007-08-29 23:37:32 +0000179 raise TestFailed("pack(%r, %r) -> %r # expected %r" % (
180 fmt, arg, res, exp))
Guido van Rossum41360a41998-03-26 19:42:58 +0000181 n = struct.calcsize(xfmt)
182 if n != len(res):
Collin Winter3add4d72007-08-29 23:37:32 +0000183 raise TestFailed("calcsize(%r) -> %d # expected %d" % (
184 xfmt, n, len(res)))
Guido van Rossum41360a41998-03-26 19:42:58 +0000185 rev = struct.unpack(xfmt, res)[0]
Brett Cannon40430012007-10-22 20:24:51 +0000186 if isinstance(arg, str):
Guido van Rossum98297ee2007-11-06 21:34:58 +0000187 # Strings are returned as bytes since you can't know the encoding of
Brett Cannon40430012007-10-22 20:24:51 +0000188 # the string when packed.
Guido van Rossum98297ee2007-11-06 21:34:58 +0000189 arg = bytes(arg, 'latin1')
Guido van Rossum41360a41998-03-26 19:42:58 +0000190 if rev != arg and not asy:
Collin Winter3add4d72007-08-29 23:37:32 +0000191 raise TestFailed("unpack(%r, %r) -> (%r,) # expected (%r,)" % (
192 fmt, res, rev, arg))
Tim Peters7b9542a2001-06-10 23:40:19 +0000193
Tim Peters7a3bfc32001-06-12 01:22:22 +0000194###########################################################################
Tim Peters17e17d42001-06-13 22:45:27 +0000195# Simple native q/Q tests.
Tim Peters7b9542a2001-06-10 23:40:19 +0000196
197has_native_qQ = 1
198try:
199 struct.pack("q", 5)
200except struct.error:
201 has_native_qQ = 0
202
203if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000204 print("Platform has native q/Q?", has_native_qQ and "Yes." or "No.")
Tim Peters7b9542a2001-06-10 23:40:19 +0000205
Tim Peters7a3bfc32001-06-12 01:22:22 +0000206any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless
Tim Peters7b9542a2001-06-10 23:40:19 +0000207simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless
208simple_err(struct.pack, "Q", "a") # ditto, but 'Q'
209
Tim Peters7a3bfc32001-06-12 01:22:22 +0000210def test_native_qQ():
Guido van Rossume625fd52007-05-27 09:19:04 +0000211 nbytes = struct.calcsize('q')
Tim Peters7b9542a2001-06-10 23:40:19 +0000212 # The expected values here are in big-endian format, primarily because
213 # I'm on a little-endian machine and so this is the clearest way (for
214 # me) to force the code to get exercised.
215 for format, input, expected in (
Guido van Rossume625fd52007-05-27 09:19:04 +0000216 ('q', -1, '\xff' * nbytes),
217 ('q', 0, '\x00' * nbytes),
218 ('Q', 0, '\x00' * nbytes),
219 ('q', 1, '\x00' * (nbytes-1) + '\x01'),
220 ('Q', (1 << (8*nbytes))-1, '\xff' * nbytes),
221 ('q', (1 << (8*nbytes-1))-1, '\x7f' + '\xff' * (nbytes - 1))):
222 expected = bytes(expected, "latin-1")
Tim Peters7b9542a2001-06-10 23:40:19 +0000223 got = struct.pack(format, input)
Tim Petersc533edc2001-06-10 23:52:59 +0000224 native_expected = bigendian_to_native(expected)
225 verify(got == native_expected,
Tim Peters7b9542a2001-06-10 23:40:19 +0000226 "%r-pack of %r gave %r, not %r" %
Tim Petersc533edc2001-06-10 23:52:59 +0000227 (format, input, got, native_expected))
Tim Peters7b9542a2001-06-10 23:40:19 +0000228 retrieved = struct.unpack(format, got)[0]
229 verify(retrieved == input,
230 "%r-unpack of %r gave %r, not %r" %
231 (format, got, retrieved, input))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000232
233if has_native_qQ:
234 test_native_qQ()
235
Tim Peters17e17d42001-06-13 22:45:27 +0000236###########################################################################
237# Standard integer tests (bBhHiIlLqQ).
Tim Peters7a3bfc32001-06-12 01:22:22 +0000238
239import binascii
Tim Peters7a3bfc32001-06-12 01:22:22 +0000240
Tim Peters17e17d42001-06-13 22:45:27 +0000241class IntTester:
Tim Peters7a3bfc32001-06-12 01:22:22 +0000242
Tim Peters17e17d42001-06-13 22:45:27 +0000243 # XXX Most std integer modes fail to test for out-of-range.
Tim Peters3eec38a2001-06-18 22:27:39 +0000244 # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
245 # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
246 # reported by Mark Favas).
247 BUGGY_RANGE_CHECK = "bBhHiIlL"
Tim Peters7a3bfc32001-06-12 01:22:22 +0000248
Tim Peters17e17d42001-06-13 22:45:27 +0000249 def __init__(self, formatpair, bytesize):
250 assert len(formatpair) == 2
251 self.formatpair = formatpair
252 for direction in "<>!=":
253 for code in formatpair:
254 format = direction + code
255 verify(struct.calcsize(format) == bytesize)
256 self.bytesize = bytesize
257 self.bitsize = bytesize * 8
258 self.signed_code, self.unsigned_code = formatpair
259 self.unsigned_min = 0
Guido van Rossume2a383d2007-01-15 16:59:06 +0000260 self.unsigned_max = 2**self.bitsize - 1
261 self.signed_min = -(2**(self.bitsize-1))
262 self.signed_max = 2**(self.bitsize-1) - 1
Tim Peters7a3bfc32001-06-12 01:22:22 +0000263
Tim Peters17e17d42001-06-13 22:45:27 +0000264 def test_one(self, x, pack=struct.pack,
265 unpack=struct.unpack,
266 unhexlify=binascii.unhexlify):
267 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000268 print("trying std", self.formatpair, "on", x, "==", hex(x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000269
Tim Peters17e17d42001-06-13 22:45:27 +0000270 # Try signed.
271 code = self.signed_code
272 if self.signed_min <= x <= self.signed_max:
273 # Try big-endian.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000274 expected = int(x)
Tim Peters17e17d42001-06-13 22:45:27 +0000275 if x < 0:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000276 expected += 1 << self.bitsize
Tim Peters17e17d42001-06-13 22:45:27 +0000277 assert expected > 0
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000278 expected = hex(expected)[2:] # chop "0x"
Tim Peters17e17d42001-06-13 22:45:27 +0000279 if len(expected) & 1:
280 expected = "0" + expected
281 expected = unhexlify(expected)
Guido van Rossume625fd52007-05-27 09:19:04 +0000282 expected = b"\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000283
Tim Peters17e17d42001-06-13 22:45:27 +0000284 # Pack work?
285 format = ">" + code
286 got = pack(format, x)
287 verify(got == expected,
288 "'%s'-pack of %r gave %r, not %r" %
289 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000290
Tim Peters17e17d42001-06-13 22:45:27 +0000291 # Unpack work?
292 retrieved = unpack(format, got)[0]
293 verify(x == retrieved,
294 "'%s'-unpack of %r gave %r, not %r" %
295 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000296
Tim Peters17e17d42001-06-13 22:45:27 +0000297 # Adding any byte should cause a "too big" error.
Guido van Rossume625fd52007-05-27 09:19:04 +0000298 any_err(unpack, format, b'\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000299
Tim Peters17e17d42001-06-13 22:45:27 +0000300 # Try little-endian.
301 format = "<" + code
302 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000303
Tim Peters17e17d42001-06-13 22:45:27 +0000304 # Pack work?
305 got = pack(format, x)
306 verify(got == expected,
307 "'%s'-pack of %r gave %r, not %r" %
308 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000309
Tim Peters17e17d42001-06-13 22:45:27 +0000310 # Unpack work?
311 retrieved = unpack(format, got)[0]
312 verify(x == retrieved,
313 "'%s'-unpack of %r gave %r, not %r" %
314 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000315
Tim Peters17e17d42001-06-13 22:45:27 +0000316 # Adding any byte should cause a "too big" error.
Guido van Rossume625fd52007-05-27 09:19:04 +0000317 any_err(unpack, format, b'\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000318
Tim Peters17e17d42001-06-13 22:45:27 +0000319 else:
320 # x is out of range -- verify pack realizes that.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000321 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000322 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000323 print("Skipping buggy range check for code", code)
Tim Peters17e17d42001-06-13 22:45:27 +0000324 else:
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000325 deprecated_err(pack, ">" + code, x)
326 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000327
Tim Peters17e17d42001-06-13 22:45:27 +0000328 # Much the same for unsigned.
329 code = self.unsigned_code
330 if self.unsigned_min <= x <= self.unsigned_max:
331 # Try big-endian.
332 format = ">" + code
Guido van Rossume2a383d2007-01-15 16:59:06 +0000333 expected = int(x)
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000334 expected = hex(expected)[2:] # chop "0x"
Tim Peters17e17d42001-06-13 22:45:27 +0000335 if len(expected) & 1:
336 expected = "0" + expected
337 expected = unhexlify(expected)
Guido van Rossume625fd52007-05-27 09:19:04 +0000338 expected = b"\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000339
Tim Peters17e17d42001-06-13 22:45:27 +0000340 # Pack work?
341 got = pack(format, x)
342 verify(got == expected,
343 "'%s'-pack of %r gave %r, not %r" %
344 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000345
Tim Peters17e17d42001-06-13 22:45:27 +0000346 # Unpack work?
347 retrieved = unpack(format, got)[0]
348 verify(x == retrieved,
349 "'%s'-unpack of %r gave %r, not %r" %
350 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000351
Tim Peters17e17d42001-06-13 22:45:27 +0000352 # Adding any byte should cause a "too big" error.
Guido van Rossume625fd52007-05-27 09:19:04 +0000353 any_err(unpack, format, b'\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000354
Tim Peters17e17d42001-06-13 22:45:27 +0000355 # Try little-endian.
356 format = "<" + code
357 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000358
Tim Peters17e17d42001-06-13 22:45:27 +0000359 # Pack work?
360 got = pack(format, x)
361 verify(got == expected,
362 "'%s'-pack of %r gave %r, not %r" %
363 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000364
Tim Peters17e17d42001-06-13 22:45:27 +0000365 # Unpack work?
366 retrieved = unpack(format, got)[0]
367 verify(x == retrieved,
368 "'%s'-unpack of %r gave %r, not %r" %
369 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000370
Tim Peters17e17d42001-06-13 22:45:27 +0000371 # Adding any byte should cause a "too big" error.
Guido van Rossume625fd52007-05-27 09:19:04 +0000372 any_err(unpack, format, b'\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000373
Tim Peters17e17d42001-06-13 22:45:27 +0000374 else:
375 # x is out of range -- verify pack realizes that.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000376 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000377 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000378 print("Skipping buggy range check for code", code)
Tim Peters17e17d42001-06-13 22:45:27 +0000379 else:
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000380 deprecated_err(pack, ">" + code, x)
381 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000382
Tim Peters17e17d42001-06-13 22:45:27 +0000383 def run(self):
384 from random import randrange
385
386 # Create all interesting powers of 2.
387 values = []
388 for exp in range(self.bitsize + 3):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000389 values.append(1 << exp)
Tim Peters17e17d42001-06-13 22:45:27 +0000390
391 # Add some random values.
392 for i in range(self.bitsize):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000393 val = 0
Tim Peters17e17d42001-06-13 22:45:27 +0000394 for j in range(self.bytesize):
395 val = (val << 8) | randrange(256)
396 values.append(val)
397
398 # Try all those, and their negations, and +-1 from them. Note
399 # that this tests all power-of-2 boundaries in range, and a few out
400 # of range, plus +-(2**n +- 1).
401 for base in values:
402 for val in -base, base:
403 for incr in -1, 0, 1:
404 x = val + incr
405 try:
406 x = int(x)
407 except OverflowError:
408 pass
409 self.test_one(x)
410
411 # Some error cases.
412 for direction in "<>":
413 for code in self.formatpair:
414 for badobject in "a string", 3+42j, randrange:
415 any_err(struct.pack, direction + code, badobject)
416
417for args in [("bB", 1),
418 ("hH", 2),
419 ("iI", 4),
420 ("lL", 4),
421 ("qQ", 8)]:
422 t = IntTester(*args)
423 t.run()
Tim Peters0891ac02001-09-15 02:35:15 +0000424
425
426###########################################################################
427# The p ("Pascal string") code.
428
429def test_p_code():
430 for code, input, expected, expectedback in [
Guido van Rossum98297ee2007-11-06 21:34:58 +0000431 ('p','abc', '\x00', b''),
432 ('1p', 'abc', '\x00', b''),
433 ('2p', 'abc', '\x01a', b'a'),
434 ('3p', 'abc', '\x02ab', b'ab'),
435 ('4p', 'abc', '\x03abc', b'abc'),
436 ('5p', 'abc', '\x03abc\x00', b'abc'),
437 ('6p', 'abc', '\x03abc\x00\x00', b'abc'),
438 ('1000p', 'x'*1000, '\xff' + 'x'*999, b'x'*255)]:
Guido van Rossume625fd52007-05-27 09:19:04 +0000439 expected = bytes(expected, "latin-1")
Tim Peters0891ac02001-09-15 02:35:15 +0000440 got = struct.pack(code, input)
441 if got != expected:
442 raise TestFailed("pack(%r, %r) == %r but expected %r" %
443 (code, input, got, expected))
444 (got,) = struct.unpack(code, got)
445 if got != expectedback:
446 raise TestFailed("unpack(%r, %r) == %r but expected %r" %
447 (code, input, got, expectedback))
448
449test_p_code()
Tim Petersd50ade62003-03-20 18:32:13 +0000450
451
452###########################################################################
453# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
454# from the low-order discarded bits could propagate into the exponent
455# field, causing the result to be wrong by a factor of 2.
456
457def test_705836():
458 import math
459
460 for base in range(1, 33):
461 # smaller <- largest representable float less than base.
462 delta = 0.5
463 while base - delta / 2.0 != base:
464 delta /= 2.0
465 smaller = base - delta
466 # Packing this rounds away a solid string of trailing 1 bits.
467 packed = struct.pack("<f", smaller)
468 unpacked = struct.unpack("<f", packed)[0]
469 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
470 # 16, respectively.
471 verify(base == unpacked)
472 bigpacked = struct.pack(">f", smaller)
473 verify(bigpacked == string_reverse(packed),
474 ">f pack should be byte-reversal of <f pack")
475 unpacked = struct.unpack(">f", bigpacked)[0]
476 verify(base == unpacked)
477
478 # Largest finite IEEE single.
479 big = (1 << 24) - 1
480 big = math.ldexp(big, 127 - 23)
481 packed = struct.pack(">f", big)
482 unpacked = struct.unpack(">f", packed)[0]
483 verify(big == unpacked)
484
485 # The same, but tack on a 1 bit so it rounds up to infinity.
486 big = (1 << 25) - 1
487 big = math.ldexp(big, 127 - 24)
488 try:
489 packed = struct.pack(">f", big)
490 except OverflowError:
491 pass
492 else:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000493 raise TestFailed("expected OverflowError")
Tim Petersd50ade62003-03-20 18:32:13 +0000494
495test_705836()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000496
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000497###########################################################################
498# SF bug 1229380. No struct.pack exception for some out of range integers
499
Thomas Wouters477c8d52006-05-27 19:21:47 +0000500def test_1229380():
501 import sys
502 for endian in ('', '>', '<'):
Walter Dörwaldaa97f042007-05-03 21:05:51 +0000503 for fmt in ('B', 'H', 'I', 'L'):
504 deprecated_err(struct.pack, endian + fmt, -1)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000505
Walter Dörwaldaa97f042007-05-03 21:05:51 +0000506 deprecated_err(struct.pack, endian + 'B', 300)
507 deprecated_err(struct.pack, endian + 'H', 70000)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000508
Christian Heimesa37d4c62007-12-04 23:02:19 +0000509 deprecated_err(struct.pack, endian + 'I', sys.maxsize * 4)
510 deprecated_err(struct.pack, endian + 'L', sys.maxsize * 4)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000511
512if PY_STRUCT_RANGE_CHECKING:
513 test_1229380()
514
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000515###########################################################################
516# SF bug 1530559. struct.pack raises TypeError where it used to convert.
517
518def check_float_coerce(format, number):
519 if PY_STRUCT_FLOAT_COERCE == 2:
520 # Test for pre-2.5 struct module
521 packed = struct.pack(format, number)
522 floored = struct.unpack(format, packed)[0]
523 if floored != int(number):
524 raise TestFailed("did not correcly coerce float to int")
525 return
526 try:
527 func(*args)
528 except (struct.error, TypeError):
529 if PY_STRUCT_FLOAT_COERCE:
530 raise TestFailed("expected DeprecationWarning for float coerce")
531 except DeprecationWarning:
532 if not PY_STRUCT_FLOAT_COERCE:
533 raise TestFailed("expected to raise struct.error for float coerce")
534 else:
535 raise TestFailed("did not raise error for float coerce")
536
537check_float_coerce = with_warning_restore(deprecated_err)
538
539def test_1530559():
540 for endian in ('', '>', '<'):
541 for fmt in ('B', 'H', 'I', 'L', 'b', 'h', 'i', 'l'):
542 check_float_coerce(endian + fmt, 1.0)
543 check_float_coerce(endian + fmt, 1.5)
544
545test_1530559()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000546
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000547###########################################################################
Guido van Rossumbae07c92007-10-08 02:46:15 +0000548# Packing and unpacking to/from memory views.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000549
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000550# Copied and modified from unittest.
551def assertRaises(excClass, callableObj, *args, **kwargs):
552 try:
553 callableObj(*args, **kwargs)
554 except excClass:
555 return
556 else:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000557 raise TestFailed("%s not raised." % excClass)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000558
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000559def test_unpack_from():
Guido van Rossume625fd52007-05-27 09:19:04 +0000560 test_string = b'abcd01234'
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000561 fmt = '4s'
562 s = struct.Struct(fmt)
Guido van Rossum254348e2007-11-21 19:29:53 +0000563 for cls in (bytes, bytearray):
Guido van Rossume625fd52007-05-27 09:19:04 +0000564 if verbose:
565 print("test_unpack_from using", cls.__name__)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000566 data = cls(test_string)
Guido van Rossum254348e2007-11-21 19:29:53 +0000567 if not isinstance(data, (bytes, bytearray)):
Guido van Rossum98297ee2007-11-06 21:34:58 +0000568 bytes_data = bytes(data, 'latin1')
Georg Brandlbd1c68c2007-10-24 18:55:37 +0000569 else:
570 bytes_data = data
Guido van Rossum98297ee2007-11-06 21:34:58 +0000571 vereq(s.unpack_from(data), (b'abcd',))
572 vereq(s.unpack_from(data, 2), (b'cd01',))
573 vereq(s.unpack_from(data, 4), (b'0123',))
Guido van Rossum805365e2007-05-07 22:24:25 +0000574 for i in range(6):
Georg Brandlbd1c68c2007-10-24 18:55:37 +0000575 vereq(s.unpack_from(data, i), (bytes_data[i:i+4],))
Guido van Rossum805365e2007-05-07 22:24:25 +0000576 for i in range(6, len(test_string) + 1):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000577 simple_err(s.unpack_from, data, i)
Guido van Rossum254348e2007-11-21 19:29:53 +0000578 for cls in (bytes, bytearray):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000579 data = cls(test_string)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000580 vereq(struct.unpack_from(fmt, data), (b'abcd',))
581 vereq(struct.unpack_from(fmt, data, 2), (b'cd01',))
582 vereq(struct.unpack_from(fmt, data, 4), (b'0123',))
Guido van Rossum805365e2007-05-07 22:24:25 +0000583 for i in range(6):
Georg Brandlbd1c68c2007-10-24 18:55:37 +0000584 vereq(struct.unpack_from(fmt, data, i), (bytes_data[i:i+4],))
Guido van Rossum805365e2007-05-07 22:24:25 +0000585 for i in range(6, len(test_string) + 1):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000586 simple_err(struct.unpack_from, fmt, data, i)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000587
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000588def test_pack_into():
Guido van Rossum99c0c222007-07-03 16:28:47 +0000589 test_string = b'Reykjavik rocks, eow!'
590 writable_buf = array.array('b', b' '*100)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000591 fmt = '21s'
592 s = struct.Struct(fmt)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000593
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000594 # Test without offset
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000595 s.pack_into(writable_buf, 0, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000596 from_buf = writable_buf.tostring()[:len(test_string)]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000597 vereq(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000598
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000599 # Test with offset.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000600 s.pack_into(writable_buf, 10, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000601 from_buf = writable_buf.tostring()[:len(test_string)+10]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000602 vereq(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000603
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000604 # Go beyond boundaries.
Guido van Rossum99c0c222007-07-03 16:28:47 +0000605 small_buf = array.array('b', b' '*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000606 assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
607 assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000608
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000609def test_pack_into_fn():
Guido van Rossum99c0c222007-07-03 16:28:47 +0000610 test_string = b'Reykjavik rocks, eow!'
611 writable_buf = array.array('b', b' '*100)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000612 fmt = '21s'
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000613 pack_into = lambda *args: struct.pack_into(fmt, *args)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000614
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000615 # Test without offset.
616 pack_into(writable_buf, 0, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000617 from_buf = writable_buf.tostring()[:len(test_string)]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000618 vereq(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000619
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000620 # Test with offset.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000621 pack_into(writable_buf, 10, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000622 from_buf = writable_buf.tostring()[:len(test_string)+10]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000623 vereq(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000624
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000625 # Go beyond boundaries.
Guido van Rossum99c0c222007-07-03 16:28:47 +0000626 small_buf = array.array('b', b' '*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000627 assertRaises(struct.error, pack_into, small_buf, 0, test_string)
628 assertRaises(struct.error, pack_into, small_buf, 2, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000629
Guido van Rossumbae07c92007-10-08 02:46:15 +0000630def test_unpack_with_memoryview():
Guido van Rossumd8faa362007-04-27 19:54:29 +0000631 # SF bug 1563759: struct.unpack doens't support buffer protocol objects
Guido van Rossume625fd52007-05-27 09:19:04 +0000632 data1 = array.array('B', b'\x12\x34\x56\x78')
Guido van Rossumbae07c92007-10-08 02:46:15 +0000633 data2 = memoryview(b'\x12\x34\x56\x78') # XXX b'......XXXX......', 6, 4
Guido van Rossumd8faa362007-04-27 19:54:29 +0000634 for data in [data1, data2]:
635 value, = struct.unpack('>I', data)
636 vereq(value, 0x12345678)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000637
Guido van Rossumbae07c92007-10-08 02:46:15 +0000638# Test methods to pack and unpack from memoryviews rather than strings.
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000639test_unpack_from()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000640test_pack_into()
641test_pack_into_fn()
Guido van Rossumbae07c92007-10-08 02:46:15 +0000642test_unpack_with_memoryview()
Thomas Woutersb2137042007-02-01 18:02:27 +0000643
644def test_bool():
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000645 for prefix in tuple("<>!=")+('',):
646 false = (), [], [], '', 0
647 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
Guido van Rossumd8faa362007-04-27 19:54:29 +0000648
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000649 falseFormat = prefix + '?' * len(false)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000650 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000651 print('trying bool pack/unpack on', false, 'using format', falseFormat)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000652 packedFalse = struct.pack(falseFormat, *false)
653 unpackedFalse = struct.unpack(falseFormat, packedFalse)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000654
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000655 trueFormat = prefix + '?' * len(true)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000656 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000657 print('trying bool pack/unpack on', true, 'using format', trueFormat)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000658 packedTrue = struct.pack(trueFormat, *true)
659 unpackedTrue = struct.unpack(trueFormat, packedTrue)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000660
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000661 if len(true) != len(unpackedTrue):
662 raise TestFailed('unpacked true array is not of same size as input')
663 if len(false) != len(unpackedFalse):
664 raise TestFailed('unpacked false array is not of same size as input')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000665
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000666 for t in unpackedFalse:
667 if t is not False:
668 raise TestFailed('%r did not unpack as False' % t)
669 for t in unpackedTrue:
670 if t is not True:
671 raise TestFailed('%r did not unpack as false' % t)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000672
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000673 if prefix and verbose:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000674 print('trying size of bool with format %r' % (prefix+'?'))
675 packed = struct.pack(prefix+'?', 1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000676
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000677 if len(packed) != struct.calcsize(prefix+'?'):
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000678 raise TestFailed('packed length is not equal to calculated size')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000679
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000680 if len(packed) != 1 and prefix:
681 raise TestFailed('encoded bool is not one byte: %r' % packed)
682 elif not prefix and verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000683 print('size of bool in native format is %i' % (len(packed)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000684
Mark Dickinson0eb6f692008-03-16 02:29:03 +0000685 for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000686 if struct.unpack('>?', c)[0] is not True:
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000687 raise TestFailed('%c did not unpack as True' % c)
Thomas Woutersb2137042007-02-01 18:02:27 +0000688
689test_bool()