blob: 925308d46a58c576e569a8eca7d3730643d6d3c8 [file] [log] [blame]
Tim Peters852eae12006-06-05 20:48:49 +00001from test.test_support import TestFailed, verbose, verify, vereq
Martin Blais2856e5f2006-05-26 12:03:27 +00002import test.test_support
Barry Warsaw07a0eec1996-12-12 23:34:06 +00003import struct
Martin Blais2856e5f2006-05-26 12:03:27 +00004import array
Bob Ippolito2fd39772006-05-29 22:55:48 +00005import warnings
Barry Warsaw07a0eec1996-12-12 23:34:06 +00006
Tim Peters17e17d42001-06-13 22:45:27 +00007import sys
8ISBIGENDIAN = sys.byteorder == "big"
9del sys
10verify((struct.pack('=i', 1)[0] == chr(0)) == ISBIGENDIAN,
11 "bigendian determination appears wrong")
12
Bob Ippolito2fd39772006-05-29 22:55:48 +000013try:
14 import _struct
15except ImportError:
16 PY_STRUCT_RANGE_CHECKING = 0
Bob Ippolito4182a752006-05-30 17:37:54 +000017 PY_STRUCT_OVERFLOW_MASKING = 1
Bob Ippolitoe6c9f982006-08-04 23:59:21 +000018 PY_STRUCT_FLOAT_COERCE = 2
Bob Ippolito2fd39772006-05-29 22:55:48 +000019else:
Bob Ippolitoe6c9f982006-08-04 23:59:21 +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)
Bob Ippolitoe27337b2006-05-26 13:15:44 +000023
Tim Peters17e17d42001-06-13 22:45:27 +000024def string_reverse(s):
Tim Peters852eae12006-06-05 20:48:49 +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)
Bob Ippolito2fd39772006-05-29 22:55:48 +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
Bob Ippolitoe6c9f982006-08-04 23:59:21 +000051def with_warning_restore(func):
52 def _with_warning_restore(*args, **kw):
Brett Cannon2ee41282007-08-14 05:51:06 +000053 with test.test_support.catch_warning():
Brett Cannon6d9520c2006-12-13 23:09:53 +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.
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)
Bob Ippolitoe6c9f982006-08-04 23:59:21 +000063 return func(*args, **kw)
Bob Ippolitoe6c9f982006-08-04 23:59:21 +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" % (
Bob Ippolito2fd39772006-05-29 22:55:48 +000074 func.__name__, args)
Bob Ippolitoe6c9f982006-08-04 23:59:21 +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
Martin v. Löwisaef4c6b2007-01-21 09:33:07 +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
Martin v. Löwisaef4c6b2007-01-21 09:33:07 +0000111t = True
Barry Warsaw07a0eec1996-12-12 23:34:06 +0000112
Guido van Rossum420c11c1997-01-03 00:09:46 +0000113for prefix in ('', '@', '<', '>', '=', '!'):
Martin v. Löwisaef4c6b2007-01-21 09:33:07 +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
Martin v. Löwisaef4c6b2007-01-21 09:33:07 +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
Martin v. Löwisaef4c6b2007-01-21 09:33:07 +0000121 int(100 * fp) != int(100 * f) or int(100 * dp) != int(100 * d) or
Tim Petersf733abb2007-01-30 03:03:46 +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)" % (
Martin v. Löwisaef4c6b2007-01-21 09:33:07 +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),
151 ('I', 70000000L, '\004,\035\200', '\200\035,\004', 0),
152 ('I', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
153 ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
154 ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
155 ('L', 70000000L, '\004,\035\200', '\200\035,\004', 0),
156 ('L', 0x100000000L-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),
Tim Petersf733abb2007-01-30 03:03:46 +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),
213 ('q', 1L, '\x00' * (bytes-1) + '\x01'),
214 ('Q', (1L << (8*bytes))-1, '\xff' * bytes),
215 ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))):
216 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
253 self.unsigned_max = 2L**self.bitsize - 1
254 self.signed_min = -(2L**(self.bitsize-1))
255 self.signed_max = 2L**(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.
267 expected = long(x)
268 if x < 0:
269 expected += 1L << self.bitsize
270 assert expected > 0
271 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
272 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.
Bob Ippolitoe27337b2006-05-26 13:15:44 +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:
Bob Ippolito2fd39772006-05-29 22:55:48 +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
326 expected = long(x)
327 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
328 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.
Bob Ippolitoaa70a172006-05-26 20:25:23 +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:
Bob Ippolito2fd39772006-05-29 22:55:48 +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):
382 values.append(1L << exp)
383
384 # Add some random values.
385 for i in range(self.bitsize):
386 val = 0L
387 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()
Bob Ippolitoeb621272006-05-24 15:32:06 +0000488
Bob Ippolitoe6c9f982006-08-04 23:59:21 +0000489###########################################################################
490# SF bug 1229380. No struct.pack exception for some out of range integers
491
Bob Ippolitoeb621272006-05-24 15:32:06 +0000492def test_1229380():
Bob Ippolitoe27337b2006-05-26 13:15:44 +0000493 import sys
Bob Ippolitoeb621272006-05-24 15:32:06 +0000494 for endian in ('', '>', '<'):
495 for cls in (int, long):
496 for fmt in ('B', 'H', 'I', 'L'):
Bob Ippolito2fd39772006-05-29 22:55:48 +0000497 deprecated_err(struct.pack, endian + fmt, cls(-1))
Bob Ippolitoeb621272006-05-24 15:32:06 +0000498
Bob Ippolito2fd39772006-05-29 22:55:48 +0000499 deprecated_err(struct.pack, endian + 'B', cls(300))
500 deprecated_err(struct.pack, endian + 'H', cls(70000))
Bob Ippolitoeb621272006-05-24 15:32:06 +0000501
Bob Ippolito2fd39772006-05-29 22:55:48 +0000502 deprecated_err(struct.pack, endian + 'I', sys.maxint * 4L)
503 deprecated_err(struct.pack, endian + 'L', sys.maxint * 4L)
Bob Ippolitoeb621272006-05-24 15:32:06 +0000504
Bob Ippolitoe27337b2006-05-26 13:15:44 +0000505if PY_STRUCT_RANGE_CHECKING:
Bob Ippolitoeb621272006-05-24 15:32:06 +0000506 test_1229380()
Martin Blais2856e5f2006-05-26 12:03:27 +0000507
Bob Ippolitoe6c9f982006-08-04 23:59:21 +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()
Martin Blais2856e5f2006-05-26 12:03:27 +0000539
Martin Blais7f7386c2006-06-02 13:03:43 +0000540###########################################################################
541# Packing and unpacking to/from buffers.
Martin Blais2856e5f2006-05-26 12:03:27 +0000542
Martin Blais7f7386c2006-06-02 13:03:43 +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:
Tim Peters852eae12006-06-05 20:48:49 +0000550 raise TestFailed("%s not raised." % excClass)
Martin Blais2856e5f2006-05-26 12:03:27 +0000551
Martin Blais7f7386c2006-06-02 13:03:43 +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)
Tim Peters852eae12006-06-05 20:48:49 +0000558 vereq(s.unpack_from(data), ('abcd',))
559 vereq(s.unpack_from(data, 2), ('cd01',))
560 vereq(s.unpack_from(data, 4), ('0123',))
Martin Blais7f7386c2006-06-02 13:03:43 +0000561 for i in xrange(6):
Tim Peters852eae12006-06-05 20:48:49 +0000562 vereq(s.unpack_from(data, i), (data[i:i+4],))
Martin Blais7f7386c2006-06-02 13:03:43 +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)
Tim Peters852eae12006-06-05 20:48:49 +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',))
Martin Blais7f7386c2006-06-02 13:03:43 +0000570 for i in xrange(6):
Tim Peters852eae12006-06-05 20:48:49 +0000571 vereq(struct.unpack_from(fmt, data, i), (data[i:i+4],))
Martin Blais7f7386c2006-06-02 13:03:43 +0000572 for i in xrange(6, len(test_string) + 1):
573 simple_err(struct.unpack_from, fmt, data, i)
Martin Blais2856e5f2006-05-26 12:03:27 +0000574
Martin Blaisaf2ae722006-06-04 13:49:49 +0000575def test_pack_into():
Martin Blais7f7386c2006-06-02 13:03:43 +0000576 test_string = 'Reykjavik rocks, eow!'
577 writable_buf = array.array('c', ' '*100)
578 fmt = '21s'
579 s = struct.Struct(fmt)
Martin Blais2856e5f2006-05-26 12:03:27 +0000580
Martin Blais7f7386c2006-06-02 13:03:43 +0000581 # Test without offset
Martin Blaisaf2ae722006-06-04 13:49:49 +0000582 s.pack_into(writable_buf, 0, test_string)
Martin Blais7f7386c2006-06-02 13:03:43 +0000583 from_buf = writable_buf.tostring()[:len(test_string)]
Tim Peters852eae12006-06-05 20:48:49 +0000584 vereq(from_buf, test_string)
Martin Blais2856e5f2006-05-26 12:03:27 +0000585
Martin Blais7f7386c2006-06-02 13:03:43 +0000586 # Test with offset.
Martin Blaisaf2ae722006-06-04 13:49:49 +0000587 s.pack_into(writable_buf, 10, test_string)
Martin Blais7f7386c2006-06-02 13:03:43 +0000588 from_buf = writable_buf.tostring()[:len(test_string)+10]
Tim Peters852eae12006-06-05 20:48:49 +0000589 vereq(from_buf, test_string[:10] + test_string)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000590
Martin Blais7f7386c2006-06-02 13:03:43 +0000591 # Go beyond boundaries.
592 small_buf = array.array('c', ' '*10)
Martin Blaisaf2ae722006-06-04 13:49:49 +0000593 assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
594 assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000595
Martin Blaisaf2ae722006-06-04 13:49:49 +0000596def test_pack_into_fn():
Martin Blais7f7386c2006-06-02 13:03:43 +0000597 test_string = 'Reykjavik rocks, eow!'
598 writable_buf = array.array('c', ' '*100)
599 fmt = '21s'
Martin Blaisaf2ae722006-06-04 13:49:49 +0000600 pack_into = lambda *args: struct.pack_into(fmt, *args)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000601
Tim Peters852eae12006-06-05 20:48:49 +0000602 # Test without offset.
Martin Blaisaf2ae722006-06-04 13:49:49 +0000603 pack_into(writable_buf, 0, test_string)
Martin Blais7f7386c2006-06-02 13:03:43 +0000604 from_buf = writable_buf.tostring()[:len(test_string)]
Tim Peters852eae12006-06-05 20:48:49 +0000605 vereq(from_buf, test_string)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000606
Martin Blais7f7386c2006-06-02 13:03:43 +0000607 # Test with offset.
Martin Blaisaf2ae722006-06-04 13:49:49 +0000608 pack_into(writable_buf, 10, test_string)
Martin Blais7f7386c2006-06-02 13:03:43 +0000609 from_buf = writable_buf.tostring()[:len(test_string)+10]
Tim Peters852eae12006-06-05 20:48:49 +0000610 vereq(from_buf, test_string[:10] + test_string)
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000611
Martin Blais7f7386c2006-06-02 13:03:43 +0000612 # Go beyond boundaries.
613 small_buf = array.array('c', ' '*10)
Martin Blaisaf2ae722006-06-04 13:49:49 +0000614 assertRaises(struct.error, pack_into, small_buf, 0, test_string)
615 assertRaises(struct.error, pack_into, small_buf, 2, test_string)
Tim Petersfe98f962006-05-26 12:26:21 +0000616
Raymond Hettinger7a3d41f2007-04-05 18:00:03 +0000617def test_unpack_with_buffer():
618 # SF bug 1563759: struct.unpack doens't support buffer protocol objects
619 data1 = array.array('B', '\x12\x34\x56\x78')
620 data2 = buffer('......\x12\x34\x56\x78......', 6, 4)
621 for data in [data1, data2]:
622 value, = struct.unpack('>I', data)
623 vereq(value, 0x12345678)
Tim Petersc65a13f2006-06-04 01:22:53 +0000624
Martin Blais7f7386c2006-06-02 13:03:43 +0000625# Test methods to pack and unpack from buffers rather than strings.
626test_unpack_from()
Martin Blaisaf2ae722006-06-04 13:49:49 +0000627test_pack_into()
628test_pack_into_fn()
Raymond Hettinger7a3d41f2007-04-05 18:00:03 +0000629test_unpack_with_buffer()
Martin v. Löwisaef4c6b2007-01-21 09:33:07 +0000630
631def test_bool():
Tim Petersf733abb2007-01-30 03:03:46 +0000632 for prefix in tuple("<>!=")+('',):
633 false = (), [], [], '', 0
634 true = [1], 'test', 5, -1, 0xffffffffL+1, 0xffffffff/2
635
636 falseFormat = prefix + 't' * len(false)
637 if verbose:
638 print 'trying bool pack/unpack on', false, 'using format', falseFormat
639 packedFalse = struct.pack(falseFormat, *false)
640 unpackedFalse = struct.unpack(falseFormat, packedFalse)
641
642 trueFormat = prefix + 't' * len(true)
643 if verbose:
644 print 'trying bool pack/unpack on', true, 'using format', trueFormat
645 packedTrue = struct.pack(trueFormat, *true)
646 unpackedTrue = struct.unpack(trueFormat, packedTrue)
647
648 if len(true) != len(unpackedTrue):
649 raise TestFailed('unpacked true array is not of same size as input')
650 if len(false) != len(unpackedFalse):
651 raise TestFailed('unpacked false array is not of same size as input')
652
653 for t in unpackedFalse:
654 if t is not False:
655 raise TestFailed('%r did not unpack as False' % t)
656 for t in unpackedTrue:
657 if t is not True:
658 raise TestFailed('%r did not unpack as false' % t)
659
660 if prefix and verbose:
661 print 'trying size of bool with format %r' % (prefix+'t')
662 packed = struct.pack(prefix+'t', 1)
663
664 if len(packed) != struct.calcsize(prefix+'t'):
665 raise TestFailed('packed length is not equal to calculated size')
666
667 if len(packed) != 1 and prefix:
668 raise TestFailed('encoded bool is not one byte: %r' % packed)
669 elif not prefix and verbose:
670 print 'size of bool in native format is %i' % (len(packed))
671
672 for c in '\x01\x7f\xff\x0f\xf0':
673 if struct.unpack('>t', c)[0] is not True:
674 raise TestFailed('%c did not unpack as True' % c)
Martin v. Löwisaef4c6b2007-01-21 09:33:07 +0000675
676test_bool()