blob: 69057fc9f9b277d81bd2a2f756abe0f9791fe060 [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
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:
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.
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:
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
Thomas Woutersb2137042007-02-01 18:02:27 +000087fmt = 'cbxxxxxxhhhhiillffdt'
88fmt3 = '3c3b18x12h6i6l6f3d3t'
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:
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
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 ('', '@', '<', '>', '=', '!'):
Thomas Woutersb2137042007-02-01 18:02:27 +0000114 for format in ('xcbhilfdt', 'xcBHILfdt'):
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
124 raise TestFailed, "unpack/pack not transitive (%s, %s)" % (
Thomas Woutersb2137042007-02-01 18:02:27 +0000125 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),
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000163 ('t', 0, '\0', '\0', 0),
164 ('t', 3, '\1', '\1', 1),
165 ('t', True, '\1', '\1', 0),
166 ('t', [], '\0', '\0', 1),
167 ('t', (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:
Walter Dörwald70a6b492004-02-12 17:35: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):
Walter Dörwald70a6b492004-02-12 17:35: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]
186 if rev != arg and not asy:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000187 raise TestFailed, "unpack(%r, %r) -> (%r,) # expected (%r,)" % (
188 fmt, res, rev, arg)
Tim Peters7b9542a2001-06-10 23:40:19 +0000189
Tim Peters7a3bfc32001-06-12 01:22:22 +0000190###########################################################################
Tim Peters17e17d42001-06-13 22:45:27 +0000191# Simple native q/Q tests.
Tim Peters7b9542a2001-06-10 23:40:19 +0000192
193has_native_qQ = 1
194try:
195 struct.pack("q", 5)
196except struct.error:
197 has_native_qQ = 0
198
199if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000200 print("Platform has native q/Q?", has_native_qQ and "Yes." or "No.")
Tim Peters7b9542a2001-06-10 23:40:19 +0000201
Tim Peters7a3bfc32001-06-12 01:22:22 +0000202any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless
Tim Peters7b9542a2001-06-10 23:40:19 +0000203simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless
204simple_err(struct.pack, "Q", "a") # ditto, but 'Q'
205
Tim Peters7a3bfc32001-06-12 01:22:22 +0000206def test_native_qQ():
Guido van Rossume625fd52007-05-27 09:19:04 +0000207 nbytes = struct.calcsize('q')
Tim Peters7b9542a2001-06-10 23:40:19 +0000208 # The expected values here are in big-endian format, primarily because
209 # I'm on a little-endian machine and so this is the clearest way (for
210 # me) to force the code to get exercised.
211 for format, input, expected in (
Guido van Rossume625fd52007-05-27 09:19:04 +0000212 ('q', -1, '\xff' * nbytes),
213 ('q', 0, '\x00' * nbytes),
214 ('Q', 0, '\x00' * nbytes),
215 ('q', 1, '\x00' * (nbytes-1) + '\x01'),
216 ('Q', (1 << (8*nbytes))-1, '\xff' * nbytes),
217 ('q', (1 << (8*nbytes-1))-1, '\x7f' + '\xff' * (nbytes - 1))):
218 expected = bytes(expected, "latin-1")
Tim Peters7b9542a2001-06-10 23:40:19 +0000219 got = struct.pack(format, input)
Tim Petersc533edc2001-06-10 23:52:59 +0000220 native_expected = bigendian_to_native(expected)
221 verify(got == native_expected,
Tim Peters7b9542a2001-06-10 23:40:19 +0000222 "%r-pack of %r gave %r, not %r" %
Tim Petersc533edc2001-06-10 23:52:59 +0000223 (format, input, got, native_expected))
Tim Peters7b9542a2001-06-10 23:40:19 +0000224 retrieved = struct.unpack(format, got)[0]
225 verify(retrieved == input,
226 "%r-unpack of %r gave %r, not %r" %
227 (format, got, retrieved, input))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000228
229if has_native_qQ:
230 test_native_qQ()
231
Tim Peters17e17d42001-06-13 22:45:27 +0000232###########################################################################
233# Standard integer tests (bBhHiIlLqQ).
Tim Peters7a3bfc32001-06-12 01:22:22 +0000234
235import binascii
Tim Peters7a3bfc32001-06-12 01:22:22 +0000236
Tim Peters17e17d42001-06-13 22:45:27 +0000237class IntTester:
Tim Peters7a3bfc32001-06-12 01:22:22 +0000238
Tim Peters17e17d42001-06-13 22:45:27 +0000239 # XXX Most std integer modes fail to test for out-of-range.
Tim Peters3eec38a2001-06-18 22:27:39 +0000240 # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
241 # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
242 # reported by Mark Favas).
243 BUGGY_RANGE_CHECK = "bBhHiIlL"
Tim Peters7a3bfc32001-06-12 01:22:22 +0000244
Tim Peters17e17d42001-06-13 22:45:27 +0000245 def __init__(self, formatpair, bytesize):
246 assert len(formatpair) == 2
247 self.formatpair = formatpair
248 for direction in "<>!=":
249 for code in formatpair:
250 format = direction + code
251 verify(struct.calcsize(format) == bytesize)
252 self.bytesize = bytesize
253 self.bitsize = bytesize * 8
254 self.signed_code, self.unsigned_code = formatpair
255 self.unsigned_min = 0
Guido van Rossume2a383d2007-01-15 16:59:06 +0000256 self.unsigned_max = 2**self.bitsize - 1
257 self.signed_min = -(2**(self.bitsize-1))
258 self.signed_max = 2**(self.bitsize-1) - 1
Tim Peters7a3bfc32001-06-12 01:22:22 +0000259
Tim Peters17e17d42001-06-13 22:45:27 +0000260 def test_one(self, x, pack=struct.pack,
261 unpack=struct.unpack,
262 unhexlify=binascii.unhexlify):
263 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000264 print("trying std", self.formatpair, "on", x, "==", hex(x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000265
Tim Peters17e17d42001-06-13 22:45:27 +0000266 # Try signed.
267 code = self.signed_code
268 if self.signed_min <= x <= self.signed_max:
269 # Try big-endian.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000270 expected = int(x)
Tim Peters17e17d42001-06-13 22:45:27 +0000271 if x < 0:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000272 expected += 1 << self.bitsize
Tim Peters17e17d42001-06-13 22:45:27 +0000273 assert expected > 0
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000274 expected = hex(expected)[2:] # chop "0x"
Tim Peters17e17d42001-06-13 22:45:27 +0000275 if len(expected) & 1:
276 expected = "0" + expected
277 expected = unhexlify(expected)
Guido van Rossume625fd52007-05-27 09:19:04 +0000278 expected = b"\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000279
Tim Peters17e17d42001-06-13 22:45:27 +0000280 # Pack work?
281 format = ">" + code
282 got = pack(format, x)
283 verify(got == expected,
284 "'%s'-pack of %r gave %r, not %r" %
285 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000286
Tim Peters17e17d42001-06-13 22:45:27 +0000287 # Unpack work?
288 retrieved = unpack(format, got)[0]
289 verify(x == retrieved,
290 "'%s'-unpack of %r gave %r, not %r" %
291 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000292
Tim Peters17e17d42001-06-13 22:45:27 +0000293 # Adding any byte should cause a "too big" error.
Guido van Rossume625fd52007-05-27 09:19:04 +0000294 any_err(unpack, format, b'\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000295
Tim Peters17e17d42001-06-13 22:45:27 +0000296 # Try little-endian.
297 format = "<" + code
298 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000299
Tim Peters17e17d42001-06-13 22:45:27 +0000300 # Pack work?
301 got = pack(format, x)
302 verify(got == expected,
303 "'%s'-pack of %r gave %r, not %r" %
304 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000305
Tim Peters17e17d42001-06-13 22:45:27 +0000306 # Unpack work?
307 retrieved = unpack(format, got)[0]
308 verify(x == retrieved,
309 "'%s'-unpack of %r gave %r, not %r" %
310 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000311
Tim Peters17e17d42001-06-13 22:45:27 +0000312 # Adding any byte should cause a "too big" error.
Guido van Rossume625fd52007-05-27 09:19:04 +0000313 any_err(unpack, format, b'\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000314
Tim Peters17e17d42001-06-13 22:45:27 +0000315 else:
316 # x is out of range -- verify pack realizes that.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000317 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000318 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000319 print("Skipping buggy range check for code", code)
Tim Peters17e17d42001-06-13 22:45:27 +0000320 else:
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000321 deprecated_err(pack, ">" + code, x)
322 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000323
Tim Peters17e17d42001-06-13 22:45:27 +0000324 # Much the same for unsigned.
325 code = self.unsigned_code
326 if self.unsigned_min <= x <= self.unsigned_max:
327 # Try big-endian.
328 format = ">" + code
Guido van Rossume2a383d2007-01-15 16:59:06 +0000329 expected = int(x)
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000330 expected = hex(expected)[2:] # chop "0x"
Tim Peters17e17d42001-06-13 22:45:27 +0000331 if len(expected) & 1:
332 expected = "0" + expected
333 expected = unhexlify(expected)
Guido van Rossume625fd52007-05-27 09:19:04 +0000334 expected = b"\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000335
Tim Peters17e17d42001-06-13 22:45:27 +0000336 # Pack work?
337 got = pack(format, x)
338 verify(got == expected,
339 "'%s'-pack of %r gave %r, not %r" %
340 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000341
Tim Peters17e17d42001-06-13 22:45:27 +0000342 # Unpack work?
343 retrieved = unpack(format, got)[0]
344 verify(x == retrieved,
345 "'%s'-unpack of %r gave %r, not %r" %
346 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000347
Tim Peters17e17d42001-06-13 22:45:27 +0000348 # Adding any byte should cause a "too big" error.
Guido van Rossume625fd52007-05-27 09:19:04 +0000349 any_err(unpack, format, b'\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000350
Tim Peters17e17d42001-06-13 22:45:27 +0000351 # Try little-endian.
352 format = "<" + code
353 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000354
Tim Peters17e17d42001-06-13 22:45:27 +0000355 # Pack work?
356 got = pack(format, x)
357 verify(got == expected,
358 "'%s'-pack of %r gave %r, not %r" %
359 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000360
Tim Peters17e17d42001-06-13 22:45:27 +0000361 # Unpack work?
362 retrieved = unpack(format, got)[0]
363 verify(x == retrieved,
364 "'%s'-unpack of %r gave %r, not %r" %
365 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000366
Tim Peters17e17d42001-06-13 22:45:27 +0000367 # Adding any byte should cause a "too big" error.
Guido van Rossume625fd52007-05-27 09:19:04 +0000368 any_err(unpack, format, b'\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000369
Tim Peters17e17d42001-06-13 22:45:27 +0000370 else:
371 # x is out of range -- verify pack realizes that.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000372 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000373 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000374 print("Skipping buggy range check for code", code)
Tim Peters17e17d42001-06-13 22:45:27 +0000375 else:
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000376 deprecated_err(pack, ">" + code, x)
377 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000378
Tim Peters17e17d42001-06-13 22:45:27 +0000379 def run(self):
380 from random import randrange
381
382 # Create all interesting powers of 2.
383 values = []
384 for exp in range(self.bitsize + 3):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000385 values.append(1 << exp)
Tim Peters17e17d42001-06-13 22:45:27 +0000386
387 # Add some random values.
388 for i in range(self.bitsize):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000389 val = 0
Tim Peters17e17d42001-06-13 22:45:27 +0000390 for j in range(self.bytesize):
391 val = (val << 8) | randrange(256)
392 values.append(val)
393
394 # Try all those, and their negations, and +-1 from them. Note
395 # that this tests all power-of-2 boundaries in range, and a few out
396 # of range, plus +-(2**n +- 1).
397 for base in values:
398 for val in -base, base:
399 for incr in -1, 0, 1:
400 x = val + incr
401 try:
402 x = int(x)
403 except OverflowError:
404 pass
405 self.test_one(x)
406
407 # Some error cases.
408 for direction in "<>":
409 for code in self.formatpair:
410 for badobject in "a string", 3+42j, randrange:
411 any_err(struct.pack, direction + code, badobject)
412
413for args in [("bB", 1),
414 ("hH", 2),
415 ("iI", 4),
416 ("lL", 4),
417 ("qQ", 8)]:
418 t = IntTester(*args)
419 t.run()
Tim Peters0891ac02001-09-15 02:35:15 +0000420
421
422###########################################################################
423# The p ("Pascal string") code.
424
425def test_p_code():
426 for code, input, expected, expectedback in [
427 ('p','abc', '\x00', ''),
428 ('1p', 'abc', '\x00', ''),
429 ('2p', 'abc', '\x01a', 'a'),
430 ('3p', 'abc', '\x02ab', 'ab'),
431 ('4p', 'abc', '\x03abc', 'abc'),
432 ('5p', 'abc', '\x03abc\x00', 'abc'),
433 ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
434 ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
Guido van Rossume625fd52007-05-27 09:19:04 +0000435 expected = bytes(expected, "latin-1")
Tim Peters0891ac02001-09-15 02:35:15 +0000436 got = struct.pack(code, input)
437 if got != expected:
438 raise TestFailed("pack(%r, %r) == %r but expected %r" %
439 (code, input, got, expected))
440 (got,) = struct.unpack(code, got)
441 if got != expectedback:
442 raise TestFailed("unpack(%r, %r) == %r but expected %r" %
443 (code, input, got, expectedback))
444
445test_p_code()
Tim Petersd50ade62003-03-20 18:32:13 +0000446
447
448###########################################################################
449# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
450# from the low-order discarded bits could propagate into the exponent
451# field, causing the result to be wrong by a factor of 2.
452
453def test_705836():
454 import math
455
456 for base in range(1, 33):
457 # smaller <- largest representable float less than base.
458 delta = 0.5
459 while base - delta / 2.0 != base:
460 delta /= 2.0
461 smaller = base - delta
462 # Packing this rounds away a solid string of trailing 1 bits.
463 packed = struct.pack("<f", smaller)
464 unpacked = struct.unpack("<f", packed)[0]
465 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
466 # 16, respectively.
467 verify(base == unpacked)
468 bigpacked = struct.pack(">f", smaller)
469 verify(bigpacked == string_reverse(packed),
470 ">f pack should be byte-reversal of <f pack")
471 unpacked = struct.unpack(">f", bigpacked)[0]
472 verify(base == unpacked)
473
474 # Largest finite IEEE single.
475 big = (1 << 24) - 1
476 big = math.ldexp(big, 127 - 23)
477 packed = struct.pack(">f", big)
478 unpacked = struct.unpack(">f", packed)[0]
479 verify(big == unpacked)
480
481 # The same, but tack on a 1 bit so it rounds up to infinity.
482 big = (1 << 25) - 1
483 big = math.ldexp(big, 127 - 24)
484 try:
485 packed = struct.pack(">f", big)
486 except OverflowError:
487 pass
488 else:
489 TestFailed("expected OverflowError")
490
491test_705836()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000492
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000493###########################################################################
494# SF bug 1229380. No struct.pack exception for some out of range integers
495
Thomas Wouters477c8d52006-05-27 19:21:47 +0000496def test_1229380():
497 import sys
498 for endian in ('', '>', '<'):
Walter Dörwaldaa97f042007-05-03 21:05:51 +0000499 for fmt in ('B', 'H', 'I', 'L'):
500 deprecated_err(struct.pack, endian + fmt, -1)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000501
Walter Dörwaldaa97f042007-05-03 21:05:51 +0000502 deprecated_err(struct.pack, endian + 'B', 300)
503 deprecated_err(struct.pack, endian + 'H', 70000)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000504
Guido van Rossume2a383d2007-01-15 16:59:06 +0000505 deprecated_err(struct.pack, endian + 'I', sys.maxint * 4)
506 deprecated_err(struct.pack, endian + 'L', sys.maxint * 4)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000507
508if PY_STRUCT_RANGE_CHECKING:
509 test_1229380()
510
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000511###########################################################################
512# SF bug 1530559. struct.pack raises TypeError where it used to convert.
513
514def check_float_coerce(format, number):
515 if PY_STRUCT_FLOAT_COERCE == 2:
516 # Test for pre-2.5 struct module
517 packed = struct.pack(format, number)
518 floored = struct.unpack(format, packed)[0]
519 if floored != int(number):
520 raise TestFailed("did not correcly coerce float to int")
521 return
522 try:
523 func(*args)
524 except (struct.error, TypeError):
525 if PY_STRUCT_FLOAT_COERCE:
526 raise TestFailed("expected DeprecationWarning for float coerce")
527 except DeprecationWarning:
528 if not PY_STRUCT_FLOAT_COERCE:
529 raise TestFailed("expected to raise struct.error for float coerce")
530 else:
531 raise TestFailed("did not raise error for float coerce")
532
533check_float_coerce = with_warning_restore(deprecated_err)
534
535def test_1530559():
536 for endian in ('', '>', '<'):
537 for fmt in ('B', 'H', 'I', 'L', 'b', 'h', 'i', 'l'):
538 check_float_coerce(endian + fmt, 1.0)
539 check_float_coerce(endian + fmt, 1.5)
540
541test_1530559()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000542
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000543###########################################################################
544# Packing and unpacking to/from buffers.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000545
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000546# Copied and modified from unittest.
547def assertRaises(excClass, callableObj, *args, **kwargs):
548 try:
549 callableObj(*args, **kwargs)
550 except excClass:
551 return
552 else:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000553 raise TestFailed("%s not raised." % excClass)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000554
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000555def test_unpack_from():
Guido van Rossume625fd52007-05-27 09:19:04 +0000556 test_string = b'abcd01234'
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000557 fmt = '4s'
558 s = struct.Struct(fmt)
Guido van Rossume625fd52007-05-27 09:19:04 +0000559 for cls in (str, str8, buffer, bytes):
560 if verbose:
561 print("test_unpack_from using", cls.__name__)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000562 data = cls(test_string)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000563 vereq(s.unpack_from(data), ('abcd',))
564 vereq(s.unpack_from(data, 2), ('cd01',))
565 vereq(s.unpack_from(data, 4), ('0123',))
Guido van Rossum805365e2007-05-07 22:24:25 +0000566 for i in range(6):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000567 vereq(s.unpack_from(data, i), (data[i:i+4],))
Guido van Rossum805365e2007-05-07 22:24:25 +0000568 for i in range(6, len(test_string) + 1):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000569 simple_err(s.unpack_from, data, i)
570 for cls in (str, buffer):
571 data = cls(test_string)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000572 vereq(struct.unpack_from(fmt, data), ('abcd',))
573 vereq(struct.unpack_from(fmt, data, 2), ('cd01',))
574 vereq(struct.unpack_from(fmt, data, 4), ('0123',))
Guido van Rossum805365e2007-05-07 22:24:25 +0000575 for i in range(6):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000576 vereq(struct.unpack_from(fmt, data, i), (data[i:i+4],))
Guido van Rossum805365e2007-05-07 22:24:25 +0000577 for i in range(6, len(test_string) + 1):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000578 simple_err(struct.unpack_from, fmt, data, i)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000579
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000580def test_pack_into():
Guido van Rossum99c0c222007-07-03 16:28:47 +0000581 test_string = b'Reykjavik rocks, eow!'
582 writable_buf = array.array('b', b' '*100)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000583 fmt = '21s'
584 s = struct.Struct(fmt)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000585
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000586 # Test without offset
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000587 s.pack_into(writable_buf, 0, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000588 from_buf = writable_buf.tostring()[:len(test_string)]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000589 vereq(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000590
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000591 # Test with offset.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000592 s.pack_into(writable_buf, 10, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000593 from_buf = writable_buf.tostring()[:len(test_string)+10]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000594 vereq(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000595
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000596 # Go beyond boundaries.
Guido van Rossum99c0c222007-07-03 16:28:47 +0000597 small_buf = array.array('b', b' '*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000598 assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
599 assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000600
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000601def test_pack_into_fn():
Guido van Rossum99c0c222007-07-03 16:28:47 +0000602 test_string = b'Reykjavik rocks, eow!'
603 writable_buf = array.array('b', b' '*100)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000604 fmt = '21s'
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000605 pack_into = lambda *args: struct.pack_into(fmt, *args)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000606
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000607 # Test without offset.
608 pack_into(writable_buf, 0, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000609 from_buf = writable_buf.tostring()[:len(test_string)]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000610 vereq(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000611
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000612 # Test with offset.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000613 pack_into(writable_buf, 10, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000614 from_buf = writable_buf.tostring()[:len(test_string)+10]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000615 vereq(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000616
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000617 # Go beyond boundaries.
Guido van Rossum99c0c222007-07-03 16:28:47 +0000618 small_buf = array.array('b', b' '*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000619 assertRaises(struct.error, pack_into, small_buf, 0, test_string)
620 assertRaises(struct.error, pack_into, small_buf, 2, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000621
Guido van Rossumd8faa362007-04-27 19:54:29 +0000622def test_unpack_with_buffer():
623 # SF bug 1563759: struct.unpack doens't support buffer protocol objects
Guido van Rossume625fd52007-05-27 09:19:04 +0000624 data1 = array.array('B', b'\x12\x34\x56\x78')
625 data2 = buffer(b'......\x12\x34\x56\x78......', 6, 4)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000626 for data in [data1, data2]:
627 value, = struct.unpack('>I', data)
628 vereq(value, 0x12345678)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000629
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000630# Test methods to pack and unpack from buffers rather than strings.
631test_unpack_from()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000632test_pack_into()
633test_pack_into_fn()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000634test_unpack_with_buffer()
Thomas Woutersb2137042007-02-01 18:02:27 +0000635
636def test_bool():
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000637 for prefix in tuple("<>!=")+('',):
638 false = (), [], [], '', 0
639 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
Guido van Rossumd8faa362007-04-27 19:54:29 +0000640
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000641 falseFormat = prefix + 't' * len(false)
642 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000643 print('trying bool pack/unpack on', false, 'using format', falseFormat)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000644 packedFalse = struct.pack(falseFormat, *false)
645 unpackedFalse = struct.unpack(falseFormat, packedFalse)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000646
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000647 trueFormat = prefix + 't' * len(true)
648 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000649 print('trying bool pack/unpack on', true, 'using format', trueFormat)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000650 packedTrue = struct.pack(trueFormat, *true)
651 unpackedTrue = struct.unpack(trueFormat, packedTrue)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000652
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000653 if len(true) != len(unpackedTrue):
654 raise TestFailed('unpacked true array is not of same size as input')
655 if len(false) != len(unpackedFalse):
656 raise TestFailed('unpacked false array is not of same size as input')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000657
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000658 for t in unpackedFalse:
659 if t is not False:
660 raise TestFailed('%r did not unpack as False' % t)
661 for t in unpackedTrue:
662 if t is not True:
663 raise TestFailed('%r did not unpack as false' % t)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000664
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000665 if prefix and verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000666 print('trying size of bool with format %r' % (prefix+'t'))
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000667 packed = struct.pack(prefix+'t', 1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000668
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000669 if len(packed) != struct.calcsize(prefix+'t'):
670 raise TestFailed('packed length is not equal to calculated size')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000671
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000672 if len(packed) != 1 and prefix:
673 raise TestFailed('encoded bool is not one byte: %r' % packed)
674 elif not prefix and verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000675 print('size of bool in native format is %i' % (len(packed)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000676
Guido van Rossume625fd52007-05-27 09:19:04 +0000677 for c in str8('\x01\x7f\xff\x0f\xf0'):
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000678 if struct.unpack('>t', c)[0] is not True:
679 raise TestFailed('%c did not unpack as True' % c)
Thomas Woutersb2137042007-02-01 18:02:27 +0000680
681test_bool()