1from collections import abc
2import array
3import math
4import operator
5import unittest
6import struct
7import sys
8
9from test import support
10
11ISBIGENDIAN = sys.byteorder == "big"
12
13integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'n', 'N'
14byteorders = '', '@', '=', '<', '>', '!'
15
16def iter_integer_formats(byteorders=byteorders):
17    for code in integer_codes:
18        for byteorder in byteorders:
19            if (byteorder not in ('', '@') and code in ('n', 'N')):
20                continue
21            yield code, byteorder
22
23def string_reverse(s):
24    return s[::-1]
25
26def bigendian_to_native(value):
27    if ISBIGENDIAN:
28        return value
29    else:
30        return string_reverse(value)
31
32class StructTest(unittest.TestCase):
33    def test_isbigendian(self):
34        self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN)
35
36    def test_consistence(self):
37        self.assertRaises(struct.error, struct.calcsize, 'Z')
38
39        sz = struct.calcsize('i')
40        self.assertEqual(sz * 3, struct.calcsize('iii'))
41
42        fmt = 'cbxxxxxxhhhhiillffd?'
43        fmt3 = '3c3b18x12h6i6l6f3d3?'
44        sz = struct.calcsize(fmt)
45        sz3 = struct.calcsize(fmt3)
46        self.assertEqual(sz * 3, sz3)
47
48        self.assertRaises(struct.error, struct.pack, 'iii', 3)
49        self.assertRaises(struct.error, struct.pack, 'i', 3, 3, 3)
50        self.assertRaises((TypeError, struct.error), struct.pack, 'i', 'foo')
51        self.assertRaises((TypeError, struct.error), struct.pack, 'P', 'foo')
52        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)
56
57    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
66
67        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)
80
81    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 = [
85            ('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),
122        ]
123
124        for fmt, arg, big, lil, asy in tests:
125            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]
131                if rev != arg:
132                    self.assertTrue(asy)
133
134    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            }
142
143        # standard integer sizes
144        for code, byteorder in iter_integer_formats(('=', '<', '>', '!')):
145            format = byteorder+code
146            size = struct.calcsize(format)
147            self.assertEqual(size, expected_size[code])
148
149        # native integer sizes
150        native_pairs = 'bB', 'hH', 'iI', 'lL', 'nN', 'qQ'
151        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
158        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'))
163        self.assertLessEqual(8, struct.calcsize('q'))
164        self.assertLessEqual(struct.calcsize('l'), struct.calcsize('q'))
165        self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('i'))
166        self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('P'))
167
168    def test_integers(self):
169        # Integer tests (bBhHiIlLqQnN).
170        import binascii
171
172        class IntTester(unittest.TestCase):
173            def __init__(self, format):
174                super(IntTester, self).__init__(methodName='test_one')
175                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
183                if self.code in tuple('bhilqn'):
184                    self.signed = True
185                    self.min_value = -(2**(self.bitsize-1))
186                    self.max_value = 2**(self.bitsize-1) - 1
187                elif self.code in tuple('BHILQN'):
188                    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)
194
195            def test_one(self, x, pack=struct.pack,
196                                  unpack=struct.unpack,
197                                  unhexlify=binascii.unhexlify):
198
199                format = self.format
200                if self.min_value <= x <= self.max_value:
201                    expected = x
202                    if self.signed and x < 0:
203                        expected += 1 << self.bitsize
204                    self.assertGreaterEqual(expected, 0)
205                    expected = '%x' % expected
206                    if len(expected) & 1:
207                        expected = "0" + expected
208                    expected = expected.encode('ascii')
209                    expected = unhexlify(expected)
210                    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)
216
217                    # Pack work?
218                    got = pack(format, x)
219                    self.assertEqual(got, expected)
220
221                    # Unpack work?
222                    retrieved = unpack(format, got)[0]
223                    self.assertEqual(x, retrieved)
224
225                    # Adding any byte should cause a "too big" error.
226                    self.assertRaises((struct.error, TypeError), unpack, format,
227                                                                 b'\x01' + got)
228                else:
229                    # x is out of range -- verify pack realizes that.
230                    self.assertRaises((OverflowError, ValueError, struct.error),
231                                      pack, format, x)
232
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
248                # 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).
255                for base in values:
256                    for val in -base, base:
257                        for incr in -1, 0, 1:
258                            x = val + incr
259                            self.test_one(x)
260
261                # Some error cases.
262                class NotAnInt:
263                    def __int__(self):
264                        return 42
265
266                # Objects with an '__index__' method should be allowed
267                # to pack as integers.  That is assuming the implemented
268                # '__index__' method returns an 'int'.
269                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
285                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,
296                                  NotAnInt())
297                self.assertRaises((TypeError, struct.error),
298                                  struct.pack, self.format,
299                                  BadIndex())
300
301                # Check for legitimate values from '__index__'.
302                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
310                # 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
317        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 ('=', '<', '>', '!'):
330                format = byteorder+code
331                assertStructError(struct.calcsize, format)
332                assertStructError(struct.pack, format, 0)
333                assertStructError(struct.unpack, format, b"")
334
335    def test_p_code(self):
336        # Test p ("Pascal string") code.
337        for code, input, expected, expectedback in [
338                ('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)]:
346            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.
355        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)
375        packed = struct.pack(">f", big)
376        unpacked = struct.unpack(">f", packed)[0]
377        self.assertEqual(big, unpacked)
378
379        # 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)
383
384    def test_1530559(self):
385        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)
389        self.assertRaises(struct.error, struct.pack, 'P', 1.0)
390        self.assertRaises(struct.error, struct.pack, 'P', 1.5)
391
392    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)
398            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):
402                self.assertEqual(s.unpack_from(data, i), (data[i:i+4],))
403            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)
414
415        # keyword arguments
416        self.assertEqual(s.unpack_from(buffer=test_string, offset=2),
417                         (b'cd01',))
418
419    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)
424
425        # Test without offset
426        s.pack_into(writable_buf, 0, test_string)
427        from_buf = writable_buf.tobytes()[:len(test_string)]
428        self.assertEqual(from_buf, test_string)
429
430        # Test with offset.
431        s.pack_into(writable_buf, 10, test_string)
432        from_buf = writable_buf.tobytes()[:len(test_string)+10]
433        self.assertEqual(from_buf, test_string[:10] + test_string)
434
435        # Go beyond boundaries.
436        small_buf = array.array('b', b' '*10)
437        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)
441
442        # Test bogus offset (issue 3694)
443        sb = small_buf
444        self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb,
445                          None)
446
447    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)
452
453        # Test without offset.
454        pack_into(writable_buf, 0, test_string)
455        from_buf = writable_buf.tobytes()[:len(test_string)]
456        self.assertEqual(from_buf, test_string)
457
458        # Test with offset.
459        pack_into(writable_buf, 10, test_string)
460        from_buf = writable_buf.tobytes()[:len(test_string)+10]
461        self.assertEqual(from_buf, test_string[:10] + test_string)
462
463        # Go beyond boundaries.
464        small_buf = array.array('b', b' '*10)
465        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)
469
470    def test_unpack_with_buffer(self):
471        # SF bug 1563759: struct.unpack doesn't support buffer protocol objects
472        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)
477
478    def test_bool(self):
479        class ExplodingBool(object):
480            def __bool__(self):
481                raise OSError
482        for prefix in tuple("<>!=")+('',):
483            false = (), [], [], '', 0
484            true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
485
486            falseFormat = prefix + '?' * len(false)
487            packedFalse = struct.pack(falseFormat, *false)
488            unpackedFalse = struct.unpack(falseFormat, packedFalse)
489
490            trueFormat = prefix + '?' * len(true)
491            packedTrue = struct.pack(trueFormat, *true)
492            unpackedTrue = struct.unpack(trueFormat, packedTrue)
493
494            self.assertEqual(len(true), len(unpackedTrue))
495            self.assertEqual(len(false), len(unpackedFalse))
496
497            for t in unpackedFalse:
498                self.assertFalse(t)
499            for t in unpackedTrue:
500                self.assertTrue(t)
501
502            packed = struct.pack(prefix+'?', 1)
503
504            self.assertEqual(len(packed), struct.calcsize(prefix+'?'))
505
506            if len(packed) != 1:
507                self.assertFalse(prefix, msg='encoded bool is not one byte: %r'
508                                             %packed)
509
510            try:
511                struct.pack(prefix + '?', ExplodingBool())
512            except OSError:
513                pass
514            else:
515                self.fail("Expected OSError: struct.pack(%r, "
516                          "ExplodingBool())" % (prefix + '?'))
517
518        for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
519            self.assertTrue(struct.unpack('>?', c)[0])
520
521    def test_count_overflow(self):
522        hugecount = '{}b'.format(sys.maxsize+1)
523        self.assertRaises(struct.error, struct.calcsize, hugecount)
524
525        hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
526        self.assertRaises(struct.error, struct.calcsize, hugecount2)
527
528    def test_trailing_counter(self):
529        store = array.array('b', b' '*100)
530
531        # format lists containing only count spec should result in an error
532        self.assertRaises(struct.error, struct.pack, '12345')
533        self.assertRaises(struct.error, struct.unpack, '12345', '')
534        self.assertRaises(struct.error, struct.pack_into, '12345', store, 0)
535        self.assertRaises(struct.error, struct.unpack_from, '12345', store, 0)
536
537        # Format lists with trailing count spec should result in an error
538        self.assertRaises(struct.error, struct.pack, 'c12345', 'x')
539        self.assertRaises(struct.error, struct.unpack, 'c12345', 'x')
540        self.assertRaises(struct.error, struct.pack_into, 'c12345', store, 0,
541                           'x')
542        self.assertRaises(struct.error, struct.unpack_from, 'c12345', store,
543                           0)
544
545        # Mixed format tests
546        self.assertRaises(struct.error, struct.pack, '14s42', 'spam and eggs')
547        self.assertRaises(struct.error, struct.unpack, '14s42',
548                          'spam and eggs')
549        self.assertRaises(struct.error, struct.pack_into, '14s42', store, 0,
550                          'spam and eggs')
551        self.assertRaises(struct.error, struct.unpack_from, '14s42', store, 0)
552
553    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')
559
560    def check_sizeof(self, format_str, number_of_codes):
561        # The size of 'PyStructObject'
562        totalsize = support.calcobjsize('2n3P')
563        # The size taken up by the 'formatcode' dynamic array
564        totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)
565        support.check_sizeof(self, struct.Struct(format_str), totalsize)
566
567    @support.cpython_only
568    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)
575        self.check_sizeof('100H', 1)
576        self.check_sizeof('187s', 1)
577        self.check_sizeof('20p', 1)
578        self.check_sizeof('0s', 1)
579        self.check_sizeof('0c', 0)
580
581
582class UnpackIteratorTest(unittest.TestCase):
583    """
584    Tests for iterative unpacking (struct.Struct.iter_unpack).
585    """
586
587    def test_construct(self):
588        def _check_iterator(it):
589            self.assertIsInstance(it, abc.Iterator)
590            self.assertIsInstance(it, abc.Iterable)
591        s = struct.Struct('>ibcp')
592        it = s.iter_unpack(b"")
593        _check_iterator(it)
594        it = s.iter_unpack(b"1234567")
595        _check_iterator(it)
596        # Wrong bytes length
597        with self.assertRaises(struct.error):
598            s.iter_unpack(b"123456")
599        with self.assertRaises(struct.error):
600            s.iter_unpack(b"12345678")
601        # Zero-length struct
602        s = struct.Struct('>')
603        with self.assertRaises(struct.error):
604            s.iter_unpack(b"")
605        with self.assertRaises(struct.error):
606            s.iter_unpack(b"12")
607
608    def test_iterate(self):
609        s = struct.Struct('>IB')
610        b = bytes(range(1, 16))
611        it = s.iter_unpack(b)
612        self.assertEqual(next(it), (0x01020304, 5))
613        self.assertEqual(next(it), (0x06070809, 10))
614        self.assertEqual(next(it), (0x0b0c0d0e, 15))
615        self.assertRaises(StopIteration, next, it)
616        self.assertRaises(StopIteration, next, it)
617
618    def test_arbitrary_buffer(self):
619        s = struct.Struct('>IB')
620        b = bytes(range(1, 11))
621        it = s.iter_unpack(memoryview(b))
622        self.assertEqual(next(it), (0x01020304, 5))
623        self.assertEqual(next(it), (0x06070809, 10))
624        self.assertRaises(StopIteration, next, it)
625        self.assertRaises(StopIteration, next, it)
626
627    def test_length_hint(self):
628        lh = operator.length_hint
629        s = struct.Struct('>IB')
630        b = bytes(range(1, 16))
631        it = s.iter_unpack(b)
632        self.assertEqual(lh(it), 3)
633        next(it)
634        self.assertEqual(lh(it), 2)
635        next(it)
636        self.assertEqual(lh(it), 1)
637        next(it)
638        self.assertEqual(lh(it), 0)
639        self.assertRaises(StopIteration, next, it)
640        self.assertEqual(lh(it), 0)
641
642    def test_module_func(self):
643        # Sanity check for the global struct.iter_unpack()
644        it = struct.iter_unpack('>IB', bytes(range(1, 11)))
645        self.assertEqual(next(it), (0x01020304, 5))
646        self.assertEqual(next(it), (0x06070809, 10))
647        self.assertRaises(StopIteration, next, it)
648        self.assertRaises(StopIteration, next, it)
649
650    def test_half_float(self):
651        # Little-endian examples from:
652        # http://en.wikipedia.org/wiki/Half_precision_floating-point_format
653        format_bits_float__cleanRoundtrip_list = [
654            (b'\x00\x3c', 1.0),
655            (b'\x00\xc0', -2.0),
656            (b'\xff\x7b', 65504.0), #  (max half precision)
657            (b'\x00\x04', 2**-14), # ~= 6.10352 * 10**-5 (min pos normal)
658            (b'\x01\x00', 2**-24), # ~= 5.96046 * 10**-8 (min pos subnormal)
659            (b'\x00\x00', 0.0),
660            (b'\x00\x80', -0.0),
661            (b'\x00\x7c', float('+inf')),
662            (b'\x00\xfc', float('-inf')),
663            (b'\x55\x35', 0.333251953125), # ~= 1/3
664        ]
665
666        for le_bits, f in format_bits_float__cleanRoundtrip_list:
667            be_bits = le_bits[::-1]
668            self.assertEqual(f, struct.unpack('<e', le_bits)[0])
669            self.assertEqual(le_bits, struct.pack('<e', f))
670            self.assertEqual(f, struct.unpack('>e', be_bits)[0])
671            self.assertEqual(be_bits, struct.pack('>e', f))
672            if sys.byteorder == 'little':
673                self.assertEqual(f, struct.unpack('e', le_bits)[0])
674                self.assertEqual(le_bits, struct.pack('e', f))
675            else:
676                self.assertEqual(f, struct.unpack('e', be_bits)[0])
677                self.assertEqual(be_bits, struct.pack('e', f))
678
679        # Check for NaN handling:
680        format_bits__nan_list = [
681            ('<e', b'\x01\xfc'),
682            ('<e', b'\x00\xfe'),
683            ('<e', b'\xff\xff'),
684            ('<e', b'\x01\x7c'),
685            ('<e', b'\x00\x7e'),
686            ('<e', b'\xff\x7f'),
687        ]
688
689        for formatcode, bits in format_bits__nan_list:
690            self.assertTrue(math.isnan(struct.unpack('<e', bits)[0]))
691            self.assertTrue(math.isnan(struct.unpack('>e', bits[::-1])[0]))
692
693        # Check that packing produces a bit pattern representing a quiet NaN:
694        # all exponent bits and the msb of the fraction should all be 1.
695        packed = struct.pack('<e', math.nan)
696        self.assertEqual(packed[1] & 0x7e, 0x7e)
697        packed = struct.pack('<e', -math.nan)
698        self.assertEqual(packed[1] & 0x7e, 0x7e)
699
700        # Checks for round-to-even behavior
701        format_bits_float__rounding_list = [
702            ('>e', b'\x00\x01', 2.0**-25 + 2.0**-35), # Rounds to minimum subnormal
703            ('>e', b'\x00\x00', 2.0**-25), # Underflows to zero (nearest even mode)
704            ('>e', b'\x00\x00', 2.0**-26), # Underflows to zero
705            ('>e', b'\x03\xff', 2.0**-14 - 2.0**-24), # Largest subnormal.
706            ('>e', b'\x03\xff', 2.0**-14 - 2.0**-25 - 2.0**-65),
707            ('>e', b'\x04\x00', 2.0**-14 - 2.0**-25),
708            ('>e', b'\x04\x00', 2.0**-14), # Smallest normal.
709            ('>e', b'\x3c\x01', 1.0+2.0**-11 + 2.0**-16), # rounds to 1.0+2**(-10)
710            ('>e', b'\x3c\x00', 1.0+2.0**-11), # rounds to 1.0 (nearest even mode)
711            ('>e', b'\x3c\x00', 1.0+2.0**-12), # rounds to 1.0
712            ('>e', b'\x7b\xff', 65504), # largest normal
713            ('>e', b'\x7b\xff', 65519), # rounds to 65504
714            ('>e', b'\x80\x01', -2.0**-25 - 2.0**-35), # Rounds to minimum subnormal
715            ('>e', b'\x80\x00', -2.0**-25), # Underflows to zero (nearest even mode)
716            ('>e', b'\x80\x00', -2.0**-26), # Underflows to zero
717            ('>e', b'\xbc\x01', -1.0-2.0**-11 - 2.0**-16), # rounds to 1.0+2**(-10)
718            ('>e', b'\xbc\x00', -1.0-2.0**-11), # rounds to 1.0 (nearest even mode)
719            ('>e', b'\xbc\x00', -1.0-2.0**-12), # rounds to 1.0
720            ('>e', b'\xfb\xff', -65519), # rounds to 65504
721        ]
722
723        for formatcode, bits, f in format_bits_float__rounding_list:
724            self.assertEqual(bits, struct.pack(formatcode, f))
725
726        # This overflows, and so raises an error
727        format_bits_float__roundingError_list = [
728            # Values that round to infinity.
729            ('>e', 65520.0),
730            ('>e', 65536.0),
731            ('>e', 1e300),
732            ('>e', -65520.0),
733            ('>e', -65536.0),
734            ('>e', -1e300),
735            ('<e', 65520.0),
736            ('<e', 65536.0),
737            ('<e', 1e300),
738            ('<e', -65520.0),
739            ('<e', -65536.0),
740            ('<e', -1e300),
741        ]
742
743        for formatcode, f in format_bits_float__roundingError_list:
744            self.assertRaises(OverflowError, struct.pack, formatcode, f)
745
746        # Double rounding
747        format_bits_float__doubleRoundingError_list = [
748            ('>e', b'\x67\xff', 0x1ffdffffff * 2**-26), # should be 2047, if double-rounded 64>32>16, becomes 2048
749        ]
750
751        for formatcode, bits, f in format_bits_float__doubleRoundingError_list:
752            self.assertEqual(bits, struct.pack(formatcode, f))
753
754
755if __name__ == '__main__':
756    unittest.main()
757