blob: 454082e66d3f86bdfbd81a24610f11d9d8808756 [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 Stinner3f2d1012017-02-02 12:09:30 +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')
Victor Stinnerc0f59ad2017-02-02 14:24:16 +0100533 self.assertRaises(struct.error, struct.unpack, '12345', b'')
Alexander Belopolsky177e8532010-06-11 16:04:59 +0000534 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')
Victor Stinnerc0f59ad2017-02-02 14:24:16 +0100539 self.assertRaises(struct.error, struct.unpack, 'c12345', b'x')
Alexander Belopolsky177e8532010-06-11 16:04:59 +0000540 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',
Victor Stinnerc0f59ad2017-02-02 14:24:16 +0100548 b'spam and eggs')
Alexander Belopolsky177e8532010-06-11 16:04:59 +0000549 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
Andrew Nesterf78b1192017-04-04 13:46:25 +0300581 def test_boundary_error_message(self):
Xiang Zhangc10b2882018-03-11 02:58:52 +0800582 regex1 = (
Andrew Nesterf78b1192017-04-04 13:46:25 +0300583 r'pack_into requires a buffer of at least 6 '
584 r'bytes for packing 1 bytes at offset 5 '
585 r'\(actual buffer size is 1\)'
586 )
Xiang Zhangc10b2882018-03-11 02:58:52 +0800587 with self.assertRaisesRegex(struct.error, regex1):
Andrew Nesterf78b1192017-04-04 13:46:25 +0300588 struct.pack_into('b', bytearray(1), 5, 1)
589
Xiang Zhangc10b2882018-03-11 02:58:52 +0800590 regex2 = (
591 r'unpack_from requires a buffer of at least 6 '
592 r'bytes for unpacking 1 bytes at offset 5 '
593 r'\(actual buffer size is 1\)'
594 )
595 with self.assertRaisesRegex(struct.error, regex2):
596 struct.unpack_from('b', bytearray(1), 5)
597
Andrew Nesterf78b1192017-04-04 13:46:25 +0300598 def test_boundary_error_message_with_negative_offset(self):
599 byte_list = bytearray(10)
600 with self.assertRaisesRegex(
601 struct.error,
602 r'no space to pack 4 bytes at offset -2'):
603 struct.pack_into('<I', byte_list, -2, 123)
604
605 with self.assertRaisesRegex(
606 struct.error,
607 'offset -11 out of range for 10-byte buffer'):
608 struct.pack_into('<B', byte_list, -11, 123)
Antoine Pitrou9f146812013-04-27 00:20:04 +0200609
Xiang Zhangc10b2882018-03-11 02:58:52 +0800610 with self.assertRaisesRegex(
611 struct.error,
612 r'not enough data to unpack 4 bytes at offset -2'):
613 struct.unpack_from('<I', byte_list, -2)
614
615 with self.assertRaisesRegex(
616 struct.error,
617 "offset -11 out of range for 10-byte buffer"):
618 struct.unpack_from('<B', byte_list, -11)
619
Johan Liuaead53b2017-06-02 14:33:04 +0800620 def test_boundary_error_message_with_large_offset(self):
621 # Test overflows cause by large offset and value size (issue 30245)
Xiang Zhangc10b2882018-03-11 02:58:52 +0800622 regex1 = (
Johan Liuaead53b2017-06-02 14:33:04 +0800623 r'pack_into requires a buffer of at least ' + str(sys.maxsize + 4) +
624 r' bytes for packing 4 bytes at offset ' + str(sys.maxsize) +
625 r' \(actual buffer size is 10\)'
626 )
Xiang Zhangc10b2882018-03-11 02:58:52 +0800627 with self.assertRaisesRegex(struct.error, regex1):
Johan Liuaead53b2017-06-02 14:33:04 +0800628 struct.pack_into('<I', bytearray(10), sys.maxsize, 1)
629
Xiang Zhangc10b2882018-03-11 02:58:52 +0800630 regex2 = (
631 r'unpack_from requires a buffer of at least ' + str(sys.maxsize + 4) +
632 r' bytes for unpacking 4 bytes at offset ' + str(sys.maxsize) +
633 r' \(actual buffer size is 10\)'
634 )
635 with self.assertRaisesRegex(struct.error, regex2):
636 struct.unpack_from('<I', bytearray(10), sys.maxsize)
637
Serhiy Storchaka40db90c2017-04-20 21:19:31 +0300638 def test_issue29802(self):
639 # When the second argument of struct.unpack() was of wrong type
640 # the Struct object was decrefed twice and the reference to
641 # deallocated object was left in a cache.
642 with self.assertRaises(TypeError):
Serhiy Storchaka73c47082017-10-21 21:59:23 +0300643 struct.unpack('b', 0)
Serhiy Storchaka40db90c2017-04-20 21:19:31 +0300644 # Shouldn't crash.
Serhiy Storchaka73c47082017-10-21 21:59:23 +0300645 self.assertEqual(struct.unpack('b', b'a'), (b'a'[0],))
Serhiy Storchaka40db90c2017-04-20 21:19:31 +0300646
Victor Stinnerf87b85f2017-06-23 15:11:12 +0200647 def test_format_attr(self):
648 s = struct.Struct('=i2H')
649 self.assertEqual(s.format, '=i2H')
650
651 # use a bytes string
652 s2 = struct.Struct(s.format.encode())
653 self.assertEqual(s2.format, s.format)
654
Serhiy Storchaka40db90c2017-04-20 21:19:31 +0300655
Antoine Pitrou9f146812013-04-27 00:20:04 +0200656class UnpackIteratorTest(unittest.TestCase):
657 """
658 Tests for iterative unpacking (struct.Struct.iter_unpack).
659 """
660
661 def test_construct(self):
662 def _check_iterator(it):
663 self.assertIsInstance(it, abc.Iterator)
664 self.assertIsInstance(it, abc.Iterable)
665 s = struct.Struct('>ibcp')
666 it = s.iter_unpack(b"")
667 _check_iterator(it)
668 it = s.iter_unpack(b"1234567")
669 _check_iterator(it)
670 # Wrong bytes length
671 with self.assertRaises(struct.error):
672 s.iter_unpack(b"123456")
673 with self.assertRaises(struct.error):
674 s.iter_unpack(b"12345678")
675 # Zero-length struct
676 s = struct.Struct('>')
677 with self.assertRaises(struct.error):
678 s.iter_unpack(b"")
679 with self.assertRaises(struct.error):
680 s.iter_unpack(b"12")
681
682 def test_iterate(self):
683 s = struct.Struct('>IB')
684 b = bytes(range(1, 16))
685 it = s.iter_unpack(b)
686 self.assertEqual(next(it), (0x01020304, 5))
687 self.assertEqual(next(it), (0x06070809, 10))
688 self.assertEqual(next(it), (0x0b0c0d0e, 15))
689 self.assertRaises(StopIteration, next, it)
690 self.assertRaises(StopIteration, next, it)
691
692 def test_arbitrary_buffer(self):
693 s = struct.Struct('>IB')
694 b = bytes(range(1, 11))
695 it = s.iter_unpack(memoryview(b))
696 self.assertEqual(next(it), (0x01020304, 5))
697 self.assertEqual(next(it), (0x06070809, 10))
698 self.assertRaises(StopIteration, next, it)
699 self.assertRaises(StopIteration, next, it)
700
701 def test_length_hint(self):
702 lh = operator.length_hint
703 s = struct.Struct('>IB')
704 b = bytes(range(1, 16))
705 it = s.iter_unpack(b)
706 self.assertEqual(lh(it), 3)
707 next(it)
708 self.assertEqual(lh(it), 2)
709 next(it)
710 self.assertEqual(lh(it), 1)
711 next(it)
712 self.assertEqual(lh(it), 0)
713 self.assertRaises(StopIteration, next, it)
714 self.assertEqual(lh(it), 0)
715
716 def test_module_func(self):
717 # Sanity check for the global struct.iter_unpack()
718 it = struct.iter_unpack('>IB', bytes(range(1, 11)))
719 self.assertEqual(next(it), (0x01020304, 5))
720 self.assertEqual(next(it), (0x06070809, 10))
721 self.assertRaises(StopIteration, next, it)
722 self.assertRaises(StopIteration, next, it)
723
Mark Dickinson7c4e4092016-09-03 17:21:29 +0100724 def test_half_float(self):
725 # Little-endian examples from:
726 # http://en.wikipedia.org/wiki/Half_precision_floating-point_format
727 format_bits_float__cleanRoundtrip_list = [
728 (b'\x00\x3c', 1.0),
729 (b'\x00\xc0', -2.0),
730 (b'\xff\x7b', 65504.0), # (max half precision)
731 (b'\x00\x04', 2**-14), # ~= 6.10352 * 10**-5 (min pos normal)
732 (b'\x01\x00', 2**-24), # ~= 5.96046 * 10**-8 (min pos subnormal)
733 (b'\x00\x00', 0.0),
734 (b'\x00\x80', -0.0),
735 (b'\x00\x7c', float('+inf')),
736 (b'\x00\xfc', float('-inf')),
737 (b'\x55\x35', 0.333251953125), # ~= 1/3
738 ]
739
740 for le_bits, f in format_bits_float__cleanRoundtrip_list:
741 be_bits = le_bits[::-1]
742 self.assertEqual(f, struct.unpack('<e', le_bits)[0])
743 self.assertEqual(le_bits, struct.pack('<e', f))
744 self.assertEqual(f, struct.unpack('>e', be_bits)[0])
745 self.assertEqual(be_bits, struct.pack('>e', f))
746 if sys.byteorder == 'little':
747 self.assertEqual(f, struct.unpack('e', le_bits)[0])
748 self.assertEqual(le_bits, struct.pack('e', f))
749 else:
750 self.assertEqual(f, struct.unpack('e', be_bits)[0])
751 self.assertEqual(be_bits, struct.pack('e', f))
752
753 # Check for NaN handling:
754 format_bits__nan_list = [
755 ('<e', b'\x01\xfc'),
756 ('<e', b'\x00\xfe'),
757 ('<e', b'\xff\xff'),
758 ('<e', b'\x01\x7c'),
759 ('<e', b'\x00\x7e'),
760 ('<e', b'\xff\x7f'),
761 ]
762
763 for formatcode, bits in format_bits__nan_list:
764 self.assertTrue(math.isnan(struct.unpack('<e', bits)[0]))
765 self.assertTrue(math.isnan(struct.unpack('>e', bits[::-1])[0]))
766
767 # Check that packing produces a bit pattern representing a quiet NaN:
768 # all exponent bits and the msb of the fraction should all be 1.
769 packed = struct.pack('<e', math.nan)
770 self.assertEqual(packed[1] & 0x7e, 0x7e)
771 packed = struct.pack('<e', -math.nan)
772 self.assertEqual(packed[1] & 0x7e, 0x7e)
773
774 # Checks for round-to-even behavior
775 format_bits_float__rounding_list = [
776 ('>e', b'\x00\x01', 2.0**-25 + 2.0**-35), # Rounds to minimum subnormal
777 ('>e', b'\x00\x00', 2.0**-25), # Underflows to zero (nearest even mode)
778 ('>e', b'\x00\x00', 2.0**-26), # Underflows to zero
779 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-24), # Largest subnormal.
780 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-25 - 2.0**-65),
781 ('>e', b'\x04\x00', 2.0**-14 - 2.0**-25),
782 ('>e', b'\x04\x00', 2.0**-14), # Smallest normal.
783 ('>e', b'\x3c\x01', 1.0+2.0**-11 + 2.0**-16), # rounds to 1.0+2**(-10)
784 ('>e', b'\x3c\x00', 1.0+2.0**-11), # rounds to 1.0 (nearest even mode)
785 ('>e', b'\x3c\x00', 1.0+2.0**-12), # rounds to 1.0
786 ('>e', b'\x7b\xff', 65504), # largest normal
787 ('>e', b'\x7b\xff', 65519), # rounds to 65504
788 ('>e', b'\x80\x01', -2.0**-25 - 2.0**-35), # Rounds to minimum subnormal
789 ('>e', b'\x80\x00', -2.0**-25), # Underflows to zero (nearest even mode)
790 ('>e', b'\x80\x00', -2.0**-26), # Underflows to zero
791 ('>e', b'\xbc\x01', -1.0-2.0**-11 - 2.0**-16), # rounds to 1.0+2**(-10)
792 ('>e', b'\xbc\x00', -1.0-2.0**-11), # rounds to 1.0 (nearest even mode)
793 ('>e', b'\xbc\x00', -1.0-2.0**-12), # rounds to 1.0
794 ('>e', b'\xfb\xff', -65519), # rounds to 65504
795 ]
796
797 for formatcode, bits, f in format_bits_float__rounding_list:
798 self.assertEqual(bits, struct.pack(formatcode, f))
799
800 # This overflows, and so raises an error
801 format_bits_float__roundingError_list = [
802 # Values that round to infinity.
803 ('>e', 65520.0),
804 ('>e', 65536.0),
805 ('>e', 1e300),
806 ('>e', -65520.0),
807 ('>e', -65536.0),
808 ('>e', -1e300),
809 ('<e', 65520.0),
810 ('<e', 65536.0),
811 ('<e', 1e300),
812 ('<e', -65520.0),
813 ('<e', -65536.0),
814 ('<e', -1e300),
815 ]
816
817 for formatcode, f in format_bits_float__roundingError_list:
818 self.assertRaises(OverflowError, struct.pack, formatcode, f)
819
820 # Double rounding
821 format_bits_float__doubleRoundingError_list = [
822 ('>e', b'\x67\xff', 0x1ffdffffff * 2**-26), # should be 2047, if double-rounded 64>32>16, becomes 2048
823 ]
824
825 for formatcode, bits, f in format_bits_float__doubleRoundingError_list:
826 self.assertEqual(bits, struct.pack(formatcode, f))
827
Antoine Pitrou9f146812013-04-27 00:20:04 +0200828
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000829if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500830 unittest.main()