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