blob: 8b241a6eec185d6530879ad5875d98f37c3500ee [file] [log] [blame]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001from test.test_support import TestFailed, verbose, verify, vereq
Thomas Wouters477c8d52006-05-27 19:21:47 +00002import test.test_support
Barry Warsaw07a0eec1996-12-12 23:34:06 +00003import struct
Thomas Wouters477c8d52006-05-27 19:21:47 +00004import array
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00005import warnings
Barry Warsaw07a0eec1996-12-12 23:34:06 +00006
Tim Peters17e17d42001-06-13 22:45:27 +00007import sys
8ISBIGENDIAN = sys.byteorder == "big"
9del sys
10verify((struct.pack('=i', 1)[0] == chr(0)) == ISBIGENDIAN,
11 "bigendian determination appears wrong")
12
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000013try:
14 import _struct
15except ImportError:
16 PY_STRUCT_RANGE_CHECKING = 0
17 PY_STRUCT_OVERFLOW_MASKING = 1
Thomas Wouters0e3f5912006-08-11 14:57:12 +000018 PY_STRUCT_FLOAT_COERCE = 2
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000019else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000020 PY_STRUCT_RANGE_CHECKING = getattr(_struct, '_PY_STRUCT_RANGE_CHECKING', 0)
21 PY_STRUCT_OVERFLOW_MASKING = getattr(_struct, '_PY_STRUCT_OVERFLOW_MASKING', 0)
22 PY_STRUCT_FLOAT_COERCE = getattr(_struct, '_PY_STRUCT_FLOAT_COERCE', 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +000023
Tim Peters17e17d42001-06-13 22:45:27 +000024def string_reverse(s):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000025 return "".join(reversed(s))
Tim Peters17e17d42001-06-13 22:45:27 +000026
27def bigendian_to_native(value):
28 if ISBIGENDIAN:
29 return value
30 else:
31 return string_reverse(value)
32
Barry Warsaw07a0eec1996-12-12 23:34:06 +000033def simple_err(func, *args):
34 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000035 func(*args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000036 except struct.error:
Guido van Rossum41360a41998-03-26 19:42:58 +000037 pass
Barry Warsaw07a0eec1996-12-12 23:34:06 +000038 else:
Guido van Rossum41360a41998-03-26 19:42:58 +000039 raise TestFailed, "%s%s did not raise struct.error" % (
40 func.__name__, args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000041
Tim Peters7a3bfc32001-06-12 01:22:22 +000042def any_err(func, *args):
43 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000044 func(*args)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000045 except (struct.error, TypeError):
Tim Peters7a3bfc32001-06-12 01:22:22 +000046 pass
47 else:
48 raise TestFailed, "%s%s did not raise error" % (
49 func.__name__, args)
Tim Peters7a3bfc32001-06-12 01:22:22 +000050
Thomas Wouters0e3f5912006-08-11 14:57:12 +000051def with_warning_restore(func):
52 def _with_warning_restore(*args, **kw):
Thomas Wouters902d6eb2007-01-09 23:18:33 +000053 with test.test_support.guard_warnings_filter():
54 # Grrr, we need this function to warn every time. Without removing
55 # the warningregistry, running test_tarfile then test_struct would fail
56 # on 64-bit platforms.
57 globals = func.func_globals
58 if '__warningregistry__' in globals:
59 del globals['__warningregistry__']
60 warnings.filterwarnings("error", r"""^struct.*""", DeprecationWarning)
61 warnings.filterwarnings("error", r""".*format requires.*""",
62 DeprecationWarning)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000063 return func(*args, **kw)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000064 return _with_warning_restore
65
66def deprecated_err(func, *args):
67 try:
68 func(*args)
69 except (struct.error, TypeError):
70 pass
71 except DeprecationWarning:
72 if not PY_STRUCT_OVERFLOW_MASKING:
73 raise TestFailed, "%s%s expected to raise struct.error" % (
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000074 func.__name__, args)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000075 else:
76 raise TestFailed, "%s%s did not raise error" % (
77 func.__name__, args)
78deprecated_err = with_warning_restore(deprecated_err)
79
Tim Peters17e17d42001-06-13 22:45:27 +000080
Tim Peters7b9542a2001-06-10 23:40:19 +000081simple_err(struct.calcsize, 'Z')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000082
83sz = struct.calcsize('i')
Fred Drake132dce22000-12-12 23:11:42 +000084if sz * 3 != struct.calcsize('iii'):
Guido van Rossum2a378501996-12-31 17:25:47 +000085 raise TestFailed, 'inconsistent sizes'
Barry Warsaw07a0eec1996-12-12 23:34:06 +000086
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:
117 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
122 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 Woutersb2137042007-02-01 18:02:27 +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:
171 if verbose:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000172 print "%r %r %r %r" % (fmt, arg, big, lil)
Guido van Rossum2a378501996-12-31 17:25:47 +0000173 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
Tim Peters17e17d42001-06-13 22:45:27 +0000174 ('='+fmt, ISBIGENDIAN and big or lil)]:
Guido van Rossum41360a41998-03-26 19:42:58 +0000175 res = struct.pack(xfmt, arg)
176 if res != exp:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000177 raise TestFailed, "pack(%r, %r) -> %r # expected %r" % (
178 fmt, arg, res, exp)
Guido van Rossum41360a41998-03-26 19:42:58 +0000179 n = struct.calcsize(xfmt)
180 if n != len(res):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000181 raise TestFailed, "calcsize(%r) -> %d # expected %d" % (
182 xfmt, n, len(res))
Guido van Rossum41360a41998-03-26 19:42:58 +0000183 rev = struct.unpack(xfmt, res)[0]
184 if rev != arg and not asy:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000185 raise TestFailed, "unpack(%r, %r) -> (%r,) # expected (%r,)" % (
186 fmt, res, rev, arg)
Tim Peters7b9542a2001-06-10 23:40:19 +0000187
Tim Peters7a3bfc32001-06-12 01:22:22 +0000188###########################################################################
Tim Peters17e17d42001-06-13 22:45:27 +0000189# Simple native q/Q tests.
Tim Peters7b9542a2001-06-10 23:40:19 +0000190
191has_native_qQ = 1
192try:
193 struct.pack("q", 5)
194except struct.error:
195 has_native_qQ = 0
196
197if verbose:
198 print "Platform has native q/Q?", has_native_qQ and "Yes." or "No."
199
Tim Peters7a3bfc32001-06-12 01:22:22 +0000200any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless
Tim Peters7b9542a2001-06-10 23:40:19 +0000201simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless
202simple_err(struct.pack, "Q", "a") # ditto, but 'Q'
203
Tim Peters7a3bfc32001-06-12 01:22:22 +0000204def test_native_qQ():
Tim Peters7b9542a2001-06-10 23:40:19 +0000205 bytes = struct.calcsize('q')
206 # The expected values here are in big-endian format, primarily because
207 # I'm on a little-endian machine and so this is the clearest way (for
208 # me) to force the code to get exercised.
209 for format, input, expected in (
210 ('q', -1, '\xff' * bytes),
211 ('q', 0, '\x00' * bytes),
212 ('Q', 0, '\x00' * bytes),
Guido van Rossume2a383d2007-01-15 16:59:06 +0000213 ('q', 1, '\x00' * (bytes-1) + '\x01'),
214 ('Q', (1 << (8*bytes))-1, '\xff' * bytes),
215 ('q', (1 << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))):
Tim Peters7b9542a2001-06-10 23:40:19 +0000216 got = struct.pack(format, input)
Tim Petersc533edc2001-06-10 23:52:59 +0000217 native_expected = bigendian_to_native(expected)
218 verify(got == native_expected,
Tim Peters7b9542a2001-06-10 23:40:19 +0000219 "%r-pack of %r gave %r, not %r" %
Tim Petersc533edc2001-06-10 23:52:59 +0000220 (format, input, got, native_expected))
Tim Peters7b9542a2001-06-10 23:40:19 +0000221 retrieved = struct.unpack(format, got)[0]
222 verify(retrieved == input,
223 "%r-unpack of %r gave %r, not %r" %
224 (format, got, retrieved, input))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000225
226if has_native_qQ:
227 test_native_qQ()
228
Tim Peters17e17d42001-06-13 22:45:27 +0000229###########################################################################
230# Standard integer tests (bBhHiIlLqQ).
Tim Peters7a3bfc32001-06-12 01:22:22 +0000231
232import binascii
Tim Peters7a3bfc32001-06-12 01:22:22 +0000233
Tim Peters17e17d42001-06-13 22:45:27 +0000234class IntTester:
Tim Peters7a3bfc32001-06-12 01:22:22 +0000235
Tim Peters17e17d42001-06-13 22:45:27 +0000236 # XXX Most std integer modes fail to test for out-of-range.
Tim Peters3eec38a2001-06-18 22:27:39 +0000237 # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
238 # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
239 # reported by Mark Favas).
240 BUGGY_RANGE_CHECK = "bBhHiIlL"
Tim Peters7a3bfc32001-06-12 01:22:22 +0000241
Tim Peters17e17d42001-06-13 22:45:27 +0000242 def __init__(self, formatpair, bytesize):
243 assert len(formatpair) == 2
244 self.formatpair = formatpair
245 for direction in "<>!=":
246 for code in formatpair:
247 format = direction + code
248 verify(struct.calcsize(format) == bytesize)
249 self.bytesize = bytesize
250 self.bitsize = bytesize * 8
251 self.signed_code, self.unsigned_code = formatpair
252 self.unsigned_min = 0
Guido van Rossume2a383d2007-01-15 16:59:06 +0000253 self.unsigned_max = 2**self.bitsize - 1
254 self.signed_min = -(2**(self.bitsize-1))
255 self.signed_max = 2**(self.bitsize-1) - 1
Tim Peters7a3bfc32001-06-12 01:22:22 +0000256
Tim Peters17e17d42001-06-13 22:45:27 +0000257 def test_one(self, x, pack=struct.pack,
258 unpack=struct.unpack,
259 unhexlify=binascii.unhexlify):
260 if verbose:
261 print "trying std", self.formatpair, "on", x, "==", hex(x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000262
Tim Peters17e17d42001-06-13 22:45:27 +0000263 # Try signed.
264 code = self.signed_code
265 if self.signed_min <= x <= self.signed_max:
266 # Try big-endian.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000267 expected = int(x)
Tim Peters17e17d42001-06-13 22:45:27 +0000268 if x < 0:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000269 expected += 1 << self.bitsize
Tim Peters17e17d42001-06-13 22:45:27 +0000270 assert expected > 0
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000271 expected = hex(expected)[2:] # chop "0x"
Tim Peters17e17d42001-06-13 22:45:27 +0000272 if len(expected) & 1:
273 expected = "0" + expected
274 expected = unhexlify(expected)
275 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000276
Tim Peters17e17d42001-06-13 22:45:27 +0000277 # Pack work?
278 format = ">" + code
279 got = pack(format, x)
280 verify(got == expected,
281 "'%s'-pack of %r gave %r, not %r" %
282 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000283
Tim Peters17e17d42001-06-13 22:45:27 +0000284 # Unpack work?
285 retrieved = unpack(format, got)[0]
286 verify(x == retrieved,
287 "'%s'-unpack of %r gave %r, not %r" %
288 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000289
Tim Peters17e17d42001-06-13 22:45:27 +0000290 # Adding any byte should cause a "too big" error.
291 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000292
Tim Peters17e17d42001-06-13 22:45:27 +0000293 # Try little-endian.
294 format = "<" + code
295 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000296
Tim Peters17e17d42001-06-13 22:45:27 +0000297 # Pack work?
298 got = pack(format, x)
299 verify(got == expected,
300 "'%s'-pack of %r gave %r, not %r" %
301 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000302
Tim Peters17e17d42001-06-13 22:45:27 +0000303 # Unpack work?
304 retrieved = unpack(format, got)[0]
305 verify(x == retrieved,
306 "'%s'-unpack of %r gave %r, not %r" %
307 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000308
Tim Peters17e17d42001-06-13 22:45:27 +0000309 # Adding any byte should cause a "too big" error.
310 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000311
Tim Peters17e17d42001-06-13 22:45:27 +0000312 else:
313 # x is out of range -- verify pack realizes that.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000314 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000315 if verbose:
316 print "Skipping buggy range check for code", code
317 else:
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000318 deprecated_err(pack, ">" + code, x)
319 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000320
Tim Peters17e17d42001-06-13 22:45:27 +0000321 # Much the same for unsigned.
322 code = self.unsigned_code
323 if self.unsigned_min <= x <= self.unsigned_max:
324 # Try big-endian.
325 format = ">" + code
Guido van Rossume2a383d2007-01-15 16:59:06 +0000326 expected = int(x)
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000327 expected = hex(expected)[2:] # chop "0x"
Tim Peters17e17d42001-06-13 22:45:27 +0000328 if len(expected) & 1:
329 expected = "0" + expected
330 expected = unhexlify(expected)
331 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000332
Tim Peters17e17d42001-06-13 22:45:27 +0000333 # Pack work?
334 got = pack(format, x)
335 verify(got == expected,
336 "'%s'-pack of %r gave %r, not %r" %
337 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000338
Tim Peters17e17d42001-06-13 22:45:27 +0000339 # Unpack work?
340 retrieved = unpack(format, got)[0]
341 verify(x == retrieved,
342 "'%s'-unpack of %r gave %r, not %r" %
343 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000344
Tim Peters17e17d42001-06-13 22:45:27 +0000345 # Adding any byte should cause a "too big" error.
346 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000347
Tim Peters17e17d42001-06-13 22:45:27 +0000348 # Try little-endian.
349 format = "<" + code
350 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000351
Tim Peters17e17d42001-06-13 22:45:27 +0000352 # Pack work?
353 got = pack(format, x)
354 verify(got == expected,
355 "'%s'-pack of %r gave %r, not %r" %
356 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000357
Tim Peters17e17d42001-06-13 22:45:27 +0000358 # Unpack work?
359 retrieved = unpack(format, got)[0]
360 verify(x == retrieved,
361 "'%s'-unpack of %r gave %r, not %r" %
362 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000363
Tim Peters17e17d42001-06-13 22:45:27 +0000364 # Adding any byte should cause a "too big" error.
365 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000366
Tim Peters17e17d42001-06-13 22:45:27 +0000367 else:
368 # x is out of range -- verify pack realizes that.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000369 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000370 if verbose:
371 print "Skipping buggy range check for code", code
372 else:
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000373 deprecated_err(pack, ">" + code, x)
374 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000375
Tim Peters17e17d42001-06-13 22:45:27 +0000376 def run(self):
377 from random import randrange
378
379 # Create all interesting powers of 2.
380 values = []
381 for exp in range(self.bitsize + 3):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000382 values.append(1 << exp)
Tim Peters17e17d42001-06-13 22:45:27 +0000383
384 # Add some random values.
385 for i in range(self.bitsize):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000386 val = 0
Tim Peters17e17d42001-06-13 22:45:27 +0000387 for j in range(self.bytesize):
388 val = (val << 8) | randrange(256)
389 values.append(val)
390
391 # Try all those, and their negations, and +-1 from them. Note
392 # that this tests all power-of-2 boundaries in range, and a few out
393 # of range, plus +-(2**n +- 1).
394 for base in values:
395 for val in -base, base:
396 for incr in -1, 0, 1:
397 x = val + incr
398 try:
399 x = int(x)
400 except OverflowError:
401 pass
402 self.test_one(x)
403
404 # Some error cases.
405 for direction in "<>":
406 for code in self.formatpair:
407 for badobject in "a string", 3+42j, randrange:
408 any_err(struct.pack, direction + code, badobject)
409
410for args in [("bB", 1),
411 ("hH", 2),
412 ("iI", 4),
413 ("lL", 4),
414 ("qQ", 8)]:
415 t = IntTester(*args)
416 t.run()
Tim Peters0891ac02001-09-15 02:35:15 +0000417
418
419###########################################################################
420# The p ("Pascal string") code.
421
422def test_p_code():
423 for code, input, expected, expectedback in [
424 ('p','abc', '\x00', ''),
425 ('1p', 'abc', '\x00', ''),
426 ('2p', 'abc', '\x01a', 'a'),
427 ('3p', 'abc', '\x02ab', 'ab'),
428 ('4p', 'abc', '\x03abc', 'abc'),
429 ('5p', 'abc', '\x03abc\x00', 'abc'),
430 ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
431 ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
432 got = struct.pack(code, input)
433 if got != expected:
434 raise TestFailed("pack(%r, %r) == %r but expected %r" %
435 (code, input, got, expected))
436 (got,) = struct.unpack(code, got)
437 if got != expectedback:
438 raise TestFailed("unpack(%r, %r) == %r but expected %r" %
439 (code, input, got, expectedback))
440
441test_p_code()
Tim Petersd50ade62003-03-20 18:32:13 +0000442
443
444###########################################################################
445# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
446# from the low-order discarded bits could propagate into the exponent
447# field, causing the result to be wrong by a factor of 2.
448
449def test_705836():
450 import math
451
452 for base in range(1, 33):
453 # smaller <- largest representable float less than base.
454 delta = 0.5
455 while base - delta / 2.0 != base:
456 delta /= 2.0
457 smaller = base - delta
458 # Packing this rounds away a solid string of trailing 1 bits.
459 packed = struct.pack("<f", smaller)
460 unpacked = struct.unpack("<f", packed)[0]
461 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
462 # 16, respectively.
463 verify(base == unpacked)
464 bigpacked = struct.pack(">f", smaller)
465 verify(bigpacked == string_reverse(packed),
466 ">f pack should be byte-reversal of <f pack")
467 unpacked = struct.unpack(">f", bigpacked)[0]
468 verify(base == unpacked)
469
470 # Largest finite IEEE single.
471 big = (1 << 24) - 1
472 big = math.ldexp(big, 127 - 23)
473 packed = struct.pack(">f", big)
474 unpacked = struct.unpack(">f", packed)[0]
475 verify(big == unpacked)
476
477 # The same, but tack on a 1 bit so it rounds up to infinity.
478 big = (1 << 25) - 1
479 big = math.ldexp(big, 127 - 24)
480 try:
481 packed = struct.pack(">f", big)
482 except OverflowError:
483 pass
484 else:
485 TestFailed("expected OverflowError")
486
487test_705836()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000488
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000489###########################################################################
490# SF bug 1229380. No struct.pack exception for some out of range integers
491
Thomas Wouters477c8d52006-05-27 19:21:47 +0000492def test_1229380():
493 import sys
494 for endian in ('', '>', '<'):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000495 for cls in (int, int):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000496 for fmt in ('B', 'H', 'I', 'L'):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000497 deprecated_err(struct.pack, endian + fmt, cls(-1))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000498
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000499 deprecated_err(struct.pack, endian + 'B', cls(300))
500 deprecated_err(struct.pack, endian + 'H', cls(70000))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000501
Guido van Rossume2a383d2007-01-15 16:59:06 +0000502 deprecated_err(struct.pack, endian + 'I', sys.maxint * 4)
503 deprecated_err(struct.pack, endian + 'L', sys.maxint * 4)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000504
505if PY_STRUCT_RANGE_CHECKING:
506 test_1229380()
507
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000508###########################################################################
509# SF bug 1530559. struct.pack raises TypeError where it used to convert.
510
511def check_float_coerce(format, number):
512 if PY_STRUCT_FLOAT_COERCE == 2:
513 # Test for pre-2.5 struct module
514 packed = struct.pack(format, number)
515 floored = struct.unpack(format, packed)[0]
516 if floored != int(number):
517 raise TestFailed("did not correcly coerce float to int")
518 return
519 try:
520 func(*args)
521 except (struct.error, TypeError):
522 if PY_STRUCT_FLOAT_COERCE:
523 raise TestFailed("expected DeprecationWarning for float coerce")
524 except DeprecationWarning:
525 if not PY_STRUCT_FLOAT_COERCE:
526 raise TestFailed("expected to raise struct.error for float coerce")
527 else:
528 raise TestFailed("did not raise error for float coerce")
529
530check_float_coerce = with_warning_restore(deprecated_err)
531
532def test_1530559():
533 for endian in ('', '>', '<'):
534 for fmt in ('B', 'H', 'I', 'L', 'b', 'h', 'i', 'l'):
535 check_float_coerce(endian + fmt, 1.0)
536 check_float_coerce(endian + fmt, 1.5)
537
538test_1530559()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000539
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000540###########################################################################
541# Packing and unpacking to/from buffers.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000542
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000543# Copied and modified from unittest.
544def assertRaises(excClass, callableObj, *args, **kwargs):
545 try:
546 callableObj(*args, **kwargs)
547 except excClass:
548 return
549 else:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000550 raise TestFailed("%s not raised." % excClass)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000551
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000552def test_unpack_from():
553 test_string = 'abcd01234'
554 fmt = '4s'
555 s = struct.Struct(fmt)
556 for cls in (str, buffer):
557 data = cls(test_string)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000558 vereq(s.unpack_from(data), ('abcd',))
559 vereq(s.unpack_from(data, 2), ('cd01',))
560 vereq(s.unpack_from(data, 4), ('0123',))
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000561 for i in xrange(6):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000562 vereq(s.unpack_from(data, i), (data[i:i+4],))
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000563 for i in xrange(6, len(test_string) + 1):
564 simple_err(s.unpack_from, data, i)
565 for cls in (str, buffer):
566 data = cls(test_string)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000567 vereq(struct.unpack_from(fmt, data), ('abcd',))
568 vereq(struct.unpack_from(fmt, data, 2), ('cd01',))
569 vereq(struct.unpack_from(fmt, data, 4), ('0123',))
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000570 for i in xrange(6):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000571 vereq(struct.unpack_from(fmt, data, i), (data[i:i+4],))
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000572 for i in xrange(6, len(test_string) + 1):
573 simple_err(struct.unpack_from, fmt, data, i)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000574
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000575def test_pack_into():
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000576 test_string = 'Reykjavik rocks, eow!'
577 writable_buf = array.array('c', ' '*100)
578 fmt = '21s'
579 s = struct.Struct(fmt)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000580
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000581 # Test without offset
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000582 s.pack_into(writable_buf, 0, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000583 from_buf = writable_buf.tostring()[:len(test_string)]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000584 vereq(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000585
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000586 # Test with offset.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000587 s.pack_into(writable_buf, 10, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000588 from_buf = writable_buf.tostring()[:len(test_string)+10]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000589 vereq(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000590
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000591 # Go beyond boundaries.
592 small_buf = array.array('c', ' '*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000593 assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
594 assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000595
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000596def test_pack_into_fn():
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000597 test_string = 'Reykjavik rocks, eow!'
598 writable_buf = array.array('c', ' '*100)
599 fmt = '21s'
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000600 pack_into = lambda *args: struct.pack_into(fmt, *args)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000601
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000602 # Test without offset.
603 pack_into(writable_buf, 0, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000604 from_buf = writable_buf.tostring()[:len(test_string)]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000605 vereq(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000606
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000607 # Test with offset.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000608 pack_into(writable_buf, 10, test_string)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000609 from_buf = writable_buf.tostring()[:len(test_string)+10]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000610 vereq(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000611
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000612 # Go beyond boundaries.
613 small_buf = array.array('c', ' '*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000614 assertRaises(struct.error, pack_into, small_buf, 0, test_string)
615 assertRaises(struct.error, pack_into, small_buf, 2, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000616
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000617
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000618# Test methods to pack and unpack from buffers rather than strings.
619test_unpack_from()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000620test_pack_into()
621test_pack_into_fn()
Thomas Woutersb2137042007-02-01 18:02:27 +0000622
623def test_bool():
624 for prefix in tuple("<>!=")+('',):
625 false = (), [], [], '', 0
626 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
627
628 falseFormat = prefix + 't' * len(false)
629 if verbose:
630 print 'trying bool pack/unpack on', false, 'using format', falseFormat
631 packedFalse = struct.pack(falseFormat, *false)
632 unpackedFalse = struct.unpack(falseFormat, packedFalse)
633
634 trueFormat = prefix + 't' * len(true)
635 if verbose:
636 print 'trying bool pack/unpack on', true, 'using format', trueFormat
637 packedTrue = struct.pack(trueFormat, *true)
638 unpackedTrue = struct.unpack(trueFormat, packedTrue)
639
640 if len(true) != len(unpackedTrue):
641 raise TestFailed('unpacked true array is not of same size as input')
642 if len(false) != len(unpackedFalse):
643 raise TestFailed('unpacked false array is not of same size as input')
644
645 for t in unpackedFalse:
646 if t is not False:
647 raise TestFailed('%r did not unpack as False' % t)
648 for t in unpackedTrue:
649 if t is not True:
650 raise TestFailed('%r did not unpack as false' % t)
651
652 if prefix and verbose:
653 print 'trying size of bool with format %r' % (prefix+'t')
654 packed = struct.pack(prefix+'t', 1)
655
656 if len(packed) != struct.calcsize(prefix+'t'):
657 raise TestFailed('packed length is not equal to calculated size')
658
659 if len(packed) != 1 and prefix:
660 raise TestFailed('encoded bool is not one byte: %r' % packed)
661 elif not prefix and verbose:
662 print 'size of bool in native format is %i' % (len(packed))
663
664 for c in '\x01\x7f\xff\x0f\xf0':
665 if struct.unpack('>t', c)[0] is not True:
666 raise TestFailed('%c did not unpack as True' % c)
667
668test_bool()