blob: 8ffa7e6144a580a4c8c1e7387ac273f30a990398 [file] [log] [blame]
Antoine Pitrou9f146812013-04-27 00:20:04 +02001from collections import abc
Thomas Wouters477c8d52006-05-27 19:21:47 +00002import array
Antoine Pitrou9f146812013-04-27 00:20:04 +02003import operator
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +00004import unittest
5import struct
Tim Peters17e17d42001-06-13 22:45:27 +00006import sys
Mark Dickinson79d38ac2010-03-05 14:44:08 +00007
Martin v. Löwis33f79972012-07-29 16:33:05 +02008from test import support
Mark Dickinson79d38ac2010-03-05 14:44:08 +00009
Tim Peters17e17d42001-06-13 22:45:27 +000010ISBIGENDIAN = sys.byteorder == "big"
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +000011IS32BIT = sys.maxsize == 0x7fffffff
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
283 # '__index__' method returns and 'int' or 'long'.
284 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.
370 import math
371
372 for base in range(1, 33):
373 # smaller <- largest representable float less than base.
374 delta = 0.5
375 while base - delta / 2.0 != base:
376 delta /= 2.0
377 smaller = base - delta
378 # Packing this rounds away a solid string of trailing 1 bits.
379 packed = struct.pack("<f", smaller)
380 unpacked = struct.unpack("<f", packed)[0]
381 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
382 # 16, respectively.
383 self.assertEqual(base, unpacked)
384 bigpacked = struct.pack(">f", smaller)
385 self.assertEqual(bigpacked, string_reverse(packed))
386 unpacked = struct.unpack(">f", bigpacked)[0]
387 self.assertEqual(base, unpacked)
388
389 # Largest finite IEEE single.
390 big = (1 << 24) - 1
391 big = math.ldexp(big, 127 - 23)
Tim Petersd50ade62003-03-20 18:32:13 +0000392 packed = struct.pack(">f", big)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000393 unpacked = struct.unpack(">f", packed)[0]
394 self.assertEqual(big, unpacked)
Tim Petersd50ade62003-03-20 18:32:13 +0000395
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000396 # The same, but tack on a 1 bit so it rounds up to infinity.
397 big = (1 << 25) - 1
398 big = math.ldexp(big, 127 - 24)
399 self.assertRaises(OverflowError, struct.pack, ">f", big)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000400
Mark Dickinsonea835e72009-04-19 20:40:33 +0000401 def test_1530559(self):
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200402 for code, byteorder in iter_integer_formats():
403 format = byteorder + code
404 self.assertRaises(struct.error, struct.pack, format, 1.0)
405 self.assertRaises(struct.error, struct.pack, format, 1.5)
Mark Dickinsonea835e72009-04-19 20:40:33 +0000406 self.assertRaises(struct.error, struct.pack, 'P', 1.0)
407 self.assertRaises(struct.error, struct.pack, 'P', 1.5)
408
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000409 def test_unpack_from(self):
410 test_string = b'abcd01234'
411 fmt = '4s'
412 s = struct.Struct(fmt)
413 for cls in (bytes, bytearray):
414 data = cls(test_string)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000415 self.assertEqual(s.unpack_from(data), (b'abcd',))
416 self.assertEqual(s.unpack_from(data, 2), (b'cd01',))
417 self.assertEqual(s.unpack_from(data, 4), (b'0123',))
418 for i in range(6):
Victor Stinnerda9ec992010-12-28 13:26:42 +0000419 self.assertEqual(s.unpack_from(data, i), (data[i:i+4],))
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000420 for i in range(6, len(test_string) + 1):
421 self.assertRaises(struct.error, s.unpack_from, data, i)
422 for cls in (bytes, bytearray):
423 data = cls(test_string)
424 self.assertEqual(struct.unpack_from(fmt, data), (b'abcd',))
425 self.assertEqual(struct.unpack_from(fmt, data, 2), (b'cd01',))
426 self.assertEqual(struct.unpack_from(fmt, data, 4), (b'0123',))
427 for i in range(6):
428 self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],))
429 for i in range(6, len(test_string) + 1):
430 self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000431
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000432 def test_pack_into(self):
433 test_string = b'Reykjavik rocks, eow!'
434 writable_buf = array.array('b', b' '*100)
435 fmt = '21s'
436 s = struct.Struct(fmt)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000437
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000438 # Test without offset
439 s.pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000440 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000441 self.assertEqual(from_buf, test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000442
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000443 # Test with offset.
444 s.pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000445 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000446 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000447
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000448 # Go beyond boundaries.
449 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000450 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0,
451 test_string)
452 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2,
453 test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000454
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000455 # Test bogus offset (issue 3694)
456 sb = small_buf
Benjamin Peterson4b83af92010-07-09 13:31:11 +0000457 self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb,
458 None)
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000459
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000460 def test_pack_into_fn(self):
461 test_string = b'Reykjavik rocks, eow!'
462 writable_buf = array.array('b', b' '*100)
463 fmt = '21s'
464 pack_into = lambda *args: struct.pack_into(fmt, *args)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000465
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000466 # Test without offset.
467 pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000468 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000469 self.assertEqual(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000470
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000471 # Test with offset.
472 pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000473 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000474 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000475
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000476 # Go beyond boundaries.
477 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000478 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0,
479 test_string)
480 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2,
481 test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000482
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000483 def test_unpack_with_buffer(self):
Ezio Melotti13925002011-03-16 11:05:33 +0200484 # SF bug 1563759: struct.unpack doesn't support buffer protocol objects
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000485 data1 = array.array('B', b'\x12\x34\x56\x78')
486 data2 = memoryview(b'\x12\x34\x56\x78') # XXX b'......XXXX......', 6, 4
487 for data in [data1, data2]:
488 value, = struct.unpack('>I', data)
489 self.assertEqual(value, 0x12345678)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000490
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000491 def test_bool(self):
Benjamin Petersonde73c452010-07-07 18:54:59 +0000492 class ExplodingBool(object):
493 def __bool__(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200494 raise OSError
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000495 for prefix in tuple("<>!=")+('',):
496 false = (), [], [], '', 0
497 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
Thomas Wouters477c8d52006-05-27 19:21:47 +0000498
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000499 falseFormat = prefix + '?' * len(false)
500 packedFalse = struct.pack(falseFormat, *false)
501 unpackedFalse = struct.unpack(falseFormat, packedFalse)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000502
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000503 trueFormat = prefix + '?' * len(true)
504 packedTrue = struct.pack(trueFormat, *true)
505 unpackedTrue = struct.unpack(trueFormat, packedTrue)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000506
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000507 self.assertEqual(len(true), len(unpackedTrue))
508 self.assertEqual(len(false), len(unpackedFalse))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000509
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000510 for t in unpackedFalse:
511 self.assertFalse(t)
512 for t in unpackedTrue:
513 self.assertTrue(t)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000514
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000515 packed = struct.pack(prefix+'?', 1)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000516
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000517 self.assertEqual(len(packed), struct.calcsize(prefix+'?'))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000518
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000519 if len(packed) != 1:
520 self.assertFalse(prefix, msg='encoded bool is not one byte: %r'
521 %packed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000522
Mark Dickinson94628ee2010-07-12 20:03:24 +0000523 try:
524 struct.pack(prefix + '?', ExplodingBool())
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200525 except OSError:
Mark Dickinson94628ee2010-07-12 20:03:24 +0000526 pass
527 else:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200528 self.fail("Expected OSError: struct.pack(%r, "
Mark Dickinson94628ee2010-07-12 20:03:24 +0000529 "ExplodingBool())" % (prefix + '?'))
Benjamin Petersonde73c452010-07-07 18:54:59 +0000530
Benjamin Petersonc937dc22010-07-07 18:44:05 +0000531 for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
532 self.assertTrue(struct.unpack('>?', c)[0])
Thomas Woutersb2137042007-02-01 18:02:27 +0000533
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000534 def test_count_overflow(self):
535 hugecount = '{}b'.format(sys.maxsize+1)
536 self.assertRaises(struct.error, struct.calcsize, hugecount)
537
Mark Dickinsonb72e6862010-06-11 19:50:30 +0000538 hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
539 self.assertRaises(struct.error, struct.calcsize, hugecount2)
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000540
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +0000541 if IS32BIT:
542 def test_crasher(self):
543 self.assertRaises(MemoryError, struct.pack, "357913941b", "a")
544
Alexander Belopolsky177e8532010-06-11 16:04:59 +0000545 def test_trailing_counter(self):
546 store = array.array('b', b' '*100)
547
548 # format lists containing only count spec should result in an error
549 self.assertRaises(struct.error, struct.pack, '12345')
550 self.assertRaises(struct.error, struct.unpack, '12345', '')
551 self.assertRaises(struct.error, struct.pack_into, '12345', store, 0)
552 self.assertRaises(struct.error, struct.unpack_from, '12345', store, 0)
553
554 # Format lists with trailing count spec should result in an error
555 self.assertRaises(struct.error, struct.pack, 'c12345', 'x')
556 self.assertRaises(struct.error, struct.unpack, 'c12345', 'x')
557 self.assertRaises(struct.error, struct.pack_into, 'c12345', store, 0,
558 'x')
559 self.assertRaises(struct.error, struct.unpack_from, 'c12345', store,
560 0)
561
562 # Mixed format tests
563 self.assertRaises(struct.error, struct.pack, '14s42', 'spam and eggs')
564 self.assertRaises(struct.error, struct.unpack, '14s42',
565 'spam and eggs')
566 self.assertRaises(struct.error, struct.pack_into, '14s42', store, 0,
567 'spam and eggs')
568 self.assertRaises(struct.error, struct.unpack_from, '14s42', store, 0)
569
Mark Dickinson5b1d35b2010-08-01 11:10:28 +0000570 def test_Struct_reinitialization(self):
571 # Issue 9422: there was a memory leak when reinitializing a
572 # Struct instance. This test can be used to detect the leak
573 # when running with regrtest -L.
574 s = struct.Struct('i')
575 s.__init__('ii')
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +0000576
Martin v. Löwis33f79972012-07-29 16:33:05 +0200577 def check_sizeof(self, format_str, number_of_codes):
578 # The size of 'PyStructObject'
Martin v. Löwis2b168442012-07-29 16:38:45 +0200579 totalsize = support.calcobjsize('2n3P')
Martin v. Löwis33f79972012-07-29 16:33:05 +0200580 # The size taken up by the 'formatcode' dynamic array
Martin v. Löwis2b168442012-07-29 16:38:45 +0200581 totalsize += struct.calcsize('P2n0P') * (number_of_codes + 1)
Martin v. Löwis33f79972012-07-29 16:33:05 +0200582 support.check_sizeof(self, struct.Struct(format_str), totalsize)
583
584 @support.cpython_only
Meador Inge90bc2dbc2012-07-28 22:16:39 -0500585 def test__sizeof__(self):
586 for code in integer_codes:
587 self.check_sizeof(code, 1)
588 self.check_sizeof('BHILfdspP', 9)
589 self.check_sizeof('B' * 1234, 1234)
590 self.check_sizeof('fd', 2)
591 self.check_sizeof('xxxxxxxxxxxxxx', 0)
592 self.check_sizeof('100H', 100)
593 self.check_sizeof('187s', 1)
594 self.check_sizeof('20p', 1)
595 self.check_sizeof('0s', 1)
596 self.check_sizeof('0c', 0)
Meador Ingeb14d8c92012-07-23 10:01:29 -0500597
Antoine Pitrou9f146812013-04-27 00:20:04 +0200598
599class UnpackIteratorTest(unittest.TestCase):
600 """
601 Tests for iterative unpacking (struct.Struct.iter_unpack).
602 """
603
604 def test_construct(self):
605 def _check_iterator(it):
606 self.assertIsInstance(it, abc.Iterator)
607 self.assertIsInstance(it, abc.Iterable)
608 s = struct.Struct('>ibcp')
609 it = s.iter_unpack(b"")
610 _check_iterator(it)
611 it = s.iter_unpack(b"1234567")
612 _check_iterator(it)
613 # Wrong bytes length
614 with self.assertRaises(struct.error):
615 s.iter_unpack(b"123456")
616 with self.assertRaises(struct.error):
617 s.iter_unpack(b"12345678")
618 # Zero-length struct
619 s = struct.Struct('>')
620 with self.assertRaises(struct.error):
621 s.iter_unpack(b"")
622 with self.assertRaises(struct.error):
623 s.iter_unpack(b"12")
624
625 def test_iterate(self):
626 s = struct.Struct('>IB')
627 b = bytes(range(1, 16))
628 it = s.iter_unpack(b)
629 self.assertEqual(next(it), (0x01020304, 5))
630 self.assertEqual(next(it), (0x06070809, 10))
631 self.assertEqual(next(it), (0x0b0c0d0e, 15))
632 self.assertRaises(StopIteration, next, it)
633 self.assertRaises(StopIteration, next, it)
634
635 def test_arbitrary_buffer(self):
636 s = struct.Struct('>IB')
637 b = bytes(range(1, 11))
638 it = s.iter_unpack(memoryview(b))
639 self.assertEqual(next(it), (0x01020304, 5))
640 self.assertEqual(next(it), (0x06070809, 10))
641 self.assertRaises(StopIteration, next, it)
642 self.assertRaises(StopIteration, next, it)
643
644 def test_length_hint(self):
645 lh = operator.length_hint
646 s = struct.Struct('>IB')
647 b = bytes(range(1, 16))
648 it = s.iter_unpack(b)
649 self.assertEqual(lh(it), 3)
650 next(it)
651 self.assertEqual(lh(it), 2)
652 next(it)
653 self.assertEqual(lh(it), 1)
654 next(it)
655 self.assertEqual(lh(it), 0)
656 self.assertRaises(StopIteration, next, it)
657 self.assertEqual(lh(it), 0)
658
659 def test_module_func(self):
660 # Sanity check for the global struct.iter_unpack()
661 it = struct.iter_unpack('>IB', bytes(range(1, 11)))
662 self.assertEqual(next(it), (0x01020304, 5))
663 self.assertEqual(next(it), (0x06070809, 10))
664 self.assertRaises(StopIteration, next, it)
665 self.assertRaises(StopIteration, next, it)
666
667
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000668def test_main():
Antoine Pitrou9f146812013-04-27 00:20:04 +0200669 support.run_unittest(__name__)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000670
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000671if __name__ == '__main__':
672 test_main()