blob: 701f7fd1e96ed58ef8435f00d1a98e7648da68f2 [file] [log] [blame]
Barry Warsaw04f357c2002-07-23 19:04:11 +00001from test.test_support import TestFailed, verbose, verify
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
5import unittest
Bob Ippolito2fd39772006-05-29 22:55:48 +00006import warnings
Barry Warsaw07a0eec1996-12-12 23:34:06 +00007
Tim Peters17e17d42001-06-13 22:45:27 +00008import sys
9ISBIGENDIAN = sys.byteorder == "big"
10del sys
11verify((struct.pack('=i', 1)[0] == chr(0)) == ISBIGENDIAN,
12 "bigendian determination appears wrong")
13
Bob Ippolito2fd39772006-05-29 22:55:48 +000014try:
15 import _struct
16except ImportError:
17 PY_STRUCT_RANGE_CHECKING = 0
18 PY_STRUCT_WRAPPING = 1
19else:
20 PY_STRUCT_RANGE_CHECKING = getattr(_struct, '_PY_STRUCT_RANGE_CHECKING', 0)
21 PY_STRUCT_WRAPPING = getattr(_struct, '_PY_STRUCT_WRAPPING', 0)
Bob Ippolitoe27337b2006-05-26 13:15:44 +000022
Tim Peters17e17d42001-06-13 22:45:27 +000023def string_reverse(s):
24 chars = list(s)
25 chars.reverse()
26 return "".join(chars)
27
28def bigendian_to_native(value):
29 if ISBIGENDIAN:
30 return value
31 else:
32 return string_reverse(value)
33
Barry Warsaw07a0eec1996-12-12 23:34:06 +000034def simple_err(func, *args):
35 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000036 func(*args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000037 except struct.error:
Guido van Rossum41360a41998-03-26 19:42:58 +000038 pass
Barry Warsaw07a0eec1996-12-12 23:34:06 +000039 else:
Guido van Rossum41360a41998-03-26 19:42:58 +000040 raise TestFailed, "%s%s did not raise struct.error" % (
41 func.__name__, args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000042
Tim Peters7a3bfc32001-06-12 01:22:22 +000043def any_err(func, *args):
44 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000045 func(*args)
Bob Ippolito2fd39772006-05-29 22:55:48 +000046 except (struct.error, TypeError):
Tim Peters7a3bfc32001-06-12 01:22:22 +000047 pass
48 else:
49 raise TestFailed, "%s%s did not raise error" % (
50 func.__name__, args)
Tim Peters7a3bfc32001-06-12 01:22:22 +000051
Bob Ippolito2fd39772006-05-29 22:55:48 +000052def deprecated_err(func, *args):
53 warnings.filterwarnings("error", r"""^struct.*""", DeprecationWarning)
54 warnings.filterwarnings("error", r""".*format requires.*""", DeprecationWarning)
55 try:
56 try:
57 func(*args)
58 except (struct.error, TypeError):
59 pass
60 except DeprecationWarning:
61 if not PY_STRUCT_WRAPPING:
62 raise TestFailed, "%s%s expected to raise struct.error" % (
63 func.__name__, args)
64 else:
65 raise TestFailed, "%s%s did not raise error" % (
66 func.__name__, args)
67 finally:
68 warnings.resetwarnings()
Tim Peters17e17d42001-06-13 22:45:27 +000069
Tim Peters7b9542a2001-06-10 23:40:19 +000070simple_err(struct.calcsize, 'Z')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000071
72sz = struct.calcsize('i')
Fred Drake132dce22000-12-12 23:11:42 +000073if sz * 3 != struct.calcsize('iii'):
Guido van Rossum2a378501996-12-31 17:25:47 +000074 raise TestFailed, 'inconsistent sizes'
Barry Warsaw07a0eec1996-12-12 23:34:06 +000075
Guido van Rossum04ebf5c1997-01-03 19:00:37 +000076fmt = 'cbxxxxxxhhhhiillffd'
77fmt3 = '3c3b18x12h6i6l6f3d'
78sz = struct.calcsize(fmt)
79sz3 = struct.calcsize(fmt3)
Fred Drake132dce22000-12-12 23:11:42 +000080if sz * 3 != sz3:
Walter Dörwald70a6b492004-02-12 17:35:32 +000081 raise TestFailed, 'inconsistent sizes (3*%r -> 3*%d = %d, %r -> %d)' % (
82 fmt, sz, 3*sz, fmt3, sz3)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000083
84simple_err(struct.pack, 'iii', 3)
85simple_err(struct.pack, 'i', 3, 3, 3)
86simple_err(struct.pack, 'i', 'foo')
Armin Rigo9f904392004-09-27 19:27:51 +000087simple_err(struct.pack, 'P', 'foo')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000088simple_err(struct.unpack, 'd', 'flap')
89s = struct.pack('ii', 1, 2)
90simple_err(struct.unpack, 'iii', s)
91simple_err(struct.unpack, 'i', s)
92
93c = 'a'
Guido van Rossum2a378501996-12-31 17:25:47 +000094b = 1
Barry Warsaw07a0eec1996-12-12 23:34:06 +000095h = 255
96i = 65535
97l = 65536
98f = 3.1415
99d = 3.1415
100
Guido van Rossum420c11c1997-01-03 00:09:46 +0000101for prefix in ('', '@', '<', '>', '=', '!'):
102 for format in ('xcbhilfd', 'xcBHILfd'):
Guido van Rossum41360a41998-03-26 19:42:58 +0000103 format = prefix + format
104 if verbose:
105 print "trying:", format
106 s = struct.pack(format, c, b, h, i, l, f, d)
107 cp, bp, hp, ip, lp, fp, dp = struct.unpack(format, s)
Fred Drake132dce22000-12-12 23:11:42 +0000108 if (cp != c or bp != b or hp != h or ip != i or lp != l or
109 int(100 * fp) != int(100 * f) or int(100 * dp) != int(100 * d)):
Guido van Rossum41360a41998-03-26 19:42:58 +0000110 # ^^^ calculate only to two decimal places
111 raise TestFailed, "unpack/pack not transitive (%s, %s)" % (
112 str(format), str((cp, bp, hp, ip, lp, fp, dp)))
Guido van Rossum2a378501996-12-31 17:25:47 +0000113
Guido van Rossum420c11c1997-01-03 00:09:46 +0000114# Test some of the new features in detail
Guido van Rossum2a378501996-12-31 17:25:47 +0000115
116# (format, argument, big-endian result, little-endian result, asymmetric)
117tests = [
118 ('c', 'a', 'a', 'a', 0),
119 ('xc', 'a', '\0a', '\0a', 0),
120 ('cx', 'a', 'a\0', 'a\0', 0),
121 ('s', 'a', 'a', 'a', 0),
122 ('0s', 'helloworld', '', '', 1),
123 ('1s', 'helloworld', 'h', 'h', 1),
124 ('9s', 'helloworld', 'helloworl', 'helloworl', 1),
125 ('10s', 'helloworld', 'helloworld', 'helloworld', 0),
126 ('11s', 'helloworld', 'helloworld\0', 'helloworld\0', 1),
127 ('20s', 'helloworld', 'helloworld'+10*'\0', 'helloworld'+10*'\0', 1),
128 ('b', 7, '\7', '\7', 0),
129 ('b', -7, '\371', '\371', 0),
130 ('B', 7, '\7', '\7', 0),
131 ('B', 249, '\371', '\371', 0),
132 ('h', 700, '\002\274', '\274\002', 0),
133 ('h', -700, '\375D', 'D\375', 0),
134 ('H', 700, '\002\274', '\274\002', 0),
135 ('H', 0x10000-700, '\375D', 'D\375', 0),
136 ('i', 70000000, '\004,\035\200', '\200\035,\004', 0),
137 ('i', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
138 ('I', 70000000L, '\004,\035\200', '\200\035,\004', 0),
139 ('I', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
140 ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
141 ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
142 ('L', 70000000L, '\004,\035\200', '\200\035,\004', 0),
143 ('L', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
Guido van Rossum420c11c1997-01-03 00:09:46 +0000144 ('f', 2.0, '@\000\000\000', '\000\000\000@', 0),
145 ('d', 2.0, '@\000\000\000\000\000\000\000',
146 '\000\000\000\000\000\000\000@', 0),
147 ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0),
148 ('d', -2.0, '\300\000\000\000\000\000\000\000',
149 '\000\000\000\000\000\000\000\300', 0),
Guido van Rossum2a378501996-12-31 17:25:47 +0000150]
151
Guido van Rossum2a378501996-12-31 17:25:47 +0000152for fmt, arg, big, lil, asy in tests:
153 if verbose:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000154 print "%r %r %r %r" % (fmt, arg, big, lil)
Guido van Rossum2a378501996-12-31 17:25:47 +0000155 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
Tim Peters17e17d42001-06-13 22:45:27 +0000156 ('='+fmt, ISBIGENDIAN and big or lil)]:
Guido van Rossum41360a41998-03-26 19:42:58 +0000157 res = struct.pack(xfmt, arg)
158 if res != exp:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000159 raise TestFailed, "pack(%r, %r) -> %r # expected %r" % (
160 fmt, arg, res, exp)
Guido van Rossum41360a41998-03-26 19:42:58 +0000161 n = struct.calcsize(xfmt)
162 if n != len(res):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000163 raise TestFailed, "calcsize(%r) -> %d # expected %d" % (
164 xfmt, n, len(res))
Guido van Rossum41360a41998-03-26 19:42:58 +0000165 rev = struct.unpack(xfmt, res)[0]
166 if rev != arg and not asy:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000167 raise TestFailed, "unpack(%r, %r) -> (%r,) # expected (%r,)" % (
168 fmt, res, rev, arg)
Tim Peters7b9542a2001-06-10 23:40:19 +0000169
Tim Peters7a3bfc32001-06-12 01:22:22 +0000170###########################################################################
Tim Peters17e17d42001-06-13 22:45:27 +0000171# Simple native q/Q tests.
Tim Peters7b9542a2001-06-10 23:40:19 +0000172
173has_native_qQ = 1
174try:
175 struct.pack("q", 5)
176except struct.error:
177 has_native_qQ = 0
178
179if verbose:
180 print "Platform has native q/Q?", has_native_qQ and "Yes." or "No."
181
Tim Peters7a3bfc32001-06-12 01:22:22 +0000182any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless
Tim Peters7b9542a2001-06-10 23:40:19 +0000183simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless
184simple_err(struct.pack, "Q", "a") # ditto, but 'Q'
185
Tim Peters7a3bfc32001-06-12 01:22:22 +0000186def test_native_qQ():
Tim Peters7b9542a2001-06-10 23:40:19 +0000187 bytes = struct.calcsize('q')
188 # The expected values here are in big-endian format, primarily because
189 # I'm on a little-endian machine and so this is the clearest way (for
190 # me) to force the code to get exercised.
191 for format, input, expected in (
192 ('q', -1, '\xff' * bytes),
193 ('q', 0, '\x00' * bytes),
194 ('Q', 0, '\x00' * bytes),
195 ('q', 1L, '\x00' * (bytes-1) + '\x01'),
196 ('Q', (1L << (8*bytes))-1, '\xff' * bytes),
197 ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))):
198 got = struct.pack(format, input)
Tim Petersc533edc2001-06-10 23:52:59 +0000199 native_expected = bigendian_to_native(expected)
200 verify(got == native_expected,
Tim Peters7b9542a2001-06-10 23:40:19 +0000201 "%r-pack of %r gave %r, not %r" %
Tim Petersc533edc2001-06-10 23:52:59 +0000202 (format, input, got, native_expected))
Tim Peters7b9542a2001-06-10 23:40:19 +0000203 retrieved = struct.unpack(format, got)[0]
204 verify(retrieved == input,
205 "%r-unpack of %r gave %r, not %r" %
206 (format, got, retrieved, input))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000207
208if has_native_qQ:
209 test_native_qQ()
210
Tim Peters17e17d42001-06-13 22:45:27 +0000211###########################################################################
212# Standard integer tests (bBhHiIlLqQ).
Tim Peters7a3bfc32001-06-12 01:22:22 +0000213
214import binascii
Tim Peters7a3bfc32001-06-12 01:22:22 +0000215
Tim Peters17e17d42001-06-13 22:45:27 +0000216class IntTester:
Tim Peters7a3bfc32001-06-12 01:22:22 +0000217
Tim Peters17e17d42001-06-13 22:45:27 +0000218 # XXX Most std integer modes fail to test for out-of-range.
Tim Peters3eec38a2001-06-18 22:27:39 +0000219 # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
220 # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
221 # reported by Mark Favas).
222 BUGGY_RANGE_CHECK = "bBhHiIlL"
Tim Peters7a3bfc32001-06-12 01:22:22 +0000223
Tim Peters17e17d42001-06-13 22:45:27 +0000224 def __init__(self, formatpair, bytesize):
225 assert len(formatpair) == 2
226 self.formatpair = formatpair
227 for direction in "<>!=":
228 for code in formatpair:
229 format = direction + code
230 verify(struct.calcsize(format) == bytesize)
231 self.bytesize = bytesize
232 self.bitsize = bytesize * 8
233 self.signed_code, self.unsigned_code = formatpair
234 self.unsigned_min = 0
235 self.unsigned_max = 2L**self.bitsize - 1
236 self.signed_min = -(2L**(self.bitsize-1))
237 self.signed_max = 2L**(self.bitsize-1) - 1
Tim Peters7a3bfc32001-06-12 01:22:22 +0000238
Tim Peters17e17d42001-06-13 22:45:27 +0000239 def test_one(self, x, pack=struct.pack,
240 unpack=struct.unpack,
241 unhexlify=binascii.unhexlify):
242 if verbose:
243 print "trying std", self.formatpair, "on", x, "==", hex(x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000244
Tim Peters17e17d42001-06-13 22:45:27 +0000245 # Try signed.
246 code = self.signed_code
247 if self.signed_min <= x <= self.signed_max:
248 # Try big-endian.
249 expected = long(x)
250 if x < 0:
251 expected += 1L << self.bitsize
252 assert expected > 0
253 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
254 if len(expected) & 1:
255 expected = "0" + expected
256 expected = unhexlify(expected)
257 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000258
Tim Peters17e17d42001-06-13 22:45:27 +0000259 # Pack work?
260 format = ">" + code
261 got = pack(format, x)
262 verify(got == expected,
263 "'%s'-pack of %r gave %r, not %r" %
264 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000265
Tim Peters17e17d42001-06-13 22:45:27 +0000266 # Unpack work?
267 retrieved = unpack(format, got)[0]
268 verify(x == retrieved,
269 "'%s'-unpack of %r gave %r, not %r" %
270 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000271
Tim Peters17e17d42001-06-13 22:45:27 +0000272 # Adding any byte should cause a "too big" error.
273 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000274
Tim Peters17e17d42001-06-13 22:45:27 +0000275 # Try little-endian.
276 format = "<" + code
277 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000278
Tim Peters17e17d42001-06-13 22:45:27 +0000279 # Pack work?
280 got = pack(format, x)
281 verify(got == expected,
282 "'%s'-pack of %r gave %r, not %r" %
283 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000284
Tim Peters17e17d42001-06-13 22:45:27 +0000285 # Unpack work?
286 retrieved = unpack(format, got)[0]
287 verify(x == retrieved,
288 "'%s'-unpack of %r gave %r, not %r" %
289 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000290
Tim Peters17e17d42001-06-13 22:45:27 +0000291 # Adding any byte should cause a "too big" error.
292 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000293
Tim Peters17e17d42001-06-13 22:45:27 +0000294 else:
295 # x is out of range -- verify pack realizes that.
Bob Ippolitoe27337b2006-05-26 13:15:44 +0000296 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000297 if verbose:
298 print "Skipping buggy range check for code", code
299 else:
Bob Ippolito2fd39772006-05-29 22:55:48 +0000300 deprecated_err(pack, ">" + code, x)
301 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000302
Tim Peters17e17d42001-06-13 22:45:27 +0000303 # Much the same for unsigned.
304 code = self.unsigned_code
305 if self.unsigned_min <= x <= self.unsigned_max:
306 # Try big-endian.
307 format = ">" + code
308 expected = long(x)
309 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
310 if len(expected) & 1:
311 expected = "0" + expected
312 expected = unhexlify(expected)
313 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000314
Tim Peters17e17d42001-06-13 22:45:27 +0000315 # Pack work?
316 got = pack(format, x)
317 verify(got == expected,
318 "'%s'-pack of %r gave %r, not %r" %
319 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000320
Tim Peters17e17d42001-06-13 22:45:27 +0000321 # Unpack work?
322 retrieved = unpack(format, got)[0]
323 verify(x == retrieved,
324 "'%s'-unpack of %r gave %r, not %r" %
325 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000326
Tim Peters17e17d42001-06-13 22:45:27 +0000327 # Adding any byte should cause a "too big" error.
328 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000329
Tim Peters17e17d42001-06-13 22:45:27 +0000330 # Try little-endian.
331 format = "<" + code
332 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000333
Tim Peters17e17d42001-06-13 22:45:27 +0000334 # Pack work?
335 got = pack(format, x)
336 verify(got == expected,
337 "'%s'-pack of %r gave %r, not %r" %
338 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000339
Tim Peters17e17d42001-06-13 22:45:27 +0000340 # Unpack work?
341 retrieved = unpack(format, got)[0]
342 verify(x == retrieved,
343 "'%s'-unpack of %r gave %r, not %r" %
344 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000345
Tim Peters17e17d42001-06-13 22:45:27 +0000346 # Adding any byte should cause a "too big" error.
347 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000348
Tim Peters17e17d42001-06-13 22:45:27 +0000349 else:
350 # x is out of range -- verify pack realizes that.
Bob Ippolitoaa70a172006-05-26 20:25:23 +0000351 if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
Tim Peters17e17d42001-06-13 22:45:27 +0000352 if verbose:
353 print "Skipping buggy range check for code", code
354 else:
Bob Ippolito2fd39772006-05-29 22:55:48 +0000355 deprecated_err(pack, ">" + code, x)
356 deprecated_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000357
Tim Peters17e17d42001-06-13 22:45:27 +0000358 def run(self):
359 from random import randrange
360
361 # Create all interesting powers of 2.
362 values = []
363 for exp in range(self.bitsize + 3):
364 values.append(1L << exp)
365
366 # Add some random values.
367 for i in range(self.bitsize):
368 val = 0L
369 for j in range(self.bytesize):
370 val = (val << 8) | randrange(256)
371 values.append(val)
372
373 # Try all those, and their negations, and +-1 from them. Note
374 # that this tests all power-of-2 boundaries in range, and a few out
375 # of range, plus +-(2**n +- 1).
376 for base in values:
377 for val in -base, base:
378 for incr in -1, 0, 1:
379 x = val + incr
380 try:
381 x = int(x)
382 except OverflowError:
383 pass
384 self.test_one(x)
385
386 # Some error cases.
387 for direction in "<>":
388 for code in self.formatpair:
389 for badobject in "a string", 3+42j, randrange:
390 any_err(struct.pack, direction + code, badobject)
391
392for args in [("bB", 1),
393 ("hH", 2),
394 ("iI", 4),
395 ("lL", 4),
396 ("qQ", 8)]:
397 t = IntTester(*args)
398 t.run()
Tim Peters0891ac02001-09-15 02:35:15 +0000399
400
401###########################################################################
402# The p ("Pascal string") code.
403
404def test_p_code():
405 for code, input, expected, expectedback in [
406 ('p','abc', '\x00', ''),
407 ('1p', 'abc', '\x00', ''),
408 ('2p', 'abc', '\x01a', 'a'),
409 ('3p', 'abc', '\x02ab', 'ab'),
410 ('4p', 'abc', '\x03abc', 'abc'),
411 ('5p', 'abc', '\x03abc\x00', 'abc'),
412 ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
413 ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
414 got = struct.pack(code, input)
415 if got != expected:
416 raise TestFailed("pack(%r, %r) == %r but expected %r" %
417 (code, input, got, expected))
418 (got,) = struct.unpack(code, got)
419 if got != expectedback:
420 raise TestFailed("unpack(%r, %r) == %r but expected %r" %
421 (code, input, got, expectedback))
422
423test_p_code()
Tim Petersd50ade62003-03-20 18:32:13 +0000424
425
426###########################################################################
427# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
428# from the low-order discarded bits could propagate into the exponent
429# field, causing the result to be wrong by a factor of 2.
430
431def test_705836():
432 import math
433
434 for base in range(1, 33):
435 # smaller <- largest representable float less than base.
436 delta = 0.5
437 while base - delta / 2.0 != base:
438 delta /= 2.0
439 smaller = base - delta
440 # Packing this rounds away a solid string of trailing 1 bits.
441 packed = struct.pack("<f", smaller)
442 unpacked = struct.unpack("<f", packed)[0]
443 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
444 # 16, respectively.
445 verify(base == unpacked)
446 bigpacked = struct.pack(">f", smaller)
447 verify(bigpacked == string_reverse(packed),
448 ">f pack should be byte-reversal of <f pack")
449 unpacked = struct.unpack(">f", bigpacked)[0]
450 verify(base == unpacked)
451
452 # Largest finite IEEE single.
453 big = (1 << 24) - 1
454 big = math.ldexp(big, 127 - 23)
455 packed = struct.pack(">f", big)
456 unpacked = struct.unpack(">f", packed)[0]
457 verify(big == unpacked)
458
459 # The same, but tack on a 1 bit so it rounds up to infinity.
460 big = (1 << 25) - 1
461 big = math.ldexp(big, 127 - 24)
462 try:
463 packed = struct.pack(">f", big)
464 except OverflowError:
465 pass
466 else:
467 TestFailed("expected OverflowError")
468
469test_705836()
Bob Ippolitoeb621272006-05-24 15:32:06 +0000470
Bob Ippolitoeb621272006-05-24 15:32:06 +0000471def test_1229380():
Bob Ippolitoe27337b2006-05-26 13:15:44 +0000472 import sys
Bob Ippolitoeb621272006-05-24 15:32:06 +0000473 for endian in ('', '>', '<'):
474 for cls in (int, long):
475 for fmt in ('B', 'H', 'I', 'L'):
Bob Ippolito2fd39772006-05-29 22:55:48 +0000476 deprecated_err(struct.pack, endian + fmt, cls(-1))
Bob Ippolitoeb621272006-05-24 15:32:06 +0000477
Bob Ippolito2fd39772006-05-29 22:55:48 +0000478 deprecated_err(struct.pack, endian + 'B', cls(300))
479 deprecated_err(struct.pack, endian + 'H', cls(70000))
Bob Ippolitoeb621272006-05-24 15:32:06 +0000480
Bob Ippolito2fd39772006-05-29 22:55:48 +0000481 deprecated_err(struct.pack, endian + 'I', sys.maxint * 4L)
482 deprecated_err(struct.pack, endian + 'L', sys.maxint * 4L)
Bob Ippolitoeb621272006-05-24 15:32:06 +0000483
Bob Ippolitoe27337b2006-05-26 13:15:44 +0000484if PY_STRUCT_RANGE_CHECKING:
Bob Ippolitoeb621272006-05-24 15:32:06 +0000485 test_1229380()
Martin Blais2856e5f2006-05-26 12:03:27 +0000486
487class PackBufferTestCase(unittest.TestCase):
488 """
489 Test the packing methods that work on buffers.
490 """
491
492 def test_unpack_from( self ):
493 test_string = 'abcd01234'
494 fmt = '4s'
495 s = struct.Struct(fmt)
496 for cls in (str, buffer):
497 data = cls(test_string)
498 self.assertEquals(s.unpack_from(data), ('abcd',))
499 self.assertEquals(s.unpack_from(data, 2), ('cd01',))
500 self.assertEquals(s.unpack_from(data, 4), ('0123',))
501 for i in xrange(6):
502 self.assertEquals(s.unpack_from(data, i), (data[i:i+4],))
503 for i in xrange(6, len(test_string) + 1):
504 simple_err(s.unpack_from, data, i)
505 for cls in (str, buffer):
506 data = cls(test_string)
507 self.assertEquals(struct.unpack_from(fmt, data), ('abcd',))
508 self.assertEquals(struct.unpack_from(fmt, data, 2), ('cd01',))
509 self.assertEquals(struct.unpack_from(fmt, data, 4), ('0123',))
510 for i in xrange(6):
511 self.assertEquals(struct.unpack_from(fmt, data, i),
512 (data[i:i+4],))
513 for i in xrange(6, len(test_string) + 1):
514 simple_err(struct.unpack_from, fmt, data, i)
515
516 def test_pack_to( self ):
517 test_string = 'Reykjavik rocks, eow!'
518 writable_buf = array.array('c', ' '*100)
519 fmt = '21s'
520 s = struct.Struct(fmt)
521
522 # Test without offset
523 s.pack_to(writable_buf, 0, test_string)
524 from_buf = writable_buf.tostring()[:len(test_string)]
525 self.assertEquals(from_buf, test_string)
526
527 # Test with offset.
528 s.pack_to(writable_buf, 10, test_string)
529 from_buf = writable_buf.tostring()[:len(test_string)+10]
530 self.assertEquals(from_buf, (test_string[:10] + test_string))
531
532 # Go beyond boundaries.
533 small_buf = array.array('c', ' '*10)
534 self.assertRaises(struct.error, s.pack_to, small_buf, 0, test_string)
535 self.assertRaises(struct.error, s.pack_to, small_buf, 2, test_string)
536
Bob Ippolito1fcdc232006-05-27 12:11:36 +0000537 def test_pack_to_fn( self ):
538 test_string = 'Reykjavik rocks, eow!'
539 writable_buf = array.array('c', ' '*100)
540 fmt = '21s'
541 pack_to = lambda *args: struct.pack_to(fmt, *args)
542
543 # Test without offset
544 pack_to(writable_buf, 0, test_string)
545 from_buf = writable_buf.tostring()[:len(test_string)]
546 self.assertEquals(from_buf, test_string)
547
548 # Test with offset.
549 pack_to(writable_buf, 10, test_string)
550 from_buf = writable_buf.tostring()[:len(test_string)+10]
551 self.assertEquals(from_buf, (test_string[:10] + test_string))
552
553 # Go beyond boundaries.
554 small_buf = array.array('c', ' '*10)
555 self.assertRaises(struct.error, pack_to, small_buf, 0, test_string)
556 self.assertRaises(struct.error, pack_to, small_buf, 2, test_string)
557
558
Martin Blais2856e5f2006-05-26 12:03:27 +0000559def test_main():
560 test.test_support.run_unittest(PackBufferTestCase)
Tim Petersfe98f962006-05-26 12:26:21 +0000561
Martin Blais2856e5f2006-05-26 12:03:27 +0000562if __name__ == "__main__":
563 test_main()