symbian-qemu-0.9.1-12/python-2.6.1/Lib/test/test_struct.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 import array
       
     2 import unittest
       
     3 import struct
       
     4 import warnings
       
     5 
       
     6 from functools import wraps
       
     7 from test.test_support import TestFailed, verbose, run_unittest
       
     8 
       
     9 import sys
       
    10 ISBIGENDIAN = sys.byteorder == "big"
       
    11 IS32BIT = sys.maxsize == 0x7fffffff
       
    12 del sys
       
    13 
       
    14 try:
       
    15     import _struct
       
    16 except ImportError:
       
    17     PY_STRUCT_RANGE_CHECKING = 0
       
    18     PY_STRUCT_OVERFLOW_MASKING = 1
       
    19     PY_STRUCT_FLOAT_COERCE = 2
       
    20 else:
       
    21     PY_STRUCT_RANGE_CHECKING = getattr(_struct, '_PY_STRUCT_RANGE_CHECKING', 0)
       
    22     PY_STRUCT_OVERFLOW_MASKING = getattr(_struct, '_PY_STRUCT_OVERFLOW_MASKING', 0)
       
    23     PY_STRUCT_FLOAT_COERCE = getattr(_struct, '_PY_STRUCT_FLOAT_COERCE', 0)
       
    24 
       
    25 def string_reverse(s):
       
    26     return "".join(reversed(s))
       
    27 
       
    28 def bigendian_to_native(value):
       
    29     if ISBIGENDIAN:
       
    30         return value
       
    31     else:
       
    32         return string_reverse(value)
       
    33 
       
    34 def with_warning_restore(func):
       
    35     @wraps(func)
       
    36     def decorator(*args, **kw):
       
    37         with warnings.catch_warnings():
       
    38             # We need this function to warn every time, so stick an
       
    39             # unqualifed 'always' at the head of the filter list
       
    40             warnings.simplefilter("always")
       
    41             warnings.filterwarnings("error", category=DeprecationWarning)
       
    42             return func(*args, **kw)
       
    43     return decorator
       
    44 
       
    45 @with_warning_restore
       
    46 def deprecated_err(func, *args):
       
    47     try:
       
    48         func(*args)
       
    49     except (struct.error, TypeError):
       
    50         pass
       
    51     except DeprecationWarning:
       
    52         if not PY_STRUCT_OVERFLOW_MASKING:
       
    53             raise TestFailed, "%s%s expected to raise DeprecationWarning" % (
       
    54                 func.__name__, args)
       
    55     else:
       
    56         raise TestFailed, "%s%s did not raise error" % (
       
    57             func.__name__, args)
       
    58 
       
    59 
       
    60 class StructTest(unittest.TestCase):
       
    61 
       
    62     @with_warning_restore
       
    63     def check_float_coerce(self, format, number):
       
    64         # SF bug 1530559. struct.pack raises TypeError where it used to convert.
       
    65         if PY_STRUCT_FLOAT_COERCE == 2:
       
    66             # Test for pre-2.5 struct module
       
    67             packed = struct.pack(format, number)
       
    68             floored = struct.unpack(format, packed)[0]
       
    69             self.assertEqual(floored, int(number),
       
    70                              "did not correcly coerce float to int")
       
    71             return
       
    72         try:
       
    73             struct.pack(format, number)
       
    74         except (struct.error, TypeError):
       
    75             if PY_STRUCT_FLOAT_COERCE:
       
    76                 self.fail("expected DeprecationWarning for float coerce")
       
    77         except DeprecationWarning:
       
    78             if not PY_STRUCT_FLOAT_COERCE:
       
    79                 self.fail("expected to raise struct.error for float coerce")
       
    80         else:
       
    81             self.fail("did not raise error for float coerce")
       
    82 
       
    83     def test_isbigendian(self):
       
    84         self.assertEqual((struct.pack('=i', 1)[0] == chr(0)), ISBIGENDIAN)
       
    85 
       
    86     def test_consistence(self):
       
    87         self.assertRaises(struct.error, struct.calcsize, 'Z')
       
    88 
       
    89         sz = struct.calcsize('i')
       
    90         self.assertEqual(sz * 3, struct.calcsize('iii'))
       
    91 
       
    92         fmt = 'cbxxxxxxhhhhiillffd?'
       
    93         fmt3 = '3c3b18x12h6i6l6f3d3?'
       
    94         sz = struct.calcsize(fmt)
       
    95         sz3 = struct.calcsize(fmt3)
       
    96         self.assertEqual(sz * 3, sz3)
       
    97 
       
    98         self.assertRaises(struct.error, struct.pack, 'iii', 3)
       
    99         self.assertRaises(struct.error, struct.pack, 'i', 3, 3, 3)
       
   100         self.assertRaises(struct.error, struct.pack, 'i', 'foo')
       
   101         self.assertRaises(struct.error, struct.pack, 'P', 'foo')
       
   102         self.assertRaises(struct.error, struct.unpack, 'd', 'flap')
       
   103         s = struct.pack('ii', 1, 2)
       
   104         self.assertRaises(struct.error, struct.unpack, 'iii', s)
       
   105         self.assertRaises(struct.error, struct.unpack, 'i', s)
       
   106 
       
   107     def test_transitiveness(self):
       
   108         c = 'a'
       
   109         b = 1
       
   110         h = 255
       
   111         i = 65535
       
   112         l = 65536
       
   113         f = 3.1415
       
   114         d = 3.1415
       
   115         t = True
       
   116 
       
   117         for prefix in ('', '@', '<', '>', '=', '!'):
       
   118             for format in ('xcbhilfd?', 'xcBHILfd?'):
       
   119                 format = prefix + format
       
   120                 s = struct.pack(format, c, b, h, i, l, f, d, t)
       
   121                 cp, bp, hp, ip, lp, fp, dp, tp = struct.unpack(format, s)
       
   122                 self.assertEqual(cp, c)
       
   123                 self.assertEqual(bp, b)
       
   124                 self.assertEqual(hp, h)
       
   125                 self.assertEqual(ip, i)
       
   126                 self.assertEqual(lp, l)
       
   127                 self.assertEqual(int(100 * fp), int(100 * f))
       
   128                 self.assertEqual(int(100 * dp), int(100 * d))
       
   129                 self.assertEqual(tp, t)
       
   130 
       
   131     def test_new_features(self):
       
   132         # Test some of the new features in detail
       
   133         # (format, argument, big-endian result, little-endian result, asymmetric)
       
   134         tests = [
       
   135             ('c', 'a', 'a', 'a', 0),
       
   136             ('xc', 'a', '\0a', '\0a', 0),
       
   137             ('cx', 'a', 'a\0', 'a\0', 0),
       
   138             ('s', 'a', 'a', 'a', 0),
       
   139             ('0s', 'helloworld', '', '', 1),
       
   140             ('1s', 'helloworld', 'h', 'h', 1),
       
   141             ('9s', 'helloworld', 'helloworl', 'helloworl', 1),
       
   142             ('10s', 'helloworld', 'helloworld', 'helloworld', 0),
       
   143             ('11s', 'helloworld', 'helloworld\0', 'helloworld\0', 1),
       
   144             ('20s', 'helloworld', 'helloworld'+10*'\0', 'helloworld'+10*'\0', 1),
       
   145             ('b', 7, '\7', '\7', 0),
       
   146             ('b', -7, '\371', '\371', 0),
       
   147             ('B', 7, '\7', '\7', 0),
       
   148             ('B', 249, '\371', '\371', 0),
       
   149             ('h', 700, '\002\274', '\274\002', 0),
       
   150             ('h', -700, '\375D', 'D\375', 0),
       
   151             ('H', 700, '\002\274', '\274\002', 0),
       
   152             ('H', 0x10000-700, '\375D', 'D\375', 0),
       
   153             ('i', 70000000, '\004,\035\200', '\200\035,\004', 0),
       
   154             ('i', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
       
   155             ('I', 70000000L, '\004,\035\200', '\200\035,\004', 0),
       
   156             ('I', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
       
   157             ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
       
   158             ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
       
   159             ('L', 70000000L, '\004,\035\200', '\200\035,\004', 0),
       
   160             ('L', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
       
   161             ('f', 2.0, '@\000\000\000', '\000\000\000@', 0),
       
   162             ('d', 2.0, '@\000\000\000\000\000\000\000',
       
   163                        '\000\000\000\000\000\000\000@', 0),
       
   164             ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0),
       
   165             ('d', -2.0, '\300\000\000\000\000\000\000\000',
       
   166                        '\000\000\000\000\000\000\000\300', 0),
       
   167                 ('?', 0, '\0', '\0', 0),
       
   168                 ('?', 3, '\1', '\1', 1),
       
   169                 ('?', True, '\1', '\1', 0),
       
   170                 ('?', [], '\0', '\0', 1),
       
   171                 ('?', (1,), '\1', '\1', 1),
       
   172         ]
       
   173 
       
   174         for fmt, arg, big, lil, asy in tests:
       
   175             for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
       
   176                                 ('='+fmt, ISBIGENDIAN and big or lil)]:
       
   177                 res = struct.pack(xfmt, arg)
       
   178                 self.assertEqual(res, exp)
       
   179                 self.assertEqual(struct.calcsize(xfmt), len(res))
       
   180                 rev = struct.unpack(xfmt, res)[0]
       
   181                 if rev != arg:
       
   182                     self.assert_(asy)
       
   183 
       
   184     def test_native_qQ(self):
       
   185         # can't pack -1 as unsigned regardless
       
   186         self.assertRaises((struct.error, TypeError), struct.pack, "Q", -1)
       
   187         # can't pack string as 'q' regardless
       
   188         self.assertRaises(struct.error, struct.pack, "q", "a")
       
   189         # ditto, but 'Q'
       
   190         self.assertRaises(struct.error, struct.pack, "Q", "a")
       
   191 
       
   192         try:
       
   193             struct.pack("q", 5)
       
   194         except struct.error:
       
   195             # does not have native q/Q
       
   196             pass
       
   197         else:
       
   198             bytes = struct.calcsize('q')
       
   199             # The expected values here are in big-endian format, primarily
       
   200             # because I'm on a little-endian machine and so this is the
       
   201             # clearest way (for me) to force the code to get exercised.
       
   202             for format, input, expected in (
       
   203                     ('q', -1, '\xff' * bytes),
       
   204                     ('q', 0, '\x00' * bytes),
       
   205                     ('Q', 0, '\x00' * bytes),
       
   206                     ('q', 1L, '\x00' * (bytes-1) + '\x01'),
       
   207                     ('Q', (1L << (8*bytes))-1, '\xff' * bytes),
       
   208                     ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))):
       
   209                 got = struct.pack(format, input)
       
   210                 native_expected = bigendian_to_native(expected)
       
   211                 self.assertEqual(got, native_expected)
       
   212                 retrieved = struct.unpack(format, got)[0]
       
   213                 self.assertEqual(retrieved, input)
       
   214 
       
   215     def test_standard_integers(self):
       
   216         # Standard integer tests (bBhHiIlLqQ).
       
   217         import binascii
       
   218 
       
   219         class IntTester(unittest.TestCase):
       
   220 
       
   221             # XXX Most std integer modes fail to test for out-of-range.
       
   222             # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
       
   223             # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
       
   224             # reported by Mark Favas).
       
   225             BUGGY_RANGE_CHECK = "bBhHiIlL"
       
   226 
       
   227             def __init__(self, formatpair, bytesize):
       
   228                 self.assertEqual(len(formatpair), 2)
       
   229                 self.formatpair = formatpair
       
   230                 for direction in "<>!=":
       
   231                     for code in formatpair:
       
   232                         format = direction + code
       
   233                         self.assertEqual(struct.calcsize(format), bytesize)
       
   234                 self.bytesize = bytesize
       
   235                 self.bitsize = bytesize * 8
       
   236                 self.signed_code, self.unsigned_code = formatpair
       
   237                 self.unsigned_min = 0
       
   238                 self.unsigned_max = 2L**self.bitsize - 1
       
   239                 self.signed_min = -(2L**(self.bitsize-1))
       
   240                 self.signed_max = 2L**(self.bitsize-1) - 1
       
   241 
       
   242             def test_one(self, x, pack=struct.pack,
       
   243                                   unpack=struct.unpack,
       
   244                                   unhexlify=binascii.unhexlify):
       
   245                 # Try signed.
       
   246                 code = self.signed_code
       
   247                 if self.signed_min <= x <= self.signed_max:
       
   248                     # Try big-endian.
       
   249                     expected = long(x)
       
   250                     if x < 0:
       
   251                         expected += 1L << self.bitsize
       
   252                         self.assert_(expected > 0)
       
   253                     expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
       
   254                     if len(expected) & 1:
       
   255                         expected = "0" + expected
       
   256                     expected = unhexlify(expected)
       
   257                     expected = "\x00" * (self.bytesize - len(expected)) + expected
       
   258 
       
   259                     # Pack work?
       
   260                     format = ">" + code
       
   261                     got = pack(format, x)
       
   262                     self.assertEqual(got, expected)
       
   263 
       
   264                     # Unpack work?
       
   265                     retrieved = unpack(format, got)[0]
       
   266                     self.assertEqual(x, retrieved)
       
   267 
       
   268                     # Adding any byte should cause a "too big" error.
       
   269                     self.assertRaises((struct.error, TypeError), unpack, format,
       
   270                                                                  '\x01' + got)
       
   271                     # Try little-endian.
       
   272                     format = "<" + code
       
   273                     expected = string_reverse(expected)
       
   274 
       
   275                     # Pack work?
       
   276                     got = pack(format, x)
       
   277                     self.assertEqual(got, expected)
       
   278 
       
   279                     # Unpack work?
       
   280                     retrieved = unpack(format, got)[0]
       
   281                     self.assertEqual(x, retrieved)
       
   282 
       
   283                     # Adding any byte should cause a "too big" error.
       
   284                     self.assertRaises((struct.error, TypeError), unpack, format,
       
   285                                                                  '\x01' + got)
       
   286 
       
   287                 else:
       
   288                     # x is out of range -- verify pack realizes that.
       
   289                     if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
       
   290                         if verbose:
       
   291                             print "Skipping buggy range check for code", code
       
   292                     else:
       
   293                         deprecated_err(pack, ">" + code, x)
       
   294                         deprecated_err(pack, "<" + code, x)
       
   295 
       
   296                 # Much the same for unsigned.
       
   297                 code = self.unsigned_code
       
   298                 if self.unsigned_min <= x <= self.unsigned_max:
       
   299                     # Try big-endian.
       
   300                     format = ">" + code
       
   301                     expected = long(x)
       
   302                     expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
       
   303                     if len(expected) & 1:
       
   304                         expected = "0" + expected
       
   305                     expected = unhexlify(expected)
       
   306                     expected = "\x00" * (self.bytesize - len(expected)) + expected
       
   307 
       
   308                     # Pack work?
       
   309                     got = pack(format, x)
       
   310                     self.assertEqual(got, expected)
       
   311 
       
   312                     # Unpack work?
       
   313                     retrieved = unpack(format, got)[0]
       
   314                     self.assertEqual(x, retrieved)
       
   315 
       
   316                     # Adding any byte should cause a "too big" error.
       
   317                     self.assertRaises((struct.error, TypeError), unpack, format,
       
   318                                                                  '\x01' + got)
       
   319 
       
   320                     # Try little-endian.
       
   321                     format = "<" + code
       
   322                     expected = string_reverse(expected)
       
   323 
       
   324                     # Pack work?
       
   325                     got = pack(format, x)
       
   326                     self.assertEqual(got, expected)
       
   327 
       
   328                     # Unpack work?
       
   329                     retrieved = unpack(format, got)[0]
       
   330                     self.assertEqual(x, retrieved)
       
   331 
       
   332                     # Adding any byte should cause a "too big" error.
       
   333                     self.assertRaises((struct.error, TypeError), unpack, format,
       
   334                                                                  '\x01' + got)
       
   335 
       
   336                 else:
       
   337                     # x is out of range -- verify pack realizes that.
       
   338                     if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
       
   339                         if verbose:
       
   340                             print "Skipping buggy range check for code", code
       
   341                     else:
       
   342                         deprecated_err(pack, ">" + code, x)
       
   343                         deprecated_err(pack, "<" + code, x)
       
   344 
       
   345             def run(self):
       
   346                 from random import randrange
       
   347 
       
   348                 # Create all interesting powers of 2.
       
   349                 values = []
       
   350                 for exp in range(self.bitsize + 3):
       
   351                     values.append(1L << exp)
       
   352 
       
   353                 # Add some random values.
       
   354                 for i in range(self.bitsize):
       
   355                     val = 0L
       
   356                     for j in range(self.bytesize):
       
   357                         val = (val << 8) | randrange(256)
       
   358                     values.append(val)
       
   359 
       
   360                 # Try all those, and their negations, and +-1 from them.  Note
       
   361                 # that this tests all power-of-2 boundaries in range, and a few out
       
   362                 # of range, plus +-(2**n +- 1).
       
   363                 for base in values:
       
   364                     for val in -base, base:
       
   365                         for incr in -1, 0, 1:
       
   366                             x = val + incr
       
   367                             try:
       
   368                                 x = int(x)
       
   369                             except OverflowError:
       
   370                                 pass
       
   371                             self.test_one(x)
       
   372 
       
   373                 # Some error cases.
       
   374                 for direction in "<>":
       
   375                     for code in self.formatpair:
       
   376                         for badobject in "a string", 3+42j, randrange:
       
   377                             self.assertRaises((struct.error, TypeError),
       
   378                                                struct.pack, direction + code,
       
   379                                                badobject)
       
   380 
       
   381         for args in [("bB", 1),
       
   382                      ("hH", 2),
       
   383                      ("iI", 4),
       
   384                      ("lL", 4),
       
   385                      ("qQ", 8)]:
       
   386             t = IntTester(*args)
       
   387             t.run()
       
   388 
       
   389     def test_p_code(self):
       
   390         # Test p ("Pascal string") code.
       
   391         for code, input, expected, expectedback in [
       
   392                 ('p','abc', '\x00', ''),
       
   393                 ('1p', 'abc', '\x00', ''),
       
   394                 ('2p', 'abc', '\x01a', 'a'),
       
   395                 ('3p', 'abc', '\x02ab', 'ab'),
       
   396                 ('4p', 'abc', '\x03abc', 'abc'),
       
   397                 ('5p', 'abc', '\x03abc\x00', 'abc'),
       
   398                 ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
       
   399                 ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
       
   400             got = struct.pack(code, input)
       
   401             self.assertEqual(got, expected)
       
   402             (got,) = struct.unpack(code, got)
       
   403             self.assertEqual(got, expectedback)
       
   404 
       
   405     def test_705836(self):
       
   406         # SF bug 705836.  "<f" and ">f" had a severe rounding bug, where a carry
       
   407         # from the low-order discarded bits could propagate into the exponent
       
   408         # field, causing the result to be wrong by a factor of 2.
       
   409         import math
       
   410 
       
   411         for base in range(1, 33):
       
   412             # smaller <- largest representable float less than base.
       
   413             delta = 0.5
       
   414             while base - delta / 2.0 != base:
       
   415                 delta /= 2.0
       
   416             smaller = base - delta
       
   417             # Packing this rounds away a solid string of trailing 1 bits.
       
   418             packed = struct.pack("<f", smaller)
       
   419             unpacked = struct.unpack("<f", packed)[0]
       
   420             # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
       
   421             # 16, respectively.
       
   422             self.assertEqual(base, unpacked)
       
   423             bigpacked = struct.pack(">f", smaller)
       
   424             self.assertEqual(bigpacked, string_reverse(packed))
       
   425             unpacked = struct.unpack(">f", bigpacked)[0]
       
   426             self.assertEqual(base, unpacked)
       
   427 
       
   428         # Largest finite IEEE single.
       
   429         big = (1 << 24) - 1
       
   430         big = math.ldexp(big, 127 - 23)
       
   431         packed = struct.pack(">f", big)
       
   432         unpacked = struct.unpack(">f", packed)[0]
       
   433         self.assertEqual(big, unpacked)
       
   434 
       
   435         # The same, but tack on a 1 bit so it rounds up to infinity.
       
   436         big = (1 << 25) - 1
       
   437         big = math.ldexp(big, 127 - 24)
       
   438         self.assertRaises(OverflowError, struct.pack, ">f", big)
       
   439 
       
   440     if PY_STRUCT_RANGE_CHECKING:
       
   441         def test_1229380(self):
       
   442             # SF bug 1229380. No struct.pack exception for some out of
       
   443             # range integers
       
   444             import sys
       
   445             for endian in ('', '>', '<'):
       
   446                 for cls in (int, long):
       
   447                     for fmt in ('B', 'H', 'I', 'L'):
       
   448                         deprecated_err(struct.pack, endian + fmt, cls(-1))
       
   449 
       
   450                     deprecated_err(struct.pack, endian + 'B', cls(300))
       
   451                     deprecated_err(struct.pack, endian + 'H', cls(70000))
       
   452 
       
   453                 deprecated_err(struct.pack, endian + 'I', sys.maxint * 4L)
       
   454                 deprecated_err(struct.pack, endian + 'L', sys.maxint * 4L)
       
   455 
       
   456     def XXXtest_1530559(self):
       
   457         # XXX This is broken: see the bug report
       
   458         # SF bug 1530559. struct.pack raises TypeError where it used to convert.
       
   459         for endian in ('', '>', '<'):
       
   460             for fmt in ('B', 'H', 'I', 'L', 'b', 'h', 'i', 'l'):
       
   461                 self.check_float_coerce(endian + fmt, 1.0)
       
   462                 self.check_float_coerce(endian + fmt, 1.5)
       
   463 
       
   464     def test_unpack_from(self):
       
   465         test_string = 'abcd01234'
       
   466         fmt = '4s'
       
   467         s = struct.Struct(fmt)
       
   468         for cls in (str, buffer):
       
   469             data = cls(test_string)
       
   470             self.assertEqual(s.unpack_from(data), ('abcd',))
       
   471             self.assertEqual(s.unpack_from(data, 2), ('cd01',))
       
   472             self.assertEqual(s.unpack_from(data, 4), ('0123',))
       
   473             for i in xrange(6):
       
   474                 self.assertEqual(s.unpack_from(data, i), (data[i:i+4],))
       
   475             for i in xrange(6, len(test_string) + 1):
       
   476                 self.assertRaises(struct.error, s.unpack_from, data, i)
       
   477         for cls in (str, buffer):
       
   478             data = cls(test_string)
       
   479             self.assertEqual(struct.unpack_from(fmt, data), ('abcd',))
       
   480             self.assertEqual(struct.unpack_from(fmt, data, 2), ('cd01',))
       
   481             self.assertEqual(struct.unpack_from(fmt, data, 4), ('0123',))
       
   482             for i in xrange(6):
       
   483                 self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],))
       
   484             for i in xrange(6, len(test_string) + 1):
       
   485                 self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
       
   486 
       
   487     def test_pack_into(self):
       
   488         test_string = 'Reykjavik rocks, eow!'
       
   489         writable_buf = array.array('c', ' '*100)
       
   490         fmt = '21s'
       
   491         s = struct.Struct(fmt)
       
   492 
       
   493         # Test without offset
       
   494         s.pack_into(writable_buf, 0, test_string)
       
   495         from_buf = writable_buf.tostring()[:len(test_string)]
       
   496         self.assertEqual(from_buf, test_string)
       
   497 
       
   498         # Test with offset.
       
   499         s.pack_into(writable_buf, 10, test_string)
       
   500         from_buf = writable_buf.tostring()[:len(test_string)+10]
       
   501         self.assertEqual(from_buf, test_string[:10] + test_string)
       
   502 
       
   503         # Go beyond boundaries.
       
   504         small_buf = array.array('c', ' '*10)
       
   505         self.assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
       
   506         self.assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
       
   507 
       
   508     def test_pack_into_fn(self):
       
   509         test_string = 'Reykjavik rocks, eow!'
       
   510         writable_buf = array.array('c', ' '*100)
       
   511         fmt = '21s'
       
   512         pack_into = lambda *args: struct.pack_into(fmt, *args)
       
   513 
       
   514         # Test without offset.
       
   515         pack_into(writable_buf, 0, test_string)
       
   516         from_buf = writable_buf.tostring()[:len(test_string)]
       
   517         self.assertEqual(from_buf, test_string)
       
   518 
       
   519         # Test with offset.
       
   520         pack_into(writable_buf, 10, test_string)
       
   521         from_buf = writable_buf.tostring()[:len(test_string)+10]
       
   522         self.assertEqual(from_buf, test_string[:10] + test_string)
       
   523 
       
   524         # Go beyond boundaries.
       
   525         small_buf = array.array('c', ' '*10)
       
   526         self.assertRaises(struct.error, pack_into, small_buf, 0, test_string)
       
   527         self.assertRaises(struct.error, pack_into, small_buf, 2, test_string)
       
   528 
       
   529     def test_unpack_with_buffer(self):
       
   530         # SF bug 1563759: struct.unpack doens't support buffer protocol objects
       
   531         data1 = array.array('B', '\x12\x34\x56\x78')
       
   532         data2 = buffer('......\x12\x34\x56\x78......', 6, 4)
       
   533         for data in [data1, data2]:
       
   534             value, = struct.unpack('>I', data)
       
   535             self.assertEqual(value, 0x12345678)
       
   536 
       
   537     def test_bool(self):
       
   538         for prefix in tuple("<>!=")+('',):
       
   539             false = (), [], [], '', 0
       
   540             true = [1], 'test', 5, -1, 0xffffffffL+1, 0xffffffff/2
       
   541 
       
   542             falseFormat = prefix + '?' * len(false)
       
   543             packedFalse = struct.pack(falseFormat, *false)
       
   544             unpackedFalse = struct.unpack(falseFormat, packedFalse)
       
   545 
       
   546             trueFormat = prefix + '?' * len(true)
       
   547             packedTrue = struct.pack(trueFormat, *true)
       
   548             unpackedTrue = struct.unpack(trueFormat, packedTrue)
       
   549 
       
   550             self.assertEqual(len(true), len(unpackedTrue))
       
   551             self.assertEqual(len(false), len(unpackedFalse))
       
   552 
       
   553             for t in unpackedFalse:
       
   554                 self.assertFalse(t)
       
   555             for t in unpackedTrue:
       
   556                 self.assertTrue(t)
       
   557 
       
   558             packed = struct.pack(prefix+'?', 1)
       
   559 
       
   560             self.assertEqual(len(packed), struct.calcsize(prefix+'?'))
       
   561 
       
   562             if len(packed) != 1:
       
   563                 self.assertFalse(prefix, msg='encoded bool is not one byte: %r'
       
   564                                              %packed)
       
   565 
       
   566             for c in '\x01\x7f\xff\x0f\xf0':
       
   567                 self.assertTrue(struct.unpack('>?', c)[0])
       
   568 
       
   569     if IS32BIT:
       
   570         def test_crasher(self):
       
   571             self.assertRaises(MemoryError, struct.pack, "357913941c", "a")
       
   572 
       
   573 
       
   574 
       
   575 def test_main():
       
   576     run_unittest(StructTest)
       
   577 
       
   578 if __name__ == '__main__':
       
   579     test_main()