1import io 2import unittest 3import StringIO 4import cStringIO 5import copy_reg 6import sys 7 8try: 9 from unittest import skipIf 10except ImportError: 11 def skipIf(condition, message): 12 def _decorator(fn): 13 if condition: 14 return fn 15 else: 16 def skipped(self): 17 pass 18 skipped.__doc__ = '%s skipped: %s' % (fn.__name__, message) 19 return skipped 20 return _decorator 21 22from test.test_support import TestFailed, have_unicode, TESTFN 23try: 24 from test.test_support import _2G, _1M, precisionbigmemtest 25except ImportError: 26 # this import might fail when run on older Python versions by test_xpickle 27 _2G = _1M = 0 28 def precisionbigmemtest(*args, **kwargs): 29 return lambda self: None 30 31from . import _is_jython 32from . import _is_pypy 33from . import _is_pure 34from zodbpickle import pickle_2 as pickle 35try: 36 from zodbpickle import _pickle as cPickle 37 has_c_implementation = not _is_pypy and not _is_pure 38except ImportError: 39 cPickle = pickle 40 has_c_implementation = False 41 42from zodbpickle import pickletools_2 as pickletools 43 44# Tests that try a number of pickle protocols should have a 45# for proto in protocols: 46# kind of outer loop. 47assert pickle.HIGHEST_PROTOCOL == cPickle.HIGHEST_PROTOCOL == 3 48protocols = range(pickle.HIGHEST_PROTOCOL + 1) 49 50# Copy of test.test_support.run_with_locale. This is needed to support Python 51# 2.4, which didn't include it. This is all to support test_xpickle, which 52# bounces pickled objects through older Python versions to test backwards 53# compatibility. 54def run_with_locale(catstr, *locales): 55 def decorator(func): 56 def inner(*args, **kwds): 57 try: 58 import locale 59 category = getattr(locale, catstr) 60 orig_locale = locale.setlocale(category) 61 except AttributeError: 62 # if the test author gives us an invalid category string 63 raise 64 except: 65 # cannot retrieve original locale, so do nothing 66 locale = orig_locale = None 67 else: 68 for loc in locales: 69 try: 70 locale.setlocale(category, loc) 71 break 72 except: 73 pass 74 75 # now run the function, resetting the locale on exceptions 76 try: 77 return func(*args, **kwds) 78 finally: 79 if locale and orig_locale: 80 locale.setlocale(category, orig_locale) 81 inner.func_name = func.func_name 82 inner.__doc__ = func.__doc__ 83 return inner 84 return decorator 85 86 87# Return True if opcode code appears in the pickle, else False. 88def opcode_in_pickle(code, pickle): 89 for op, dummy, dummy in pickletools.genops(pickle): 90 if op.code == code: 91 return True 92 return False 93 94# Return the number of times opcode code appears in pickle. 95def count_opcode(code, pickle): 96 n = 0 97 for op, dummy, dummy in pickletools.genops(pickle): 98 if op.code == code: 99 n += 1 100 return n 101 102# We can't very well test the extension registry without putting known stuff 103# in it, but we have to be careful to restore its original state. Code 104# should do this: 105# 106# e = ExtensionSaver(extension_code) 107# try: 108# fiddle w/ the extension registry's stuff for extension_code 109# finally: 110# e.restore() 111 112class ExtensionSaver: 113 # Remember current registration for code (if any), and remove it (if 114 # there is one). 115 def __init__(self, code): 116 self.code = code 117 if code in copy_reg._inverted_registry: 118 self.pair = copy_reg._inverted_registry[code] 119 copy_reg.remove_extension(self.pair[0], self.pair[1], code) 120 else: 121 self.pair = None 122 123 # Restore previous registration for code. 124 def restore(self): 125 code = self.code 126 curpair = copy_reg._inverted_registry.get(code) 127 if curpair is not None: 128 copy_reg.remove_extension(curpair[0], curpair[1], code) 129 pair = self.pair 130 if pair is not None: 131 copy_reg.add_extension(pair[0], pair[1], code) 132 133class C: 134 def __cmp__(self, other): 135 return cmp(self.__dict__, other.__dict__) 136 137import __main__ 138__main__.C = C 139C.__module__ = "__main__" 140 141class myint(int): 142 def __init__(self, x): 143 self.str = str(x) 144 145class initarg(C): 146 147 def __init__(self, a, b): 148 self.a = a 149 self.b = b 150 151 def __getinitargs__(self): 152 return self.a, self.b 153 154class metaclass(type): 155 pass 156 157class use_metaclass(object): 158 __metaclass__ = metaclass 159 160class pickling_metaclass(type): 161 def __eq__(self, other): 162 return (type(self) == type(other) and 163 self.reduce_args == other.reduce_args) 164 165 def __reduce__(self): 166 return (create_dynamic_class, self.reduce_args) 167 168 __hash__ = None 169 170def create_dynamic_class(name, bases): 171 result = pickling_metaclass(name, bases, dict()) 172 result.reduce_args = (name, bases) 173 return result 174 175# DATA0 .. DATA2 are the pickles we expect under the various protocols, for 176# the object returned by create_data(). 177 178# break into multiple strings to avoid confusing font-lock-mode 179DATA0 = """(lp1 180I0 181aL1L 182aF2 183ac__builtin__ 184complex 185p2 186""" + \ 187"""(F3 188F0 189tRp3 190aI1 191aI-1 192aI255 193aI-255 194aI-256 195aI65535 196aI-65535 197aI-65536 198aI2147483647 199aI-2147483647 200aI-2147483648 201a""" + \ 202"""(S'abc' 203p4 204g4 205""" + \ 206"""(i__main__ 207C 208p5 209""" + \ 210"""(dp6 211S'foo' 212p7 213I1 214sS'bar' 215p8 216I2 217sbg5 218tp9 219ag9 220aI5 221a. 222""" 223 224# Disassembly of DATA0. 225DATA0_DIS = """\ 226 0: ( MARK 227 1: l LIST (MARK at 0) 228 2: p PUT 1 229 5: I INT 0 230 8: a APPEND 231 9: L LONG 1L 232 13: a APPEND 233 14: F FLOAT 2.0 234 17: a APPEND 235 18: c GLOBAL '__builtin__ complex' 236 39: p PUT 2 237 42: ( MARK 238 43: F FLOAT 3.0 239 46: F FLOAT 0.0 240 49: t TUPLE (MARK at 42) 241 50: R REDUCE 242 51: p PUT 3 243 54: a APPEND 244 55: I INT 1 245 58: a APPEND 246 59: I INT -1 247 63: a APPEND 248 64: I INT 255 249 69: a APPEND 250 70: I INT -255 251 76: a APPEND 252 77: I INT -256 253 83: a APPEND 254 84: I INT 65535 255 91: a APPEND 256 92: I INT -65535 257 100: a APPEND 258 101: I INT -65536 259 109: a APPEND 260 110: I INT 2147483647 261 122: a APPEND 262 123: I INT -2147483647 263 136: a APPEND 264 137: I INT -2147483648 265 150: a APPEND 266 151: ( MARK 267 152: S STRING 'abc' 268 159: p PUT 4 269 162: g GET 4 270 165: ( MARK 271 166: i INST '__main__ C' (MARK at 165) 272 178: p PUT 5 273 181: ( MARK 274 182: d DICT (MARK at 181) 275 183: p PUT 6 276 186: S STRING 'foo' 277 193: p PUT 7 278 196: I INT 1 279 199: s SETITEM 280 200: S STRING 'bar' 281 207: p PUT 8 282 210: I INT 2 283 213: s SETITEM 284 214: b BUILD 285 215: g GET 5 286 218: t TUPLE (MARK at 151) 287 219: p PUT 9 288 222: a APPEND 289 223: g GET 9 290 226: a APPEND 291 227: I INT 5 292 230: a APPEND 293 231: . STOP 294highest protocol among opcodes = 0 295""" 296 297DATA1 = (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00' 298 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00' 299 '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff' 300 '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff' 301 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00' 302 '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n' 303 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh' 304 '\x06tq\nh\nK\x05e.' 305 ) 306 307# Disassembly of DATA1. 308DATA1_DIS = """\ 309 0: ] EMPTY_LIST 310 1: q BINPUT 1 311 3: ( MARK 312 4: K BININT1 0 313 6: L LONG 1L 314 10: G BINFLOAT 2.0 315 19: c GLOBAL '__builtin__ complex' 316 40: q BINPUT 2 317 42: ( MARK 318 43: G BINFLOAT 3.0 319 52: G BINFLOAT 0.0 320 61: t TUPLE (MARK at 42) 321 62: R REDUCE 322 63: q BINPUT 3 323 65: K BININT1 1 324 67: J BININT -1 325 72: K BININT1 255 326 74: J BININT -255 327 79: J BININT -256 328 84: M BININT2 65535 329 87: J BININT -65535 330 92: J BININT -65536 331 97: J BININT 2147483647 332 102: J BININT -2147483647 333 107: J BININT -2147483648 334 112: ( MARK 335 113: U SHORT_BINSTRING 'abc' 336 118: q BINPUT 4 337 120: h BINGET 4 338 122: ( MARK 339 123: c GLOBAL '__main__ C' 340 135: q BINPUT 5 341 137: o OBJ (MARK at 122) 342 138: q BINPUT 6 343 140: } EMPTY_DICT 344 141: q BINPUT 7 345 143: ( MARK 346 144: U SHORT_BINSTRING 'foo' 347 149: q BINPUT 8 348 151: K BININT1 1 349 153: U SHORT_BINSTRING 'bar' 350 158: q BINPUT 9 351 160: K BININT1 2 352 162: u SETITEMS (MARK at 143) 353 163: b BUILD 354 164: h BINGET 6 355 166: t TUPLE (MARK at 112) 356 167: q BINPUT 10 357 169: h BINGET 10 358 171: K BININT1 5 359 173: e APPENDS (MARK at 3) 360 174: . STOP 361highest protocol among opcodes = 1 362""" 363 364DATA2 = ('\x80\x02]q\x01(K\x00\x8a\x01\x01G@\x00\x00\x00\x00\x00\x00\x00' 365 'c__builtin__\ncomplex\nq\x02G@\x08\x00\x00\x00\x00\x00\x00G\x00' 366 '\x00\x00\x00\x00\x00\x00\x00\x86Rq\x03K\x01J\xff\xff\xff\xffK' 367 '\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xff' 368 'J\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00' 369 '\x80(U\x03abcq\x04h\x04(c__main__\nC\nq\x05oq\x06}q\x07(U\x03foo' 370 'q\x08K\x01U\x03barq\tK\x02ubh\x06tq\nh\nK\x05e.') 371 372# Disassembly of DATA2. 373DATA2_DIS = """\ 374 0: \x80 PROTO 2 375 2: ] EMPTY_LIST 376 3: q BINPUT 1 377 5: ( MARK 378 6: K BININT1 0 379 8: \x8a LONG1 1L 380 11: G BINFLOAT 2.0 381 20: c GLOBAL '__builtin__ complex' 382 41: q BINPUT 2 383 43: G BINFLOAT 3.0 384 52: G BINFLOAT 0.0 385 61: \x86 TUPLE2 386 62: R REDUCE 387 63: q BINPUT 3 388 65: K BININT1 1 389 67: J BININT -1 390 72: K BININT1 255 391 74: J BININT -255 392 79: J BININT -256 393 84: M BININT2 65535 394 87: J BININT -65535 395 92: J BININT -65536 396 97: J BININT 2147483647 397 102: J BININT -2147483647 398 107: J BININT -2147483648 399 112: ( MARK 400 113: U SHORT_BINSTRING 'abc' 401 118: q BINPUT 4 402 120: h BINGET 4 403 122: ( MARK 404 123: c GLOBAL '__main__ C' 405 135: q BINPUT 5 406 137: o OBJ (MARK at 122) 407 138: q BINPUT 6 408 140: } EMPTY_DICT 409 141: q BINPUT 7 410 143: ( MARK 411 144: U SHORT_BINSTRING 'foo' 412 149: q BINPUT 8 413 151: K BININT1 1 414 153: U SHORT_BINSTRING 'bar' 415 158: q BINPUT 9 416 160: K BININT1 2 417 162: u SETITEMS (MARK at 143) 418 163: b BUILD 419 164: h BINGET 6 420 166: t TUPLE (MARK at 112) 421 167: q BINPUT 10 422 169: h BINGET 10 423 171: K BININT1 5 424 173: e APPENDS (MARK at 5) 425 174: . STOP 426highest protocol among opcodes = 2 427""" 428 429def create_data(): 430 c = C() 431 c.foo = 1 432 c.bar = 2 433 x = [0, 1L, 2.0, 3.0+0j] 434 # Append some integer test cases at cPickle.c's internal size 435 # cutoffs. 436 uint1max = 0xff 437 uint2max = 0xffff 438 int4max = 0x7fffffff 439 x.extend([1, -1, 440 uint1max, -uint1max, -uint1max-1, 441 uint2max, -uint2max, -uint2max-1, 442 int4max, -int4max, -int4max-1]) 443 y = ('abc', 'abc', c, c) 444 x.append(y) 445 x.append(y) 446 x.append(5) 447 return x 448 449class AbstractPickleTests(unittest.TestCase): 450 # Subclass must define self.dumps, self.loads, self.error. 451 452 _testdata = create_data() 453 454 def setUp(self): 455 pass 456 457 def test_misc(self): 458 # test various datatypes not tested by testdata 459 for proto in protocols: 460 x = myint(4) 461 s = self.dumps(x, proto) 462 y = self.loads(s) 463 self.assertEqual(x, y) 464 465 x = (1, ()) 466 s = self.dumps(x, proto) 467 y = self.loads(s) 468 self.assertEqual(x, y) 469 470 x = initarg(1, x) 471 s = self.dumps(x, proto) 472 y = self.loads(s) 473 self.assertEqual(x, y) 474 475 # XXX test __reduce__ protocol? 476 477 def test_roundtrip_equality(self): 478 expected = self._testdata 479 for proto in protocols: 480 s = self.dumps(expected, proto) 481 got = self.loads(s) 482 self.assertEqual(expected, got) 483 484 def test_load_from_canned_string(self): 485 expected = self._testdata 486 for canned in DATA0, DATA1, DATA2: 487 got = self.loads(canned) 488 self.assertEqual(expected, got) 489 490 # There are gratuitous differences between pickles produced by 491 # pickle and cPickle, largely because cPickle starts PUT indices at 492 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() -- 493 # there's a comment with an exclamation point there whose meaning 494 # is a mystery. cPickle also suppresses PUT for objects with a refcount 495 # of 1. 496 def dont_test_disassembly(self): 497 from pickletools import dis 498 499 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS): 500 s = self.dumps(self._testdata, proto) 501 filelike = cStringIO.StringIO() 502 dis(s, out=filelike) 503 got = filelike.getvalue() 504 self.assertEqual(expected, got) 505 506 def test_recursive_list(self): 507 l = [] 508 l.append(l) 509 for proto in protocols: 510 s = self.dumps(l, proto) 511 x = self.loads(s) 512 self.assertEqual(len(x), 1) 513 self.assertTrue(x is x[0]) 514 515 def test_recursive_tuple(self): 516 t = ([],) 517 t[0].append(t) 518 for proto in protocols: 519 s = self.dumps(t, proto) 520 x = self.loads(s) 521 self.assertEqual(len(x), 1) 522 self.assertEqual(len(x[0]), 1) 523 self.assertTrue(x is x[0][0]) 524 525 def test_recursive_dict(self): 526 d = {} 527 d[1] = d 528 for proto in protocols: 529 s = self.dumps(d, proto) 530 x = self.loads(s) 531 self.assertEqual(x.keys(), [1]) 532 self.assertTrue(x[1] is x) 533 534 def test_recursive_inst(self): 535 i = C() 536 i.attr = i 537 for proto in protocols: 538 s = self.dumps(i, proto) 539 x = self.loads(s) 540 self.assertEqual(dir(x), dir(i)) 541 self.assertIs(x.attr, x) 542 543 def test_recursive_multi(self): 544 l = [] 545 d = {1:l} 546 i = C() 547 i.attr = d 548 l.append(i) 549 for proto in protocols: 550 s = self.dumps(l, proto) 551 x = self.loads(s) 552 self.assertEqual(len(x), 1) 553 self.assertEqual(dir(x[0]), dir(i)) 554 self.assertEqual(x[0].attr.keys(), [1]) 555 self.assertTrue(x[0].attr[1] is x) 556 557 def test_garyp(self): 558 self.assertRaises(self.error, self.loads, 'garyp') 559 560 def test_insecure_strings(self): 561 insecure = ["abc", "2 + 2", # not quoted 562 #"'abc' + 'def'", # not a single quoted string 563 "'abc", # quote is not closed 564 "'abc\"", # open quote and close quote don't match 565 "'abc' ?", # junk after close quote 566 "'\\'", # trailing backslash 567 "'", # issue #17710 568 "' ", # issue #17710 569 # some tests of the quoting rules 570 #"'abc\"\''", 571 #"'\\\\a\'\'\'\\\'\\\\\''", 572 ] 573 for s in insecure: 574 buf = "S" + s + "\012p0\012." 575 self.assertRaises(ValueError, self.loads, buf) 576 577 if have_unicode: 578 def test_unicode(self): 579 endcases = [u'', u'<\\u>', u'<\\\u1234>', u'<\n>', 580 u'<\\>', u'<\\\U00012345>'] 581 for proto in protocols: 582 for u in endcases: 583 p = self.dumps(u, proto) 584 u2 = self.loads(p) 585 self.assertEqual(u2, u) 586 587 def test_unicode_high_plane(self): 588 t = u'\U00012345' 589 for proto in protocols: 590 p = self.dumps(t, proto) 591 t2 = self.loads(p) 592 self.assertEqual(t2, t) 593 594 def test_ints(self): 595 import sys 596 for proto in protocols: 597 n = sys.maxint 598 while n: 599 for expected in (-n, n): 600 s = self.dumps(expected, proto) 601 n2 = self.loads(s) 602 self.assertEqual(expected, n2) 603 n = n >> 1 604 605 def test_maxint64(self): 606 maxint64 = (1L << 63) - 1 607 data = 'I' + str(maxint64) + '\n.' 608 got = self.loads(data) 609 self.assertEqual(got, maxint64) 610 611 # Try too with a bogus literal. 612 data = 'I' + str(maxint64) + 'JUNK\n.' 613 self.assertRaises(ValueError, self.loads, data) 614 615 def test_long(self): 616 for proto in protocols: 617 # 256 bytes is where LONG4 begins. 618 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257: 619 nbase = 1L << nbits 620 for npos in nbase-1, nbase, nbase+1: 621 for n in npos, -npos: 622 pickle = self.dumps(n, proto) 623 got = self.loads(pickle) 624 self.assertEqual(n, got) 625 # Try a monster. This is quadratic-time in protos 0 & 1, so don't 626 # bother with those. 627 nbase = long("deadbeeffeedface", 16) 628 nbase += nbase << 1000000 629 for n in nbase, -nbase: 630 p = self.dumps(n, 2) 631 got = self.loads(p) 632 self.assertEqual(n, got) 633 634 def test_float(self): 635 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5, 636 3.14, 263.44582062374053, 6.022e23, 1e30] 637 test_values = test_values + [-x for x in test_values] 638 for proto in protocols: 639 for value in test_values: 640 pickle = self.dumps(value, proto) 641 got = self.loads(pickle) 642 self.assertEqual(value, got) 643 644 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR') 645 def test_float_format(self): 646 # make sure that floats are formatted locale independent 647 self.assertEqual(self.dumps(1.2)[0:3], 'F1.') 648 649 def test_reduce(self): 650 pass 651 652 def test_getinitargs(self): 653 pass 654 655 def test_metaclass(self): 656 a = use_metaclass() 657 for proto in protocols: 658 s = self.dumps(a, proto) 659 b = self.loads(s) 660 self.assertEqual(a.__class__, b.__class__) 661 662 def test_dynamic_class(self): 663 a = create_dynamic_class("my_dynamic_class", (object,)) 664 copy_reg.pickle(pickling_metaclass, pickling_metaclass.__reduce__) 665 for proto in protocols: 666 s = self.dumps(a, proto) 667 b = self.loads(s) 668 self.assertEqual(a, b) 669 670 def test_structseq(self): 671 import time 672 import os 673 674 t = time.localtime() 675 for proto in protocols: 676 s = self.dumps(t, proto) 677 u = self.loads(s) 678 self.assertEqual(t, u) 679 if hasattr(os, "stat"): 680 t = os.stat(os.curdir) 681 s = self.dumps(t, proto) 682 u = self.loads(s) 683 self.assertEqual(t, u) 684 if hasattr(os, "statvfs"): 685 t = os.statvfs(os.curdir) 686 s = self.dumps(t, proto) 687 u = self.loads(s) 688 self.assertEqual(t, u) 689 690 # Tests for protocol 2 691 692 def test_proto(self): 693 build_none = pickle.NONE + pickle.STOP 694 for proto in protocols: 695 expected = build_none 696 if proto >= 2: 697 expected = pickle.PROTO + chr(proto) + expected 698 p = self.dumps(None, proto) 699 self.assertEqual(p, expected) 700 701 oob = protocols[-1] + 1 # a future protocol 702 badpickle = pickle.PROTO + chr(oob) + build_none 703 try: 704 self.loads(badpickle) 705 except ValueError, detail: 706 self.assertTrue(str(detail).startswith( 707 "unsupported pickle protocol")) 708 else: 709 self.fail("expected bad protocol number to raise ValueError") 710 711 def test_long1(self): 712 x = 12345678910111213141516178920L 713 for proto in protocols: 714 s = self.dumps(x, proto) 715 y = self.loads(s) 716 self.assertEqual(x, y) 717 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2) 718 719 def test_long4(self): 720 x = 12345678910111213141516178920L << (256*8) 721 for proto in protocols: 722 s = self.dumps(x, proto) 723 y = self.loads(s) 724 self.assertEqual(x, y) 725 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2) 726 727 def test_shortbinbytes(self): 728 from zodbpickle import binary 729 x = binary(b'\x00ABC\x80') 730 for proto in protocols: 731 s = self.dumps(x, proto) 732 y = self.loads(s) 733 self.assertEqual(x, y) 734 self.assertEqual(opcode_in_pickle(pickle.SHORT_BINBYTES, s), 735 proto >= 3, str(self.__class__)) 736 737 def test_binbytes(self): 738 from zodbpickle import binary 739 x = binary(b'\x00ABC\x80' * 100) 740 for proto in protocols: 741 s = self.dumps(x, proto) 742 y = self.loads(s) 743 self.assertEqual(x, y) 744 self.assertEqual(opcode_in_pickle(pickle.BINBYTES, s), 745 proto >= 3, str(self.__class__)) 746 747 def test_short_tuples(self): 748 # Map (proto, len(tuple)) to expected opcode. 749 expected_opcode = {(0, 0): pickle.TUPLE, 750 (0, 1): pickle.TUPLE, 751 (0, 2): pickle.TUPLE, 752 (0, 3): pickle.TUPLE, 753 (0, 4): pickle.TUPLE, 754 755 (1, 0): pickle.EMPTY_TUPLE, 756 (1, 1): pickle.TUPLE, 757 (1, 2): pickle.TUPLE, 758 (1, 3): pickle.TUPLE, 759 (1, 4): pickle.TUPLE, 760 761 (2, 0): pickle.EMPTY_TUPLE, 762 (2, 1): pickle.TUPLE1, 763 (2, 2): pickle.TUPLE2, 764 (2, 3): pickle.TUPLE3, 765 (2, 4): pickle.TUPLE, 766 767 (3, 0): pickle.EMPTY_TUPLE, 768 (3, 1): pickle.TUPLE1, 769 (3, 2): pickle.TUPLE2, 770 (3, 3): pickle.TUPLE3, 771 (3, 4): pickle.TUPLE, 772 } 773 a = () 774 b = (1,) 775 c = (1, 2) 776 d = (1, 2, 3) 777 e = (1, 2, 3, 4) 778 for proto in protocols: 779 for x in a, b, c, d, e: 780 s = self.dumps(x, proto) 781 y = self.loads(s) 782 self.assertEqual(x, y, (proto, x, s, y)) 783 expected = expected_opcode[proto, len(x)] 784 self.assertEqual(opcode_in_pickle(expected, s), True) 785 786 def test_singletons(self): 787 # Map (proto, singleton) to expected opcode. 788 expected_opcode = {(0, None): pickle.NONE, 789 (1, None): pickle.NONE, 790 (2, None): pickle.NONE, 791 (3, None): pickle.NONE, 792 793 (0, True): pickle.INT, 794 (1, True): pickle.INT, 795 (2, True): pickle.NEWTRUE, 796 (3, True): pickle.NEWTRUE, 797 798 (0, False): pickle.INT, 799 (1, False): pickle.INT, 800 (2, False): pickle.NEWFALSE, 801 (3, False): pickle.NEWFALSE, 802 } 803 for proto in protocols: 804 for x in None, False, True: 805 s = self.dumps(x, proto) 806 y = self.loads(s) 807 self.assertTrue(x is y, (proto, x, s, y)) 808 expected = expected_opcode[proto, x] 809 self.assertEqual(opcode_in_pickle(expected, s), True) 810 811 def test_newobj_tuple(self): 812 x = MyTuple([1, 2, 3]) 813 x.foo = 42 814 x.bar = "hello" 815 for proto in protocols: 816 s = self.dumps(x, proto) 817 y = self.loads(s) 818 self.assertEqual(tuple(x), tuple(y)) 819 self.assertEqual(x.__dict__, y.__dict__) 820 821 def test_newobj_list(self): 822 x = MyList([1, 2, 3]) 823 x.foo = 42 824 x.bar = "hello" 825 for proto in protocols: 826 s = self.dumps(x, proto) 827 y = self.loads(s) 828 self.assertEqual(list(x), list(y)) 829 self.assertEqual(x.__dict__, y.__dict__) 830 831 def test_newobj_generic(self): 832 for proto in protocols: 833 for C in myclasses: 834 B = C.__base__ 835 x = C(C.sample) 836 x.foo = 42 837 s = self.dumps(x, proto) 838 y = self.loads(s) 839 detail = (proto, C, B, x, y, type(y)) 840 self.assertEqual(B(x), B(y), detail) 841 self.assertEqual(x.__dict__, y.__dict__, detail) 842 843 # Register a type with copy_reg, with extension code extcode. Pickle 844 # an object of that type. Check that the resulting pickle uses opcode 845 # (EXT[124]) under proto 2, and not in proto 1. 846 847 def produce_global_ext(self, extcode, opcode): 848 e = ExtensionSaver(extcode) 849 try: 850 copy_reg.add_extension(__name__, "MyList", extcode) 851 x = MyList([1, 2, 3]) 852 x.foo = 42 853 x.bar = "hello" 854 855 # Dump using protocol 1 for comparison. 856 s1 = self.dumps(x, 1) 857 self.assertIn(__name__, s1) 858 self.assertIn("MyList", s1) 859 self.assertEqual(opcode_in_pickle(opcode, s1), False) 860 861 y = self.loads(s1) 862 self.assertEqual(list(x), list(y)) 863 self.assertEqual(x.__dict__, y.__dict__) 864 865 # Dump using protocol 2 for test. 866 s2 = self.dumps(x, 2) 867 self.assertNotIn(__name__, s2) 868 self.assertNotIn("MyList", s2) 869 self.assertEqual(opcode_in_pickle(opcode, s2), True) 870 871 y = self.loads(s2) 872 self.assertEqual(list(x), list(y)) 873 self.assertEqual(x.__dict__, y.__dict__) 874 875 finally: 876 e.restore() 877 878 def test_global_ext1(self): 879 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code 880 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code 881 882 def test_global_ext2(self): 883 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code 884 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code 885 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness 886 887 def test_global_ext4(self): 888 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code 889 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code 890 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness 891 892 def test_list_chunking(self): 893 n = 10 # too small to chunk 894 x = range(n) 895 for proto in protocols: 896 s = self.dumps(x, proto) 897 y = self.loads(s) 898 self.assertEqual(x, y) 899 num_appends = count_opcode(pickle.APPENDS, s) 900 self.assertEqual(num_appends, proto > 0) 901 902 n = 2500 # expect at least two chunks when proto > 0 903 x = range(n) 904 for proto in protocols: 905 s = self.dumps(x, proto) 906 y = self.loads(s) 907 self.assertEqual(x, y) 908 num_appends = count_opcode(pickle.APPENDS, s) 909 if proto == 0: 910 self.assertEqual(num_appends, 0) 911 else: 912 self.assertTrue(num_appends >= 2) 913 914 def test_dict_chunking(self): 915 n = 10 # too small to chunk 916 x = dict.fromkeys(range(n)) 917 for proto in protocols: 918 s = self.dumps(x, proto) 919 y = self.loads(s) 920 self.assertEqual(x, y) 921 num_setitems = count_opcode(pickle.SETITEMS, s) 922 self.assertEqual(num_setitems, proto > 0) 923 924 n = 2500 # expect at least two chunks when proto > 0 925 x = dict.fromkeys(range(n)) 926 for proto in protocols: 927 s = self.dumps(x, proto) 928 y = self.loads(s) 929 self.assertEqual(x, y) 930 num_setitems = count_opcode(pickle.SETITEMS, s) 931 if proto == 0: 932 self.assertEqual(num_setitems, 0) 933 else: 934 self.assertTrue(num_setitems >= 2) 935 936 def test_simple_newobj(self): 937 x = object.__new__(SimpleNewObj) # avoid __init__ 938 x.abc = 666 939 for proto in protocols: 940 s = self.dumps(x, proto) 941 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s), proto >= 2) 942 y = self.loads(s) # will raise TypeError if __init__ called 943 self.assertEqual(y.abc, 666) 944 self.assertEqual(x.__dict__, y.__dict__) 945 946 def test_newobj_list_slots(self): 947 x = SlotList([1, 2, 3]) 948 x.foo = 42 949 x.bar = "hello" 950 s = self.dumps(x, 2) 951 y = self.loads(s) 952 self.assertEqual(list(x), list(y)) 953 self.assertEqual(x.__dict__, y.__dict__) 954 self.assertEqual(x.foo, y.foo) 955 self.assertEqual(x.bar, y.bar) 956 957 def test_reduce_overrides_default_reduce_ex(self): 958 for proto in protocols: 959 x = REX_one() 960 self.assertEqual(x._reduce_called, 0) 961 s = self.dumps(x, proto) 962 self.assertEqual(x._reduce_called, 1) 963 y = self.loads(s) 964 self.assertEqual(y._reduce_called, 0) 965 966 def test_reduce_ex_called(self): 967 for proto in protocols: 968 x = REX_two() 969 self.assertEqual(x._proto, None) 970 s = self.dumps(x, proto) 971 self.assertEqual(x._proto, proto) 972 y = self.loads(s) 973 self.assertEqual(y._proto, None) 974 975 def test_reduce_ex_overrides_reduce(self): 976 for proto in protocols: 977 x = REX_three() 978 self.assertEqual(x._proto, None) 979 s = self.dumps(x, proto) 980 self.assertEqual(x._proto, proto) 981 y = self.loads(s) 982 self.assertEqual(y._proto, None) 983 984 def test_reduce_ex_calls_base(self): 985 for proto in protocols: 986 x = REX_four() 987 self.assertEqual(x._proto, None) 988 s = self.dumps(x, proto) 989 self.assertEqual(x._proto, proto) 990 y = self.loads(s) 991 self.assertEqual(y._proto, proto) 992 993 def test_reduce_calls_base(self): 994 for proto in protocols: 995 x = REX_five() 996 self.assertEqual(x._reduce_called, 0) 997 s = self.dumps(x, proto) 998 self.assertEqual(x._reduce_called, 1) 999 y = self.loads(s) 1000 self.assertEqual(y._reduce_called, 1) 1001 1002 def test_reduce_bad_iterator(self): 1003 # Issue4176: crash when 4th and 5th items of __reduce__() 1004 # are not iterators 1005 class C(object): 1006 def __reduce__(self): 1007 # 4th item is not an iterator 1008 return list, (), None, [], None 1009 class D(object): 1010 def __reduce__(self): 1011 # 5th item is not an iterator 1012 return dict, (), None, None, [] 1013 1014 # Protocol 0 is less strict and also accept iterables. 1015 for proto in protocols: 1016 try: 1017 self.dumps(C(), proto) 1018 except (AttributeError, pickle.PickleError, cPickle.PickleError): 1019 pass 1020 try: 1021 self.dumps(D(), proto) 1022 except (AttributeError, pickle.PickleError, cPickle.PickleError): 1023 pass 1024 1025 def test_many_puts_and_gets(self): 1026 # Test that internal data structures correctly deal with lots of 1027 # puts/gets. 1028 keys = ("aaa" + str(i) for i in xrange(100)) 1029 large_dict = dict((k, [4, 5, 6]) for k in keys) 1030 obj = [dict(large_dict), dict(large_dict), dict(large_dict)] 1031 1032 for proto in protocols: 1033 dumped = self.dumps(obj, proto) 1034 loaded = self.loads(dumped) 1035 self.assertEqual(loaded, obj, 1036 "Failed protocol %d: %r != %r" 1037 % (proto, obj, loaded)) 1038 1039 @skipIf(_is_jython, "Jython interns strings at the Java level " 1040 "but creates new PyString wrappers when __dict__ is " 1041 "accessed. See PyStringMap.") 1042 def test_attribute_name_interning(self): 1043 # Test that attribute names of pickled objects are interned when 1044 # unpickling. 1045 for proto in protocols: 1046 x = C() 1047 x.foo = 42 1048 x.bar = "hello" 1049 s = self.dumps(x, proto) 1050 y = self.loads(s) 1051 x_keys = sorted(x.__dict__) 1052 y_keys = sorted(y.__dict__) 1053 for x_key, y_key in zip(x_keys, y_keys): 1054 self.assertIs(x_key, y_key) 1055 1056if sys.version_info < (2, 7): 1057 1058 def assertIs(self, expr1, expr2, msg=None): 1059 self.assertTrue(expr1 is expr2, msg) 1060 1061 def assertIn(self, expr1, expr2, msg=None): 1062 self.assertTrue(expr1 in expr2, msg) 1063 1064 def assertNotIn(self, expr1, expr2, msg=None): 1065 self.assertTrue(expr1 not in expr2, msg) 1066 1067 AbstractPickleTests.assertIs = assertIs 1068 AbstractPickleTests.assertIn = assertIn 1069 AbstractPickleTests.assertNotIn = assertNotIn 1070 1071 1072# Test classes for reduce_ex 1073 1074class REX_one(object): 1075 _reduce_called = 0 1076 def __reduce__(self): 1077 self._reduce_called = 1 1078 return REX_one, () 1079 # No __reduce_ex__ here, but inheriting it from object 1080 1081class REX_two(object): 1082 _proto = None 1083 def __reduce_ex__(self, proto): 1084 self._proto = proto 1085 return REX_two, () 1086 # No __reduce__ here, but inheriting it from object 1087 1088class REX_three(object): 1089 _proto = None 1090 def __reduce_ex__(self, proto): 1091 self._proto = proto 1092 return REX_two, () 1093 def __reduce__(self): 1094 raise TestFailed, "This __reduce__ shouldn't be called" 1095 1096class REX_four(object): 1097 _proto = None 1098 def __reduce_ex__(self, proto): 1099 self._proto = proto 1100 return object.__reduce_ex__(self, proto) 1101 # Calling base class method should succeed 1102 1103class REX_five(object): 1104 _reduce_called = 0 1105 def __reduce__(self): 1106 self._reduce_called = 1 1107 if _is_jython: 1108 return super(REX_five,self).__reduce__() 1109 return object.__reduce__(self) 1110 # This one used to fail with infinite recursion; 1111 # on Jython 2.7rc2 it still does if super() is not used; this 1112 # is a bug in Jython http://bugs.jython.org/issue2323 1113 1114# Test classes for newobj 1115 1116class MyInt(int): 1117 sample = 1 1118 1119class MyLong(long): 1120 sample = 1L 1121 1122class MyFloat(float): 1123 sample = 1.0 1124 1125class MyComplex(complex): 1126 sample = 1.0 + 0.0j 1127 1128class MyStr(str): 1129 sample = "hello" 1130 1131class MyUnicode(unicode): 1132 sample = u"hello \u1234" 1133 1134class MyTuple(tuple): 1135 sample = (1, 2, 3) 1136 1137class MyList(list): 1138 sample = [1, 2, 3] 1139 1140class MyDict(dict): 1141 sample = {"a": 1, "b": 2} 1142 1143myclasses = [MyInt, MyLong, MyFloat, 1144 MyComplex, 1145 MyStr, MyUnicode, 1146 MyTuple, MyList, MyDict] 1147 1148 1149class SlotList(MyList): 1150 __slots__ = ["foo"] 1151 1152class SimpleNewObj(object): 1153 def __init__(self, a, b, c): 1154 # raise an error, to make sure this isn't called 1155 raise TypeError("SimpleNewObj.__init__() didn't expect to get called") 1156 1157class AbstractPickleModuleTests(unittest.TestCase): 1158 1159 def test_dump_closed_file(self): 1160 import os 1161 f = open(TESTFN, "w") 1162 try: 1163 f.close() 1164 self.assertRaises(ValueError, self.module.dump, 123, f) 1165 finally: 1166 os.remove(TESTFN) 1167 1168 def test_load_closed_file(self): 1169 import os 1170 f = open(TESTFN, "w") 1171 try: 1172 f.close() 1173 self.assertRaises(ValueError, self.module.dump, 123, f) 1174 finally: 1175 os.remove(TESTFN) 1176 1177 def test_load_from_and_dump_to_file(self): 1178 stream = cStringIO.StringIO() 1179 data = [123, {}, 124] 1180 self.module.dump(data, stream) 1181 stream.seek(0) 1182 unpickled = self.module.load(stream) 1183 self.assertEqual(unpickled, data) 1184 1185 def test_highest_protocol(self): 1186 # Of course this needs to be changed when HIGHEST_PROTOCOL changes. 1187 self.assertEqual(self.module.HIGHEST_PROTOCOL, 3) 1188 1189 def test_callapi(self): 1190 f = cStringIO.StringIO() 1191 # With and without keyword arguments 1192 self.module.dump(123, f, -1) 1193 self.module.dump(123, file=f, protocol=-1) 1194 self.module.dumps(123, -1) 1195 self.module.dumps(123, protocol=-1) 1196 self.module.Pickler(f, -1) 1197 self.module.Pickler(f, protocol=-1) 1198 1199 def test_incomplete_input(self): 1200 s = StringIO.StringIO("X''.") 1201 self.assertRaises(EOFError, self.module.load, s) 1202 1203 @skipIf(_is_pypy or _is_jython, "Fails to access the redefined builtins") 1204 def test_restricted(self): 1205 # issue7128: cPickle failed in restricted mode 1206 builtins = {'pickleme': self.module, 1207 '__import__': __import__} 1208 d = {} 1209 teststr = "def f(): pickleme.dumps(0)" 1210 exec teststr in {'__builtins__': builtins}, d 1211 d['f']() 1212 1213 def test_bad_input(self): 1214 # Test issue4298 1215 s = '\x58\0\0\0\x54' 1216 self.assertRaises(EOFError, self.module.loads, s) 1217 # Test issue7455 1218 s = '0' 1219 # XXX Why doesn't pickle raise UnpicklingError? 1220 self.assertRaises((IndexError, cPickle.UnpicklingError), 1221 self.module.loads, s) 1222 1223class AbstractPersistentPicklerTests(unittest.TestCase): 1224 1225 # This class defines persistent_id() and persistent_load() 1226 # functions that should be used by the pickler. All even integers 1227 # are pickled using persistent ids. 1228 1229 def persistent_id(self, object): 1230 if isinstance(object, int) and object % 2 == 0: 1231 self.id_count += 1 1232 return str(object) 1233 else: 1234 return None 1235 1236 def persistent_load(self, oid): 1237 self.load_count += 1 1238 object = int(oid) 1239 assert object % 2 == 0 1240 return object 1241 1242 def test_persistence(self): 1243 self.id_count = 0 1244 self.load_count = 0 1245 L = range(10) 1246 self.assertEqual(self.loads(self.dumps(L)), L) 1247 self.assertEqual(self.id_count, 5) 1248 self.assertEqual(self.load_count, 5) 1249 1250 def test_bin_persistence(self): 1251 self.id_count = 0 1252 self.load_count = 0 1253 L = range(10) 1254 self.assertEqual(self.loads(self.dumps(L, 1)), L) 1255 self.assertEqual(self.id_count, 5) 1256 self.assertEqual(self.load_count, 5) 1257 1258 1259REDUCE_A = 'reduce_A' 1260 1261class AAA(object): 1262 def __reduce__(self): 1263 return str, (REDUCE_A,) 1264 1265class BBB(object): 1266 pass 1267 1268 1269class AbstractPicklerUnpicklerObjectTests(unittest.TestCase): 1270 1271 pickler_class = None 1272 unpickler_class = None 1273 1274 def setUp(self): 1275 assert self.pickler_class 1276 assert self.unpickler_class 1277 1278 def test_clear_pickler_memo(self): 1279 # To test whether clear_memo() has any effect, we pickle an object, 1280 # then pickle it again without clearing the memo; the two serialized 1281 # forms should be different. If we clear_memo() and then pickle the 1282 # object again, the third serialized form should be identical to the 1283 # first one we obtained. 1284 data = ["abcdefg", "abcdefg", 44] 1285 f = cStringIO.StringIO() 1286 pickler = self.pickler_class(f) 1287 1288 pickler.dump(data) 1289 first_pickled = f.getvalue() 1290 1291 # Reset StringIO object. 1292 f.seek(0) 1293 f.truncate() 1294 1295 pickler.dump(data) 1296 second_pickled = f.getvalue() 1297 1298 # Reset the Pickler and StringIO objects. 1299 pickler.clear_memo() 1300 f.seek(0) 1301 f.truncate() 1302 1303 pickler.dump(data) 1304 third_pickled = f.getvalue() 1305 1306 self.assertNotEqual(first_pickled, second_pickled) 1307 self.assertEqual(first_pickled, third_pickled) 1308 1309 def test_priming_pickler_memo(self): 1310 # Verify that we can set the Pickler's memo attribute. 1311 data = ["abcdefg", "abcdefg", 44] 1312 f = cStringIO.StringIO() 1313 pickler = self.pickler_class(f) 1314 1315 pickler.dump(data) 1316 first_pickled = f.getvalue() 1317 1318 f = cStringIO.StringIO() 1319 primed = self.pickler_class(f) 1320 primed.memo = pickler.memo 1321 1322 primed.dump(data) 1323 primed_pickled = f.getvalue() 1324 1325 self.assertNotEqual(first_pickled, primed_pickled) 1326 1327 def test_priming_unpickler_memo(self): 1328 # Verify that we can set the Unpickler's memo attribute. 1329 data = ["abcdefg", "abcdefg", 44] 1330 f = cStringIO.StringIO() 1331 pickler = self.pickler_class(f) 1332 1333 pickler.dump(data) 1334 first_pickled = f.getvalue() 1335 1336 f = cStringIO.StringIO() 1337 primed = self.pickler_class(f) 1338 primed.memo = pickler.memo 1339 1340 primed.dump(data) 1341 primed_pickled = f.getvalue() 1342 1343 unpickler = self.unpickler_class(cStringIO.StringIO(first_pickled)) 1344 unpickled_data1 = unpickler.load() 1345 1346 self.assertEqual(unpickled_data1, data) 1347 1348 primed = self.unpickler_class(cStringIO.StringIO(primed_pickled)) 1349 primed.memo = unpickler.memo 1350 unpickled_data2 = primed.load() 1351 1352 primed.memo.clear() 1353 1354 self.assertEqual(unpickled_data2, data) 1355 self.assertTrue(unpickled_data2 is unpickled_data1) 1356 1357 def test_reusing_unpickler_objects(self): 1358 data1 = ["abcdefg", "abcdefg", 44] 1359 f = cStringIO.StringIO() 1360 pickler = self.pickler_class(f) 1361 pickler.dump(data1) 1362 pickled1 = f.getvalue() 1363 1364 data2 = ["abcdefg", 44, 44] 1365 f = cStringIO.StringIO() 1366 pickler = self.pickler_class(f) 1367 pickler.dump(data2) 1368 pickled2 = f.getvalue() 1369 1370 f = cStringIO.StringIO() 1371 f.write(pickled1) 1372 f.seek(0) 1373 unpickler = self.unpickler_class(f) 1374 self.assertEqual(unpickler.load(), data1) 1375 1376 f.seek(0) 1377 f.truncate() 1378 f.write(pickled2) 1379 f.seek(0) 1380 self.assertEqual(unpickler.load(), data2) 1381 1382 def test_noload_object(self): 1383 global _NOLOAD_OBJECT 1384 after = {} 1385 _NOLOAD_OBJECT = object() 1386 aaa = AAA() 1387 bbb = BBB() 1388 ccc = 1 1389 ddd = 1.0 1390 eee = ('eee', 1) 1391 fff = ['fff'] 1392 ggg = {'ggg': 0} 1393 unpickler = self.unpickler_class 1394 f = io.BytesIO() 1395 pickler = self.pickler_class(f, protocol=2) 1396 pickler.dump(_NOLOAD_OBJECT) 1397 after['_NOLOAD_OBJECT'] = f.tell() 1398 pickler.dump(aaa) 1399 after['aaa'] = f.tell() 1400 pickler.dump(bbb) 1401 after['bbb'] = f.tell() 1402 pickler.dump(ccc) 1403 after['ccc'] = f.tell() 1404 pickler.dump(ddd) 1405 after['ddd'] = f.tell() 1406 pickler.dump(eee) 1407 after['eee'] = f.tell() 1408 pickler.dump(fff) 1409 after['fff'] = f.tell() 1410 pickler.dump(ggg) 1411 after['ggg'] = f.tell() 1412 1413 f.seek(0) 1414 unpickler = self.unpickler_class(f) 1415 unpickler.noload() # read past _NOLOAD_OBJECT 1416 1417 self.assertEqual(f.tell(), after['_NOLOAD_OBJECT']) 1418 noload = unpickler.noload() # read past aaa 1419 self.assertEqual(noload, None) 1420 self.assertEqual(f.tell(), after['aaa']) 1421 1422 unpickler.noload() # read past bbb 1423 self.assertEqual(f.tell(), after['bbb']) 1424 1425 noload = unpickler.noload() # read past ccc 1426 self.assertEqual(noload, ccc) 1427 self.assertEqual(f.tell(), after['ccc']) 1428 1429 noload = unpickler.noload() # read past ddd 1430 self.assertEqual(noload, ddd) 1431 self.assertEqual(f.tell(), after['ddd']) 1432 1433 noload = unpickler.noload() # read past eee 1434 self.assertEqual(noload, eee) 1435 self.assertEqual(f.tell(), after['eee']) 1436 1437 noload = unpickler.noload() # read past fff 1438 self.assertEqual(noload, fff) 1439 self.assertEqual(f.tell(), after['fff']) 1440 1441 noload = unpickler.noload() # read past ggg 1442 self.assertEqual(noload, ggg) 1443 self.assertEqual(f.tell(), after['ggg']) 1444 1445 def test_functional_noload_dict_subclass(self): 1446 """noload() doesn't break or produce any output given a dict subclass""" 1447 # See http://bugs.python.org/issue1101399 1448 o = MyDict() 1449 o['x'] = 1 1450 f = io.BytesIO() 1451 pickler = self.pickler_class(f, protocol=2) 1452 pickler.dump(o) 1453 f.seek(0) 1454 unpickler = self.unpickler_class(f) 1455 noload = unpickler.noload() 1456 self.assertEqual(noload, None) 1457 1458 1459 def test_functional_noload_list_subclass(self): 1460 """noload() doesn't break or produce any output given a list subclass""" 1461 # See http://bugs.python.org/issue1101399 1462 o = MyList() 1463 o.append(1) 1464 f = io.BytesIO() 1465 pickler = self.pickler_class(f, protocol=2) 1466 pickler.dump(o) 1467 f.seek(0) 1468 unpickler = self.unpickler_class(f) 1469 noload = unpickler.noload() 1470 self.assertEqual(noload, None) 1471 1472 def test_functional_noload_dict(self): 1473 """noload() implements the Python 2.6 behaviour and fills in dicts""" 1474 # See http://bugs.python.org/issue1101399 1475 o = dict() 1476 o['x'] = 1 1477 f = io.BytesIO() 1478 pickler = self.pickler_class(f, protocol=2) 1479 pickler.dump(o) 1480 f.seek(0) 1481 unpickler = self.unpickler_class(f) 1482 noload = unpickler.noload() 1483 self.assertEqual(noload, o) 1484 1485 1486 def test_functional_noload_list(self): 1487 """noload() implements the Python 2.6 behaviour and fills in lists""" 1488 # See http://bugs.python.org/issue1101399 1489 o = list() 1490 o.append(1) 1491 f = io.BytesIO() 1492 pickler = self.pickler_class(f, protocol=2) 1493 pickler.dump(o) 1494 f.seek(0) 1495 unpickler = self.unpickler_class(f) 1496 noload = unpickler.noload() 1497 self.assertEqual(noload, o) 1498 1499 1500class BigmemPickleTests(unittest.TestCase): 1501 1502 # Memory requirements: 1 byte per character for input strings, 1 byte 1503 # for pickled data, 1 byte for unpickled strings, 1 byte for internal 1504 # buffer and 1 byte of free space for resizing of internal buffer. 1505 1506 @precisionbigmemtest(size=_2G + 100*_1M, memuse=5) 1507 def test_huge_strlist(self, size): 1508 chunksize = 2**20 1509 data = [] 1510 while size > chunksize: 1511 data.append('x' * chunksize) 1512 size -= chunksize 1513 chunksize += 1 1514 data.append('y' * size) 1515 1516 try: 1517 for proto in protocols: 1518 try: 1519 pickled = self.dumps(data, proto) 1520 res = self.loads(pickled) 1521 self.assertEqual(res, data) 1522 finally: 1523 res = None 1524 pickled = None 1525 finally: 1526 data = None 1527