blob: 0107eebca6bb7fbb5ac685bf475b3069095a6b00 [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"
Tim Peters17e17d42001-06-13 22:45:27 +000011
Antoine Pitrou45d9c912011-10-06 15:27:40 +020012integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'n', 'N'
Mark Dickinsonb9f751a2010-04-03 15:07:40 +000013byteorders = '', '@', '=', '<', '>', '!'
14
Antoine Pitrou45d9c912011-10-06 15:27:40 +020015def iter_integer_formats(byteorders=byteorders):
16 for code in integer_codes:
17 for byteorder in byteorders:
18 if (byteorder in ('', '@') and code in ('q', 'Q') and
19 not HAVE_LONG_LONG):
20 continue
21 if (byteorder not in ('', '@') and code in ('n', 'N')):
22 continue
23 yield code, byteorder
24
Mark Dickinsonb9f751a2010-04-03 15:07:40 +000025# Native 'q' packing isn't available on systems that don't have the C
26# long long type.
27try:
28 struct.pack('q', 5)
29except struct.error:
30 HAVE_LONG_LONG = False
31else:
32 HAVE_LONG_LONG = True
33
Tim Peters17e17d42001-06-13 22:45:27 +000034def string_reverse(s):
Guido van Rossume625fd52007-05-27 09:19:04 +000035 return s[::-1]
Tim Peters17e17d42001-06-13 22:45:27 +000036
37def bigendian_to_native(value):
38 if ISBIGENDIAN:
39 return value
40 else:
41 return string_reverse(value)
42
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000043class StructTest(unittest.TestCase):
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000044 def test_isbigendian(self):
Amaury Forgeot d'Arcf9f29822008-06-17 21:56:01 +000045 self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN)
Tim Peters7a3bfc32001-06-12 01:22:22 +000046
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000047 def test_consistence(self):
48 self.assertRaises(struct.error, struct.calcsize, 'Z')
Tim Peters7a3bfc32001-06-12 01:22:22 +000049
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000050 sz = struct.calcsize('i')
51 self.assertEqual(sz * 3, struct.calcsize('iii'))
Tim Peters7a3bfc32001-06-12 01:22:22 +000052
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000053 fmt = 'cbxxxxxxhhhhiillffd?'
54 fmt3 = '3c3b18x12h6i6l6f3d3?'
55 sz = struct.calcsize(fmt)
56 sz3 = struct.calcsize(fmt3)
57 self.assertEqual(sz * 3, sz3)
Tim Peters7a3bfc32001-06-12 01:22:22 +000058
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000059 self.assertRaises(struct.error, struct.pack, 'iii', 3)
60 self.assertRaises(struct.error, struct.pack, 'i', 3, 3, 3)
Benjamin Petersona04a32d2010-07-09 13:28:42 +000061 self.assertRaises((TypeError, struct.error), struct.pack, 'i', 'foo')
62 self.assertRaises((TypeError, struct.error), struct.pack, 'P', 'foo')
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000063 self.assertRaises(struct.error, struct.unpack, 'd', b'flap')
64 s = struct.pack('ii', 1, 2)
65 self.assertRaises(struct.error, struct.unpack, 'iii', s)
66 self.assertRaises(struct.error, struct.unpack, 'i', s)
Tim Peters7a3bfc32001-06-12 01:22:22 +000067
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000068 def test_transitiveness(self):
69 c = b'a'
70 b = 1
71 h = 255
72 i = 65535
73 l = 65536
74 f = 3.1415
75 d = 3.1415
76 t = True
Tim Peters7a3bfc32001-06-12 01:22:22 +000077
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000078 for prefix in ('', '@', '<', '>', '=', '!'):
79 for format in ('xcbhilfd?', 'xcBHILfd?'):
80 format = prefix + format
81 s = struct.pack(format, c, b, h, i, l, f, d, t)
82 cp, bp, hp, ip, lp, fp, dp, tp = struct.unpack(format, s)
83 self.assertEqual(cp, c)
84 self.assertEqual(bp, b)
85 self.assertEqual(hp, h)
86 self.assertEqual(ip, i)
87 self.assertEqual(lp, l)
88 self.assertEqual(int(100 * fp), int(100 * f))
89 self.assertEqual(int(100 * dp), int(100 * d))
90 self.assertEqual(tp, t)
Tim Peters7a3bfc32001-06-12 01:22:22 +000091
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +000092 def test_new_features(self):
93 # Test some of the new features in detail
94 # (format, argument, big-endian result, little-endian result, asymmetric)
95 tests = [
Victor Stinnerda9ec992010-12-28 13:26:42 +000096 ('c', b'a', b'a', b'a', 0),
97 ('xc', b'a', b'\0a', b'\0a', 0),
98 ('cx', b'a', b'a\0', b'a\0', 0),
99 ('s', b'a', b'a', b'a', 0),
100 ('0s', b'helloworld', b'', b'', 1),
101 ('1s', b'helloworld', b'h', b'h', 1),
102 ('9s', b'helloworld', b'helloworl', b'helloworl', 1),
103 ('10s', b'helloworld', b'helloworld', b'helloworld', 0),
104 ('11s', b'helloworld', b'helloworld\0', b'helloworld\0', 1),
105 ('20s', b'helloworld', b'helloworld'+10*b'\0', b'helloworld'+10*b'\0', 1),
106 ('b', 7, b'\7', b'\7', 0),
107 ('b', -7, b'\371', b'\371', 0),
108 ('B', 7, b'\7', b'\7', 0),
109 ('B', 249, b'\371', b'\371', 0),
110 ('h', 700, b'\002\274', b'\274\002', 0),
111 ('h', -700, b'\375D', b'D\375', 0),
112 ('H', 700, b'\002\274', b'\274\002', 0),
113 ('H', 0x10000-700, b'\375D', b'D\375', 0),
114 ('i', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
115 ('i', -70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
116 ('I', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
117 ('I', 0x100000000-70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
118 ('l', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
119 ('l', -70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
120 ('L', 70000000, b'\004,\035\200', b'\200\035,\004', 0),
121 ('L', 0x100000000-70000000, b'\373\323\342\200', b'\200\342\323\373', 0),
122 ('f', 2.0, b'@\000\000\000', b'\000\000\000@', 0),
123 ('d', 2.0, b'@\000\000\000\000\000\000\000',
124 b'\000\000\000\000\000\000\000@', 0),
125 ('f', -2.0, b'\300\000\000\000', b'\000\000\000\300', 0),
126 ('d', -2.0, b'\300\000\000\000\000\000\000\000',
127 b'\000\000\000\000\000\000\000\300', 0),
128 ('?', 0, b'\0', b'\0', 0),
129 ('?', 3, b'\1', b'\1', 1),
130 ('?', True, b'\1', b'\1', 0),
131 ('?', [], b'\0', b'\0', 1),
132 ('?', (1,), b'\1', b'\1', 1),
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000133 ]
Tim Peters7a3bfc32001-06-12 01:22:22 +0000134
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000135 for fmt, arg, big, lil, asy in tests:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000136 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
137 ('='+fmt, ISBIGENDIAN and big or lil)]:
138 res = struct.pack(xfmt, arg)
139 self.assertEqual(res, exp)
140 self.assertEqual(struct.calcsize(xfmt), len(res))
141 rev = struct.unpack(xfmt, res)[0]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000142 if rev != arg:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000143 self.assertTrue(asy)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000144
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000145 def test_calcsize(self):
146 expected_size = {
147 'b': 1, 'B': 1,
148 'h': 2, 'H': 2,
149 'i': 4, 'I': 4,
150 'l': 4, 'L': 4,
151 'q': 8, 'Q': 8,
152 }
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000153
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000154 # standard integer sizes
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200155 for code, byteorder in iter_integer_formats(('=', '<', '>', '!')):
156 format = byteorder+code
157 size = struct.calcsize(format)
158 self.assertEqual(size, expected_size[code])
Tim Peters7a3bfc32001-06-12 01:22:22 +0000159
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000160 # native integer sizes
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200161 native_pairs = 'bB', 'hH', 'iI', 'lL', 'nN'
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000162 if HAVE_LONG_LONG:
163 native_pairs += 'qQ',
164 for format_pair in native_pairs:
165 for byteorder in '', '@':
166 signed_size = struct.calcsize(byteorder + format_pair[0])
167 unsigned_size = struct.calcsize(byteorder + format_pair[1])
168 self.assertEqual(signed_size, unsigned_size)
169
170 # bounds for native integer sizes
Ezio Melotti4c28ddc2010-04-04 07:21:15 +0000171 self.assertEqual(struct.calcsize('b'), 1)
172 self.assertLessEqual(2, struct.calcsize('h'))
173 self.assertLessEqual(4, struct.calcsize('l'))
174 self.assertLessEqual(struct.calcsize('h'), struct.calcsize('i'))
175 self.assertLessEqual(struct.calcsize('i'), struct.calcsize('l'))
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000176 if HAVE_LONG_LONG:
Ezio Melotti4c28ddc2010-04-04 07:21:15 +0000177 self.assertLessEqual(8, struct.calcsize('q'))
178 self.assertLessEqual(struct.calcsize('l'), struct.calcsize('q'))
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200179 self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('i'))
180 self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('P'))
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000181
182 def test_integers(self):
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200183 # Integer tests (bBhHiIlLqQnN).
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000184 import binascii
Tim Peters17e17d42001-06-13 22:45:27 +0000185
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000186 class IntTester(unittest.TestCase):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000187 def __init__(self, format):
Benjamin Peterson7fe73a12009-04-04 16:35:46 +0000188 super(IntTester, self).__init__(methodName='test_one')
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000189 self.format = format
190 self.code = format[-1]
191 self.byteorder = format[:-1]
192 if not self.byteorder in byteorders:
193 raise ValueError("unrecognized packing byteorder: %s" %
194 self.byteorder)
195 self.bytesize = struct.calcsize(format)
196 self.bitsize = self.bytesize * 8
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200197 if self.code in tuple('bhilqn'):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000198 self.signed = True
199 self.min_value = -(2**(self.bitsize-1))
200 self.max_value = 2**(self.bitsize-1) - 1
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200201 elif self.code in tuple('BHILQN'):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000202 self.signed = False
203 self.min_value = 0
204 self.max_value = 2**self.bitsize - 1
205 else:
206 raise ValueError("unrecognized format code: %s" %
207 self.code)
Tim Peters17e17d42001-06-13 22:45:27 +0000208
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000209 def test_one(self, x, pack=struct.pack,
210 unpack=struct.unpack,
211 unhexlify=binascii.unhexlify):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000212
213 format = self.format
214 if self.min_value <= x <= self.max_value:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000215 expected = x
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000216 if self.signed and x < 0:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000217 expected += 1 << self.bitsize
Ezio Melotti4c28ddc2010-04-04 07:21:15 +0000218 self.assertGreaterEqual(expected, 0)
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000219 expected = '%x' % expected
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000220 if len(expected) & 1:
221 expected = "0" + expected
Florent Xiclunaf1046ca2010-07-27 21:20:15 +0000222 expected = expected.encode('ascii')
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000223 expected = unhexlify(expected)
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000224 expected = (b"\x00" * (self.bytesize - len(expected)) +
225 expected)
226 if (self.byteorder == '<' or
227 self.byteorder in ('', '@', '=') and not ISBIGENDIAN):
228 expected = string_reverse(expected)
229 self.assertEqual(len(expected), self.bytesize)
Tim Peters0891ac02001-09-15 02:35:15 +0000230
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000231 # Pack work?
232 got = pack(format, x)
233 self.assertEqual(got, expected)
Tim Petersd50ade62003-03-20 18:32:13 +0000234
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000235 # Unpack work?
236 retrieved = unpack(format, got)[0]
237 self.assertEqual(x, retrieved)
Tim Petersd50ade62003-03-20 18:32:13 +0000238
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000239 # Adding any byte should cause a "too big" error.
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000240 self.assertRaises((struct.error, TypeError), unpack, format,
241 b'\x01' + got)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000242 else:
243 # x is out of range -- verify pack realizes that.
Benjamin Peterson0d62f5b2010-07-10 15:14:45 +0000244 self.assertRaises((OverflowError, ValueError, struct.error),
245 pack, format, x)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000246
247 def run(self):
248 from random import randrange
249
250 # Create all interesting powers of 2.
251 values = []
252 for exp in range(self.bitsize + 3):
253 values.append(1 << exp)
254
255 # Add some random values.
256 for i in range(self.bitsize):
257 val = 0
258 for j in range(self.bytesize):
259 val = (val << 8) | randrange(256)
260 values.append(val)
261
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000262 # Values absorbed from other tests
263 values.extend([300, 700000, sys.maxsize*4])
264
265 # Try all those, and their negations, and +-1 from
266 # them. Note that this tests all power-of-2
267 # boundaries in range, and a few out of range, plus
268 # +-(2**n +- 1).
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000269 for base in values:
270 for val in -base, base:
271 for incr in -1, 0, 1:
272 x = val + incr
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000273 self.test_one(x)
274
275 # Some error cases.
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000276 class NotAnInt:
277 def __int__(self):
278 return 42
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000279
Mark Dickinsone9493a12010-04-04 08:52:51 +0000280 # Objects with an '__index__' method should be allowed
281 # to pack as integers. That is assuming the implemented
Serhiy Storchaka95949422013-08-27 19:40:23 +0300282 # '__index__' method returns an 'int'.
Mark Dickinsone9493a12010-04-04 08:52:51 +0000283 class Indexable(object):
284 def __init__(self, value):
285 self._value = value
286
287 def __index__(self):
288 return self._value
289
290 # If the '__index__' method raises a type error, then
291 # '__int__' should be used with a deprecation warning.
292 class BadIndex(object):
293 def __index__(self):
294 raise TypeError
295
296 def __int__(self):
297 return 42
298
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000299 self.assertRaises((TypeError, struct.error),
300 struct.pack, self.format,
301 "a string")
302 self.assertRaises((TypeError, struct.error),
303 struct.pack, self.format,
304 randrange)
305 self.assertRaises((TypeError, struct.error),
306 struct.pack, self.format,
307 3+42j)
308 self.assertRaises((TypeError, struct.error),
309 struct.pack, self.format,
Mark Dickinsone9493a12010-04-04 08:52:51 +0000310 NotAnInt())
311 self.assertRaises((TypeError, struct.error),
312 struct.pack, self.format,
313 BadIndex())
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000314
Mark Dickinsone9493a12010-04-04 08:52:51 +0000315 # Check for legitimate values from '__index__'.
Mark Dickinsonc5935772010-04-03 15:54:36 +0000316 for obj in (Indexable(0), Indexable(10), Indexable(17),
317 Indexable(42), Indexable(100), Indexable(127)):
318 try:
319 struct.pack(format, obj)
320 except:
321 self.fail("integer code pack failed on object "
322 "with '__index__' method")
323
Mark Dickinsone9493a12010-04-04 08:52:51 +0000324 # Check for bogus values from '__index__'.
325 for obj in (Indexable(b'a'), Indexable('b'), Indexable(None),
326 Indexable({'a': 1}), Indexable([1, 2, 3])):
327 self.assertRaises((TypeError, struct.error),
328 struct.pack, self.format,
329 obj)
330
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200331 for code, byteorder in iter_integer_formats():
332 format = byteorder+code
333 t = IntTester(format)
334 t.run()
335
336 def test_nN_code(self):
337 # n and N don't exist in standard sizes
338 def assertStructError(func, *args, **kwargs):
339 with self.assertRaises(struct.error) as cm:
340 func(*args, **kwargs)
341 self.assertIn("bad char in struct format", str(cm.exception))
342 for code in 'nN':
343 for byteorder in ('=', '<', '>', '!'):
Mark Dickinsonb9f751a2010-04-03 15:07:40 +0000344 format = byteorder+code
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200345 assertStructError(struct.calcsize, format)
346 assertStructError(struct.pack, format, 0)
347 assertStructError(struct.unpack, format, b"")
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000348
349 def test_p_code(self):
350 # Test p ("Pascal string") code.
351 for code, input, expected, expectedback in [
Victor Stinnerda9ec992010-12-28 13:26:42 +0000352 ('p', b'abc', b'\x00', b''),
353 ('1p', b'abc', b'\x00', b''),
354 ('2p', b'abc', b'\x01a', b'a'),
355 ('3p', b'abc', b'\x02ab', b'ab'),
356 ('4p', b'abc', b'\x03abc', b'abc'),
357 ('5p', b'abc', b'\x03abc\x00', b'abc'),
358 ('6p', b'abc', b'\x03abc\x00\x00', b'abc'),
359 ('1000p', b'x'*1000, b'\xff' + b'x'*999, b'x'*255)]:
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000360 got = struct.pack(code, input)
361 self.assertEqual(got, expected)
362 (got,) = struct.unpack(code, got)
363 self.assertEqual(got, expectedback)
364
365 def test_705836(self):
366 # SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
367 # from the low-order discarded bits could propagate into the exponent
368 # field, causing the result to be wrong by a factor of 2.
369 import math
370
371 for base in range(1, 33):
372 # smaller <- largest representable float less than base.
373 delta = 0.5
374 while base - delta / 2.0 != base:
375 delta /= 2.0
376 smaller = base - delta
377 # Packing this rounds away a solid string of trailing 1 bits.
378 packed = struct.pack("<f", smaller)
379 unpacked = struct.unpack("<f", packed)[0]
380 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
381 # 16, respectively.
382 self.assertEqual(base, unpacked)
383 bigpacked = struct.pack(">f", smaller)
384 self.assertEqual(bigpacked, string_reverse(packed))
385 unpacked = struct.unpack(">f", bigpacked)[0]
386 self.assertEqual(base, unpacked)
387
388 # Largest finite IEEE single.
389 big = (1 << 24) - 1
390 big = math.ldexp(big, 127 - 23)
Tim Petersd50ade62003-03-20 18:32:13 +0000391 packed = struct.pack(">f", big)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000392 unpacked = struct.unpack(">f", packed)[0]
393 self.assertEqual(big, unpacked)
Tim Petersd50ade62003-03-20 18:32:13 +0000394
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000395 # The same, but tack on a 1 bit so it rounds up to infinity.
396 big = (1 << 25) - 1
397 big = math.ldexp(big, 127 - 24)
398 self.assertRaises(OverflowError, struct.pack, ">f", big)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000399
Mark Dickinsonea835e72009-04-19 20:40:33 +0000400 def test_1530559(self):
Antoine Pitrou45d9c912011-10-06 15:27:40 +0200401 for code, byteorder in iter_integer_formats():
402 format = byteorder + code
403 self.assertRaises(struct.error, struct.pack, format, 1.0)
404 self.assertRaises(struct.error, struct.pack, format, 1.5)
Mark Dickinsonea835e72009-04-19 20:40:33 +0000405 self.assertRaises(struct.error, struct.pack, 'P', 1.0)
406 self.assertRaises(struct.error, struct.pack, 'P', 1.5)
407
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000408 def test_unpack_from(self):
409 test_string = b'abcd01234'
410 fmt = '4s'
411 s = struct.Struct(fmt)
412 for cls in (bytes, bytearray):
413 data = cls(test_string)
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000414 self.assertEqual(s.unpack_from(data), (b'abcd',))
415 self.assertEqual(s.unpack_from(data, 2), (b'cd01',))
416 self.assertEqual(s.unpack_from(data, 4), (b'0123',))
417 for i in range(6):
Victor Stinnerda9ec992010-12-28 13:26:42 +0000418 self.assertEqual(s.unpack_from(data, i), (data[i:i+4],))
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000419 for i in range(6, len(test_string) + 1):
420 self.assertRaises(struct.error, s.unpack_from, data, i)
421 for cls in (bytes, bytearray):
422 data = cls(test_string)
423 self.assertEqual(struct.unpack_from(fmt, data), (b'abcd',))
424 self.assertEqual(struct.unpack_from(fmt, data, 2), (b'cd01',))
425 self.assertEqual(struct.unpack_from(fmt, data, 4), (b'0123',))
426 for i in range(6):
427 self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],))
428 for i in range(6, len(test_string) + 1):
429 self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000430
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000431 def test_pack_into(self):
432 test_string = b'Reykjavik rocks, eow!'
433 writable_buf = array.array('b', b' '*100)
434 fmt = '21s'
435 s = struct.Struct(fmt)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000436
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000437 # Test without offset
438 s.pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000439 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000440 self.assertEqual(from_buf, test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000441
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000442 # Test with offset.
443 s.pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000444 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000445 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000446
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000447 # Go beyond boundaries.
448 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000449 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0,
450 test_string)
451 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2,
452 test_string)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000453
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000454 # Test bogus offset (issue 3694)
455 sb = small_buf
Benjamin Peterson4b83af92010-07-09 13:31:11 +0000456 self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb,
457 None)
Georg Brandl75c3d6f2009-02-13 11:01:07 +0000458
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000459 def test_pack_into_fn(self):
460 test_string = b'Reykjavik rocks, eow!'
461 writable_buf = array.array('b', b' '*100)
462 fmt = '21s'
463 pack_into = lambda *args: struct.pack_into(fmt, *args)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000464
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000465 # Test without offset.
466 pack_into(writable_buf, 0, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000467 from_buf = writable_buf.tobytes()[:len(test_string)]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000468 self.assertEqual(from_buf, test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000469
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000470 # Test with offset.
471 pack_into(writable_buf, 10, test_string)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000472 from_buf = writable_buf.tobytes()[:len(test_string)+10]
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000473 self.assertEqual(from_buf, test_string[:10] + test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000474
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000475 # Go beyond boundaries.
476 small_buf = array.array('b', b' '*10)
Benjamin Peterson6ef08a02010-07-07 22:45:06 +0000477 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0,
478 test_string)
479 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2,
480 test_string)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000481
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000482 def test_unpack_with_buffer(self):
Ezio Melotti13925002011-03-16 11:05:33 +0200483 # SF bug 1563759: struct.unpack doesn't support buffer protocol objects
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000484 data1 = array.array('B', b'\x12\x34\x56\x78')
485 data2 = memoryview(b'\x12\x34\x56\x78') # XXX b'......XXXX......', 6, 4
486 for data in [data1, data2]:
487 value, = struct.unpack('>I', data)
488 self.assertEqual(value, 0x12345678)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000489
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000490 def test_bool(self):
Benjamin Petersonde73c452010-07-07 18:54:59 +0000491 class ExplodingBool(object):
492 def __bool__(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200493 raise OSError
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000494 for prefix in tuple("<>!=")+('',):
495 false = (), [], [], '', 0
496 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
Thomas Wouters477c8d52006-05-27 19:21:47 +0000497
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000498 falseFormat = prefix + '?' * len(false)
499 packedFalse = struct.pack(falseFormat, *false)
500 unpackedFalse = struct.unpack(falseFormat, packedFalse)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000501
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000502 trueFormat = prefix + '?' * len(true)
503 packedTrue = struct.pack(trueFormat, *true)
504 unpackedTrue = struct.unpack(trueFormat, packedTrue)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000505
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000506 self.assertEqual(len(true), len(unpackedTrue))
507 self.assertEqual(len(false), len(unpackedFalse))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000508
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000509 for t in unpackedFalse:
510 self.assertFalse(t)
511 for t in unpackedTrue:
512 self.assertTrue(t)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000513
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000514 packed = struct.pack(prefix+'?', 1)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000515
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000516 self.assertEqual(len(packed), struct.calcsize(prefix+'?'))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000517
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000518 if len(packed) != 1:
519 self.assertFalse(prefix, msg='encoded bool is not one byte: %r'
520 %packed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000521
Mark Dickinson94628ee2010-07-12 20:03:24 +0000522 try:
523 struct.pack(prefix + '?', ExplodingBool())
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200524 except OSError:
Mark Dickinson94628ee2010-07-12 20:03:24 +0000525 pass
526 else:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200527 self.fail("Expected OSError: struct.pack(%r, "
Mark Dickinson94628ee2010-07-12 20:03:24 +0000528 "ExplodingBool())" % (prefix + '?'))
Benjamin Petersonde73c452010-07-07 18:54:59 +0000529
Benjamin Petersonc937dc22010-07-07 18:44:05 +0000530 for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
531 self.assertTrue(struct.unpack('>?', c)[0])
Thomas Woutersb2137042007-02-01 18:02:27 +0000532
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000533 def test_count_overflow(self):
534 hugecount = '{}b'.format(sys.maxsize+1)
535 self.assertRaises(struct.error, struct.calcsize, hugecount)
536
Mark Dickinsonb72e6862010-06-11 19:50:30 +0000537 hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
538 self.assertRaises(struct.error, struct.calcsize, hugecount2)
Mark Dickinsonab4096f2010-06-11 16:56:34 +0000539
Alexander Belopolsky177e8532010-06-11 16:04:59 +0000540 def test_trailing_counter(self):
541 store = array.array('b', b' '*100)
542
543 # format lists containing only count spec should result in an error
544 self.assertRaises(struct.error, struct.pack, '12345')
545 self.assertRaises(struct.error, struct.unpack, '12345', '')
546 self.assertRaises(struct.error, struct.pack_into, '12345', store, 0)
547 self.assertRaises(struct.error, struct.unpack_from, '12345', store, 0)
548
549 # Format lists with trailing count spec should result in an error
550 self.assertRaises(struct.error, struct.pack, 'c12345', 'x')
551 self.assertRaises(struct.error, struct.unpack, 'c12345', 'x')
552 self.assertRaises(struct.error, struct.pack_into, 'c12345', store, 0,
553 'x')
554 self.assertRaises(struct.error, struct.unpack_from, 'c12345', store,
555 0)
556
557 # Mixed format tests
558 self.assertRaises(struct.error, struct.pack, '14s42', 'spam and eggs')
559 self.assertRaises(struct.error, struct.unpack, '14s42',
560 'spam and eggs')
561 self.assertRaises(struct.error, struct.pack_into, '14s42', store, 0,
562 'spam and eggs')
563 self.assertRaises(struct.error, struct.unpack_from, '14s42', store, 0)
564
Mark Dickinson5b1d35b2010-08-01 11:10:28 +0000565 def test_Struct_reinitialization(self):
566 # Issue 9422: there was a memory leak when reinitializing a
567 # Struct instance. This test can be used to detect the leak
568 # when running with regrtest -L.
569 s = struct.Struct('i')
570 s.__init__('ii')
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +0000571
Martin v. Löwis33f79972012-07-29 16:33:05 +0200572 def check_sizeof(self, format_str, number_of_codes):
573 # The size of 'PyStructObject'
Martin v. Löwis2b168442012-07-29 16:38:45 +0200574 totalsize = support.calcobjsize('2n3P')
Martin v. Löwis33f79972012-07-29 16:33:05 +0200575 # The size taken up by the 'formatcode' dynamic array
Serhiy Storchakafff61f22013-05-17 10:49:44 +0300576 totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)
Martin v. Löwis33f79972012-07-29 16:33:05 +0200577 support.check_sizeof(self, struct.Struct(format_str), totalsize)
578
579 @support.cpython_only
Meador Inge90bc2dbc2012-07-28 22:16:39 -0500580 def test__sizeof__(self):
581 for code in integer_codes:
582 self.check_sizeof(code, 1)
583 self.check_sizeof('BHILfdspP', 9)
584 self.check_sizeof('B' * 1234, 1234)
585 self.check_sizeof('fd', 2)
586 self.check_sizeof('xxxxxxxxxxxxxx', 0)
Serhiy Storchakafff61f22013-05-17 10:49:44 +0300587 self.check_sizeof('100H', 1)
Meador Inge90bc2dbc2012-07-28 22:16:39 -0500588 self.check_sizeof('187s', 1)
589 self.check_sizeof('20p', 1)
590 self.check_sizeof('0s', 1)
591 self.check_sizeof('0c', 0)
Meador Ingeb14d8c92012-07-23 10:01:29 -0500592
Antoine Pitrou9f146812013-04-27 00:20:04 +0200593
594class UnpackIteratorTest(unittest.TestCase):
595 """
596 Tests for iterative unpacking (struct.Struct.iter_unpack).
597 """
598
599 def test_construct(self):
600 def _check_iterator(it):
601 self.assertIsInstance(it, abc.Iterator)
602 self.assertIsInstance(it, abc.Iterable)
603 s = struct.Struct('>ibcp')
604 it = s.iter_unpack(b"")
605 _check_iterator(it)
606 it = s.iter_unpack(b"1234567")
607 _check_iterator(it)
608 # Wrong bytes length
609 with self.assertRaises(struct.error):
610 s.iter_unpack(b"123456")
611 with self.assertRaises(struct.error):
612 s.iter_unpack(b"12345678")
613 # Zero-length struct
614 s = struct.Struct('>')
615 with self.assertRaises(struct.error):
616 s.iter_unpack(b"")
617 with self.assertRaises(struct.error):
618 s.iter_unpack(b"12")
619
620 def test_iterate(self):
621 s = struct.Struct('>IB')
622 b = bytes(range(1, 16))
623 it = s.iter_unpack(b)
624 self.assertEqual(next(it), (0x01020304, 5))
625 self.assertEqual(next(it), (0x06070809, 10))
626 self.assertEqual(next(it), (0x0b0c0d0e, 15))
627 self.assertRaises(StopIteration, next, it)
628 self.assertRaises(StopIteration, next, it)
629
630 def test_arbitrary_buffer(self):
631 s = struct.Struct('>IB')
632 b = bytes(range(1, 11))
633 it = s.iter_unpack(memoryview(b))
634 self.assertEqual(next(it), (0x01020304, 5))
635 self.assertEqual(next(it), (0x06070809, 10))
636 self.assertRaises(StopIteration, next, it)
637 self.assertRaises(StopIteration, next, it)
638
639 def test_length_hint(self):
640 lh = operator.length_hint
641 s = struct.Struct('>IB')
642 b = bytes(range(1, 16))
643 it = s.iter_unpack(b)
644 self.assertEqual(lh(it), 3)
645 next(it)
646 self.assertEqual(lh(it), 2)
647 next(it)
648 self.assertEqual(lh(it), 1)
649 next(it)
650 self.assertEqual(lh(it), 0)
651 self.assertRaises(StopIteration, next, it)
652 self.assertEqual(lh(it), 0)
653
654 def test_module_func(self):
655 # Sanity check for the global struct.iter_unpack()
656 it = struct.iter_unpack('>IB', bytes(range(1, 11)))
657 self.assertEqual(next(it), (0x01020304, 5))
658 self.assertEqual(next(it), (0x06070809, 10))
659 self.assertRaises(StopIteration, next, it)
660 self.assertRaises(StopIteration, next, it)
661
662
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000663def test_main():
Antoine Pitrou9f146812013-04-27 00:20:04 +0200664 support.run_unittest(__name__)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000665
Amaury Forgeot d'Arcfdfe62d2008-06-17 20:36:03 +0000666if __name__ == '__main__':
667 test_main()