Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/test/test_struct.py

    r2 r391  
     1import os
    12import array
    23import unittest
    34import struct
    4 import warnings
    5 warnings.filterwarnings("ignore", "struct integer overflow masking is deprecated",
    6                         DeprecationWarning)
    7 
    8 from functools import wraps
    9 from test.test_support import TestFailed, verbose, run_unittest
     5import inspect
     6from test import test_support as support
     7from test.test_support import (check_warnings, check_py3k_warnings)
    108
    119import sys
    1210ISBIGENDIAN = sys.byteorder == "big"
    1311IS32BIT = sys.maxsize == 0x7fffffff
    14 del sys
    15 
     12
     13integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q'
     14
     15testmod_filename = os.path.splitext(__file__)[0] + '.py'
     16# Native 'q' packing isn't available on systems that don't have the C
     17# long long type.
    1618try:
    17     import _struct
    18 except ImportError:
    19     PY_STRUCT_RANGE_CHECKING = 0
    20     PY_STRUCT_OVERFLOW_MASKING = 1
    21     PY_STRUCT_FLOAT_COERCE = 2
     19    struct.pack('q', 5)
     20except struct.error:
     21    HAVE_LONG_LONG = False
    2222else:
    23     PY_STRUCT_RANGE_CHECKING = getattr(_struct, '_PY_STRUCT_RANGE_CHECKING', 0)
    24     PY_STRUCT_OVERFLOW_MASKING = getattr(_struct, '_PY_STRUCT_OVERFLOW_MASKING', 0)
    25     PY_STRUCT_FLOAT_COERCE = getattr(_struct, '_PY_STRUCT_FLOAT_COERCE', 0)
     23    HAVE_LONG_LONG = True
    2624
    2725def string_reverse(s):
     
    3432        return string_reverse(value)
    3533
    36 def with_warning_restore(func):
    37     @wraps(func)
    38     def decorator(*args, **kw):
    39         with warnings.catch_warnings():
    40             # We need this function to warn every time, so stick an
    41             # unqualifed 'always' at the head of the filter list
    42             warnings.simplefilter("always")
    43             warnings.filterwarnings("error", category=DeprecationWarning)
    44             return func(*args, **kw)
    45     return decorator
    46 
    47 @with_warning_restore
    48 def deprecated_err(func, *args):
    49     try:
    50         func(*args)
    51     except (struct.error, TypeError):
    52         pass
    53     except DeprecationWarning:
    54         if not PY_STRUCT_OVERFLOW_MASKING:
    55             raise TestFailed, "%s%s expected to raise DeprecationWarning" % (
    56                 func.__name__, args)
    57     else:
    58         raise TestFailed, "%s%s did not raise error" % (
    59             func.__name__, args)
    60 
    61 
    6234class StructTest(unittest.TestCase):
    6335
    64     @with_warning_restore
    6536    def check_float_coerce(self, format, number):
    66         # SF bug 1530559. struct.pack raises TypeError where it used to convert.
    67         if PY_STRUCT_FLOAT_COERCE == 2:
    68             # Test for pre-2.5 struct module
    69             packed = struct.pack(format, number)
    70             floored = struct.unpack(format, packed)[0]
    71             self.assertEqual(floored, int(number),
    72                              "did not correcly coerce float to int")
    73             return
    74         try:
    75             struct.pack(format, number)
    76         except (struct.error, TypeError):
    77             if PY_STRUCT_FLOAT_COERCE:
    78                 self.fail("expected DeprecationWarning for float coerce")
    79         except DeprecationWarning:
    80             if not PY_STRUCT_FLOAT_COERCE:
    81                 self.fail("expected to raise struct.error for float coerce")
    82         else:
    83             self.fail("did not raise error for float coerce")
     37        # SF bug 1530559. struct.pack raises TypeError where it used
     38        # to convert.
     39        with check_warnings((".*integer argument expected, got float",
     40                             DeprecationWarning)) as w:
     41            got = struct.pack(format, number)
     42        lineno = inspect.currentframe().f_lineno - 1
     43        self.assertEqual(w.filename, testmod_filename)
     44        self.assertEqual(w.lineno, lineno)
     45        self.assertEqual(len(w.warnings), 1)
     46        expected = struct.pack(format, int(number))
     47        self.assertEqual(got, expected)
    8448
    8549    def test_isbigendian(self):
     
    10064        self.assertRaises(struct.error, struct.pack, 'iii', 3)
    10165        self.assertRaises(struct.error, struct.pack, 'i', 3, 3, 3)
    102         self.assertRaises(struct.error, struct.pack, 'i', 'foo')
    103         self.assertRaises(struct.error, struct.pack, 'P', 'foo')
     66        self.assertRaises((TypeError, struct.error), struct.pack, 'i', 'foo')
     67        self.assertRaises((TypeError, struct.error), struct.pack, 'P', 'foo')
    10468        self.assertRaises(struct.error, struct.unpack, 'd', 'flap')
    10569        s = struct.pack('ii', 1, 2)
     
    182146                rev = struct.unpack(xfmt, res)[0]
    183147                if rev != arg:
    184                     self.assert_(asy)
    185 
    186     def test_native_qQ(self):
    187         # can't pack -1 as unsigned regardless
    188         self.assertRaises((struct.error, TypeError), struct.pack, "Q", -1)
    189         # can't pack string as 'q' regardless
    190         self.assertRaises(struct.error, struct.pack, "q", "a")
    191         # ditto, but 'Q'
    192         self.assertRaises(struct.error, struct.pack, "Q", "a")
    193 
    194         try:
    195             struct.pack("q", 5)
    196         except struct.error:
    197             # does not have native q/Q
    198             pass
    199         else:
    200             bytes = struct.calcsize('q')
    201             # The expected values here are in big-endian format, primarily
    202             # because I'm on a little-endian machine and so this is the
    203             # clearest way (for me) to force the code to get exercised.
    204             for format, input, expected in (
    205                     ('q', -1, '\xff' * bytes),
    206                     ('q', 0, '\x00' * bytes),
    207                     ('Q', 0, '\x00' * bytes),
    208                     ('q', 1L, '\x00' * (bytes-1) + '\x01'),
    209                     ('Q', (1L << (8*bytes))-1, '\xff' * bytes),
    210                     ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))):
    211                 got = struct.pack(format, input)
    212                 native_expected = bigendian_to_native(expected)
    213                 self.assertEqual(got, native_expected)
    214                 retrieved = struct.unpack(format, got)[0]
    215                 self.assertEqual(retrieved, input)
    216 
    217     def test_standard_integers(self):
    218         # Standard integer tests (bBhHiIlLqQ).
     148                    self.assertTrue(asy)
     149
     150    def test_calcsize(self):
     151        expected_size = {
     152            'b': 1, 'B': 1,
     153            'h': 2, 'H': 2,
     154            'i': 4, 'I': 4,
     155            'l': 4, 'L': 4,
     156            'q': 8, 'Q': 8,
     157            }
     158
     159        # standard integer sizes
     160        for code in integer_codes:
     161            for byteorder in ('=', '<', '>', '!'):
     162                format = byteorder+code
     163                size = struct.calcsize(format)
     164                self.assertEqual(size, expected_size[code])
     165
     166        # native integer sizes, except 'q' and 'Q'
     167        for format_pair in ('bB', 'hH', 'iI', 'lL'):
     168            for byteorder in ['', '@']:
     169                signed_size = struct.calcsize(byteorder + format_pair[0])
     170                unsigned_size = struct.calcsize(byteorder + format_pair[1])
     171                self.assertEqual(signed_size, unsigned_size)
     172
     173        # bounds for native integer sizes
     174        self.assertEqual(struct.calcsize('b'), 1)
     175        self.assertLessEqual(2, struct.calcsize('h'))
     176        self.assertLessEqual(4, struct.calcsize('l'))
     177        self.assertLessEqual(struct.calcsize('h'), struct.calcsize('i'))
     178        self.assertLessEqual(struct.calcsize('i'), struct.calcsize('l'))
     179
     180        # tests for native 'q' and 'Q' when applicable
     181        if HAVE_LONG_LONG:
     182            self.assertEqual(struct.calcsize('q'), struct.calcsize('Q'))
     183            self.assertLessEqual(8, struct.calcsize('q'))
     184            self.assertLessEqual(struct.calcsize('l'), struct.calcsize('q'))
     185
     186    def test_integers(self):
     187        # Integer tests (bBhHiIlLqQ).
    219188        import binascii
    220189
    221190        class IntTester(unittest.TestCase):
    222 
    223             # XXX Most std integer modes fail to test for out-of-range.
    224             # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
    225             # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
    226             # reported by Mark Favas).
    227             BUGGY_RANGE_CHECK = "bBhHiIlL"
    228 
    229             def __init__(self, formatpair, bytesize):
    230                 self.assertEqual(len(formatpair), 2)
    231                 self.formatpair = formatpair
    232                 for direction in "<>!=":
    233                     for code in formatpair:
    234                         format = direction + code
    235                         self.assertEqual(struct.calcsize(format), bytesize)
    236                 self.bytesize = bytesize
    237                 self.bitsize = bytesize * 8
    238                 self.signed_code, self.unsigned_code = formatpair
    239                 self.unsigned_min = 0
    240                 self.unsigned_max = 2L**self.bitsize - 1
    241                 self.signed_min = -(2L**(self.bitsize-1))
    242                 self.signed_max = 2L**(self.bitsize-1) - 1
     191            def __init__(self, format):
     192                super(IntTester, self).__init__(methodName='test_one')
     193                self.format = format
     194                self.code = format[-1]
     195                self.direction = format[:-1]
     196                if not self.direction in ('', '@', '=', '<', '>', '!'):
     197                    raise ValueError("unrecognized packing direction: %s" %
     198                                     self.direction)
     199                self.bytesize = struct.calcsize(format)
     200                self.bitsize = self.bytesize * 8
     201                if self.code in tuple('bhilq'):
     202                    self.signed = True
     203                    self.min_value = -(2L**(self.bitsize-1))
     204                    self.max_value = 2L**(self.bitsize-1) - 1
     205                elif self.code in tuple('BHILQ'):
     206                    self.signed = False
     207                    self.min_value = 0
     208                    self.max_value = 2L**self.bitsize - 1
     209                else:
     210                    raise ValueError("unrecognized format code: %s" %
     211                                     self.code)
    243212
    244213            def test_one(self, x, pack=struct.pack,
    245214                                  unpack=struct.unpack,
    246215                                  unhexlify=binascii.unhexlify):
    247                 # Try signed.
    248                 code = self.signed_code
    249                 if self.signed_min <= x <= self.signed_max:
    250                     # Try big-endian.
     216
     217                format = self.format
     218                if self.min_value <= x <= self.max_value:
    251219                    expected = long(x)
    252                     if x < 0:
     220                    if self.signed and x < 0:
    253221                        expected += 1L << self.bitsize
    254                         self.assert_(expected > 0)
    255                     expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
     222                    self.assertGreaterEqual(expected, 0)
     223                    expected = '%x' % expected
    256224                    if len(expected) & 1:
    257225                        expected = "0" + expected
    258226                    expected = unhexlify(expected)
    259                     expected = "\x00" * (self.bytesize - len(expected)) + expected
     227                    expected = ("\x00" * (self.bytesize - len(expected)) +
     228                                expected)
     229                    if (self.direction == '<' or
     230                        self.direction in ('', '@', '=') and not ISBIGENDIAN):
     231                        expected = string_reverse(expected)
     232                    self.assertEqual(len(expected), self.bytesize)
    260233
    261234                    # Pack work?
    262                     format = ">" + code
    263235                    got = pack(format, x)
    264236                    self.assertEqual(got, expected)
     
    271243                    self.assertRaises((struct.error, TypeError), unpack, format,
    272244                                                                 '\x01' + got)
    273                     # Try little-endian.
    274                     format = "<" + code
    275                     expected = string_reverse(expected)
    276 
    277                     # Pack work?
    278                     got = pack(format, x)
    279                     self.assertEqual(got, expected)
    280 
    281                     # Unpack work?
    282                     retrieved = unpack(format, got)[0]
    283                     self.assertEqual(x, retrieved)
    284 
    285                     # Adding any byte should cause a "too big" error.
    286                     self.assertRaises((struct.error, TypeError), unpack, format,
    287                                                                  '\x01' + got)
    288 
    289245                else:
    290246                    # x is out of range -- verify pack realizes that.
    291                     if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
    292                         if verbose:
    293                             print "Skipping buggy range check for code", code
    294                     else:
    295                         deprecated_err(pack, ">" + code, x)
    296                         deprecated_err(pack, "<" + code, x)
    297 
    298                 # Much the same for unsigned.
    299                 code = self.unsigned_code
    300                 if self.unsigned_min <= x <= self.unsigned_max:
    301                     # Try big-endian.
    302                     format = ">" + code
    303                     expected = long(x)
    304                     expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
    305                     if len(expected) & 1:
    306                         expected = "0" + expected
    307                     expected = unhexlify(expected)
    308                     expected = "\x00" * (self.bytesize - len(expected)) + expected
    309 
    310                     # Pack work?
    311                     got = pack(format, x)
    312                     self.assertEqual(got, expected)
    313 
    314                     # Unpack work?
    315                     retrieved = unpack(format, got)[0]
    316                     self.assertEqual(x, retrieved)
    317 
    318                     # Adding any byte should cause a "too big" error.
    319                     self.assertRaises((struct.error, TypeError), unpack, format,
    320                                                                  '\x01' + got)
    321 
    322                     # Try little-endian.
    323                     format = "<" + code
    324                     expected = string_reverse(expected)
    325 
    326                     # Pack work?
    327                     got = pack(format, x)
    328                     self.assertEqual(got, expected)
    329 
    330                     # Unpack work?
    331                     retrieved = unpack(format, got)[0]
    332                     self.assertEqual(x, retrieved)
    333 
    334                     # Adding any byte should cause a "too big" error.
    335                     self.assertRaises((struct.error, TypeError), unpack, format,
    336                                                                  '\x01' + got)
    337 
    338                 else:
    339                     # x is out of range -- verify pack realizes that.
    340                     if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
    341                         if verbose:
    342                             print "Skipping buggy range check for code", code
    343                     else:
    344                         deprecated_err(pack, ">" + code, x)
    345                         deprecated_err(pack, "<" + code, x)
     247                    self.assertRaises((OverflowError, ValueError, struct.error),
     248                                      pack, format, x)
    346249
    347250            def run(self):
     
    360263                    values.append(val)
    361264
    362                 # Try all those, and their negations, and +-1 from them.  Note
    363                 # that this tests all power-of-2 boundaries in range, and a few out
    364                 # of range, plus +-(2**n +- 1).
     265                # Values absorbed from other tests
     266                values.extend([300, 700000, sys.maxint*4])
     267
     268                # Try all those, and their negations, and +-1 from
     269                # them.  Note that this tests all power-of-2
     270                # boundaries in range, and a few out of range, plus
     271                # +-(2**n +- 1).
    365272                for base in values:
    366273                    for val in -base, base:
    367274                        for incr in -1, 0, 1:
    368275                            x = val + incr
    369                             try:
    370                                 x = int(x)
    371                             except OverflowError:
    372                                 pass
    373                             self.test_one(x)
     276                            self.test_one(int(x))
     277                            self.test_one(long(x))
    374278
    375279                # Some error cases.
    376                 for direction in "<>":
    377                     for code in self.formatpair:
    378                         for badobject in "a string", 3+42j, randrange:
    379                             self.assertRaises((struct.error, TypeError),
    380                                                struct.pack, direction + code,
    381                                                badobject)
    382 
    383         for args in [("bB", 1),
    384                      ("hH", 2),
    385                      ("iI", 4),
    386                      ("lL", 4),
    387                      ("qQ", 8)]:
    388             t = IntTester(*args)
    389             t.run()
     280                class NotAnIntNS(object):
     281                    def __int__(self):
     282                        return 42
     283
     284                    def __long__(self):
     285                        return 1729L
     286
     287                class NotAnIntOS:
     288                    def __int__(self):
     289                        return 85
     290
     291                    def __long__(self):
     292                        return -163L
     293
     294                # Objects with an '__index__' method should be allowed
     295                # to pack as integers.  That is assuming the implemented
     296                # '__index__' method returns and 'int' or 'long'.
     297                class Indexable(object):
     298                    def __init__(self, value):
     299                        self._value = value
     300
     301                    def __index__(self):
     302                        return self._value
     303
     304                # If the '__index__' method raises a type error, then
     305                # '__int__' should be used with a deprecation warning.
     306                class BadIndex(object):
     307                    def __index__(self):
     308                        raise TypeError
     309
     310                    def __int__(self):
     311                        return 42
     312
     313                self.assertRaises((TypeError, struct.error),
     314                                  struct.pack, self.format,
     315                                  "a string")
     316                self.assertRaises((TypeError, struct.error),
     317                                  struct.pack, self.format,
     318                                  randrange)
     319                with check_warnings(("integer argument expected, "
     320                                     "got non-integer", DeprecationWarning)):
     321                    with self.assertRaises((TypeError, struct.error)):
     322                        struct.pack(self.format, 3+42j)
     323
     324                # an attempt to convert a non-integer (with an
     325                # implicit conversion via __int__) should succeed,
     326                # with a DeprecationWarning
     327                for nonint in NotAnIntNS(), NotAnIntOS(), BadIndex():
     328                    with check_warnings((".*integer argument expected, got non"
     329                                         "-integer", DeprecationWarning)) as w:
     330                        got = struct.pack(self.format, nonint)
     331                    lineno = inspect.currentframe().f_lineno - 1
     332                    self.assertEqual(w.filename, testmod_filename)
     333                    self.assertEqual(w.lineno, lineno)
     334                    self.assertEqual(len(w.warnings), 1)
     335                    expected = struct.pack(self.format, int(nonint))
     336                    self.assertEqual(got, expected)
     337
     338                # Check for legitimate values from '__index__'.
     339                for obj in (Indexable(0), Indexable(10), Indexable(17),
     340                            Indexable(42), Indexable(100), Indexable(127)):
     341                    try:
     342                        struct.pack(format, obj)
     343                    except:
     344                        self.fail("integer code pack failed on object "
     345                                  "with '__index__' method")
     346
     347                # Check for bogus values from '__index__'.
     348                for obj in (Indexable('a'), Indexable(u'b'), Indexable(None),
     349                            Indexable({'a': 1}), Indexable([1, 2, 3])):
     350                    self.assertRaises((TypeError, struct.error),
     351                                      struct.pack, self.format,
     352                                      obj)
     353
     354        byteorders = '', '@', '=', '<', '>', '!'
     355        for code in integer_codes:
     356            for byteorder in byteorders:
     357                if (byteorder in ('', '@') and code in ('q', 'Q') and
     358                    not HAVE_LONG_LONG):
     359                    continue
     360                format = byteorder+code
     361                t = IntTester(format)
     362                t.run()
    390363
    391364    def test_p_code(self):
     
    440413        self.assertRaises(OverflowError, struct.pack, ">f", big)
    441414
    442     if PY_STRUCT_RANGE_CHECKING:
    443         def test_1229380(self):
    444             # SF bug 1229380. No struct.pack exception for some out of
    445             # range integers
    446             import sys
    447             for endian in ('', '>', '<'):
    448                 for cls in (int, long):
    449                     for fmt in ('B', 'H', 'I', 'L'):
    450                         deprecated_err(struct.pack, endian + fmt, cls(-1))
    451 
    452                     deprecated_err(struct.pack, endian + 'B', cls(300))
    453                     deprecated_err(struct.pack, endian + 'H', cls(70000))
    454 
    455                 deprecated_err(struct.pack, endian + 'I', sys.maxint * 4L)
    456                 deprecated_err(struct.pack, endian + 'L', sys.maxint * 4L)
    457 
    458     def XXXtest_1530559(self):
    459         # XXX This is broken: see the bug report
     415    def test_1530559(self):
    460416        # SF bug 1530559. struct.pack raises TypeError where it used to convert.
    461417        for endian in ('', '>', '<'):
    462             for fmt in ('B', 'H', 'I', 'L', 'b', 'h', 'i', 'l'):
     418            for fmt in integer_codes:
    463419                self.check_float_coerce(endian + fmt, 1.0)
    464420                self.check_float_coerce(endian + fmt, 1.5)
    465421
    466     def test_issue4228(self):
    467         # Packing a long may yield either 32 or 64 bits
    468         x = struct.pack('L', -1)[:4]
    469         self.assertEqual(x, '\xff'*4)
    470 
    471     def test_unpack_from(self):
    472         test_string = 'abcd01234'
     422    def test_unpack_from(self, cls=str):
     423        data = cls('abcd01234')
    473424        fmt = '4s'
    474425        s = struct.Struct(fmt)
    475         for cls in (str, buffer):
    476             data = cls(test_string)
    477             self.assertEqual(s.unpack_from(data), ('abcd',))
    478             self.assertEqual(s.unpack_from(data, 2), ('cd01',))
    479             self.assertEqual(s.unpack_from(data, 4), ('0123',))
    480             for i in xrange(6):
    481                 self.assertEqual(s.unpack_from(data, i), (data[i:i+4],))
    482             for i in xrange(6, len(test_string) + 1):
    483                 self.assertRaises(struct.error, s.unpack_from, data, i)
    484         for cls in (str, buffer):
    485             data = cls(test_string)
    486             self.assertEqual(struct.unpack_from(fmt, data), ('abcd',))
    487             self.assertEqual(struct.unpack_from(fmt, data, 2), ('cd01',))
    488             self.assertEqual(struct.unpack_from(fmt, data, 4), ('0123',))
    489             for i in xrange(6):
    490                 self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],))
    491             for i in xrange(6, len(test_string) + 1):
    492                 self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
     426
     427        self.assertEqual(s.unpack_from(data), ('abcd',))
     428        self.assertEqual(struct.unpack_from(fmt, data), ('abcd',))
     429        for i in xrange(6):
     430            self.assertEqual(s.unpack_from(data, i), (data[i:i+4],))
     431            self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],))
     432        for i in xrange(6, len(data) + 1):
     433            self.assertRaises(struct.error, s.unpack_from, data, i)
     434            self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
    493435
    494436    def test_pack_into(self):
     
    510452        # Go beyond boundaries.
    511453        small_buf = array.array('c', ' '*10)
    512         self.assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
    513         self.assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
     454        self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0,
     455                          test_string)
     456        self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2,
     457                          test_string)
    514458
    515459        # Test bogus offset (issue 3694)
    516460        sb = small_buf
    517         self.assertRaises(TypeError, struct.pack_into, b'1', sb, None)
     461        self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb,
     462                          None)
    518463
    519464    def test_pack_into_fn(self):
     
    535480        # Go beyond boundaries.
    536481        small_buf = array.array('c', ' '*10)
    537         self.assertRaises(struct.error, pack_into, small_buf, 0, test_string)
    538         self.assertRaises(struct.error, pack_into, small_buf, 2, test_string)
     482        self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0,
     483                          test_string)
     484        self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2,
     485                          test_string)
    539486
    540487    def test_unpack_with_buffer(self):
    541         # SF bug 1563759: struct.unpack doens't support buffer protocol objects
    542         data1 = array.array('B', '\x12\x34\x56\x78')
    543         data2 = buffer('......\x12\x34\x56\x78......', 6, 4)
    544         for data in [data1, data2]:
     488        with check_py3k_warnings(("buffer.. not supported in 3.x",
     489                                  DeprecationWarning)):
     490            # SF bug 1563759: struct.unpack doesn't support buffer protocol objects
     491            data1 = array.array('B', '\x12\x34\x56\x78')
     492            data2 = buffer('......\x12\x34\x56\x78......', 6, 4)
     493            for data in [data1, data2]:
     494                value, = struct.unpack('>I', data)
     495                self.assertEqual(value, 0x12345678)
     496
     497            self.test_unpack_from(cls=buffer)
     498
     499    def test_unpack_with_memoryview(self):
     500        # Bug 10212: struct.unpack doesn't support new buffer protocol objects
     501        data1 = memoryview('\x12\x34\x56\x78')
     502        for data in [data1,]:
    545503            value, = struct.unpack('>I', data)
    546504            self.assertEqual(value, 0x12345678)
     505        self.test_unpack_from(cls=memoryview)
    547506
    548507    def test_bool(self):
     508        class ExplodingBool(object):
     509            def __nonzero__(self):
     510                raise IOError
    549511        for prefix in tuple("<>!=")+('',):
    550512            false = (), [], [], '', 0
    551             true = [1], 'test', 5, -1, 0xffffffffL+1, 0xffffffff/2
     513            true = [1], 'test', 5, -1, 0xffffffffL+1, 0xffffffff//2
    552514
    553515            falseFormat = prefix + '?' * len(false)
     
    575537                                             %packed)
    576538
    577             for c in '\x01\x7f\xff\x0f\xf0':
    578                 self.assertTrue(struct.unpack('>?', c)[0])
    579 
    580     if IS32BIT:
    581         def test_crasher(self):
    582             self.assertRaises(MemoryError, struct.pack, "357913941c", "a")
    583 
    584 
     539            self.assertRaises(IOError, struct.pack, prefix + '?',
     540                              ExplodingBool())
     541
     542        for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
     543            self.assertTrue(struct.unpack('>?', c)[0])
     544
     545    @unittest.skipUnless(IS32BIT, "Specific to 32bit machines")
     546    def test_crasher(self):
     547        self.assertRaises(MemoryError, struct.pack, "357913941c", "a")
     548
     549    def test_count_overflow(self):
     550        hugecount = '{}b'.format(sys.maxsize+1)
     551        self.assertRaises(struct.error, struct.calcsize, hugecount)
     552
     553        hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
     554        self.assertRaises(struct.error, struct.calcsize, hugecount2)
     555
     556    def check_sizeof(self, format_str, number_of_codes):
     557        # The size of 'PyStructObject'
     558        totalsize = support.calcobjsize('5P')
     559        # The size taken up by the 'formatcode' dynamic array
     560        totalsize += struct.calcsize('3P') * (number_of_codes + 1)
     561        support.check_sizeof(self, struct.Struct(format_str), totalsize)
     562
     563    @support.cpython_only
     564    def test__sizeof__(self):
     565        for code in integer_codes:
     566            self.check_sizeof(code, 1)
     567        self.check_sizeof('BHILfdspP', 9)
     568        self.check_sizeof('B' * 1234, 1234)
     569        self.check_sizeof('fd', 2)
     570        self.check_sizeof('xxxxxxxxxxxxxx', 0)
     571        self.check_sizeof('100H', 100)
     572        self.check_sizeof('187s', 1)
     573        self.check_sizeof('20p', 1)
     574        self.check_sizeof('0s', 1)
     575        self.check_sizeof('0c', 0)
    585576
    586577def test_main():
    587     run_unittest(StructTest)
     578    support.run_unittest(StructTest)
    588579
    589580if __name__ == '__main__':
Note: See TracChangeset for help on using the changeset viewer.