Home | History | Annotate | Download | only in test
      1 # -*- coding: iso-8859-1 -*-
      2 
      3 from test import test_support
      4 import marshal
      5 import sys
      6 import unittest
      7 import os
      8 
      9 try:
     10     import _testcapi
     11 except ImportError:
     12     _testcapi = None
     13 
     14 class IntTestCase(unittest.TestCase):
     15     def test_ints(self):
     16         # Test the full range of Python ints.
     17         n = sys.maxint
     18         while n:
     19             for expected in (-n, n):
     20                 s = marshal.dumps(expected)
     21                 got = marshal.loads(s)
     22                 self.assertEqual(expected, got)
     23                 marshal.dump(expected, file(test_support.TESTFN, "wb"))
     24                 got = marshal.load(file(test_support.TESTFN, "rb"))
     25                 self.assertEqual(expected, got)
     26             n = n >> 1
     27         os.unlink(test_support.TESTFN)
     28 
     29     def test_int64(self):
     30         # Simulate int marshaling on a 64-bit box.  This is most interesting if
     31         # we're running the test on a 32-bit box, of course.
     32 
     33         def to_little_endian_string(value, nbytes):
     34             bytes = []
     35             for i in range(nbytes):
     36                 bytes.append(chr(value & 0xff))
     37                 value >>= 8
     38             return ''.join(bytes)
     39 
     40         maxint64 = (1L << 63) - 1
     41         minint64 = -maxint64-1
     42 
     43         for base in maxint64, minint64, -maxint64, -(minint64 >> 1):
     44             while base:
     45                 s = 'I' + to_little_endian_string(base, 8)
     46                 got = marshal.loads(s)
     47                 self.assertEqual(base, got)
     48                 if base == -1:  # a fixed-point for shifting right 1
     49                     base = 0
     50                 else:
     51                     base >>= 1
     52 
     53     def test_bool(self):
     54         for b in (True, False):
     55             new = marshal.loads(marshal.dumps(b))
     56             self.assertEqual(b, new)
     57             self.assertEqual(type(b), type(new))
     58             marshal.dump(b, file(test_support.TESTFN, "wb"))
     59             new = marshal.load(file(test_support.TESTFN, "rb"))
     60             self.assertEqual(b, new)
     61             self.assertEqual(type(b), type(new))
     62 
     63 class FloatTestCase(unittest.TestCase):
     64     def test_floats(self):
     65         # Test a few floats
     66         small = 1e-25
     67         n = sys.maxint * 3.7e250
     68         while n > small:
     69             for expected in (-n, n):
     70                 f = float(expected)
     71                 s = marshal.dumps(f)
     72                 got = marshal.loads(s)
     73                 self.assertEqual(f, got)
     74                 marshal.dump(f, file(test_support.TESTFN, "wb"))
     75                 got = marshal.load(file(test_support.TESTFN, "rb"))
     76                 self.assertEqual(f, got)
     77             n /= 123.4567
     78 
     79         f = 0.0
     80         s = marshal.dumps(f, 2)
     81         got = marshal.loads(s)
     82         self.assertEqual(f, got)
     83         # and with version <= 1 (floats marshalled differently then)
     84         s = marshal.dumps(f, 1)
     85         got = marshal.loads(s)
     86         self.assertEqual(f, got)
     87 
     88         n = sys.maxint * 3.7e-250
     89         while n < small:
     90             for expected in (-n, n):
     91                 f = float(expected)
     92 
     93                 s = marshal.dumps(f)
     94                 got = marshal.loads(s)
     95                 self.assertEqual(f, got)
     96 
     97                 s = marshal.dumps(f, 1)
     98                 got = marshal.loads(s)
     99                 self.assertEqual(f, got)
    100 
    101                 marshal.dump(f, file(test_support.TESTFN, "wb"))
    102                 got = marshal.load(file(test_support.TESTFN, "rb"))
    103                 self.assertEqual(f, got)
    104 
    105                 marshal.dump(f, file(test_support.TESTFN, "wb"), 1)
    106                 got = marshal.load(file(test_support.TESTFN, "rb"))
    107                 self.assertEqual(f, got)
    108             n *= 123.4567
    109         os.unlink(test_support.TESTFN)
    110 
    111 class StringTestCase(unittest.TestCase):
    112     def test_unicode(self):
    113         for s in [u"", u"Andr Previn", u"abc", u" "*10000]:
    114             new = marshal.loads(marshal.dumps(s))
    115             self.assertEqual(s, new)
    116             self.assertEqual(type(s), type(new))
    117             marshal.dump(s, file(test_support.TESTFN, "wb"))
    118             new = marshal.load(file(test_support.TESTFN, "rb"))
    119             self.assertEqual(s, new)
    120             self.assertEqual(type(s), type(new))
    121         os.unlink(test_support.TESTFN)
    122 
    123     def test_string(self):
    124         for s in ["", "Andr Previn", "abc", " "*10000]:
    125             new = marshal.loads(marshal.dumps(s))
    126             self.assertEqual(s, new)
    127             self.assertEqual(type(s), type(new))
    128             marshal.dump(s, file(test_support.TESTFN, "wb"))
    129             new = marshal.load(file(test_support.TESTFN, "rb"))
    130             self.assertEqual(s, new)
    131             self.assertEqual(type(s), type(new))
    132         os.unlink(test_support.TESTFN)
    133 
    134     def test_buffer(self):
    135         for s in ["", "Andr Previn", "abc", " "*10000]:
    136             with test_support.check_py3k_warnings(("buffer.. not supported",
    137                                                      DeprecationWarning)):
    138                 b = buffer(s)
    139             new = marshal.loads(marshal.dumps(b))
    140             self.assertEqual(s, new)
    141             marshal.dump(b, file(test_support.TESTFN, "wb"))
    142             new = marshal.load(file(test_support.TESTFN, "rb"))
    143             self.assertEqual(s, new)
    144         os.unlink(test_support.TESTFN)
    145 
    146 class ExceptionTestCase(unittest.TestCase):
    147     def test_exceptions(self):
    148         new = marshal.loads(marshal.dumps(StopIteration))
    149         self.assertEqual(StopIteration, new)
    150 
    151 class CodeTestCase(unittest.TestCase):
    152     def test_code(self):
    153         co = ExceptionTestCase.test_exceptions.func_code
    154         new = marshal.loads(marshal.dumps(co))
    155         self.assertEqual(co, new)
    156 
    157 class ContainerTestCase(unittest.TestCase):
    158     d = {'astring': 'foo (at] bar.baz.spam',
    159          'afloat': 7283.43,
    160          'anint': 2**20,
    161          'ashortlong': 2L,
    162          'alist': ['.zyx.41'],
    163          'atuple': ('.zyx.41',)*10,
    164          'aboolean': False,
    165          'aunicode': u"Andr Previn"
    166          }
    167     def test_dict(self):
    168         new = marshal.loads(marshal.dumps(self.d))
    169         self.assertEqual(self.d, new)
    170         marshal.dump(self.d, file(test_support.TESTFN, "wb"))
    171         new = marshal.load(file(test_support.TESTFN, "rb"))
    172         self.assertEqual(self.d, new)
    173         os.unlink(test_support.TESTFN)
    174 
    175     def test_list(self):
    176         lst = self.d.items()
    177         new = marshal.loads(marshal.dumps(lst))
    178         self.assertEqual(lst, new)
    179         marshal.dump(lst, file(test_support.TESTFN, "wb"))
    180         new = marshal.load(file(test_support.TESTFN, "rb"))
    181         self.assertEqual(lst, new)
    182         os.unlink(test_support.TESTFN)
    183 
    184     def test_tuple(self):
    185         t = tuple(self.d.keys())
    186         new = marshal.loads(marshal.dumps(t))
    187         self.assertEqual(t, new)
    188         marshal.dump(t, file(test_support.TESTFN, "wb"))
    189         new = marshal.load(file(test_support.TESTFN, "rb"))
    190         self.assertEqual(t, new)
    191         os.unlink(test_support.TESTFN)
    192 
    193     def test_sets(self):
    194         for constructor in (set, frozenset):
    195             t = constructor(self.d.keys())
    196             new = marshal.loads(marshal.dumps(t))
    197             self.assertEqual(t, new)
    198             self.assertTrue(isinstance(new, constructor))
    199             self.assertNotEqual(id(t), id(new))
    200             marshal.dump(t, file(test_support.TESTFN, "wb"))
    201             new = marshal.load(file(test_support.TESTFN, "rb"))
    202             self.assertEqual(t, new)
    203             os.unlink(test_support.TESTFN)
    204 
    205 class BugsTestCase(unittest.TestCase):
    206     def test_bug_5888452(self):
    207         # Simple-minded check for SF 588452: Debug build crashes
    208         marshal.dumps([128] * 1000)
    209 
    210     def test_patch_873224(self):
    211         self.assertRaises(Exception, marshal.loads, '0')
    212         self.assertRaises(Exception, marshal.loads, 'f')
    213         self.assertRaises(Exception, marshal.loads, marshal.dumps(5L)[:-1])
    214 
    215     def test_version_argument(self):
    216         # Python 2.4.0 crashes for any call to marshal.dumps(x, y)
    217         self.assertEqual(marshal.loads(marshal.dumps(5, 0)), 5)
    218         self.assertEqual(marshal.loads(marshal.dumps(5, 1)), 5)
    219 
    220     def test_fuzz(self):
    221         # simple test that it's at least not *totally* trivial to
    222         # crash from bad marshal data
    223         for c in [chr(i) for i in range(256)]:
    224             try:
    225                 marshal.loads(c)
    226             except Exception:
    227                 pass
    228 
    229     def test_loads_recursion(self):
    230         s = 'c' + ('X' * 4*4) + '{' * 2**20
    231         self.assertRaises(ValueError, marshal.loads, s)
    232 
    233     def test_recursion_limit(self):
    234         # Create a deeply nested structure.
    235         head = last = []
    236         # The max stack depth should match the value in Python/marshal.c.
    237         if os.name == 'nt' and hasattr(sys, 'gettotalrefcount'):
    238             MAX_MARSHAL_STACK_DEPTH = 1000
    239         else:
    240             MAX_MARSHAL_STACK_DEPTH = 2000
    241         for i in range(MAX_MARSHAL_STACK_DEPTH - 2):
    242             last.append([0])
    243             last = last[-1]
    244 
    245         # Verify we don't blow out the stack with dumps/load.
    246         data = marshal.dumps(head)
    247         new_head = marshal.loads(data)
    248         # Don't use == to compare objects, it can exceed the recursion limit.
    249         self.assertEqual(len(new_head), len(head))
    250         self.assertEqual(len(new_head[0]), len(head[0]))
    251         self.assertEqual(len(new_head[-1]), len(head[-1]))
    252 
    253         last.append([0])
    254         self.assertRaises(ValueError, marshal.dumps, head)
    255 
    256     def test_exact_type_match(self):
    257         # Former bug:
    258         #   >>> class Int(int): pass
    259         #   >>> type(loads(dumps(Int())))
    260         #   <type 'int'>
    261         for typ in (int, long, float, complex, tuple, list, dict, set, frozenset):
    262             # Note: str and unicode subclasses are not tested because they get handled
    263             # by marshal's routines for objects supporting the buffer API.
    264             subtyp = type('subtyp', (typ,), {})
    265             self.assertRaises(ValueError, marshal.dumps, subtyp())
    266 
    267     # Issue #1792 introduced a change in how marshal increases the size of its
    268     # internal buffer; this test ensures that the new code is exercised.
    269     def test_large_marshal(self):
    270         size = int(1e6)
    271         testString = 'abc' * size
    272         marshal.dumps(testString)
    273 
    274     def test_invalid_longs(self):
    275         # Issue #7019: marshal.loads shouldn't produce unnormalized PyLongs
    276         invalid_string = 'l\x02\x00\x00\x00\x00\x00\x00\x00'
    277         self.assertRaises(ValueError, marshal.loads, invalid_string)
    278 
    279 LARGE_SIZE = 2**31
    280 character_size = 4 if sys.maxunicode > 0xFFFF else 2
    281 pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4
    282 
    283 @unittest.skipIf(LARGE_SIZE > sys.maxsize, "test cannot run on 32-bit systems")
    284 class LargeValuesTestCase(unittest.TestCase):
    285     def check_unmarshallable(self, data):
    286         f = open(test_support.TESTFN, 'wb')
    287         self.addCleanup(test_support.unlink, test_support.TESTFN)
    288         with f:
    289             self.assertRaises(ValueError, marshal.dump, data, f)
    290 
    291     @test_support.precisionbigmemtest(size=LARGE_SIZE, memuse=1, dry_run=False)
    292     def test_string(self, size):
    293         self.check_unmarshallable('x' * size)
    294 
    295     @test_support.precisionbigmemtest(size=LARGE_SIZE,
    296             memuse=character_size + 2, dry_run=False)
    297     def test_unicode(self, size):
    298         self.check_unmarshallable(u'x' * size)
    299 
    300     @test_support.precisionbigmemtest(size=LARGE_SIZE,
    301             memuse=pointer_size, dry_run=False)
    302     def test_tuple(self, size):
    303         self.check_unmarshallable((None,) * size)
    304 
    305     @test_support.precisionbigmemtest(size=LARGE_SIZE,
    306             memuse=pointer_size, dry_run=False)
    307     def test_list(self, size):
    308         self.check_unmarshallable([None] * size)
    309 
    310     @test_support.precisionbigmemtest(size=LARGE_SIZE,
    311             memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1),
    312             dry_run=False)
    313     def test_set(self, size):
    314         self.check_unmarshallable(set(range(size)))
    315 
    316     @test_support.precisionbigmemtest(size=LARGE_SIZE,
    317             memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1),
    318             dry_run=False)
    319     def test_frozenset(self, size):
    320         self.check_unmarshallable(frozenset(range(size)))
    321 
    322     @test_support.precisionbigmemtest(size=LARGE_SIZE, memuse=1, dry_run=False)
    323     def test_bytearray(self, size):
    324         self.check_unmarshallable(bytearray(size))
    325 
    326 
    327 @test_support.cpython_only
    328 @unittest.skipUnless(_testcapi, 'requires _testcapi')
    329 class CAPI_TestCase(unittest.TestCase):
    330 
    331     def test_write_long_to_file(self):
    332         for v in range(marshal.version + 1):
    333             _testcapi.pymarshal_write_long_to_file(0x12345678, test_support.TESTFN, v)
    334             with open(test_support.TESTFN, 'rb') as f:
    335                 data = f.read()
    336             test_support.unlink(test_support.TESTFN)
    337             self.assertEqual(data, b'\x78\x56\x34\x12')
    338 
    339     def test_write_object_to_file(self):
    340         obj = ('\u20ac', b'abc', 123, 45.6, 7+8j, 'long line '*1000)
    341         for v in range(marshal.version + 1):
    342             _testcapi.pymarshal_write_object_to_file(obj, test_support.TESTFN, v)
    343             with open(test_support.TESTFN, 'rb') as f:
    344                 data = f.read()
    345             test_support.unlink(test_support.TESTFN)
    346             self.assertEqual(marshal.loads(data), obj)
    347 
    348     def test_read_short_from_file(self):
    349         with open(test_support.TESTFN, 'wb') as f:
    350             f.write(b'\x34\x12xxxx')
    351         r, p = _testcapi.pymarshal_read_short_from_file(test_support.TESTFN)
    352         test_support.unlink(test_support.TESTFN)
    353         self.assertEqual(r, 0x1234)
    354         self.assertEqual(p, 2)
    355 
    356     def test_read_long_from_file(self):
    357         with open(test_support.TESTFN, 'wb') as f:
    358             f.write(b'\x78\x56\x34\x12xxxx')
    359         r, p = _testcapi.pymarshal_read_long_from_file(test_support.TESTFN)
    360         test_support.unlink(test_support.TESTFN)
    361         self.assertEqual(r, 0x12345678)
    362         self.assertEqual(p, 4)
    363 
    364     def test_read_last_object_from_file(self):
    365         obj = ('\u20ac', b'abc', 123, 45.6, 7+8j)
    366         for v in range(marshal.version + 1):
    367             data = marshal.dumps(obj, v)
    368             with open(test_support.TESTFN, 'wb') as f:
    369                 f.write(data + b'xxxx')
    370             r, p = _testcapi.pymarshal_read_last_object_from_file(test_support.TESTFN)
    371             test_support.unlink(test_support.TESTFN)
    372             self.assertEqual(r, obj)
    373 
    374     def test_read_object_from_file(self):
    375         obj = ('\u20ac', b'abc', 123, 45.6, 7+8j)
    376         for v in range(marshal.version + 1):
    377             data = marshal.dumps(obj, v)
    378             with open(test_support.TESTFN, 'wb') as f:
    379                 f.write(data + b'xxxx')
    380             r, p = _testcapi.pymarshal_read_object_from_file(test_support.TESTFN)
    381             test_support.unlink(test_support.TESTFN)
    382             self.assertEqual(r, obj)
    383             self.assertEqual(p, len(data))
    384 
    385 
    386 def test_main():
    387     test_support.run_unittest(IntTestCase,
    388                               FloatTestCase,
    389                               StringTestCase,
    390                               CodeTestCase,
    391                               ContainerTestCase,
    392                               ExceptionTestCase,
    393                               BugsTestCase,
    394                               LargeValuesTestCase,
    395                               CAPI_TestCase,
    396                              )
    397 
    398 if __name__ == "__main__":
    399     test_main()
    400