blob: be0047589cb465cbe42d3cfb7668527b94d26c26 [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
Victor Stinnera5917d12017-02-02 14:18:18 +0100415 # keyword arguments
416 self.assertEqual(s.unpack_from(buffer=test_string, offset=2),
417 (b'cd01',))
418
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000419 def test_pack_into(self):
420 test_string = b'Reykjavik rocks, eow!'
421 writable_buf = array.array('b', b' '*100)
422 fmt = '21s'
423 s = struct.Struct(fmt)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000424
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000425 # Test without offset
426 s.pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000427 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000428 self.assertEqual(from_buf, test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000429
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000430 # Test with offset.
431 s.pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000432 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000433 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000434
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000435 # Go beyond boundaries.
436 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000437 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0,
438 test_string)
439 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2,
440 test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000441
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000442 # Test bogus offset (issue 3694)
443 sb = small_buf
Benjamin Peterson4b83af92010-07-09 13:31:11 +0000444 self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb,
445 None)
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000446
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000447 def test_pack_into_fn(self):
448 test_string = b'Reykjavik rocks, eow!'
449 writable_buf = array.array('b', b' '*100)
450 fmt = '21s'
451 pack_into = lambda *args: struct.pack_into(fmt, *args)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000452
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000453 # Test without offset.
454 pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000455 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000456 self.assertEqual(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000457
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000458 # Test with offset.
459 pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000460 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000461 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000462
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000463 # Go beyond boundaries.
464 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000465 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0,
466 test_string)
467 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2,
468 test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000469
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000470 def test_unpack_with_buffer(self):
Ezio Melotti13925002011-03-16 11:05:33 +0200471 # SF bug 1563759: struct.unpack doesn't support buffer protocol objects
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000472 data1 = array.array('B', b'\x12\x34\x56\x78')
473 data2 = memoryview(b'\x12\x34\x56\x78') # XXX b'......XXXX......', 6, 4
474 for data in [data1, data2]:
475 value, = struct.unpack('>I', data)
476 self.assertEqual(value, 0x12345678)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000477
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000478 def test_bool(self):
Benjamin Petersonde73c452010-07-07 18:54:59 +0000479 class ExplodingBool(object):
480 def __bool__(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200481 raise OSError
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000482 for prefix in tuple("<>!=")+('',):
483 false = (), [], [], '', 0
484 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
Thomas Wouters477c8d52006-05-27 19:21:47 +0000485
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000486 falseFormat = prefix + '?' * len(false)
487 packedFalse = struct.pack(falseFormat, *false)
488 unpackedFalse = struct.unpack(falseFormat, packedFalse)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000489
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000490 trueFormat = prefix + '?' * len(true)
491 packedTrue = struct.pack(trueFormat, *true)
492 unpackedTrue = struct.unpack(trueFormat, packedTrue)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000493
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000494 self.assertEqual(len(true), len(unpackedTrue))
495 self.assertEqual(len(false), len(unpackedFalse))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000496
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000497 for t in unpackedFalse:
498 self.assertFalse(t)
499 for t in unpackedTrue:
500 self.assertTrue(t)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000501
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000502 packed = struct.pack(prefix+'?', 1)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000503
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000504 self.assertEqual(len(packed), struct.calcsize(prefix+'?'))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000505
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000506 if len(packed) != 1:
507 self.assertFalse(prefix, msg='encoded bool is not one byte: %r'
508 %packed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000509
Mark Dickinson94628ee2010-07-12 20:03:24 +0000510 try:
511 struct.pack(prefix + '?', ExplodingBool())
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200512 except OSError:
Mark Dickinson94628ee2010-07-12 20:03:24 +0000513 pass
514 else:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200515 self.fail("Expected OSError: struct.pack(%r, "
Mark Dickinson94628ee2010-07-12 20:03:24 +0000516 "ExplodingBool())" % (prefix + '?'))
Benjamin Petersonde73c452010-07-07 18:54:59 +0000517
Benjamin Petersonc937dc22010-07-07 18:44:05 +0000518 for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
519 self.assertTrue(struct.unpack('>?', c)[0])
Thomas Woutersb2137042007-02-01 18:02:27 +0000520
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000521 def test_count_overflow(self):
522 hugecount = '{}b'.format(sys.maxsize+1)
523 self.assertRaises(struct.error, struct.calcsize, hugecount)
524
Mark Dickinsonb72e6862010-06-11 19:50:30 +0000525 hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
526 self.assertRaises(struct.error, struct.calcsize, hugecount2)
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000527
Alexander Belopolsky177e8532010-06-11 16:04:59 +0000528 def test_trailing_counter(self):
529 store = array.array('b', b' '*100)
530
531 # format lists containing only count spec should result in an error
532 self.assertRaises(struct.error, struct.pack, '12345')
533 self.assertRaises(struct.error, struct.unpack, '12345', '')
534 self.assertRaises(struct.error, struct.pack_into, '12345', store, 0)
535 self.assertRaises(struct.error, struct.unpack_from, '12345', store, 0)
536
537 # Format lists with trailing count spec should result in an error
538 self.assertRaises(struct.error, struct.pack, 'c12345', 'x')
539 self.assertRaises(struct.error, struct.unpack, 'c12345', 'x')
540 self.assertRaises(struct.error, struct.pack_into, 'c12345', store, 0,
541 'x')
542 self.assertRaises(struct.error, struct.unpack_from, 'c12345', store,
543 0)
544
545 # Mixed format tests
546 self.assertRaises(struct.error, struct.pack, '14s42', 'spam and eggs')
547 self.assertRaises(struct.error, struct.unpack, '14s42',
548 'spam and eggs')
549 self.assertRaises(struct.error, struct.pack_into, '14s42', store, 0,
550 'spam and eggs')
551 self.assertRaises(struct.error, struct.unpack_from, '14s42', store, 0)
552
Mark Dickinson5b1d35b2010-08-01 11:10:28 +0000553 def test_Struct_reinitialization(self):
554 # Issue 9422: there was a memory leak when reinitializing a
555 # Struct instance. This test can be used to detect the leak
556 # when running with regrtest -L.
557 s = struct.Struct('i')
558 s.__init__('ii')
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +0000559
Martin v. Löwis33f79972012-07-29 16:33:05 +0200560 def check_sizeof(self, format_str, number_of_codes):
561 # The size of 'PyStructObject'
Martin v. Löwis2b168442012-07-29 16:38:45 +0200562 totalsize = support.calcobjsize('2n3P')
Martin v. Löwis33f79972012-07-29 16:33:05 +0200563 # The size taken up by the 'formatcode' dynamic array
Serhiy Storchakafff61f22013-05-17 10:49:44 +0300564 totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)
Martin v. Löwis33f79972012-07-29 16:33:05 +0200565 support.check_sizeof(self, struct.Struct(format_str), totalsize)
566
567 @support.cpython_only
Meador Inge90bc2dbc2012-07-28 22:16:39 -0500568 def test__sizeof__(self):
569 for code in integer_codes:
570 self.check_sizeof(code, 1)
571 self.check_sizeof('BHILfdspP', 9)
572 self.check_sizeof('B' * 1234, 1234)
573 self.check_sizeof('fd', 2)
574 self.check_sizeof('xxxxxxxxxxxxxx', 0)
Serhiy Storchakafff61f22013-05-17 10:49:44 +0300575 self.check_sizeof('100H', 1)
Meador Inge90bc2dbc2012-07-28 22:16:39 -0500576 self.check_sizeof('187s', 1)
577 self.check_sizeof('20p', 1)
578 self.check_sizeof('0s', 1)
579 self.check_sizeof('0c', 0)
Meador Ingeb14d8c92012-07-23 10:01:29 -0500580
Antoine Pitrou9f146812013-04-27 00:20:04 +0200581
582class UnpackIteratorTest(unittest.TestCase):
583 """
584 Tests for iterative unpacking (struct.Struct.iter_unpack).
585 """
586
587 def test_construct(self):
588 def _check_iterator(it):
589 self.assertIsInstance(it, abc.Iterator)
590 self.assertIsInstance(it, abc.Iterable)
591 s = struct.Struct('>ibcp')
592 it = s.iter_unpack(b"")
593 _check_iterator(it)
594 it = s.iter_unpack(b"1234567")
595 _check_iterator(it)
596 # Wrong bytes length
597 with self.assertRaises(struct.error):
598 s.iter_unpack(b"123456")
599 with self.assertRaises(struct.error):
600 s.iter_unpack(b"12345678")
601 # Zero-length struct
602 s = struct.Struct('>')
603 with self.assertRaises(struct.error):
604 s.iter_unpack(b"")
605 with self.assertRaises(struct.error):
606 s.iter_unpack(b"12")
607
608 def test_iterate(self):
609 s = struct.Struct('>IB')
610 b = bytes(range(1, 16))
611 it = s.iter_unpack(b)
612 self.assertEqual(next(it), (0x01020304, 5))
613 self.assertEqual(next(it), (0x06070809, 10))
614 self.assertEqual(next(it), (0x0b0c0d0e, 15))
615 self.assertRaises(StopIteration, next, it)
616 self.assertRaises(StopIteration, next, it)
617
618 def test_arbitrary_buffer(self):
619 s = struct.Struct('>IB')
620 b = bytes(range(1, 11))
621 it = s.iter_unpack(memoryview(b))
622 self.assertEqual(next(it), (0x01020304, 5))
623 self.assertEqual(next(it), (0x06070809, 10))
624 self.assertRaises(StopIteration, next, it)
625 self.assertRaises(StopIteration, next, it)
626
627 def test_length_hint(self):
628 lh = operator.length_hint
629 s = struct.Struct('>IB')
630 b = bytes(range(1, 16))
631 it = s.iter_unpack(b)
632 self.assertEqual(lh(it), 3)
633 next(it)
634 self.assertEqual(lh(it), 2)
635 next(it)
636 self.assertEqual(lh(it), 1)
637 next(it)
638 self.assertEqual(lh(it), 0)
639 self.assertRaises(StopIteration, next, it)
640 self.assertEqual(lh(it), 0)
641
642 def test_module_func(self):
643 # Sanity check for the global struct.iter_unpack()
644 it = struct.iter_unpack('>IB', bytes(range(1, 11)))
645 self.assertEqual(next(it), (0x01020304, 5))
646 self.assertEqual(next(it), (0x06070809, 10))
647 self.assertRaises(StopIteration, next, it)
648 self.assertRaises(StopIteration, next, it)
649
Mark Dickinson7c4e4092016-09-03 17:21:29 +0100650 def test_half_float(self):
651 # Little-endian examples from:
652 # http://en.wikipedia.org/wiki/Half_precision_floating-point_format
653 format_bits_float__cleanRoundtrip_list = [
654 (b'\x00\x3c', 1.0),
655 (b'\x00\xc0', -2.0),
656 (b'\xff\x7b', 65504.0), # (max half precision)
657 (b'\x00\x04', 2**-14), # ~= 6.10352 * 10**-5 (min pos normal)
658 (b'\x01\x00', 2**-24), # ~= 5.96046 * 10**-8 (min pos subnormal)
659 (b'\x00\x00', 0.0),
660 (b'\x00\x80', -0.0),
661 (b'\x00\x7c', float('+inf')),
662 (b'\x00\xfc', float('-inf')),
663 (b'\x55\x35', 0.333251953125), # ~= 1/3
664 ]
665
666 for le_bits, f in format_bits_float__cleanRoundtrip_list:
667 be_bits = le_bits[::-1]
668 self.assertEqual(f, struct.unpack('<e', le_bits)[0])
669 self.assertEqual(le_bits, struct.pack('<e', f))
670 self.assertEqual(f, struct.unpack('>e', be_bits)[0])
671 self.assertEqual(be_bits, struct.pack('>e', f))
672 if sys.byteorder == 'little':
673 self.assertEqual(f, struct.unpack('e', le_bits)[0])
674 self.assertEqual(le_bits, struct.pack('e', f))
675 else:
676 self.assertEqual(f, struct.unpack('e', be_bits)[0])
677 self.assertEqual(be_bits, struct.pack('e', f))
678
679 # Check for NaN handling:
680 format_bits__nan_list = [
681 ('<e', b'\x01\xfc'),
682 ('<e', b'\x00\xfe'),
683 ('<e', b'\xff\xff'),
684 ('<e', b'\x01\x7c'),
685 ('<e', b'\x00\x7e'),
686 ('<e', b'\xff\x7f'),
687 ]
688
689 for formatcode, bits in format_bits__nan_list:
690 self.assertTrue(math.isnan(struct.unpack('<e', bits)[0]))
691 self.assertTrue(math.isnan(struct.unpack('>e', bits[::-1])[0]))
692
693 # Check that packing produces a bit pattern representing a quiet NaN:
694 # all exponent bits and the msb of the fraction should all be 1.
695 packed = struct.pack('<e', math.nan)
696 self.assertEqual(packed[1] & 0x7e, 0x7e)
697 packed = struct.pack('<e', -math.nan)
698 self.assertEqual(packed[1] & 0x7e, 0x7e)
699
700 # Checks for round-to-even behavior
701 format_bits_float__rounding_list = [
702 ('>e', b'\x00\x01', 2.0**-25 + 2.0**-35), # Rounds to minimum subnormal
703 ('>e', b'\x00\x00', 2.0**-25), # Underflows to zero (nearest even mode)
704 ('>e', b'\x00\x00', 2.0**-26), # Underflows to zero
705 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-24), # Largest subnormal.
706 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-25 - 2.0**-65),
707 ('>e', b'\x04\x00', 2.0**-14 - 2.0**-25),
708 ('>e', b'\x04\x00', 2.0**-14), # Smallest normal.
709 ('>e', b'\x3c\x01', 1.0+2.0**-11 + 2.0**-16), # rounds to 1.0+2**(-10)
710 ('>e', b'\x3c\x00', 1.0+2.0**-11), # rounds to 1.0 (nearest even mode)
711 ('>e', b'\x3c\x00', 1.0+2.0**-12), # rounds to 1.0
712 ('>e', b'\x7b\xff', 65504), # largest normal
713 ('>e', b'\x7b\xff', 65519), # rounds to 65504
714 ('>e', b'\x80\x01', -2.0**-25 - 2.0**-35), # Rounds to minimum subnormal
715 ('>e', b'\x80\x00', -2.0**-25), # Underflows to zero (nearest even mode)
716 ('>e', b'\x80\x00', -2.0**-26), # Underflows to zero
717 ('>e', b'\xbc\x01', -1.0-2.0**-11 - 2.0**-16), # rounds to 1.0+2**(-10)
718 ('>e', b'\xbc\x00', -1.0-2.0**-11), # rounds to 1.0 (nearest even mode)
719 ('>e', b'\xbc\x00', -1.0-2.0**-12), # rounds to 1.0
720 ('>e', b'\xfb\xff', -65519), # rounds to 65504
721 ]
722
723 for formatcode, bits, f in format_bits_float__rounding_list:
724 self.assertEqual(bits, struct.pack(formatcode, f))
725
726 # This overflows, and so raises an error
727 format_bits_float__roundingError_list = [
728 # Values that round to infinity.
729 ('>e', 65520.0),
730 ('>e', 65536.0),
731 ('>e', 1e300),
732 ('>e', -65520.0),
733 ('>e', -65536.0),
734 ('>e', -1e300),
735 ('<e', 65520.0),
736 ('<e', 65536.0),
737 ('<e', 1e300),
738 ('<e', -65520.0),
739 ('<e', -65536.0),
740 ('<e', -1e300),
741 ]
742
743 for formatcode, f in format_bits_float__roundingError_list:
744 self.assertRaises(OverflowError, struct.pack, formatcode, f)
745
746 # Double rounding
747 format_bits_float__doubleRoundingError_list = [
748 ('>e', b'\x67\xff', 0x1ffdffffff * 2**-26), # should be 2047, if double-rounded 64>32>16, becomes 2048
749 ]
750
751 for formatcode, bits, f in format_bits_float__doubleRoundingError_list:
752 self.assertEqual(bits, struct.pack(formatcode, f))
753
Antoine Pitrou9f146812013-04-27 00:20:04 +0200754
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000755if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500756 unittest.main()