Home | History | Annotate | Download | only in test
      1 from collections import abc
      2 import array
      3 import math
      4 import operator
      5 import unittest
      6 import struct
      7 import sys
      8 
      9 from test import support
     10 
     11 ISBIGENDIAN = sys.byteorder == "big"
     12 
     13 integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'n', 'N'
     14 byteorders = '', '@', '=', '<', '>', '!'
     15 
     16 def 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 
     23 def string_reverse(s):
     24     return s[::-1]
     25 
     26 def bigendian_to_native(value):
     27     if ISBIGENDIAN:
     28         return value
     29     else:
     30         return string_reverse(value)
     31 
     32 class 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 
    582 class 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 
    755 if __name__ == '__main__':
    756     unittest.main()
    757