blob: 2ce855d4585a1a99b731754db67d89d45a4ea1e1 [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:
19 if (byteorder in ('', '@') and code in ('q', 'Q') and
20 not HAVE_LONG_LONG):
21 continue
22 if (byteorder not in ('', '@') and code in ('n', 'N')):
23 continue
24 yield code, byteorder
25
Mark Dickinsonb9f751a2010-04-03 15:07:40 +000026# Native 'q' packing isn't available on systems that don't have the C
27# long long type.
28try:
29 struct.pack('q', 5)
30except struct.error:
31 HAVE_LONG_LONG = False
32else:
33 HAVE_LONG_LONG = True
34
Tim Peters17e17d42001-06-13 22:45:27 +000035def string_reverse(s):
Guido van Rossume625fd52007-05-27 09:19:04 +000036 return s[::-1]
Tim Peters17e17d42001-06-13 22:45:27 +000037
38def bigendian_to_native(value):
39 if ISBIGENDIAN:
40 return value
41 else:
42 return string_reverse(value)
43
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000044class StructTest(unittest.TestCase):
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000045 def test_isbigendian(self):
Amaury Forgeot d'Arcf9f29822008-06-17 21:56:01 +000046 self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN)
Tim Peters7a3bfc32001-06-12 01:22:22 +000047
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000048 def test_consistence(self):
49 self.assertRaises(struct.error, struct.calcsize, 'Z')
Tim Peters7a3bfc32001-06-12 01:22:22 +000050
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000051 sz = struct.calcsize('i')
52 self.assertEqual(sz * 3, struct.calcsize('iii'))
Tim Peters7a3bfc32001-06-12 01:22:22 +000053
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000054 fmt = 'cbxxxxxxhhhhiillffd?'
55 fmt3 = '3c3b18x12h6i6l6f3d3?'
56 sz = struct.calcsize(fmt)
57 sz3 = struct.calcsize(fmt3)
58 self.assertEqual(sz * 3, sz3)
Tim Peters7a3bfc32001-06-12 01:22:22 +000059
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000060 self.assertRaises(struct.error, struct.pack, 'iii', 3)
61 self.assertRaises(struct.error, struct.pack, 'i', 3, 3, 3)
Benjamin Petersona04a32d2010-07-09 13:28:42 +000062 self.assertRaises((TypeError, struct.error), struct.pack, 'i', 'foo')
63 self.assertRaises((TypeError, struct.error), struct.pack, 'P', 'foo')
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000064 self.assertRaises(struct.error, struct.unpack, 'd', b'flap')
65 s = struct.pack('ii', 1, 2)
66 self.assertRaises(struct.error, struct.unpack, 'iii', s)
67 self.assertRaises(struct.error, struct.unpack, 'i', s)
Tim Peters7a3bfc32001-06-12 01:22:22 +000068
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000069 def test_transitiveness(self):
70 c = b'a'
71 b = 1
72 h = 255
73 i = 65535
74 l = 65536
75 f = 3.1415
76 d = 3.1415
77 t = True
Tim Peters7a3bfc32001-06-12 01:22:22 +000078
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000079 for prefix in ('', '@', '<', '>', '=', '!'):
80 for format in ('xcbhilfd?', 'xcBHILfd?'):
81 format = prefix + format
82 s = struct.pack(format, c, b, h, i, l, f, d, t)
83 cp, bp, hp, ip, lp, fp, dp, tp = struct.unpack(format, s)
84 self.assertEqual(cp, c)
85 self.assertEqual(bp, b)
86 self.assertEqual(hp, h)
87 self.assertEqual(ip, i)
88 self.assertEqual(lp, l)
89 self.assertEqual(int(100 * fp), int(100 * f))
90 self.assertEqual(int(100 * dp), int(100 * d))
91 self.assertEqual(tp, t)
Tim Peters7a3bfc32001-06-12 01:22:22 +000092
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000093 def test_new_features(self):
94 # Test some of the new features in detail
95 # (format, argument, big-endian result, little-endian result, asymmetric)
96 tests = [
Victor Stinnerda9ec992010-12-28 13:26:42 +000097 ('c', b'a', b'a', b'a', 0),
98 ('xc', b'a', b'\0a', b'\0a', 0),
99 ('cx', b'a', b'a\0', b'a\0', 0),
100 ('s', b'a', b'a', b'a', 0),
101 ('0s', b'helloworld', b'', b'', 1),
102 ('1s', b'helloworld', b'h', b'h', 1),
103 ('9s', b'helloworld', b'helloworl', b'helloworl', 1),
104 ('10s', b'helloworld', b'helloworld', b'helloworld', 0),
105 ('11s', b'helloworld', b'helloworld\0', b'helloworld\0', 1),
106 ('20s', b'helloworld', b'helloworld'+10*b'\0', b'helloworld'+10*b'\0', 1),
107 ('b', 7, b'\7', b'\7', 0),
108 ('b', -7, b'\371', b'\371', 0),
109 ('B', 7, b'\7', b'\7', 0),
110 ('B', 249, b'\371', b'\371', 0),
111 ('h', 700, b'\002\274', b'\274\002', 0),
112 ('h', -700, b'\375D', b'D\375', 0),
113 ('H', 700, b'\002\274', b'\274\002', 0),
114 ('H', 0x10000-700, b'\375D', b'D\375', 0),
115 ('i', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
116 ('i', -70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
117 ('I', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
118 ('I', 0x100000000-70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
119 ('l', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
120 ('l', -70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
121 ('L', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
122 ('L', 0x100000000-70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
123 ('f', 2.0, b'@\000\000\000', b'\000\000\000@', 0),
124 ('d', 2.0, b'@\000\000\000\000\000\000\000',
125 b'\000\000\000\000\000\000\000@', 0),
126 ('f', -2.0, b'\300\000\000\000', b'\000\000\000\300', 0),
127 ('d', -2.0, b'\300\000\000\000\000\000\000\000',
128 b'\000\000\000\000\000\000\000\300', 0),
129 ('?', 0, b'\0', b'\0', 0),
130 ('?', 3, b'\1', b'\1', 1),
131 ('?', True, b'\1', b'\1', 0),
132 ('?', [], b'\0', b'\0', 1),
133 ('?', (1,), b'\1', b'\1', 1),
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000134 ]
Tim Peters7a3bfc32001-06-12 01:22:22 +0000135
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000136 for fmt, arg, big, lil, asy in tests:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000137 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
138 ('='+fmt, ISBIGENDIAN and big or lil)]:
139 res = struct.pack(xfmt, arg)
140 self.assertEqual(res, exp)
141 self.assertEqual(struct.calcsize(xfmt), len(res))
142 rev = struct.unpack(xfmt, res)[0]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000143 if rev != arg:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000144 self.assertTrue(asy)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000145
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000146 def test_calcsize(self):
147 expected_size = {
148 'b': 1, 'B': 1,
149 'h': 2, 'H': 2,
150 'i': 4, 'I': 4,
151 'l': 4, 'L': 4,
152 'q': 8, 'Q': 8,
153 }
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000154
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000155 # standard integer sizes
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200156 for code, byteorder in iter_integer_formats(('=', '<', '>', '!')):
157 format = byteorder+code
158 size = struct.calcsize(format)
159 self.assertEqual(size, expected_size[code])
Tim Peters7a3bfc32001-06-12 01:22:22 +0000160
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000161 # native integer sizes
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200162 native_pairs = 'bB', 'hH', 'iI', 'lL', 'nN'
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000163 if HAVE_LONG_LONG:
164 native_pairs += 'qQ',
165 for format_pair in native_pairs:
166 for byteorder in '', '@':
167 signed_size = struct.calcsize(byteorder + format_pair[0])
168 unsigned_size = struct.calcsize(byteorder + format_pair[1])
169 self.assertEqual(signed_size, unsigned_size)
170
171 # bounds for native integer sizes
Ezio Melotti4c28ddc2010-04-04 07:21:15 +0000172 self.assertEqual(struct.calcsize('b'), 1)
173 self.assertLessEqual(2, struct.calcsize('h'))
174 self.assertLessEqual(4, struct.calcsize('l'))
175 self.assertLessEqual(struct.calcsize('h'), struct.calcsize('i'))
176 self.assertLessEqual(struct.calcsize('i'), struct.calcsize('l'))
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000177 if HAVE_LONG_LONG:
Ezio Melotti4c28ddc2010-04-04 07:21:15 +0000178 self.assertLessEqual(8, struct.calcsize('q'))
179 self.assertLessEqual(struct.calcsize('l'), struct.calcsize('q'))
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200180 self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('i'))
181 self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('P'))
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000182
183 def test_integers(self):
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200184 # Integer tests (bBhHiIlLqQnN).
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000185 import binascii
Tim Peters17e17d42001-06-13 22:45:27 +0000186
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000187 class IntTester(unittest.TestCase):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000188 def __init__(self, format):
Benjamin Peterson7fe73a12009-04-04 16:35:46 +0000189 super(IntTester, self).__init__(methodName='test_one')
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000190 self.format = format
191 self.code = format[-1]
192 self.byteorder = format[:-1]
193 if not self.byteorder in byteorders:
194 raise ValueError("unrecognized packing byteorder: %s" %
195 self.byteorder)
196 self.bytesize = struct.calcsize(format)
197 self.bitsize = self.bytesize * 8
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200198 if self.code in tuple('bhilqn'):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000199 self.signed = True
200 self.min_value = -(2**(self.bitsize-1))
201 self.max_value = 2**(self.bitsize-1) - 1
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200202 elif self.code in tuple('BHILQN'):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000203 self.signed = False
204 self.min_value = 0
205 self.max_value = 2**self.bitsize - 1
206 else:
207 raise ValueError("unrecognized format code: %s" %
208 self.code)
Tim Peters17e17d42001-06-13 22:45:27 +0000209
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000210 def test_one(self, x, pack=struct.pack,
211 unpack=struct.unpack,
212 unhexlify=binascii.unhexlify):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000213
214 format = self.format
215 if self.min_value <= x <= self.max_value:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000216 expected = x
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000217 if self.signed and x < 0:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000218 expected += 1 << self.bitsize
Ezio Melotti4c28ddc2010-04-04 07:21:15 +0000219 self.assertGreaterEqual(expected, 0)
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000220 expected = '%x' % expected
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000221 if len(expected) & 1:
222 expected = "0" + expected
Florent Xiclunaf1046ca2010-07-27 21:20:15 +0000223 expected = expected.encode('ascii')
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000224 expected = unhexlify(expected)
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000225 expected = (b"\x00" * (self.bytesize - len(expected)) +
226 expected)
227 if (self.byteorder == '<' or
228 self.byteorder in ('', '@', '=') and not ISBIGENDIAN):
229 expected = string_reverse(expected)
230 self.assertEqual(len(expected), self.bytesize)
Tim Peters0891ac02001-09-15 02:35:15 +0000231
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000232 # Pack work?
233 got = pack(format, x)
234 self.assertEqual(got, expected)
Tim Petersd50ade62003-03-20 18:32:13 +0000235
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000236 # Unpack work?
237 retrieved = unpack(format, got)[0]
238 self.assertEqual(x, retrieved)
Tim Petersd50ade62003-03-20 18:32:13 +0000239
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000240 # Adding any byte should cause a "too big" error.
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000241 self.assertRaises((struct.error, TypeError), unpack, format,
242 b'\x01' + got)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000243 else:
244 # x is out of range -- verify pack realizes that.
Benjamin Peterson0d62f5b2010-07-10 15:14:45 +0000245 self.assertRaises((OverflowError, ValueError, struct.error),
246 pack, format, x)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000247
248 def run(self):
249 from random import randrange
250
251 # Create all interesting powers of 2.
252 values = []
253 for exp in range(self.bitsize + 3):
254 values.append(1 << exp)
255
256 # Add some random values.
257 for i in range(self.bitsize):
258 val = 0
259 for j in range(self.bytesize):
260 val = (val << 8) | randrange(256)
261 values.append(val)
262
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000263 # Values absorbed from other tests
264 values.extend([300, 700000, sys.maxsize*4])
265
266 # Try all those, and their negations, and +-1 from
267 # them. Note that this tests all power-of-2
268 # boundaries in range, and a few out of range, plus
269 # +-(2**n +- 1).
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000270 for base in values:
271 for val in -base, base:
272 for incr in -1, 0, 1:
273 x = val + incr
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000274 self.test_one(x)
275
276 # Some error cases.
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000277 class NotAnInt:
278 def __int__(self):
279 return 42
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000280
Mark Dickinsone9493a12010-04-04 08:52:51 +0000281 # Objects with an '__index__' method should be allowed
282 # to pack as integers. That is assuming the implemented
Serhiy Storchaka95949422013-08-27 19:40:23 +0300283 # '__index__' method returns an 'int'.
Mark Dickinsone9493a12010-04-04 08:52:51 +0000284 class Indexable(object):
285 def __init__(self, value):
286 self._value = value
287
288 def __index__(self):
289 return self._value
290
291 # If the '__index__' method raises a type error, then
292 # '__int__' should be used with a deprecation warning.
293 class BadIndex(object):
294 def __index__(self):
295 raise TypeError
296
297 def __int__(self):
298 return 42
299
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000300 self.assertRaises((TypeError, struct.error),
301 struct.pack, self.format,
302 "a string")
303 self.assertRaises((TypeError, struct.error),
304 struct.pack, self.format,
305 randrange)
306 self.assertRaises((TypeError, struct.error),
307 struct.pack, self.format,
308 3+42j)
309 self.assertRaises((TypeError, struct.error),
310 struct.pack, self.format,
Mark Dickinsone9493a12010-04-04 08:52:51 +0000311 NotAnInt())
312 self.assertRaises((TypeError, struct.error),
313 struct.pack, self.format,
314 BadIndex())
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000315
Mark Dickinsone9493a12010-04-04 08:52:51 +0000316 # Check for legitimate values from '__index__'.
Mark Dickinsonc5935772010-04-03 15:54:36 +0000317 for obj in (Indexable(0), Indexable(10), Indexable(17),
318 Indexable(42), Indexable(100), Indexable(127)):
319 try:
320 struct.pack(format, obj)
321 except:
322 self.fail("integer code pack failed on object "
323 "with '__index__' method")
324
Mark Dickinsone9493a12010-04-04 08:52:51 +0000325 # Check for bogus values from '__index__'.
326 for obj in (Indexable(b'a'), Indexable('b'), Indexable(None),
327 Indexable({'a': 1}), Indexable([1, 2, 3])):
328 self.assertRaises((TypeError, struct.error),
329 struct.pack, self.format,
330 obj)
331
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200332 for code, byteorder in iter_integer_formats():
333 format = byteorder+code
334 t = IntTester(format)
335 t.run()
336
337 def test_nN_code(self):
338 # n and N don't exist in standard sizes
339 def assertStructError(func, *args, **kwargs):
340 with self.assertRaises(struct.error) as cm:
341 func(*args, **kwargs)
342 self.assertIn("bad char in struct format", str(cm.exception))
343 for code in 'nN':
344 for byteorder in ('=', '<', '>', '!'):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000345 format = byteorder+code
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200346 assertStructError(struct.calcsize, format)
347 assertStructError(struct.pack, format, 0)
348 assertStructError(struct.unpack, format, b"")
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000349
350 def test_p_code(self):
351 # Test p ("Pascal string") code.
352 for code, input, expected, expectedback in [
Victor Stinnerda9ec992010-12-28 13:26:42 +0000353 ('p', b'abc', b'\x00', b''),
354 ('1p', b'abc', b'\x00', b''),
355 ('2p', b'abc', b'\x01a', b'a'),
356 ('3p', b'abc', b'\x02ab', b'ab'),
357 ('4p', b'abc', b'\x03abc', b'abc'),
358 ('5p', b'abc', b'\x03abc\x00', b'abc'),
359 ('6p', b'abc', b'\x03abc\x00\x00', b'abc'),
360 ('1000p', b'x'*1000, b'\xff' + b'x'*999, b'x'*255)]:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000361 got = struct.pack(code, input)
362 self.assertEqual(got, expected)
363 (got,) = struct.unpack(code, got)
364 self.assertEqual(got, expectedback)
365
366 def test_705836(self):
367 # SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
368 # from the low-order discarded bits could propagate into the exponent
369 # field, causing the result to be wrong by a factor of 2.
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000370 for base in range(1, 33):
371 # smaller <- largest representable float less than base.
372 delta = 0.5
373 while base - delta / 2.0 != base:
374 delta /= 2.0
375 smaller = base - delta
376 # Packing this rounds away a solid string of trailing 1 bits.
377 packed = struct.pack("<f", smaller)
378 unpacked = struct.unpack("<f", packed)[0]
379 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
380 # 16, respectively.
381 self.assertEqual(base, unpacked)
382 bigpacked = struct.pack(">f", smaller)
383 self.assertEqual(bigpacked, string_reverse(packed))
384 unpacked = struct.unpack(">f", bigpacked)[0]
385 self.assertEqual(base, unpacked)
386
387 # Largest finite IEEE single.
388 big = (1 << 24) - 1
389 big = math.ldexp(big, 127 - 23)
Tim Petersd50ade62003-03-20 18:32:13 +0000390 packed = struct.pack(">f", big)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000391 unpacked = struct.unpack(">f", packed)[0]
392 self.assertEqual(big, unpacked)
Tim Petersd50ade62003-03-20 18:32:13 +0000393
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000394 # The same, but tack on a 1 bit so it rounds up to infinity.
395 big = (1 << 25) - 1
396 big = math.ldexp(big, 127 - 24)
397 self.assertRaises(OverflowError, struct.pack, ">f", big)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000398
Mark Dickinsonea835e72009-04-19 20:40:33 +0000399 def test_1530559(self):
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200400 for code, byteorder in iter_integer_formats():
401 format = byteorder + code
402 self.assertRaises(struct.error, struct.pack, format, 1.0)
403 self.assertRaises(struct.error, struct.pack, format, 1.5)
Mark Dickinsonea835e72009-04-19 20:40:33 +0000404 self.assertRaises(struct.error, struct.pack, 'P', 1.0)
405 self.assertRaises(struct.error, struct.pack, 'P', 1.5)
406
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000407 def test_unpack_from(self):
408 test_string = b'abcd01234'
409 fmt = '4s'
410 s = struct.Struct(fmt)
411 for cls in (bytes, bytearray):
412 data = cls(test_string)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000413 self.assertEqual(s.unpack_from(data), (b'abcd',))
414 self.assertEqual(s.unpack_from(data, 2), (b'cd01',))
415 self.assertEqual(s.unpack_from(data, 4), (b'0123',))
416 for i in range(6):
Victor Stinnerda9ec992010-12-28 13:26:42 +0000417 self.assertEqual(s.unpack_from(data, i), (data[i:i+4],))
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000418 for i in range(6, len(test_string) + 1):
419 self.assertRaises(struct.error, s.unpack_from, data, i)
420 for cls in (bytes, bytearray):
421 data = cls(test_string)
422 self.assertEqual(struct.unpack_from(fmt, data), (b'abcd',))
423 self.assertEqual(struct.unpack_from(fmt, data, 2), (b'cd01',))
424 self.assertEqual(struct.unpack_from(fmt, data, 4), (b'0123',))
425 for i in range(6):
426 self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],))
427 for i in range(6, len(test_string) + 1):
428 self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000429
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000430 def test_pack_into(self):
431 test_string = b'Reykjavik rocks, eow!'
432 writable_buf = array.array('b', b' '*100)
433 fmt = '21s'
434 s = struct.Struct(fmt)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000435
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000436 # Test without offset
437 s.pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000438 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000439 self.assertEqual(from_buf, test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000440
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000441 # Test with offset.
442 s.pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000443 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000444 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000445
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000446 # Go beyond boundaries.
447 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000448 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0,
449 test_string)
450 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2,
451 test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000452
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000453 # Test bogus offset (issue 3694)
454 sb = small_buf
Benjamin Peterson4b83af92010-07-09 13:31:11 +0000455 self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb,
456 None)
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000457
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000458 def test_pack_into_fn(self):
459 test_string = b'Reykjavik rocks, eow!'
460 writable_buf = array.array('b', b' '*100)
461 fmt = '21s'
462 pack_into = lambda *args: struct.pack_into(fmt, *args)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000463
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000464 # Test without offset.
465 pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000466 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000467 self.assertEqual(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000468
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000469 # Test with offset.
470 pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000471 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000472 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000473
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000474 # Go beyond boundaries.
475 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000476 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0,
477 test_string)
478 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2,
479 test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000480
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000481 def test_unpack_with_buffer(self):
Ezio Melotti13925002011-03-16 11:05:33 +0200482 # SF bug 1563759: struct.unpack doesn't support buffer protocol objects
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000483 data1 = array.array('B', b'\x12\x34\x56\x78')
484 data2 = memoryview(b'\x12\x34\x56\x78') # XXX b'......XXXX......', 6, 4
485 for data in [data1, data2]:
486 value, = struct.unpack('>I', data)
487 self.assertEqual(value, 0x12345678)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000488
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000489 def test_bool(self):
Benjamin Petersonde73c452010-07-07 18:54:59 +0000490 class ExplodingBool(object):
491 def __bool__(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200492 raise OSError
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000493 for prefix in tuple("<>!=")+('',):
494 false = (), [], [], '', 0
495 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
Thomas Wouters477c8d52006-05-27 19:21:47 +0000496
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000497 falseFormat = prefix + '?' * len(false)
498 packedFalse = struct.pack(falseFormat, *false)
499 unpackedFalse = struct.unpack(falseFormat, packedFalse)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000500
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000501 trueFormat = prefix + '?' * len(true)
502 packedTrue = struct.pack(trueFormat, *true)
503 unpackedTrue = struct.unpack(trueFormat, packedTrue)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000504
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000505 self.assertEqual(len(true), len(unpackedTrue))
506 self.assertEqual(len(false), len(unpackedFalse))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000507
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000508 for t in unpackedFalse:
509 self.assertFalse(t)
510 for t in unpackedTrue:
511 self.assertTrue(t)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000512
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000513 packed = struct.pack(prefix+'?', 1)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000514
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000515 self.assertEqual(len(packed), struct.calcsize(prefix+'?'))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000516
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000517 if len(packed) != 1:
518 self.assertFalse(prefix, msg='encoded bool is not one byte: %r'
519 %packed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000520
Mark Dickinson94628ee2010-07-12 20:03:24 +0000521 try:
522 struct.pack(prefix + '?', ExplodingBool())
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200523 except OSError:
Mark Dickinson94628ee2010-07-12 20:03:24 +0000524 pass
525 else:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200526 self.fail("Expected OSError: struct.pack(%r, "
Mark Dickinson94628ee2010-07-12 20:03:24 +0000527 "ExplodingBool())" % (prefix + '?'))
Benjamin Petersonde73c452010-07-07 18:54:59 +0000528
Benjamin Petersonc937dc22010-07-07 18:44:05 +0000529 for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
530 self.assertTrue(struct.unpack('>?', c)[0])
Thomas Woutersb2137042007-02-01 18:02:27 +0000531
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000532 def test_count_overflow(self):
533 hugecount = '{}b'.format(sys.maxsize+1)
534 self.assertRaises(struct.error, struct.calcsize, hugecount)
535
Mark Dickinsonb72e6862010-06-11 19:50:30 +0000536 hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
537 self.assertRaises(struct.error, struct.calcsize, hugecount2)
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000538
Alexander Belopolsky177e8532010-06-11 16:04:59 +0000539 def test_trailing_counter(self):
540 store = array.array('b', b' '*100)
541
542 # format lists containing only count spec should result in an error
543 self.assertRaises(struct.error, struct.pack, '12345')
544 self.assertRaises(struct.error, struct.unpack, '12345', '')
545 self.assertRaises(struct.error, struct.pack_into, '12345', store, 0)
546 self.assertRaises(struct.error, struct.unpack_from, '12345', store, 0)
547
548 # Format lists with trailing count spec should result in an error
549 self.assertRaises(struct.error, struct.pack, 'c12345', 'x')
550 self.assertRaises(struct.error, struct.unpack, 'c12345', 'x')
551 self.assertRaises(struct.error, struct.pack_into, 'c12345', store, 0,
552 'x')
553 self.assertRaises(struct.error, struct.unpack_from, 'c12345', store,
554 0)
555
556 # Mixed format tests
557 self.assertRaises(struct.error, struct.pack, '14s42', 'spam and eggs')
558 self.assertRaises(struct.error, struct.unpack, '14s42',
559 'spam and eggs')
560 self.assertRaises(struct.error, struct.pack_into, '14s42', store, 0,
561 'spam and eggs')
562 self.assertRaises(struct.error, struct.unpack_from, '14s42', store, 0)
563
Mark Dickinson5b1d35b2010-08-01 11:10:28 +0000564 def test_Struct_reinitialization(self):
565 # Issue 9422: there was a memory leak when reinitializing a
566 # Struct instance. This test can be used to detect the leak
567 # when running with regrtest -L.
568 s = struct.Struct('i')
569 s.__init__('ii')
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +0000570
Martin v. Löwis33f79972012-07-29 16:33:05 +0200571 def check_sizeof(self, format_str, number_of_codes):
572 # The size of 'PyStructObject'
Martin v. Löwis2b168442012-07-29 16:38:45 +0200573 totalsize = support.calcobjsize('2n3P')
Martin v. Löwis33f79972012-07-29 16:33:05 +0200574 # The size taken up by the 'formatcode' dynamic array
Serhiy Storchakafff61f22013-05-17 10:49:44 +0300575 totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)
Martin v. Löwis33f79972012-07-29 16:33:05 +0200576 support.check_sizeof(self, struct.Struct(format_str), totalsize)
577
578 @support.cpython_only
Meador Inge90bc2dbc2012-07-28 22:16:39 -0500579 def test__sizeof__(self):
580 for code in integer_codes:
581 self.check_sizeof(code, 1)
582 self.check_sizeof('BHILfdspP', 9)
583 self.check_sizeof('B' * 1234, 1234)
584 self.check_sizeof('fd', 2)
585 self.check_sizeof('xxxxxxxxxxxxxx', 0)
Serhiy Storchakafff61f22013-05-17 10:49:44 +0300586 self.check_sizeof('100H', 1)
Meador Inge90bc2dbc2012-07-28 22:16:39 -0500587 self.check_sizeof('187s', 1)
588 self.check_sizeof('20p', 1)
589 self.check_sizeof('0s', 1)
590 self.check_sizeof('0c', 0)
Meador Ingeb14d8c92012-07-23 10:01:29 -0500591
Antoine Pitrou9f146812013-04-27 00:20:04 +0200592
593class UnpackIteratorTest(unittest.TestCase):
594 """
595 Tests for iterative unpacking (struct.Struct.iter_unpack).
596 """
597
598 def test_construct(self):
599 def _check_iterator(it):
600 self.assertIsInstance(it, abc.Iterator)
601 self.assertIsInstance(it, abc.Iterable)
602 s = struct.Struct('>ibcp')
603 it = s.iter_unpack(b"")
604 _check_iterator(it)
605 it = s.iter_unpack(b"1234567")
606 _check_iterator(it)
607 # Wrong bytes length
608 with self.assertRaises(struct.error):
609 s.iter_unpack(b"123456")
610 with self.assertRaises(struct.error):
611 s.iter_unpack(b"12345678")
612 # Zero-length struct
613 s = struct.Struct('>')
614 with self.assertRaises(struct.error):
615 s.iter_unpack(b"")
616 with self.assertRaises(struct.error):
617 s.iter_unpack(b"12")
618
619 def test_iterate(self):
620 s = struct.Struct('>IB')
621 b = bytes(range(1, 16))
622 it = s.iter_unpack(b)
623 self.assertEqual(next(it), (0x01020304, 5))
624 self.assertEqual(next(it), (0x06070809, 10))
625 self.assertEqual(next(it), (0x0b0c0d0e, 15))
626 self.assertRaises(StopIteration, next, it)
627 self.assertRaises(StopIteration, next, it)
628
629 def test_arbitrary_buffer(self):
630 s = struct.Struct('>IB')
631 b = bytes(range(1, 11))
632 it = s.iter_unpack(memoryview(b))
633 self.assertEqual(next(it), (0x01020304, 5))
634 self.assertEqual(next(it), (0x06070809, 10))
635 self.assertRaises(StopIteration, next, it)
636 self.assertRaises(StopIteration, next, it)
637
638 def test_length_hint(self):
639 lh = operator.length_hint
640 s = struct.Struct('>IB')
641 b = bytes(range(1, 16))
642 it = s.iter_unpack(b)
643 self.assertEqual(lh(it), 3)
644 next(it)
645 self.assertEqual(lh(it), 2)
646 next(it)
647 self.assertEqual(lh(it), 1)
648 next(it)
649 self.assertEqual(lh(it), 0)
650 self.assertRaises(StopIteration, next, it)
651 self.assertEqual(lh(it), 0)
652
653 def test_module_func(self):
654 # Sanity check for the global struct.iter_unpack()
655 it = struct.iter_unpack('>IB', bytes(range(1, 11)))
656 self.assertEqual(next(it), (0x01020304, 5))
657 self.assertEqual(next(it), (0x06070809, 10))
658 self.assertRaises(StopIteration, next, it)
659 self.assertRaises(StopIteration, next, it)
660
Mark Dickinson7c4e4092016-09-03 17:21:29 +0100661 def test_half_float(self):
662 # Little-endian examples from:
663 # http://en.wikipedia.org/wiki/Half_precision_floating-point_format
664 format_bits_float__cleanRoundtrip_list = [
665 (b'\x00\x3c', 1.0),
666 (b'\x00\xc0', -2.0),
667 (b'\xff\x7b', 65504.0), # (max half precision)
668 (b'\x00\x04', 2**-14), # ~= 6.10352 * 10**-5 (min pos normal)
669 (b'\x01\x00', 2**-24), # ~= 5.96046 * 10**-8 (min pos subnormal)
670 (b'\x00\x00', 0.0),
671 (b'\x00\x80', -0.0),
672 (b'\x00\x7c', float('+inf')),
673 (b'\x00\xfc', float('-inf')),
674 (b'\x55\x35', 0.333251953125), # ~= 1/3
675 ]
676
677 for le_bits, f in format_bits_float__cleanRoundtrip_list:
678 be_bits = le_bits[::-1]
679 self.assertEqual(f, struct.unpack('<e', le_bits)[0])
680 self.assertEqual(le_bits, struct.pack('<e', f))
681 self.assertEqual(f, struct.unpack('>e', be_bits)[0])
682 self.assertEqual(be_bits, struct.pack('>e', f))
683 if sys.byteorder == 'little':
684 self.assertEqual(f, struct.unpack('e', le_bits)[0])
685 self.assertEqual(le_bits, struct.pack('e', f))
686 else:
687 self.assertEqual(f, struct.unpack('e', be_bits)[0])
688 self.assertEqual(be_bits, struct.pack('e', f))
689
690 # Check for NaN handling:
691 format_bits__nan_list = [
692 ('<e', b'\x01\xfc'),
693 ('<e', b'\x00\xfe'),
694 ('<e', b'\xff\xff'),
695 ('<e', b'\x01\x7c'),
696 ('<e', b'\x00\x7e'),
697 ('<e', b'\xff\x7f'),
698 ]
699
700 for formatcode, bits in format_bits__nan_list:
701 self.assertTrue(math.isnan(struct.unpack('<e', bits)[0]))
702 self.assertTrue(math.isnan(struct.unpack('>e', bits[::-1])[0]))
703
704 # Check that packing produces a bit pattern representing a quiet NaN:
705 # all exponent bits and the msb of the fraction should all be 1.
706 packed = struct.pack('<e', math.nan)
707 self.assertEqual(packed[1] & 0x7e, 0x7e)
708 packed = struct.pack('<e', -math.nan)
709 self.assertEqual(packed[1] & 0x7e, 0x7e)
710
711 # Checks for round-to-even behavior
712 format_bits_float__rounding_list = [
713 ('>e', b'\x00\x01', 2.0**-25 + 2.0**-35), # Rounds to minimum subnormal
714 ('>e', b'\x00\x00', 2.0**-25), # Underflows to zero (nearest even mode)
715 ('>e', b'\x00\x00', 2.0**-26), # Underflows to zero
716 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-24), # Largest subnormal.
717 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-25 - 2.0**-65),
718 ('>e', b'\x04\x00', 2.0**-14 - 2.0**-25),
719 ('>e', b'\x04\x00', 2.0**-14), # Smallest normal.
720 ('>e', b'\x3c\x01', 1.0+2.0**-11 + 2.0**-16), # rounds to 1.0+2**(-10)
721 ('>e', b'\x3c\x00', 1.0+2.0**-11), # rounds to 1.0 (nearest even mode)
722 ('>e', b'\x3c\x00', 1.0+2.0**-12), # rounds to 1.0
723 ('>e', b'\x7b\xff', 65504), # largest normal
724 ('>e', b'\x7b\xff', 65519), # rounds to 65504
725 ('>e', b'\x80\x01', -2.0**-25 - 2.0**-35), # Rounds to minimum subnormal
726 ('>e', b'\x80\x00', -2.0**-25), # Underflows to zero (nearest even mode)
727 ('>e', b'\x80\x00', -2.0**-26), # Underflows to zero
728 ('>e', b'\xbc\x01', -1.0-2.0**-11 - 2.0**-16), # rounds to 1.0+2**(-10)
729 ('>e', b'\xbc\x00', -1.0-2.0**-11), # rounds to 1.0 (nearest even mode)
730 ('>e', b'\xbc\x00', -1.0-2.0**-12), # rounds to 1.0
731 ('>e', b'\xfb\xff', -65519), # rounds to 65504
732 ]
733
734 for formatcode, bits, f in format_bits_float__rounding_list:
735 self.assertEqual(bits, struct.pack(formatcode, f))
736
737 # This overflows, and so raises an error
738 format_bits_float__roundingError_list = [
739 # Values that round to infinity.
740 ('>e', 65520.0),
741 ('>e', 65536.0),
742 ('>e', 1e300),
743 ('>e', -65520.0),
744 ('>e', -65536.0),
745 ('>e', -1e300),
746 ('<e', 65520.0),
747 ('<e', 65536.0),
748 ('<e', 1e300),
749 ('<e', -65520.0),
750 ('<e', -65536.0),
751 ('<e', -1e300),
752 ]
753
754 for formatcode, f in format_bits_float__roundingError_list:
755 self.assertRaises(OverflowError, struct.pack, formatcode, f)
756
757 # Double rounding
758 format_bits_float__doubleRoundingError_list = [
759 ('>e', b'\x67\xff', 0x1ffdffffff * 2**-26), # should be 2047, if double-rounded 64>32>16, becomes 2048
760 ]
761
762 for formatcode, bits, f in format_bits_float__doubleRoundingError_list:
763 self.assertEqual(bits, struct.pack(formatcode, f))
764
Antoine Pitrou9f146812013-04-27 00:20:04 +0200765
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000766if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500767 unittest.main()