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', b'')
    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', b'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                           b'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     def test_boundary_error_message(self):
    582         regex = (
    583             r'pack_into requires a buffer of at least 6 '
    584             r'bytes for packing 1 bytes at offset 5 '
    585             r'\(actual buffer size is 1\)'
    586         )
    587         with self.assertRaisesRegex(struct.error, regex):
    588             struct.pack_into('b', bytearray(1), 5, 1)
    589 
    590     def test_boundary_error_message_with_negative_offset(self):
    591         byte_list = bytearray(10)
    592         with self.assertRaisesRegex(
    593                 struct.error,
    594                 r'no space to pack 4 bytes at offset -2'):
    595             struct.pack_into('<I', byte_list, -2, 123)
    596 
    597         with self.assertRaisesRegex(
    598                 struct.error,
    599                 'offset -11 out of range for 10-byte buffer'):
    600             struct.pack_into('<B', byte_list, -11, 123)
    601 
    602     def test_boundary_error_message_with_large_offset(self):
    603         # Test overflows cause by large offset and value size (issue 30245)
    604         regex = (
    605             r'pack_into requires a buffer of at least ' + str(sys.maxsize + 4) +
    606             r' bytes for packing 4 bytes at offset ' + str(sys.maxsize) +
    607             r' \(actual buffer size is 10\)'
    608         )
    609         with self.assertRaisesRegex(struct.error, regex):
    610             struct.pack_into('<I', bytearray(10), sys.maxsize, 1)
    611 
    612     def test_issue29802(self):
    613         # When the second argument of struct.unpack() was of wrong type
    614         # the Struct object was decrefed twice and the reference to
    615         # deallocated object was left in a cache.
    616         with self.assertRaises(TypeError):
    617             struct.unpack('b', 0)
    618         # Shouldn't crash.
    619         self.assertEqual(struct.unpack('b', b'a'), (b'a'[0],))
    620 
    621     def test_format_attr(self):
    622         s = struct.Struct('=i2H')
    623         self.assertEqual(s.format, '=i2H')
    624 
    625         # use a bytes string
    626         s2 = struct.Struct(s.format.encode())
    627         self.assertEqual(s2.format, s.format)
    628 
    629 
    630 class UnpackIteratorTest(unittest.TestCase):
    631     """
    632     Tests for iterative unpacking (struct.Struct.iter_unpack).
    633     """
    634 
    635     def test_construct(self):
    636         def _check_iterator(it):
    637             self.assertIsInstance(it, abc.Iterator)
    638             self.assertIsInstance(it, abc.Iterable)
    639         s = struct.Struct('>ibcp')
    640         it = s.iter_unpack(b"")
    641         _check_iterator(it)
    642         it = s.iter_unpack(b"1234567")
    643         _check_iterator(it)
    644         # Wrong bytes length
    645         with self.assertRaises(struct.error):
    646             s.iter_unpack(b"123456")
    647         with self.assertRaises(struct.error):
    648             s.iter_unpack(b"12345678")
    649         # Zero-length struct
    650         s = struct.Struct('>')
    651         with self.assertRaises(struct.error):
    652             s.iter_unpack(b"")
    653         with self.assertRaises(struct.error):
    654             s.iter_unpack(b"12")
    655 
    656     def test_iterate(self):
    657         s = struct.Struct('>IB')
    658         b = bytes(range(1, 16))
    659         it = s.iter_unpack(b)
    660         self.assertEqual(next(it), (0x01020304, 5))
    661         self.assertEqual(next(it), (0x06070809, 10))
    662         self.assertEqual(next(it), (0x0b0c0d0e, 15))
    663         self.assertRaises(StopIteration, next, it)
    664         self.assertRaises(StopIteration, next, it)
    665 
    666     def test_arbitrary_buffer(self):
    667         s = struct.Struct('>IB')
    668         b = bytes(range(1, 11))
    669         it = s.iter_unpack(memoryview(b))
    670         self.assertEqual(next(it), (0x01020304, 5))
    671         self.assertEqual(next(it), (0x06070809, 10))
    672         self.assertRaises(StopIteration, next, it)
    673         self.assertRaises(StopIteration, next, it)
    674 
    675     def test_length_hint(self):
    676         lh = operator.length_hint
    677         s = struct.Struct('>IB')
    678         b = bytes(range(1, 16))
    679         it = s.iter_unpack(b)
    680         self.assertEqual(lh(it), 3)
    681         next(it)
    682         self.assertEqual(lh(it), 2)
    683         next(it)
    684         self.assertEqual(lh(it), 1)
    685         next(it)
    686         self.assertEqual(lh(it), 0)
    687         self.assertRaises(StopIteration, next, it)
    688         self.assertEqual(lh(it), 0)
    689 
    690     def test_module_func(self):
    691         # Sanity check for the global struct.iter_unpack()
    692         it = struct.iter_unpack('>IB', bytes(range(1, 11)))
    693         self.assertEqual(next(it), (0x01020304, 5))
    694         self.assertEqual(next(it), (0x06070809, 10))
    695         self.assertRaises(StopIteration, next, it)
    696         self.assertRaises(StopIteration, next, it)
    697 
    698     def test_half_float(self):
    699         # Little-endian examples from:
    700         # http://en.wikipedia.org/wiki/Half_precision_floating-point_format
    701         format_bits_float__cleanRoundtrip_list = [
    702             (b'\x00\x3c', 1.0),
    703             (b'\x00\xc0', -2.0),
    704             (b'\xff\x7b', 65504.0), #  (max half precision)
    705             (b'\x00\x04', 2**-14), # ~= 6.10352 * 10**-5 (min pos normal)
    706             (b'\x01\x00', 2**-24), # ~= 5.96046 * 10**-8 (min pos subnormal)
    707             (b'\x00\x00', 0.0),
    708             (b'\x00\x80', -0.0),
    709             (b'\x00\x7c', float('+inf')),
    710             (b'\x00\xfc', float('-inf')),
    711             (b'\x55\x35', 0.333251953125), # ~= 1/3
    712         ]
    713 
    714         for le_bits, f in format_bits_float__cleanRoundtrip_list:
    715             be_bits = le_bits[::-1]
    716             self.assertEqual(f, struct.unpack('<e', le_bits)[0])
    717             self.assertEqual(le_bits, struct.pack('<e', f))
    718             self.assertEqual(f, struct.unpack('>e', be_bits)[0])
    719             self.assertEqual(be_bits, struct.pack('>e', f))
    720             if sys.byteorder == 'little':
    721                 self.assertEqual(f, struct.unpack('e', le_bits)[0])
    722                 self.assertEqual(le_bits, struct.pack('e', f))
    723             else:
    724                 self.assertEqual(f, struct.unpack('e', be_bits)[0])
    725                 self.assertEqual(be_bits, struct.pack('e', f))
    726 
    727         # Check for NaN handling:
    728         format_bits__nan_list = [
    729             ('<e', b'\x01\xfc'),
    730             ('<e', b'\x00\xfe'),
    731             ('<e', b'\xff\xff'),
    732             ('<e', b'\x01\x7c'),
    733             ('<e', b'\x00\x7e'),
    734             ('<e', b'\xff\x7f'),
    735         ]
    736 
    737         for formatcode, bits in format_bits__nan_list:
    738             self.assertTrue(math.isnan(struct.unpack('<e', bits)[0]))
    739             self.assertTrue(math.isnan(struct.unpack('>e', bits[::-1])[0]))
    740 
    741         # Check that packing produces a bit pattern representing a quiet NaN:
    742         # all exponent bits and the msb of the fraction should all be 1.
    743         packed = struct.pack('<e', math.nan)
    744         self.assertEqual(packed[1] & 0x7e, 0x7e)
    745         packed = struct.pack('<e', -math.nan)
    746         self.assertEqual(packed[1] & 0x7e, 0x7e)
    747 
    748         # Checks for round-to-even behavior
    749         format_bits_float__rounding_list = [
    750             ('>e', b'\x00\x01', 2.0**-25 + 2.0**-35), # Rounds to minimum subnormal
    751             ('>e', b'\x00\x00', 2.0**-25), # Underflows to zero (nearest even mode)
    752             ('>e', b'\x00\x00', 2.0**-26), # Underflows to zero
    753             ('>e', b'\x03\xff', 2.0**-14 - 2.0**-24), # Largest subnormal.
    754             ('>e', b'\x03\xff', 2.0**-14 - 2.0**-25 - 2.0**-65),
    755             ('>e', b'\x04\x00', 2.0**-14 - 2.0**-25),
    756             ('>e', b'\x04\x00', 2.0**-14), # Smallest normal.
    757             ('>e', b'\x3c\x01', 1.0+2.0**-11 + 2.0**-16), # rounds to 1.0+2**(-10)
    758             ('>e', b'\x3c\x00', 1.0+2.0**-11), # rounds to 1.0 (nearest even mode)
    759             ('>e', b'\x3c\x00', 1.0+2.0**-12), # rounds to 1.0
    760             ('>e', b'\x7b\xff', 65504), # largest normal
    761             ('>e', b'\x7b\xff', 65519), # rounds to 65504
    762             ('>e', b'\x80\x01', -2.0**-25 - 2.0**-35), # Rounds to minimum subnormal
    763             ('>e', b'\x80\x00', -2.0**-25), # Underflows to zero (nearest even mode)
    764             ('>e', b'\x80\x00', -2.0**-26), # Underflows to zero
    765             ('>e', b'\xbc\x01', -1.0-2.0**-11 - 2.0**-16), # rounds to 1.0+2**(-10)
    766             ('>e', b'\xbc\x00', -1.0-2.0**-11), # rounds to 1.0 (nearest even mode)
    767             ('>e', b'\xbc\x00', -1.0-2.0**-12), # rounds to 1.0
    768             ('>e', b'\xfb\xff', -65519), # rounds to 65504
    769         ]
    770 
    771         for formatcode, bits, f in format_bits_float__rounding_list:
    772             self.assertEqual(bits, struct.pack(formatcode, f))
    773 
    774         # This overflows, and so raises an error
    775         format_bits_float__roundingError_list = [
    776             # Values that round to infinity.
    777             ('>e', 65520.0),
    778             ('>e', 65536.0),
    779             ('>e', 1e300),
    780             ('>e', -65520.0),
    781             ('>e', -65536.0),
    782             ('>e', -1e300),
    783             ('<e', 65520.0),
    784             ('<e', 65536.0),
    785             ('<e', 1e300),
    786             ('<e', -65520.0),
    787             ('<e', -65536.0),
    788             ('<e', -1e300),
    789         ]
    790 
    791         for formatcode, f in format_bits_float__roundingError_list:
    792             self.assertRaises(OverflowError, struct.pack, formatcode, f)
    793 
    794         # Double rounding
    795         format_bits_float__doubleRoundingError_list = [
    796             ('>e', b'\x67\xff', 0x1ffdffffff * 2**-26), # should be 2047, if double-rounded 64>32>16, becomes 2048
    797         ]
    798 
    799         for formatcode, bits, f in format_bits_float__doubleRoundingError_list:
    800             self.assertEqual(bits, struct.pack(formatcode, f))
    801 
    802 
    803 if __name__ == '__main__':
    804     unittest.main()
    805