7 from test
.test_support
import TestFailed
, have_unicode
, TESTFN
9 # Tests that try a number of pickle protocols should have a
10 # for proto in protocols:
12 assert pickle
.HIGHEST_PROTOCOL
== cPickle
.HIGHEST_PROTOCOL
== 2
13 protocols
= range(pickle
.HIGHEST_PROTOCOL
+ 1)
16 # Return True if opcode code appears in the pickle, else False.
17 def opcode_in_pickle(code
, pickle
):
18 for op
, dummy
, dummy
in pickletools
.genops(pickle
):
23 # Return the number of times opcode code appears in pickle.
24 def count_opcode(code
, pickle
):
26 for op
, dummy
, dummy
in pickletools
.genops(pickle
):
31 # We can't very well test the extension registry without putting known stuff
32 # in it, but we have to be careful to restore its original state. Code
35 # e = ExtensionSaver(extension_code)
37 # fiddle w/ the extension registry's stuff for extension_code
42 # Remember current registration for code (if any), and remove it (if
44 def __init__(self
, code
):
46 if code
in copy_reg
._inverted
_registry
:
47 self
.pair
= copy_reg
._inverted
_registry
[code
]
48 copy_reg
.remove_extension(self
.pair
[0], self
.pair
[1], code
)
52 # Restore previous registration for code.
55 curpair
= copy_reg
._inverted
_registry
.get(code
)
56 if curpair
is not None:
57 copy_reg
.remove_extension(curpair
[0], curpair
[1], code
)
60 copy_reg
.add_extension(pair
[0], pair
[1], code
)
63 def __cmp__(self
, other
):
64 return cmp(self
.__dict
__, other
.__dict
__)
68 C
.__module
__ = "__main__"
71 def __init__(self
, x
):
76 def __init__(self
, a
, b
):
80 def __getinitargs__(self
):
83 class metaclass(type):
86 class use_metaclass(object):
87 __metaclass__
= metaclass
89 # DATA0 .. DATA2 are the pickles we expect under the various protocols, for
90 # the object returned by create_data().
92 # break into multiple strings to avoid confusing font-lock-mode
138 # Disassembly of DATA0.
141 1: l LIST (MARK at 0)
149 18: c GLOBAL '__builtin__ complex'
154 49: t TUPLE (MARK at 42)
174 110: I INT 2147483647
176 123: I INT -2147483647
178 137: I INT -2147483648
185 166: i INST '__main__ C' (MARK at 165)
188 182: d DICT (MARK at 181)
200 218: t TUPLE (MARK at 151)
208 highest protocol among opcodes = 0
211 DATA1
= (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00'
212 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00'
213 '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff'
214 '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff'
215 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00'
216 '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n'
217 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh'
221 # Disassembly of DATA1.
229 19: c GLOBAL '__builtin__ complex'
234 61: t TUPLE (MARK at 42)
245 97: J BININT 2147483647
246 102: J BININT -2147483647
247 107: J BININT -2147483648
249 113: U SHORT_BINSTRING 'abc'
253 123: c GLOBAL '__main__ C'
255 137: o OBJ (MARK at 122)
260 144: U SHORT_BINSTRING 'foo'
263 153: U SHORT_BINSTRING 'bar'
266 162: u SETITEMS (MARK at 143)
269 166: t TUPLE (MARK at 112)
273 173: e APPENDS (MARK at 3)
275 highest protocol among opcodes = 1
278 DATA2
= ('\x80\x02]q\x01(K\x00\x8a\x01\x01G@\x00\x00\x00\x00\x00\x00\x00'
279 'c__builtin__\ncomplex\nq\x02G@\x08\x00\x00\x00\x00\x00\x00G\x00'
280 '\x00\x00\x00\x00\x00\x00\x00\x86Rq\x03K\x01J\xff\xff\xff\xffK'
281 '\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xff'
282 'J\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00'
283 '\x80(U\x03abcq\x04h\x04(c__main__\nC\nq\x05oq\x06}q\x07(U\x03foo'
284 'q\x08K\x01U\x03barq\tK\x02ubh\x06tq\nh\nK\x05e.')
286 # Disassembly of DATA2.
295 20: c GLOBAL '__builtin__ complex'
310 97: J BININT 2147483647
311 102: J BININT -2147483647
312 107: J BININT -2147483648
314 113: U SHORT_BINSTRING 'abc'
318 123: c GLOBAL '__main__ C'
320 137: o OBJ (MARK at 122)
325 144: U SHORT_BINSTRING 'foo'
328 153: U SHORT_BINSTRING 'bar'
331 162: u SETITEMS (MARK at 143)
334 166: t TUPLE (MARK at 112)
338 173: e APPENDS (MARK at 5)
340 highest protocol among opcodes = 2
347 x
= [0, 1L, 2.0, 3.0+0j
]
348 # Append some integer test cases at cPickle.c's internal size
354 uint1max
, -uint1max
, -uint1max
-1,
355 uint2max
, -uint2max
, -uint2max
-1,
356 int4max
, -int4max
, -int4max
-1])
357 y
= ('abc', 'abc', c
, c
)
363 class AbstractPickleTests(unittest
.TestCase
):
364 # Subclass must define self.dumps, self.loads, self.error.
366 _testdata
= create_data()
372 # test various datatypes not tested by testdata
373 for proto
in protocols
:
375 s
= self
.dumps(x
, proto
)
377 self
.assertEqual(x
, y
)
380 s
= self
.dumps(x
, proto
)
382 self
.assertEqual(x
, y
)
385 s
= self
.dumps(x
, proto
)
387 self
.assertEqual(x
, y
)
389 # XXX test __reduce__ protocol?
391 def test_roundtrip_equality(self
):
392 expected
= self
._testdata
393 for proto
in protocols
:
394 s
= self
.dumps(expected
, proto
)
396 self
.assertEqual(expected
, got
)
398 def test_load_from_canned_string(self
):
399 expected
= self
._testdata
400 for canned
in DATA0
, DATA1
, DATA2
:
401 got
= self
.loads(canned
)
402 self
.assertEqual(expected
, got
)
404 # There are gratuitous differences between pickles produced by
405 # pickle and cPickle, largely because cPickle starts PUT indices at
406 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
407 # there's a comment with an exclamation point there whose meaning
408 # is a mystery. cPickle also suppresses PUT for objects with a refcount
410 def dont_test_disassembly(self
):
411 from cStringIO
import StringIO
412 from pickletools
import dis
414 for proto
, expected
in (0, DATA0_DIS
), (1, DATA1_DIS
):
415 s
= self
.dumps(self
._testdata
, proto
)
416 filelike
= StringIO()
418 got
= filelike
.getvalue()
419 self
.assertEqual(expected
, got
)
421 def test_recursive_list(self
):
424 for proto
in protocols
:
425 s
= self
.dumps(l
, proto
)
427 self
.assertEqual(x
, l
)
428 self
.assertEqual(x
, x
[0])
429 self
.assertEqual(id(x
), id(x
[0]))
431 def test_recursive_dict(self
):
434 for proto
in protocols
:
435 s
= self
.dumps(d
, proto
)
437 self
.assertEqual(x
, d
)
438 self
.assertEqual(x
[1], x
)
439 self
.assertEqual(id(x
[1]), id(x
))
441 def test_recursive_inst(self
):
444 for proto
in protocols
:
447 self
.assertEqual(x
, i
)
448 self
.assertEqual(x
.attr
, x
)
449 self
.assertEqual(id(x
.attr
), id(x
))
451 def test_recursive_multi(self
):
457 for proto
in protocols
:
458 s
= self
.dumps(l
, proto
)
460 self
.assertEqual(x
, l
)
461 self
.assertEqual(x
[0], i
)
462 self
.assertEqual(x
[0].attr
, d
)
463 self
.assertEqual(x
[0].attr
[1], x
)
464 self
.assertEqual(x
[0].attr
[1][0], i
)
465 self
.assertEqual(x
[0].attr
[1][0].attr
, d
)
467 def test_garyp(self
):
468 self
.assertRaises(self
.error
, self
.loads
, 'garyp')
470 def test_insecure_strings(self
):
471 insecure
= ["abc", "2 + 2", # not quoted
472 #"'abc' + 'def'", # not a single quoted string
473 "'abc", # quote is not closed
474 "'abc\"", # open quote and close quote don't match
475 "'abc' ?", # junk after close quote
476 "'\\'", # trailing backslash
477 # some tests of the quoting rules
479 #"'\\\\a\'\'\'\\\'\\\\\''",
482 buf
= "S" + s
+ "\012p0\012."
483 self
.assertRaises(ValueError, self
.loads
, buf
)
486 def test_unicode(self
):
487 endcases
= [unicode(''), unicode('<\\u>'), unicode('<\\\u1234>'),
488 unicode('<\n>'), unicode('<\\>')]
489 for proto
in protocols
:
491 p
= self
.dumps(u
, proto
)
493 self
.assertEqual(u2
, u
)
497 for proto
in protocols
:
500 for expected
in (-n
, n
):
501 s
= self
.dumps(expected
, proto
)
503 self
.assertEqual(expected
, n2
)
506 def test_maxint64(self
):
507 maxint64
= (1L << 63) - 1
508 data
= 'I' + str(maxint64
) + '\n.'
509 got
= self
.loads(data
)
510 self
.assertEqual(got
, maxint64
)
512 # Try too with a bogus literal.
513 data
= 'I' + str(maxint64
) + 'JUNK\n.'
514 self
.assertRaises(ValueError, self
.loads
, data
)
517 for proto
in protocols
:
518 # 256 bytes is where LONG4 begins.
519 for nbits
in 1, 8, 8*254, 8*255, 8*256, 8*257:
521 for npos
in nbase
-1, nbase
, nbase
+1:
522 for n
in npos
, -npos
:
523 pickle
= self
.dumps(n
, proto
)
524 got
= self
.loads(pickle
)
525 self
.assertEqual(n
, got
)
526 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
528 nbase
= long("deadbeeffeedface", 16)
529 nbase
+= nbase
<< 1000000
530 for n
in nbase
, -nbase
:
533 self
.assertEqual(n
, got
)
535 def test_reduce(self
):
538 def test_getinitargs(self
):
541 def test_metaclass(self
):
543 for proto
in protocols
:
544 s
= self
.dumps(a
, proto
)
546 self
.assertEqual(a
.__class
__, b
.__class
__)
548 def test_structseq(self
):
553 for proto
in protocols
:
554 s
= self
.dumps(t
, proto
)
556 self
.assertEqual(t
, u
)
557 if hasattr(os
, "stat"):
558 t
= os
.stat(os
.curdir
)
559 s
= self
.dumps(t
, proto
)
561 self
.assertEqual(t
, u
)
562 if hasattr(os
, "statvfs"):
563 t
= os
.statvfs(os
.curdir
)
564 s
= self
.dumps(t
, proto
)
566 self
.assertEqual(t
, u
)
568 # Tests for protocol 2
570 def test_proto(self
):
571 build_none
= pickle
.NONE
+ pickle
.STOP
572 for proto
in protocols
:
573 expected
= build_none
575 expected
= pickle
.PROTO
+ chr(proto
) + expected
576 p
= self
.dumps(None, proto
)
577 self
.assertEqual(p
, expected
)
579 oob
= protocols
[-1] + 1 # a future protocol
580 badpickle
= pickle
.PROTO
+ chr(oob
) + build_none
582 self
.loads(badpickle
)
583 except ValueError, detail
:
584 self
.failUnless(str(detail
).startswith(
585 "unsupported pickle protocol"))
587 self
.fail("expected bad protocol number to raise ValueError")
589 def test_long1(self
):
590 x
= 12345678910111213141516178920L
591 for proto
in protocols
:
592 s
= self
.dumps(x
, proto
)
594 self
.assertEqual(x
, y
)
595 self
.assertEqual(opcode_in_pickle(pickle
.LONG1
, s
), proto
>= 2)
597 def test_long4(self
):
598 x
= 12345678910111213141516178920L << (256*8)
599 for proto
in protocols
:
600 s
= self
.dumps(x
, proto
)
602 self
.assertEqual(x
, y
)
603 self
.assertEqual(opcode_in_pickle(pickle
.LONG4
, s
), proto
>= 2)
605 def test_short_tuples(self
):
606 # Map (proto, len(tuple)) to expected opcode.
607 expected_opcode
= {(0, 0): pickle
.TUPLE
,
608 (0, 1): pickle
.TUPLE
,
609 (0, 2): pickle
.TUPLE
,
610 (0, 3): pickle
.TUPLE
,
611 (0, 4): pickle
.TUPLE
,
613 (1, 0): pickle
.EMPTY_TUPLE
,
614 (1, 1): pickle
.TUPLE
,
615 (1, 2): pickle
.TUPLE
,
616 (1, 3): pickle
.TUPLE
,
617 (1, 4): pickle
.TUPLE
,
619 (2, 0): pickle
.EMPTY_TUPLE
,
620 (2, 1): pickle
.TUPLE1
,
621 (2, 2): pickle
.TUPLE2
,
622 (2, 3): pickle
.TUPLE3
,
623 (2, 4): pickle
.TUPLE
,
630 for proto
in protocols
:
631 for x
in a
, b
, c
, d
, e
:
632 s
= self
.dumps(x
, proto
)
634 self
.assertEqual(x
, y
, (proto
, x
, s
, y
))
635 expected
= expected_opcode
[proto
, len(x
)]
636 self
.assertEqual(opcode_in_pickle(expected
, s
), True)
638 def test_singletons(self
):
639 # Map (proto, singleton) to expected opcode.
640 expected_opcode
= {(0, None): pickle
.NONE
,
641 (1, None): pickle
.NONE
,
642 (2, None): pickle
.NONE
,
644 (0, True): pickle
.INT
,
645 (1, True): pickle
.INT
,
646 (2, True): pickle
.NEWTRUE
,
648 (0, False): pickle
.INT
,
649 (1, False): pickle
.INT
,
650 (2, False): pickle
.NEWFALSE
,
652 for proto
in protocols
:
653 for x
in None, False, True:
654 s
= self
.dumps(x
, proto
)
656 self
.assert_(x
is y
, (proto
, x
, s
, y
))
657 expected
= expected_opcode
[proto
, x
]
658 self
.assertEqual(opcode_in_pickle(expected
, s
), True)
660 def test_newobj_tuple(self
):
661 x
= MyTuple([1, 2, 3])
664 for proto
in protocols
:
665 s
= self
.dumps(x
, proto
)
667 self
.assertEqual(tuple(x
), tuple(y
))
668 self
.assertEqual(x
.__dict
__, y
.__dict
__)
670 def test_newobj_list(self
):
671 x
= MyList([1, 2, 3])
674 for proto
in protocols
:
675 s
= self
.dumps(x
, proto
)
677 self
.assertEqual(list(x
), list(y
))
678 self
.assertEqual(x
.__dict
__, y
.__dict
__)
680 def test_newobj_generic(self
):
681 for proto
in protocols
:
686 s
= self
.dumps(x
, proto
)
688 detail
= (proto
, C
, B
, x
, y
, type(y
))
689 self
.assertEqual(B(x
), B(y
), detail
)
690 self
.assertEqual(x
.__dict
__, y
.__dict
__, detail
)
692 # Register a type with copy_reg, with extension code extcode. Pickle
693 # an object of that type. Check that the resulting pickle uses opcode
694 # (EXT[124]) under proto 2, and not in proto 1.
696 def produce_global_ext(self
, extcode
, opcode
):
697 e
= ExtensionSaver(extcode
)
699 copy_reg
.add_extension(__name__
, "MyList", extcode
)
700 x
= MyList([1, 2, 3])
704 # Dump using protocol 1 for comparison.
705 s1
= self
.dumps(x
, 1)
706 self
.assert_(__name__
in s1
)
707 self
.assert_("MyList" in s1
)
708 self
.assertEqual(opcode_in_pickle(opcode
, s1
), False)
711 self
.assertEqual(list(x
), list(y
))
712 self
.assertEqual(x
.__dict
__, y
.__dict
__)
714 # Dump using protocol 2 for test.
715 s2
= self
.dumps(x
, 2)
716 self
.assert_(__name__
not in s2
)
717 self
.assert_("MyList" not in s2
)
718 self
.assertEqual(opcode_in_pickle(opcode
, s2
), True)
721 self
.assertEqual(list(x
), list(y
))
722 self
.assertEqual(x
.__dict
__, y
.__dict
__)
727 def test_global_ext1(self
):
728 self
.produce_global_ext(0x00000001, pickle
.EXT1
) # smallest EXT1 code
729 self
.produce_global_ext(0x000000ff, pickle
.EXT1
) # largest EXT1 code
731 def test_global_ext2(self
):
732 self
.produce_global_ext(0x00000100, pickle
.EXT2
) # smallest EXT2 code
733 self
.produce_global_ext(0x0000ffff, pickle
.EXT2
) # largest EXT2 code
734 self
.produce_global_ext(0x0000abcd, pickle
.EXT2
) # check endianness
736 def test_global_ext4(self
):
737 self
.produce_global_ext(0x00010000, pickle
.EXT4
) # smallest EXT4 code
738 self
.produce_global_ext(0x7fffffff, pickle
.EXT4
) # largest EXT4 code
739 self
.produce_global_ext(0x12abcdef, pickle
.EXT4
) # check endianness
741 def test_list_chunking(self
):
742 n
= 10 # too small to chunk
744 for proto
in protocols
:
745 s
= self
.dumps(x
, proto
)
747 self
.assertEqual(x
, y
)
748 num_appends
= count_opcode(pickle
.APPENDS
, s
)
749 self
.assertEqual(num_appends
, proto
> 0)
751 n
= 2500 # expect at least two chunks when proto > 0
753 for proto
in protocols
:
754 s
= self
.dumps(x
, proto
)
756 self
.assertEqual(x
, y
)
757 num_appends
= count_opcode(pickle
.APPENDS
, s
)
759 self
.assertEqual(num_appends
, 0)
761 self
.failUnless(num_appends
>= 2)
763 def test_dict_chunking(self
):
764 n
= 10 # too small to chunk
765 x
= dict.fromkeys(range(n
))
766 for proto
in protocols
:
767 s
= self
.dumps(x
, proto
)
769 self
.assertEqual(x
, y
)
770 num_setitems
= count_opcode(pickle
.SETITEMS
, s
)
771 self
.assertEqual(num_setitems
, proto
> 0)
773 n
= 2500 # expect at least two chunks when proto > 0
774 x
= dict.fromkeys(range(n
))
775 for proto
in protocols
:
776 s
= self
.dumps(x
, proto
)
778 self
.assertEqual(x
, y
)
779 num_setitems
= count_opcode(pickle
.SETITEMS
, s
)
781 self
.assertEqual(num_setitems
, 0)
783 self
.failUnless(num_setitems
>= 2)
785 def test_simple_newobj(self
):
786 x
= object.__new
__(SimpleNewObj
) # avoid __init__
788 for proto
in protocols
:
789 s
= self
.dumps(x
, proto
)
790 self
.assertEqual(opcode_in_pickle(pickle
.NEWOBJ
, s
), proto
>= 2)
791 y
= self
.loads(s
) # will raise TypeError if __init__ called
792 self
.assertEqual(y
.abc
, 666)
793 self
.assertEqual(x
.__dict
__, y
.__dict
__)
795 def test_newobj_list_slots(self
):
796 x
= SlotList([1, 2, 3])
801 self
.assertEqual(list(x
), list(y
))
802 self
.assertEqual(x
.__dict
__, y
.__dict
__)
803 self
.assertEqual(x
.foo
, y
.foo
)
804 self
.assertEqual(x
.bar
, y
.bar
)
806 def test_reduce_overrides_default_reduce_ex(self
):
807 for proto
in 0, 1, 2:
809 self
.assertEqual(x
._reduce
_called
, 0)
810 s
= self
.dumps(x
, proto
)
811 self
.assertEqual(x
._reduce
_called
, 1)
813 self
.assertEqual(y
._reduce
_called
, 0)
815 def test_reduce_ex_called(self
):
816 for proto
in 0, 1, 2:
818 self
.assertEqual(x
._proto
, None)
819 s
= self
.dumps(x
, proto
)
820 self
.assertEqual(x
._proto
, proto
)
822 self
.assertEqual(y
._proto
, None)
824 def test_reduce_ex_overrides_reduce(self
):
825 for proto
in 0, 1, 2:
827 self
.assertEqual(x
._proto
, None)
828 s
= self
.dumps(x
, proto
)
829 self
.assertEqual(x
._proto
, proto
)
831 self
.assertEqual(y
._proto
, None)
833 # Test classes for reduce_ex
835 class REX_one(object):
837 def __reduce__(self
):
838 self
._reduce
_called
= 1
840 # No __reduce_ex__ here, but inheriting it from object
842 class REX_two(object):
844 def __reduce_ex__(self
, proto
):
847 # No __reduce__ here, but inheriting it from object
849 class REX_three(object):
851 def __reduce_ex__(self
, proto
):
854 def __reduce__(self
):
855 raise TestFailed
, "This __reduce__ shouldn't be called"
857 # Test classes for newobj
865 class MyFloat(float):
868 class MyComplex(complex):
874 class MyUnicode(unicode):
875 sample
= u
"hello \u1234"
877 class MyTuple(tuple):
884 sample
= {"a": 1, "b": 2}
886 myclasses
= [MyInt
, MyLong
, MyFloat
,
889 MyTuple
, MyList
, MyDict
]
892 class SlotList(MyList
):
895 class SimpleNewObj(object):
896 def __init__(self
, a
, b
, c
):
897 # raise an error, to make sure this isn't called
898 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
900 class AbstractPickleModuleTests(unittest
.TestCase
):
902 def test_dump_closed_file(self
):
904 f
= open(TESTFN
, "w")
907 self
.assertRaises(ValueError, self
.module
.dump
, 123, f
)
911 def test_load_closed_file(self
):
913 f
= open(TESTFN
, "w")
916 self
.assertRaises(ValueError, self
.module
.dump
, 123, f
)
920 def test_highest_protocol(self
):
921 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
922 self
.assertEqual(self
.module
.HIGHEST_PROTOCOL
, 2)
925 class AbstractPersistentPicklerTests(unittest
.TestCase
):
927 # This class defines persistent_id() and persistent_load()
928 # functions that should be used by the pickler. All even integers
929 # are pickled using persistent ids.
931 def persistent_id(self
, object):
932 if isinstance(object, int) and object % 2 == 0:
938 def persistent_load(self
, oid
):
941 assert object % 2 == 0
944 def test_persistence(self
):
948 self
.assertEqual(self
.loads(self
.dumps(L
)), L
)
949 self
.assertEqual(self
.id_count
, 5)
950 self
.assertEqual(self
.load_count
, 5)
952 def test_bin_persistence(self
):
956 self
.assertEqual(self
.loads(self
.dumps(L
, 1)), L
)
957 self
.assertEqual(self
.id_count
, 5)
958 self
.assertEqual(self
.load_count
, 5)