blob: 4d9d601ef4627850183fe98c4ce59d1df576fd80 [file] [log] [blame]
Antoine Pitrou9f146812013-04-27 00:20:04 +02001from collections import abc
Thomas Wouters477c8d52006-05-27 19:21:47 +00002import array
Mark Dickinson7c4e4092016-09-03 17:21:29 +01003import math
Antoine Pitrou9f146812013-04-27 00:20:04 +02004import operator
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +00005import unittest
6import struct
Tim Peters17e17d42001-06-13 22:45:27 +00007import sys
Mark Dickinson79d38ac2010-03-05 14:44:08 +00008
Martin v. Löwis33f79972012-07-29 16:33:05 +02009from test import support
Mark Dickinson79d38ac2010-03-05 14:44:08 +000010
Tim Peters17e17d42001-06-13 22:45:27 +000011ISBIGENDIAN = sys.byteorder == "big"
Tim Peters17e17d42001-06-13 22:45:27 +000012
Antoine Pitrou45d9c912011-10-06 15:27:40 +020013integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'n', 'N'
Mark Dickinsonb9f751a2010-04-03 15:07:40 +000014byteorders = '', '@', '=', '<', '>', '!'
15
Antoine Pitrou45d9c912011-10-06 15:27:40 +020016def iter_integer_formats(byteorders=byteorders):
17 for code in integer_codes:
18 for byteorder in byteorders:
Antoine Pitrou45d9c912011-10-06 15:27:40 +020019 if (byteorder not in ('', '@') and code in ('n', 'N')):
20 continue
21 yield code, byteorder
22
Tim Peters17e17d42001-06-13 22:45:27 +000023def string_reverse(s):
Guido van Rossume625fd52007-05-27 09:19:04 +000024 return s[::-1]
Tim Peters17e17d42001-06-13 22:45:27 +000025
26def bigendian_to_native(value):
27 if ISBIGENDIAN:
28 return value
29 else:
30 return string_reverse(value)
31
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000032class StructTest(unittest.TestCase):
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000033 def test_isbigendian(self):
Amaury Forgeot d'Arcf9f29822008-06-17 21:56:01 +000034 self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN)
Tim Peters7a3bfc32001-06-12 01:22:22 +000035
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000036 def test_consistence(self):
37 self.assertRaises(struct.error, struct.calcsize, 'Z')
Tim Peters7a3bfc32001-06-12 01:22:22 +000038
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000039 sz = struct.calcsize('i')
40 self.assertEqual(sz * 3, struct.calcsize('iii'))
Tim Peters7a3bfc32001-06-12 01:22:22 +000041
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000042 fmt = 'cbxxxxxxhhhhiillffd?'
43 fmt3 = '3c3b18x12h6i6l6f3d3?'
44 sz = struct.calcsize(fmt)
45 sz3 = struct.calcsize(fmt3)
46 self.assertEqual(sz * 3, sz3)
Tim Peters7a3bfc32001-06-12 01:22:22 +000047
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000048 self.assertRaises(struct.error, struct.pack, 'iii', 3)
49 self.assertRaises(struct.error, struct.pack, 'i', 3, 3, 3)
Benjamin Petersona04a32d2010-07-09 13:28:42 +000050 self.assertRaises((TypeError, struct.error), struct.pack, 'i', 'foo')
51 self.assertRaises((TypeError, struct.error), struct.pack, 'P', 'foo')
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000052 self.assertRaises(struct.error, struct.unpack, 'd', b'flap')
53 s = struct.pack('ii', 1, 2)
54 self.assertRaises(struct.error, struct.unpack, 'iii', s)
55 self.assertRaises(struct.error, struct.unpack, 'i', s)
Tim Peters7a3bfc32001-06-12 01:22:22 +000056
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000057 def test_transitiveness(self):
58 c = b'a'
59 b = 1
60 h = 255
61 i = 65535
62 l = 65536
63 f = 3.1415
64 d = 3.1415
65 t = True
Tim Peters7a3bfc32001-06-12 01:22:22 +000066
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000067 for prefix in ('', '@', '<', '>', '=', '!'):
68 for format in ('xcbhilfd?', 'xcBHILfd?'):
69 format = prefix + format
70 s = struct.pack(format, c, b, h, i, l, f, d, t)
71 cp, bp, hp, ip, lp, fp, dp, tp = struct.unpack(format, s)
72 self.assertEqual(cp, c)
73 self.assertEqual(bp, b)
74 self.assertEqual(hp, h)
75 self.assertEqual(ip, i)
76 self.assertEqual(lp, l)
77 self.assertEqual(int(100 * fp), int(100 * f))
78 self.assertEqual(int(100 * dp), int(100 * d))
79 self.assertEqual(tp, t)
Tim Peters7a3bfc32001-06-12 01:22:22 +000080
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000081 def test_new_features(self):
82 # Test some of the new features in detail
83 # (format, argument, big-endian result, little-endian result, asymmetric)
84 tests = [
Victor Stinnerda9ec992010-12-28 13:26:42 +000085 ('c', b'a', b'a', b'a', 0),
86 ('xc', b'a', b'\0a', b'\0a', 0),
87 ('cx', b'a', b'a\0', b'a\0', 0),
88 ('s', b'a', b'a', b'a', 0),
89 ('0s', b'helloworld', b'', b'', 1),
90 ('1s', b'helloworld', b'h', b'h', 1),
91 ('9s', b'helloworld', b'helloworl', b'helloworl', 1),
92 ('10s', b'helloworld', b'helloworld', b'helloworld', 0),
93 ('11s', b'helloworld', b'helloworld\0', b'helloworld\0', 1),
94 ('20s', b'helloworld', b'helloworld'+10*b'\0', b'helloworld'+10*b'\0', 1),
95 ('b', 7, b'\7', b'\7', 0),
96 ('b', -7, b'\371', b'\371', 0),
97 ('B', 7, b'\7', b'\7', 0),
98 ('B', 249, b'\371', b'\371', 0),
99 ('h', 700, b'\002\274', b'\274\002', 0),
100 ('h', -700, b'\375D', b'D\375', 0),
101 ('H', 700, b'\002\274', b'\274\002', 0),
102 ('H', 0x10000-700, b'\375D', b'D\375', 0),
103 ('i', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
104 ('i', -70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
105 ('I', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
106 ('I', 0x100000000-70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
107 ('l', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
108 ('l', -70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
109 ('L', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
110 ('L', 0x100000000-70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
111 ('f', 2.0, b'@\000\000\000', b'\000\000\000@', 0),
112 ('d', 2.0, b'@\000\000\000\000\000\000\000',
113 b'\000\000\000\000\000\000\000@', 0),
114 ('f', -2.0, b'\300\000\000\000', b'\000\000\000\300', 0),
115 ('d', -2.0, b'\300\000\000\000\000\000\000\000',
116 b'\000\000\000\000\000\000\000\300', 0),
117 ('?', 0, b'\0', b'\0', 0),
118 ('?', 3, b'\1', b'\1', 1),
119 ('?', True, b'\1', b'\1', 0),
120 ('?', [], b'\0', b'\0', 1),
121 ('?', (1,), b'\1', b'\1', 1),
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000122 ]
Tim Peters7a3bfc32001-06-12 01:22:22 +0000123
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000124 for fmt, arg, big, lil, asy in tests:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000125 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
126 ('='+fmt, ISBIGENDIAN and big or lil)]:
127 res = struct.pack(xfmt, arg)
128 self.assertEqual(res, exp)
129 self.assertEqual(struct.calcsize(xfmt), len(res))
130 rev = struct.unpack(xfmt, res)[0]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000131 if rev != arg:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000132 self.assertTrue(asy)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000133
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000134 def test_calcsize(self):
135 expected_size = {
136 'b': 1, 'B': 1,
137 'h': 2, 'H': 2,
138 'i': 4, 'I': 4,
139 'l': 4, 'L': 4,
140 'q': 8, 'Q': 8,
141 }
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000142
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000143 # standard integer sizes
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200144 for code, byteorder in iter_integer_formats(('=', '<', '>', '!')):
145 format = byteorder+code
146 size = struct.calcsize(format)
147 self.assertEqual(size, expected_size[code])
Tim Peters7a3bfc32001-06-12 01:22:22 +0000148
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000149 # native integer sizes
Benjamin Petersoned4aa832016-09-05 17:44:18 -0700150 native_pairs = 'bB', 'hH', 'iI', 'lL', 'nN', 'qQ'
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000151 for format_pair in native_pairs:
152 for byteorder in '', '@':
153 signed_size = struct.calcsize(byteorder + format_pair[0])
154 unsigned_size = struct.calcsize(byteorder + format_pair[1])
155 self.assertEqual(signed_size, unsigned_size)
156
157 # bounds for native integer sizes
Ezio Melotti4c28ddc2010-04-04 07:21:15 +0000158 self.assertEqual(struct.calcsize('b'), 1)
159 self.assertLessEqual(2, struct.calcsize('h'))
160 self.assertLessEqual(4, struct.calcsize('l'))
161 self.assertLessEqual(struct.calcsize('h'), struct.calcsize('i'))
162 self.assertLessEqual(struct.calcsize('i'), struct.calcsize('l'))
Benjamin Petersoned4aa832016-09-05 17:44:18 -0700163 self.assertLessEqual(8, struct.calcsize('q'))
164 self.assertLessEqual(struct.calcsize('l'), struct.calcsize('q'))
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200165 self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('i'))
166 self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('P'))
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000167
168 def test_integers(self):
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200169 # Integer tests (bBhHiIlLqQnN).
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000170 import binascii
Tim Peters17e17d42001-06-13 22:45:27 +0000171
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000172 class IntTester(unittest.TestCase):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000173 def __init__(self, format):
Benjamin Peterson7fe73a12009-04-04 16:35:46 +0000174 super(IntTester, self).__init__(methodName='test_one')
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000175 self.format = format
176 self.code = format[-1]
177 self.byteorder = format[:-1]
178 if not self.byteorder in byteorders:
179 raise ValueError("unrecognized packing byteorder: %s" %
180 self.byteorder)
181 self.bytesize = struct.calcsize(format)
182 self.bitsize = self.bytesize * 8
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200183 if self.code in tuple('bhilqn'):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000184 self.signed = True
185 self.min_value = -(2**(self.bitsize-1))
186 self.max_value = 2**(self.bitsize-1) - 1
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200187 elif self.code in tuple('BHILQN'):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000188 self.signed = False
189 self.min_value = 0
190 self.max_value = 2**self.bitsize - 1
191 else:
192 raise ValueError("unrecognized format code: %s" %
193 self.code)
Tim Peters17e17d42001-06-13 22:45:27 +0000194
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000195 def test_one(self, x, pack=struct.pack,
196 unpack=struct.unpack,
197 unhexlify=binascii.unhexlify):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000198
199 format = self.format
200 if self.min_value <= x <= self.max_value:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000201 expected = x
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000202 if self.signed and x < 0:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000203 expected += 1 << self.bitsize
Ezio Melotti4c28ddc2010-04-04 07:21:15 +0000204 self.assertGreaterEqual(expected, 0)
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000205 expected = '%x' % expected
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000206 if len(expected) & 1:
207 expected = "0" + expected
Florent Xiclunaf1046ca2010-07-27 21:20:15 +0000208 expected = expected.encode('ascii')
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000209 expected = unhexlify(expected)
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000210 expected = (b"\x00" * (self.bytesize - len(expected)) +
211 expected)
212 if (self.byteorder == '<' or
213 self.byteorder in ('', '@', '=') and not ISBIGENDIAN):
214 expected = string_reverse(expected)
215 self.assertEqual(len(expected), self.bytesize)
Tim Peters0891ac02001-09-15 02:35:15 +0000216
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000217 # Pack work?
218 got = pack(format, x)
219 self.assertEqual(got, expected)
Tim Petersd50ade62003-03-20 18:32:13 +0000220
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000221 # Unpack work?
222 retrieved = unpack(format, got)[0]
223 self.assertEqual(x, retrieved)
Tim Petersd50ade62003-03-20 18:32:13 +0000224
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000225 # Adding any byte should cause a "too big" error.
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000226 self.assertRaises((struct.error, TypeError), unpack, format,
227 b'\x01' + got)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000228 else:
229 # x is out of range -- verify pack realizes that.
Benjamin Peterson0d62f5b2010-07-10 15:14:45 +0000230 self.assertRaises((OverflowError, ValueError, struct.error),
231 pack, format, x)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000232
233 def run(self):
234 from random import randrange
235
236 # Create all interesting powers of 2.
237 values = []
238 for exp in range(self.bitsize + 3):
239 values.append(1 << exp)
240
241 # Add some random values.
242 for i in range(self.bitsize):
243 val = 0
244 for j in range(self.bytesize):
245 val = (val << 8) | randrange(256)
246 values.append(val)
247
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000248 # Values absorbed from other tests
249 values.extend([300, 700000, sys.maxsize*4])
250
251 # Try all those, and their negations, and +-1 from
252 # them. Note that this tests all power-of-2
253 # boundaries in range, and a few out of range, plus
254 # +-(2**n +- 1).
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000255 for base in values:
256 for val in -base, base:
257 for incr in -1, 0, 1:
258 x = val + incr
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000259 self.test_one(x)
260
261 # Some error cases.
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000262 class NotAnInt:
263 def __int__(self):
264 return 42
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000265
Mark Dickinsone9493a12010-04-04 08:52:51 +0000266 # Objects with an '__index__' method should be allowed
267 # to pack as integers. That is assuming the implemented
Serhiy Storchaka95949422013-08-27 19:40:23 +0300268 # '__index__' method returns an 'int'.
Mark Dickinsone9493a12010-04-04 08:52:51 +0000269 class Indexable(object):
270 def __init__(self, value):
271 self._value = value
272
273 def __index__(self):
274 return self._value
275
276 # If the '__index__' method raises a type error, then
277 # '__int__' should be used with a deprecation warning.
278 class BadIndex(object):
279 def __index__(self):
280 raise TypeError
281
282 def __int__(self):
283 return 42
284
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000285 self.assertRaises((TypeError, struct.error),
286 struct.pack, self.format,
287 "a string")
288 self.assertRaises((TypeError, struct.error),
289 struct.pack, self.format,
290 randrange)
291 self.assertRaises((TypeError, struct.error),
292 struct.pack, self.format,
293 3+42j)
294 self.assertRaises((TypeError, struct.error),
295 struct.pack, self.format,
Mark Dickinsone9493a12010-04-04 08:52:51 +0000296 NotAnInt())
297 self.assertRaises((TypeError, struct.error),
298 struct.pack, self.format,
299 BadIndex())
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000300
Mark Dickinsone9493a12010-04-04 08:52:51 +0000301 # Check for legitimate values from '__index__'.
Mark Dickinsonc5935772010-04-03 15:54:36 +0000302 for obj in (Indexable(0), Indexable(10), Indexable(17),
303 Indexable(42), Indexable(100), Indexable(127)):
304 try:
305 struct.pack(format, obj)
306 except:
307 self.fail("integer code pack failed on object "
308 "with '__index__' method")
309
Mark Dickinsone9493a12010-04-04 08:52:51 +0000310 # Check for bogus values from '__index__'.
311 for obj in (Indexable(b'a'), Indexable('b'), Indexable(None),
312 Indexable({'a': 1}), Indexable([1, 2, 3])):
313 self.assertRaises((TypeError, struct.error),
314 struct.pack, self.format,
315 obj)
316
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200317 for code, byteorder in iter_integer_formats():
318 format = byteorder+code
319 t = IntTester(format)
320 t.run()
321
322 def test_nN_code(self):
323 # n and N don't exist in standard sizes
324 def assertStructError(func, *args, **kwargs):
325 with self.assertRaises(struct.error) as cm:
326 func(*args, **kwargs)
327 self.assertIn("bad char in struct format", str(cm.exception))
328 for code in 'nN':
329 for byteorder in ('=', '<', '>', '!'):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000330 format = byteorder+code
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200331 assertStructError(struct.calcsize, format)
332 assertStructError(struct.pack, format, 0)
333 assertStructError(struct.unpack, format, b"")
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000334
335 def test_p_code(self):
336 # Test p ("Pascal string") code.
337 for code, input, expected, expectedback in [
Victor Stinnerda9ec992010-12-28 13:26:42 +0000338 ('p', b'abc', b'\x00', b''),
339 ('1p', b'abc', b'\x00', b''),
340 ('2p', b'abc', b'\x01a', b'a'),
341 ('3p', b'abc', b'\x02ab', b'ab'),
342 ('4p', b'abc', b'\x03abc', b'abc'),
343 ('5p', b'abc', b'\x03abc\x00', b'abc'),
344 ('6p', b'abc', b'\x03abc\x00\x00', b'abc'),
345 ('1000p', b'x'*1000, b'\xff' + b'x'*999, b'x'*255)]:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000346 got = struct.pack(code, input)
347 self.assertEqual(got, expected)
348 (got,) = struct.unpack(code, got)
349 self.assertEqual(got, expectedback)
350
351 def test_705836(self):
352 # SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
353 # from the low-order discarded bits could propagate into the exponent
354 # field, causing the result to be wrong by a factor of 2.
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000355 for base in range(1, 33):
356 # smaller <- largest representable float less than base.
357 delta = 0.5
358 while base - delta / 2.0 != base:
359 delta /= 2.0
360 smaller = base - delta
361 # Packing this rounds away a solid string of trailing 1 bits.
362 packed = struct.pack("<f", smaller)
363 unpacked = struct.unpack("<f", packed)[0]
364 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
365 # 16, respectively.
366 self.assertEqual(base, unpacked)
367 bigpacked = struct.pack(">f", smaller)
368 self.assertEqual(bigpacked, string_reverse(packed))
369 unpacked = struct.unpack(">f", bigpacked)[0]
370 self.assertEqual(base, unpacked)
371
372 # Largest finite IEEE single.
373 big = (1 << 24) - 1
374 big = math.ldexp(big, 127 - 23)
Tim Petersd50ade62003-03-20 18:32:13 +0000375 packed = struct.pack(">f", big)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000376 unpacked = struct.unpack(">f", packed)[0]
377 self.assertEqual(big, unpacked)
Tim Petersd50ade62003-03-20 18:32:13 +0000378
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000379 # The same, but tack on a 1 bit so it rounds up to infinity.
380 big = (1 << 25) - 1
381 big = math.ldexp(big, 127 - 24)
382 self.assertRaises(OverflowError, struct.pack, ">f", big)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000383
Mark Dickinsonea835e72009-04-19 20:40:33 +0000384 def test_1530559(self):
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200385 for code, byteorder in iter_integer_formats():
386 format = byteorder + code
387 self.assertRaises(struct.error, struct.pack, format, 1.0)
388 self.assertRaises(struct.error, struct.pack, format, 1.5)
Mark Dickinsonea835e72009-04-19 20:40:33 +0000389 self.assertRaises(struct.error, struct.pack, 'P', 1.0)
390 self.assertRaises(struct.error, struct.pack, 'P', 1.5)
391
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000392 def test_unpack_from(self):
393 test_string = b'abcd01234'
394 fmt = '4s'
395 s = struct.Struct(fmt)
396 for cls in (bytes, bytearray):
397 data = cls(test_string)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000398 self.assertEqual(s.unpack_from(data), (b'abcd',))
399 self.assertEqual(s.unpack_from(data, 2), (b'cd01',))
400 self.assertEqual(s.unpack_from(data, 4), (b'0123',))
401 for i in range(6):
Victor Stinnerda9ec992010-12-28 13:26:42 +0000402 self.assertEqual(s.unpack_from(data, i), (data[i:i+4],))
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000403 for i in range(6, len(test_string) + 1):
404 self.assertRaises(struct.error, s.unpack_from, data, i)
405 for cls in (bytes, bytearray):
406 data = cls(test_string)
407 self.assertEqual(struct.unpack_from(fmt, data), (b'abcd',))
408 self.assertEqual(struct.unpack_from(fmt, data, 2), (b'cd01',))
409 self.assertEqual(struct.unpack_from(fmt, data, 4), (b'0123',))
410 for i in range(6):
411 self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],))
412 for i in range(6, len(test_string) + 1):
413 self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000414
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000415 def test_pack_into(self):
416 test_string = b'Reykjavik rocks, eow!'
417 writable_buf = array.array('b', b' '*100)
418 fmt = '21s'
419 s = struct.Struct(fmt)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000420
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000421 # Test without offset
422 s.pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000423 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000424 self.assertEqual(from_buf, test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000425
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000426 # Test with offset.
427 s.pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000428 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000429 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000430
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000431 # Go beyond boundaries.
432 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000433 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0,
434 test_string)
435 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2,
436 test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000437
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000438 # Test bogus offset (issue 3694)
439 sb = small_buf
Benjamin Peterson4b83af92010-07-09 13:31:11 +0000440 self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb,
441 None)
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000442
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000443 def test_pack_into_fn(self):
444 test_string = b'Reykjavik rocks, eow!'
445 writable_buf = array.array('b', b' '*100)
446 fmt = '21s'
447 pack_into = lambda *args: struct.pack_into(fmt, *args)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000448
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000449 # Test without offset.
450 pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000451 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000452 self.assertEqual(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000453
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000454 # Test with offset.
455 pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000456 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000457 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000458
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000459 # Go beyond boundaries.
460 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000461 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0,
462 test_string)
463 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2,
464 test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000465
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000466 def test_unpack_with_buffer(self):
Ezio Melotti13925002011-03-16 11:05:33 +0200467 # SF bug 1563759: struct.unpack doesn't support buffer protocol objects
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000468 data1 = array.array('B', b'\x12\x34\x56\x78')
469 data2 = memoryview(b'\x12\x34\x56\x78') # XXX b'......XXXX......', 6, 4
470 for data in [data1, data2]:
471 value, = struct.unpack('>I', data)
472 self.assertEqual(value, 0x12345678)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000473
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000474 def test_bool(self):
Benjamin Petersonde73c452010-07-07 18:54:59 +0000475 class ExplodingBool(object):
476 def __bool__(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200477 raise OSError
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000478 for prefix in tuple("<>!=")+('',):
479 false = (), [], [], '', 0
480 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
Thomas Wouters477c8d52006-05-27 19:21:47 +0000481
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000482 falseFormat = prefix + '?' * len(false)
483 packedFalse = struct.pack(falseFormat, *false)
484 unpackedFalse = struct.unpack(falseFormat, packedFalse)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000485
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000486 trueFormat = prefix + '?' * len(true)
487 packedTrue = struct.pack(trueFormat, *true)
488 unpackedTrue = struct.unpack(trueFormat, packedTrue)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000489
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000490 self.assertEqual(len(true), len(unpackedTrue))
491 self.assertEqual(len(false), len(unpackedFalse))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000492
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000493 for t in unpackedFalse:
494 self.assertFalse(t)
495 for t in unpackedTrue:
496 self.assertTrue(t)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000497
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000498 packed = struct.pack(prefix+'?', 1)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000499
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000500 self.assertEqual(len(packed), struct.calcsize(prefix+'?'))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000501
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000502 if len(packed) != 1:
503 self.assertFalse(prefix, msg='encoded bool is not one byte: %r'
504 %packed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000505
Mark Dickinson94628ee2010-07-12 20:03:24 +0000506 try:
507 struct.pack(prefix + '?', ExplodingBool())
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200508 except OSError:
Mark Dickinson94628ee2010-07-12 20:03:24 +0000509 pass
510 else:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200511 self.fail("Expected OSError: struct.pack(%r, "
Mark Dickinson94628ee2010-07-12 20:03:24 +0000512 "ExplodingBool())" % (prefix + '?'))
Benjamin Petersonde73c452010-07-07 18:54:59 +0000513
Benjamin Petersonc937dc22010-07-07 18:44:05 +0000514 for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
515 self.assertTrue(struct.unpack('>?', c)[0])
Thomas Woutersb2137042007-02-01 18:02:27 +0000516
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000517 def test_count_overflow(self):
518 hugecount = '{}b'.format(sys.maxsize+1)
519 self.assertRaises(struct.error, struct.calcsize, hugecount)
520
Mark Dickinsonb72e6862010-06-11 19:50:30 +0000521 hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
522 self.assertRaises(struct.error, struct.calcsize, hugecount2)
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000523
Alexander Belopolsky177e8532010-06-11 16:04:59 +0000524 def test_trailing_counter(self):
525 store = array.array('b', b' '*100)
526
527 # format lists containing only count spec should result in an error
528 self.assertRaises(struct.error, struct.pack, '12345')
529 self.assertRaises(struct.error, struct.unpack, '12345', '')
530 self.assertRaises(struct.error, struct.pack_into, '12345', store, 0)
531 self.assertRaises(struct.error, struct.unpack_from, '12345', store, 0)
532
533 # Format lists with trailing count spec should result in an error
534 self.assertRaises(struct.error, struct.pack, 'c12345', 'x')
535 self.assertRaises(struct.error, struct.unpack, 'c12345', 'x')
536 self.assertRaises(struct.error, struct.pack_into, 'c12345', store, 0,
537 'x')
538 self.assertRaises(struct.error, struct.unpack_from, 'c12345', store,
539 0)
540
541 # Mixed format tests
542 self.assertRaises(struct.error, struct.pack, '14s42', 'spam and eggs')
543 self.assertRaises(struct.error, struct.unpack, '14s42',
544 'spam and eggs')
545 self.assertRaises(struct.error, struct.pack_into, '14s42', store, 0,
546 'spam and eggs')
547 self.assertRaises(struct.error, struct.unpack_from, '14s42', store, 0)
548
Mark Dickinson5b1d35b2010-08-01 11:10:28 +0000549 def test_Struct_reinitialization(self):
550 # Issue 9422: there was a memory leak when reinitializing a
551 # Struct instance. This test can be used to detect the leak
552 # when running with regrtest -L.
553 s = struct.Struct('i')
554 s.__init__('ii')
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +0000555
Martin v. Löwis33f79972012-07-29 16:33:05 +0200556 def check_sizeof(self, format_str, number_of_codes):
557 # The size of 'PyStructObject'
Martin v. Löwis2b168442012-07-29 16:38:45 +0200558 totalsize = support.calcobjsize('2n3P')
Martin v. Löwis33f79972012-07-29 16:33:05 +0200559 # The size taken up by the 'formatcode' dynamic array
Serhiy Storchakafff61f22013-05-17 10:49:44 +0300560 totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)
Martin v. Löwis33f79972012-07-29 16:33:05 +0200561 support.check_sizeof(self, struct.Struct(format_str), totalsize)
562
563 @support.cpython_only
Meador Inge90bc2dbc2012-07-28 22:16:39 -0500564 def test__sizeof__(self):
565 for code in integer_codes:
566 self.check_sizeof(code, 1)
567 self.check_sizeof('BHILfdspP', 9)
568 self.check_sizeof('B' * 1234, 1234)
569 self.check_sizeof('fd', 2)
570 self.check_sizeof('xxxxxxxxxxxxxx', 0)
Serhiy Storchakafff61f22013-05-17 10:49:44 +0300571 self.check_sizeof('100H', 1)
Meador Inge90bc2dbc2012-07-28 22:16:39 -0500572 self.check_sizeof('187s', 1)
573 self.check_sizeof('20p', 1)
574 self.check_sizeof('0s', 1)
575 self.check_sizeof('0c', 0)
Meador Ingeb14d8c92012-07-23 10:01:29 -0500576
Antoine Pitrou9f146812013-04-27 00:20:04 +0200577
578class UnpackIteratorTest(unittest.TestCase):
579 """
580 Tests for iterative unpacking (struct.Struct.iter_unpack).
581 """
582
583 def test_construct(self):
584 def _check_iterator(it):
585 self.assertIsInstance(it, abc.Iterator)
586 self.assertIsInstance(it, abc.Iterable)
587 s = struct.Struct('>ibcp')
588 it = s.iter_unpack(b"")
589 _check_iterator(it)
590 it = s.iter_unpack(b"1234567")
591 _check_iterator(it)
592 # Wrong bytes length
593 with self.assertRaises(struct.error):
594 s.iter_unpack(b"123456")
595 with self.assertRaises(struct.error):
596 s.iter_unpack(b"12345678")
597 # Zero-length struct
598 s = struct.Struct('>')
599 with self.assertRaises(struct.error):
600 s.iter_unpack(b"")
601 with self.assertRaises(struct.error):
602 s.iter_unpack(b"12")
603
604 def test_iterate(self):
605 s = struct.Struct('>IB')
606 b = bytes(range(1, 16))
607 it = s.iter_unpack(b)
608 self.assertEqual(next(it), (0x01020304, 5))
609 self.assertEqual(next(it), (0x06070809, 10))
610 self.assertEqual(next(it), (0x0b0c0d0e, 15))
611 self.assertRaises(StopIteration, next, it)
612 self.assertRaises(StopIteration, next, it)
613
614 def test_arbitrary_buffer(self):
615 s = struct.Struct('>IB')
616 b = bytes(range(1, 11))
617 it = s.iter_unpack(memoryview(b))
618 self.assertEqual(next(it), (0x01020304, 5))
619 self.assertEqual(next(it), (0x06070809, 10))
620 self.assertRaises(StopIteration, next, it)
621 self.assertRaises(StopIteration, next, it)
622
623 def test_length_hint(self):
624 lh = operator.length_hint
625 s = struct.Struct('>IB')
626 b = bytes(range(1, 16))
627 it = s.iter_unpack(b)
628 self.assertEqual(lh(it), 3)
629 next(it)
630 self.assertEqual(lh(it), 2)
631 next(it)
632 self.assertEqual(lh(it), 1)
633 next(it)
634 self.assertEqual(lh(it), 0)
635 self.assertRaises(StopIteration, next, it)
636 self.assertEqual(lh(it), 0)
637
638 def test_module_func(self):
639 # Sanity check for the global struct.iter_unpack()
640 it = struct.iter_unpack('>IB', bytes(range(1, 11)))
641 self.assertEqual(next(it), (0x01020304, 5))
642 self.assertEqual(next(it), (0x06070809, 10))
643 self.assertRaises(StopIteration, next, it)
644 self.assertRaises(StopIteration, next, it)
645
Mark Dickinson7c4e4092016-09-03 17:21:29 +0100646 def test_half_float(self):
647 # Little-endian examples from:
648 # http://en.wikipedia.org/wiki/Half_precision_floating-point_format
649 format_bits_float__cleanRoundtrip_list = [
650 (b'\x00\x3c', 1.0),
651 (b'\x00\xc0', -2.0),
652 (b'\xff\x7b', 65504.0), # (max half precision)
653 (b'\x00\x04', 2**-14), # ~= 6.10352 * 10**-5 (min pos normal)
654 (b'\x01\x00', 2**-24), # ~= 5.96046 * 10**-8 (min pos subnormal)
655 (b'\x00\x00', 0.0),
656 (b'\x00\x80', -0.0),
657 (b'\x00\x7c', float('+inf')),
658 (b'\x00\xfc', float('-inf')),
659 (b'\x55\x35', 0.333251953125), # ~= 1/3
660 ]
661
662 for le_bits, f in format_bits_float__cleanRoundtrip_list:
663 be_bits = le_bits[::-1]
664 self.assertEqual(f, struct.unpack('<e', le_bits)[0])
665 self.assertEqual(le_bits, struct.pack('<e', f))
666 self.assertEqual(f, struct.unpack('>e', be_bits)[0])
667 self.assertEqual(be_bits, struct.pack('>e', f))
668 if sys.byteorder == 'little':
669 self.assertEqual(f, struct.unpack('e', le_bits)[0])
670 self.assertEqual(le_bits, struct.pack('e', f))
671 else:
672 self.assertEqual(f, struct.unpack('e', be_bits)[0])
673 self.assertEqual(be_bits, struct.pack('e', f))
674
675 # Check for NaN handling:
676 format_bits__nan_list = [
677 ('<e', b'\x01\xfc'),
678 ('<e', b'\x00\xfe'),
679 ('<e', b'\xff\xff'),
680 ('<e', b'\x01\x7c'),
681 ('<e', b'\x00\x7e'),
682 ('<e', b'\xff\x7f'),
683 ]
684
685 for formatcode, bits in format_bits__nan_list:
686 self.assertTrue(math.isnan(struct.unpack('<e', bits)[0]))
687 self.assertTrue(math.isnan(struct.unpack('>e', bits[::-1])[0]))
688
689 # Check that packing produces a bit pattern representing a quiet NaN:
690 # all exponent bits and the msb of the fraction should all be 1.
691 packed = struct.pack('<e', math.nan)
692 self.assertEqual(packed[1] & 0x7e, 0x7e)
693 packed = struct.pack('<e', -math.nan)
694 self.assertEqual(packed[1] & 0x7e, 0x7e)
695
696 # Checks for round-to-even behavior
697 format_bits_float__rounding_list = [
698 ('>e', b'\x00\x01', 2.0**-25 + 2.0**-35), # Rounds to minimum subnormal
699 ('>e', b'\x00\x00', 2.0**-25), # Underflows to zero (nearest even mode)
700 ('>e', b'\x00\x00', 2.0**-26), # Underflows to zero
701 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-24), # Largest subnormal.
702 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-25 - 2.0**-65),
703 ('>e', b'\x04\x00', 2.0**-14 - 2.0**-25),
704 ('>e', b'\x04\x00', 2.0**-14), # Smallest normal.
705 ('>e', b'\x3c\x01', 1.0+2.0**-11 + 2.0**-16), # rounds to 1.0+2**(-10)
706 ('>e', b'\x3c\x00', 1.0+2.0**-11), # rounds to 1.0 (nearest even mode)
707 ('>e', b'\x3c\x00', 1.0+2.0**-12), # rounds to 1.0
708 ('>e', b'\x7b\xff', 65504), # largest normal
709 ('>e', b'\x7b\xff', 65519), # rounds to 65504
710 ('>e', b'\x80\x01', -2.0**-25 - 2.0**-35), # Rounds to minimum subnormal
711 ('>e', b'\x80\x00', -2.0**-25), # Underflows to zero (nearest even mode)
712 ('>e', b'\x80\x00', -2.0**-26), # Underflows to zero
713 ('>e', b'\xbc\x01', -1.0-2.0**-11 - 2.0**-16), # rounds to 1.0+2**(-10)
714 ('>e', b'\xbc\x00', -1.0-2.0**-11), # rounds to 1.0 (nearest even mode)
715 ('>e', b'\xbc\x00', -1.0-2.0**-12), # rounds to 1.0
716 ('>e', b'\xfb\xff', -65519), # rounds to 65504
717 ]
718
719 for formatcode, bits, f in format_bits_float__rounding_list:
720 self.assertEqual(bits, struct.pack(formatcode, f))
721
722 # This overflows, and so raises an error
723 format_bits_float__roundingError_list = [
724 # Values that round to infinity.
725 ('>e', 65520.0),
726 ('>e', 65536.0),
727 ('>e', 1e300),
728 ('>e', -65520.0),
729 ('>e', -65536.0),
730 ('>e', -1e300),
731 ('<e', 65520.0),
732 ('<e', 65536.0),
733 ('<e', 1e300),
734 ('<e', -65520.0),
735 ('<e', -65536.0),
736 ('<e', -1e300),
737 ]
738
739 for formatcode, f in format_bits_float__roundingError_list:
740 self.assertRaises(OverflowError, struct.pack, formatcode, f)
741
742 # Double rounding
743 format_bits_float__doubleRoundingError_list = [
744 ('>e', b'\x67\xff', 0x1ffdffffff * 2**-26), # should be 2047, if double-rounded 64>32>16, becomes 2048
745 ]
746
747 for formatcode, bits, f in format_bits_float__doubleRoundingError_list:
748 self.assertEqual(bits, struct.pack(formatcode, f))
749
Antoine Pitrou9f146812013-04-27 00:20:04 +0200750
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000751if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500752 unittest.main()