1# -*- coding: iso-8859-1 -*- 2 3from test import test_support 4import marshal 5import sys 6import unittest 7import os 8 9try: 10 import _testcapi 11except ImportError: 12 _testcapi = None 13 14class 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 63class 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 111class 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 146class ExceptionTestCase(unittest.TestCase): 147 def test_exceptions(self): 148 new = marshal.loads(marshal.dumps(StopIteration)) 149 self.assertEqual(StopIteration, new) 150 151class 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 157class ContainerTestCase(unittest.TestCase): 158 d = {'astring': '[email protected]', 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 205class 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 def run_tests(N, check): 231 # (((...None...),),) 232 check(b'(\x01\x00\x00\x00' * N + b'N') 233 # [[[...None...]]] 234 check(b'[\x01\x00\x00\x00' * N + b'N') 235 # {None: {None: {None: ...None...}}} 236 check(b'{N' * N + b'N' + b'0' * N) 237 # frozenset([frozenset([frozenset([...None...])])]) 238 check(b'>\x01\x00\x00\x00' * N + b'N') 239 # Check that the generated marshal data is valid and marshal.loads() 240 # works for moderately deep nesting 241 run_tests(100, marshal.loads) 242 # Very deeply nested structure shouldn't blow the stack 243 def check(s): 244 self.assertRaises(ValueError, marshal.loads, s) 245 run_tests(2**20, check) 246 247 def test_recursion_limit(self): 248 # Create a deeply nested structure. 249 head = last = [] 250 # The max stack depth should match the value in Python/marshal.c. 251 if os.name == 'nt' and hasattr(sys, 'gettotalrefcount'): 252 MAX_MARSHAL_STACK_DEPTH = 1000 253 else: 254 MAX_MARSHAL_STACK_DEPTH = 2000 255 for i in range(MAX_MARSHAL_STACK_DEPTH - 2): 256 last.append([0]) 257 last = last[-1] 258 259 # Verify we don't blow out the stack with dumps/load. 260 data = marshal.dumps(head) 261 new_head = marshal.loads(data) 262 # Don't use == to compare objects, it can exceed the recursion limit. 263 self.assertEqual(len(new_head), len(head)) 264 self.assertEqual(len(new_head[0]), len(head[0])) 265 self.assertEqual(len(new_head[-1]), len(head[-1])) 266 267 last.append([0]) 268 self.assertRaises(ValueError, marshal.dumps, head) 269 270 def test_exact_type_match(self): 271 # Former bug: 272 # >>> class Int(int): pass 273 # >>> type(loads(dumps(Int()))) 274 # <type 'int'> 275 for typ in (int, long, float, complex, tuple, list, dict, set, frozenset): 276 # Note: str and unicode subclasses are not tested because they get handled 277 # by marshal's routines for objects supporting the buffer API. 278 subtyp = type('subtyp', (typ,), {}) 279 self.assertRaises(ValueError, marshal.dumps, subtyp()) 280 281 # Issue #1792 introduced a change in how marshal increases the size of its 282 # internal buffer; this test ensures that the new code is exercised. 283 def test_large_marshal(self): 284 size = int(1e6) 285 testString = 'abc' * size 286 marshal.dumps(testString) 287 288 def test_invalid_longs(self): 289 # Issue #7019: marshal.loads shouldn't produce unnormalized PyLongs 290 invalid_string = 'l\x02\x00\x00\x00\x00\x00\x00\x00' 291 self.assertRaises(ValueError, marshal.loads, invalid_string) 292 293LARGE_SIZE = 2**31 294character_size = 4 if sys.maxunicode > 0xFFFF else 2 295pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4 296 297@unittest.skipIf(LARGE_SIZE > sys.maxsize, "test cannot run on 32-bit systems") 298class LargeValuesTestCase(unittest.TestCase): 299 def check_unmarshallable(self, data): 300 f = open(test_support.TESTFN, 'wb') 301 self.addCleanup(test_support.unlink, test_support.TESTFN) 302 with f: 303 self.assertRaises(ValueError, marshal.dump, data, f) 304 305 @test_support.precisionbigmemtest(size=LARGE_SIZE, memuse=1, dry_run=False) 306 def test_string(self, size): 307 self.check_unmarshallable('x' * size) 308 309 @test_support.precisionbigmemtest(size=LARGE_SIZE, 310 memuse=character_size + 2, dry_run=False) 311 def test_unicode(self, size): 312 self.check_unmarshallable(u'x' * size) 313 314 @test_support.precisionbigmemtest(size=LARGE_SIZE, 315 memuse=pointer_size, dry_run=False) 316 def test_tuple(self, size): 317 self.check_unmarshallable((None,) * size) 318 319 @test_support.precisionbigmemtest(size=LARGE_SIZE, 320 memuse=pointer_size, dry_run=False) 321 def test_list(self, size): 322 self.check_unmarshallable([None] * size) 323 324 @test_support.precisionbigmemtest(size=LARGE_SIZE, 325 memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1), 326 dry_run=False) 327 def test_set(self, size): 328 self.check_unmarshallable(set(range(size))) 329 330 @test_support.precisionbigmemtest(size=LARGE_SIZE, 331 memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1), 332 dry_run=False) 333 def test_frozenset(self, size): 334 self.check_unmarshallable(frozenset(range(size))) 335 336 @test_support.precisionbigmemtest(size=LARGE_SIZE, memuse=1, dry_run=False) 337 def test_bytearray(self, size): 338 self.check_unmarshallable(bytearray(size)) 339 340 341@test_support.cpython_only 342@unittest.skipUnless(_testcapi, 'requires _testcapi') 343class CAPI_TestCase(unittest.TestCase): 344 345 def test_write_long_to_file(self): 346 for v in range(marshal.version + 1): 347 _testcapi.pymarshal_write_long_to_file(0x12345678, test_support.TESTFN, v) 348 with open(test_support.TESTFN, 'rb') as f: 349 data = f.read() 350 test_support.unlink(test_support.TESTFN) 351 self.assertEqual(data, b'\x78\x56\x34\x12') 352 353 def test_write_object_to_file(self): 354 obj = ('\u20ac', b'abc', 123, 45.6, 7+8j, 'long line '*1000) 355 for v in range(marshal.version + 1): 356 _testcapi.pymarshal_write_object_to_file(obj, test_support.TESTFN, v) 357 with open(test_support.TESTFN, 'rb') as f: 358 data = f.read() 359 test_support.unlink(test_support.TESTFN) 360 self.assertEqual(marshal.loads(data), obj) 361 362 def test_read_short_from_file(self): 363 with open(test_support.TESTFN, 'wb') as f: 364 f.write(b'\x34\x12xxxx') 365 r, p = _testcapi.pymarshal_read_short_from_file(test_support.TESTFN) 366 test_support.unlink(test_support.TESTFN) 367 self.assertEqual(r, 0x1234) 368 self.assertEqual(p, 2) 369 370 def test_read_long_from_file(self): 371 with open(test_support.TESTFN, 'wb') as f: 372 f.write(b'\x78\x56\x34\x12xxxx') 373 r, p = _testcapi.pymarshal_read_long_from_file(test_support.TESTFN) 374 test_support.unlink(test_support.TESTFN) 375 self.assertEqual(r, 0x12345678) 376 self.assertEqual(p, 4) 377 378 def test_read_last_object_from_file(self): 379 obj = ('\u20ac', b'abc', 123, 45.6, 7+8j) 380 for v in range(marshal.version + 1): 381 data = marshal.dumps(obj, v) 382 with open(test_support.TESTFN, 'wb') as f: 383 f.write(data + b'xxxx') 384 r, p = _testcapi.pymarshal_read_last_object_from_file(test_support.TESTFN) 385 test_support.unlink(test_support.TESTFN) 386 self.assertEqual(r, obj) 387 388 def test_read_object_from_file(self): 389 obj = ('\u20ac', b'abc', 123, 45.6, 7+8j) 390 for v in range(marshal.version + 1): 391 data = marshal.dumps(obj, v) 392 with open(test_support.TESTFN, 'wb') as f: 393 f.write(data + b'xxxx') 394 r, p = _testcapi.pymarshal_read_object_from_file(test_support.TESTFN) 395 test_support.unlink(test_support.TESTFN) 396 self.assertEqual(r, obj) 397 self.assertEqual(p, len(data)) 398 399 400def test_main(): 401 test_support.run_unittest(IntTestCase, 402 FloatTestCase, 403 StringTestCase, 404 CodeTestCase, 405 ContainerTestCase, 406 ExceptionTestCase, 407 BugsTestCase, 408 LargeValuesTestCase, 409 CAPI_TestCase, 410 ) 411 412if __name__ == "__main__": 413 test_main() 414