blob: 66b3f5712df8c5ec3f586c2df35c4f5786e877fc [file] [log] [blame]
Jeremy Hylton66426532001-10-15 21:38:56 +00001import unittest
Tim Peters4190fb82003-02-02 16:09:05 +00002import pickle
Tim Peters31f119e2003-02-03 16:20:13 +00003import pickletools
Tim Peters4190fb82003-02-02 16:09:05 +00004
Guido van Rossum3b0a3292002-08-09 16:38:32 +00005from test.test_support import TestFailed, have_unicode, TESTFN
Tim Peterse089c682001-04-10 03:41:41 +00006
Tim Petersee1a53c2003-02-02 02:57:53 +00007# Tests that try a number of pickle protocols should have a
8# for proto in protocols:
9# kind of outer loop. Bump the 3 to 4 if/when protocol 3 is invented.
10protocols = range(3)
11
Jeremy Hylton66426532001-10-15 21:38:56 +000012class C:
13 def __cmp__(self, other):
14 return cmp(self.__dict__, other.__dict__)
15
16import __main__
17__main__.C = C
18C.__module__ = "__main__"
19
20class myint(int):
21 def __init__(self, x):
22 self.str = str(x)
23
24class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +000025
Jeremy Hylton66426532001-10-15 21:38:56 +000026 def __init__(self, a, b):
27 self.a = a
28 self.b = b
29
30 def __getinitargs__(self):
31 return self.a, self.b
32
Guido van Rossum04a86612001-12-19 16:58:54 +000033class metaclass(type):
34 pass
35
36class use_metaclass(object):
37 __metaclass__ = metaclass
38
Tim Peters70b02d72003-02-02 17:26:40 +000039# DATA0 .. DATA2 are the pickles we expect under the various protocols, for
40# the object returned by create_data().
41# XXX DATA2 doesn't exist yet, as it's not fully implemented in cPickle.
Tim Petersee1a53c2003-02-02 02:57:53 +000042
Jeremy Hylton66426532001-10-15 21:38:56 +000043# break into multiple strings to avoid confusing font-lock-mode
Tim Peters70b02d72003-02-02 17:26:40 +000044DATA0 = """(lp1
Tim Peterse9358162001-01-22 22:05:20 +000045I0
46aL1L
Tim Peters461922a2001-04-09 20:07:05 +000047aF2
Tim Peterse9358162001-01-22 22:05:20 +000048ac__builtin__
49complex
Tim Peters461922a2001-04-09 20:07:05 +000050p2
51""" + \
52"""(F3
53F0
54tRp3
55aI1
56aI-1
57aI255
58aI-255
59aI-256
60aI65535
61aI-65535
62aI-65536
63aI2147483647
64aI-2147483647
65aI-2147483648
66a""" + \
67"""(S'abc'
Tim Peterse9358162001-01-22 22:05:20 +000068p4
69g4
Tim Peters461922a2001-04-09 20:07:05 +000070""" + \
Guido van Rossum42f92da2001-04-16 00:28:21 +000071"""(i__main__
Tim Peterse9358162001-01-22 22:05:20 +000072C
73p5
Tim Peters461922a2001-04-09 20:07:05 +000074""" + \
Tim Peterse9358162001-01-22 22:05:20 +000075"""(dp6
76S'foo'
77p7
78I1
79sS'bar'
80p8
81I2
82sbg5
83tp9
84ag9
85aI5
86a.
87"""
88
Tim Peters70b02d72003-02-02 17:26:40 +000089# Disassembly of DATA0.
90DATA0_DIS = """\
91 0: ( MARK
92 1: l LIST (MARK at 0)
93 2: p PUT 1
94 5: I INT 0
95 8: a APPEND
96 9: L LONG 1L
97 13: a APPEND
98 14: F FLOAT 2.0
99 17: a APPEND
100 18: c GLOBAL '__builtin__ complex'
101 39: p PUT 2
102 42: ( MARK
103 43: F FLOAT 3.0
104 46: F FLOAT 0.0
105 49: t TUPLE (MARK at 42)
106 50: R REDUCE
107 51: p PUT 3
108 54: a APPEND
109 55: I INT 1
110 58: a APPEND
111 59: I INT -1
112 63: a APPEND
113 64: I INT 255
114 69: a APPEND
115 70: I INT -255
116 76: a APPEND
117 77: I INT -256
118 83: a APPEND
119 84: I INT 65535
120 91: a APPEND
121 92: I INT -65535
122 100: a APPEND
123 101: I INT -65536
124 109: a APPEND
125 110: I INT 2147483647
126 122: a APPEND
127 123: I INT -2147483647
128 136: a APPEND
129 137: I INT -2147483648
130 150: a APPEND
131 151: ( MARK
132 152: S STRING 'abc'
133 159: p PUT 4
134 162: g GET 4
135 165: ( MARK
136 166: i INST '__main__ C' (MARK at 165)
137 178: p PUT 5
138 181: ( MARK
139 182: d DICT (MARK at 181)
140 183: p PUT 6
141 186: S STRING 'foo'
142 193: p PUT 7
143 196: I INT 1
144 199: s SETITEM
145 200: S STRING 'bar'
146 207: p PUT 8
147 210: I INT 2
148 213: s SETITEM
149 214: b BUILD
150 215: g GET 5
151 218: t TUPLE (MARK at 151)
152 219: p PUT 9
153 222: a APPEND
154 223: g GET 9
155 226: a APPEND
156 227: I INT 5
157 230: a APPEND
158 231: . STOP
159highest protocol among opcodes = 0
160"""
161
162DATA1 = (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00'
163 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00'
164 '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff'
165 '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff'
166 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00'
167 '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n'
168 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh'
169 '\x06tq\nh\nK\x05e.'
170 )
171
172# Disassembly of DATA1.
173DATA1_DIS = """\
174 0: ] EMPTY_LIST
175 1: q BINPUT 1
176 3: ( MARK
177 4: K BININT1 0
178 6: L LONG 1L
179 10: G BINFLOAT 2.0
180 19: c GLOBAL '__builtin__ complex'
181 40: q BINPUT 2
182 42: ( MARK
183 43: G BINFLOAT 3.0
184 52: G BINFLOAT 0.0
185 61: t TUPLE (MARK at 42)
186 62: R REDUCE
187 63: q BINPUT 3
188 65: K BININT1 1
189 67: J BININT -1
190 72: K BININT1 255
191 74: J BININT -255
192 79: J BININT -256
193 84: M BININT2 65535
194 87: J BININT -65535
195 92: J BININT -65536
196 97: J BININT 2147483647
197 102: J BININT -2147483647
198 107: J BININT -2147483648
199 112: ( MARK
200 113: U SHORT_BINSTRING 'abc'
201 118: q BINPUT 4
202 120: h BINGET 4
203 122: ( MARK
204 123: c GLOBAL '__main__ C'
205 135: q BINPUT 5
206 137: o OBJ (MARK at 122)
207 138: q BINPUT 6
208 140: } EMPTY_DICT
209 141: q BINPUT 7
210 143: ( MARK
211 144: U SHORT_BINSTRING 'foo'
212 149: q BINPUT 8
213 151: K BININT1 1
214 153: U SHORT_BINSTRING 'bar'
215 158: q BINPUT 9
216 160: K BININT1 2
217 162: u SETITEMS (MARK at 143)
218 163: b BUILD
219 164: h BINGET 6
220 166: t TUPLE (MARK at 112)
221 167: q BINPUT 10
222 169: h BINGET 10
223 171: K BININT1 5
224 173: e APPENDS (MARK at 3)
225 174: . STOP
226highest protocol among opcodes = 1
227"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000228
Jeremy Hylton66426532001-10-15 21:38:56 +0000229def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000230 c = C()
231 c.foo = 1
232 c.bar = 2
233 x = [0, 1L, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000234 # Append some integer test cases at cPickle.c's internal size
235 # cutoffs.
236 uint1max = 0xff
237 uint2max = 0xffff
238 int4max = 0x7fffffff
239 x.extend([1, -1,
240 uint1max, -uint1max, -uint1max-1,
241 uint2max, -uint2max, -uint2max-1,
242 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000243 y = ('abc', 'abc', c, c)
244 x.append(y)
245 x.append(y)
246 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000247 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000248
Jeremy Hylton66426532001-10-15 21:38:56 +0000249class AbstractPickleTests(unittest.TestCase):
Tim Peters70b02d72003-02-02 17:26:40 +0000250 # Subclass must define self.dumps, self.loads, self.error.
Tim Petersc58440f2001-04-09 17:16:31 +0000251
Jeremy Hylton66426532001-10-15 21:38:56 +0000252 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000253
Jeremy Hylton66426532001-10-15 21:38:56 +0000254 def setUp(self):
Tim Peterse9358162001-01-22 22:05:20 +0000255 pass
Tim Petersc58440f2001-04-09 17:16:31 +0000256
Tim Peters61bf2572003-02-03 21:31:22 +0000257 # Return True if opcode code appears in the pickle, else False.
258 def opcode_in_pickle(self, code, pickle):
Tim Peters31f119e2003-02-03 16:20:13 +0000259 for op, dummy, dummy in pickletools.genops(pickle):
260 if op.code == code:
Tim Peters61bf2572003-02-03 21:31:22 +0000261 return True
262 return False
Tim Peters31f119e2003-02-03 16:20:13 +0000263
Jeremy Hylton66426532001-10-15 21:38:56 +0000264 def test_misc(self):
265 # test various datatypes not tested by testdata
Tim Peters70b02d72003-02-02 17:26:40 +0000266 for proto in protocols:
267 x = myint(4)
268 s = self.dumps(x, proto)
269 y = self.loads(s)
270 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000271
Tim Peters70b02d72003-02-02 17:26:40 +0000272 x = (1, ())
273 s = self.dumps(x, proto)
274 y = self.loads(s)
275 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000276
Tim Peters70b02d72003-02-02 17:26:40 +0000277 x = initarg(1, x)
278 s = self.dumps(x, proto)
279 y = self.loads(s)
280 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000281
Jeremy Hylton66426532001-10-15 21:38:56 +0000282 # XXX test __reduce__ protocol?
283
Tim Peters70b02d72003-02-02 17:26:40 +0000284 def test_roundtrip_equality(self):
285 expected = self._testdata
286 for proto in protocols:
287 s = self.dumps(expected, proto)
288 got = self.loads(s)
289 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000290
Tim Peters70b02d72003-02-02 17:26:40 +0000291 def test_load_from_canned_string(self):
292 expected = self._testdata
293 for canned in DATA0, DATA1:
294 got = self.loads(canned)
295 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000296
Tim Peters70b02d72003-02-02 17:26:40 +0000297 # There are gratuitous differences between pickles produced by
298 # pickle and cPickle, largely because cPickle starts PUT indices at
299 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
300 # there's a comment with an exclamation point there whose meaning
301 # is a mystery. cPickle also suppresses PUT for objects with a refcount
302 # of 1.
303 def dont_test_disassembly(self):
304 from cStringIO import StringIO
305 from pickletools import dis
306
307 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
308 s = self.dumps(self._testdata, proto)
309 filelike = StringIO()
310 dis(s, out=filelike)
311 got = filelike.getvalue()
312 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000313
314 def test_recursive_list(self):
315 l = []
316 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +0000317 for proto in protocols:
318 s = self.dumps(l, proto)
319 x = self.loads(s)
320 self.assertEqual(x, l)
321 self.assertEqual(x, x[0])
322 self.assertEqual(id(x), id(x[0]))
Jeremy Hylton66426532001-10-15 21:38:56 +0000323
324 def test_recursive_dict(self):
325 d = {}
326 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +0000327 for proto in protocols:
328 s = self.dumps(d, proto)
329 x = self.loads(s)
330 self.assertEqual(x, d)
331 self.assertEqual(x[1], x)
332 self.assertEqual(id(x[1]), id(x))
Jeremy Hylton66426532001-10-15 21:38:56 +0000333
334 def test_recursive_inst(self):
335 i = C()
336 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +0000337 for proto in protocols:
338 s = self.dumps(i, 2)
339 x = self.loads(s)
340 self.assertEqual(x, i)
341 self.assertEqual(x.attr, x)
342 self.assertEqual(id(x.attr), id(x))
Jeremy Hylton66426532001-10-15 21:38:56 +0000343
344 def test_recursive_multi(self):
345 l = []
346 d = {1:l}
347 i = C()
348 i.attr = d
349 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +0000350 for proto in protocols:
351 s = self.dumps(l, proto)
352 x = self.loads(s)
353 self.assertEqual(x, l)
354 self.assertEqual(x[0], i)
355 self.assertEqual(x[0].attr, d)
356 self.assertEqual(x[0].attr[1], x)
357 self.assertEqual(x[0].attr[1][0], i)
358 self.assertEqual(x[0].attr[1][0].attr, d)
Jeremy Hylton66426532001-10-15 21:38:56 +0000359
360 def test_garyp(self):
361 self.assertRaises(self.error, self.loads, 'garyp')
362
363 def test_insecure_strings(self):
364 insecure = ["abc", "2 + 2", # not quoted
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000365 #"'abc' + 'def'", # not a single quoted string
Jeremy Hylton66426532001-10-15 21:38:56 +0000366 "'abc", # quote is not closed
367 "'abc\"", # open quote and close quote don't match
368 "'abc' ?", # junk after close quote
Martin v. Löwiseb3f00a2002-08-14 08:22:50 +0000369 "'\\'", # trailing backslash
Jeremy Hylton66426532001-10-15 21:38:56 +0000370 # some tests of the quoting rules
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000371 #"'abc\"\''",
372 #"'\\\\a\'\'\'\\\'\\\\\''",
Jeremy Hylton66426532001-10-15 21:38:56 +0000373 ]
374 for s in insecure:
375 buf = "S" + s + "\012p0\012."
376 self.assertRaises(ValueError, self.loads, buf)
377
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000378 if have_unicode:
Jeremy Hylton66426532001-10-15 21:38:56 +0000379 def test_unicode(self):
380 endcases = [unicode(''), unicode('<\\u>'), unicode('<\\\u1234>'),
381 unicode('<\n>'), unicode('<\\>')]
Tim Petersee1a53c2003-02-02 02:57:53 +0000382 for proto in protocols:
383 for u in endcases:
384 p = self.dumps(u, proto)
385 u2 = self.loads(p)
386 self.assertEqual(u2, u)
Tim Peterse089c682001-04-10 03:41:41 +0000387
Jeremy Hylton66426532001-10-15 21:38:56 +0000388 def test_ints(self):
389 import sys
Tim Petersee1a53c2003-02-02 02:57:53 +0000390 for proto in protocols:
391 n = sys.maxint
392 while n:
393 for expected in (-n, n):
394 s = self.dumps(expected, proto)
395 n2 = self.loads(s)
396 self.assertEqual(expected, n2)
397 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +0000398
Jeremy Hylton66426532001-10-15 21:38:56 +0000399 def test_maxint64(self):
400 maxint64 = (1L << 63) - 1
401 data = 'I' + str(maxint64) + '\n.'
402 got = self.loads(data)
403 self.assertEqual(got, maxint64)
404
405 # Try too with a bogus literal.
406 data = 'I' + str(maxint64) + 'JUNK\n.'
407 self.assertRaises(ValueError, self.loads, data)
408
Tim Petersee1a53c2003-02-02 02:57:53 +0000409 def test_long(self):
410 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +0000411 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +0000412 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
413 nbase = 1L << nbits
414 for npos in nbase-1, nbase, nbase+1:
415 for n in npos, -npos:
416 pickle = self.dumps(n, proto)
417 got = self.loads(pickle)
418 self.assertEqual(n, got)
419 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
420 # bother with those.
Tim Petersee1a53c2003-02-02 02:57:53 +0000421 nbase = long("deadbeeffeedface", 16)
422 nbase += nbase << 1000000
423 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +0000424 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000425 got = self.loads(p)
Tim Petersee1a53c2003-02-02 02:57:53 +0000426 self.assertEqual(n, got)
427
Jeremy Hylton66426532001-10-15 21:38:56 +0000428 def test_reduce(self):
Tim Peters19ef62d2001-08-28 22:21:18 +0000429 pass
Jeremy Hylton66426532001-10-15 21:38:56 +0000430
431 def test_getinitargs(self):
432 pass
433
Guido van Rossum04a86612001-12-19 16:58:54 +0000434 def test_metaclass(self):
435 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +0000436 for proto in protocols:
437 s = self.dumps(a, proto)
438 b = self.loads(s)
439 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +0000440
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000441 def test_structseq(self):
442 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +0000443 import os
Tim Peters70b02d72003-02-02 17:26:40 +0000444
445 t = time.localtime()
446 for proto in protocols:
447 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +0000448 u = self.loads(s)
449 self.assertEqual(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000450 if hasattr(os, "stat"):
451 t = os.stat(os.curdir)
452 s = self.dumps(t, proto)
453 u = self.loads(s)
454 self.assertEqual(t, u)
455 if hasattr(os, "statvfs"):
456 t = os.statvfs(os.curdir)
457 s = self.dumps(t, proto)
458 u = self.loads(s)
459 self.assertEqual(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000460
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000461 # Tests for protocol 2
462
Tim Peters4190fb82003-02-02 16:09:05 +0000463 def test_proto(self):
464 build_none = pickle.NONE + pickle.STOP
465 for proto in protocols:
466 expected = build_none
467 if proto >= 2:
468 expected = pickle.PROTO + chr(proto) + expected
469 p = self.dumps(None, proto)
470 self.assertEqual(p, expected)
471
472 oob = protocols[-1] + 1 # a future protocol
473 badpickle = pickle.PROTO + chr(oob) + build_none
474 try:
475 self.loads(badpickle)
476 except ValueError, detail:
477 self.failUnless(str(detail).startswith(
478 "unsupported pickle protocol"))
479 else:
480 self.fail("expected bad protocol number to raise ValueError")
481
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000482 def test_long1(self):
483 x = 12345678910111213141516178920L
Tim Peters61bf2572003-02-03 21:31:22 +0000484 for proto in protocols:
485 s = self.dumps(x, proto)
486 y = self.loads(s)
487 self.assertEqual(x, y)
488 self.assertEqual(self.opcode_in_pickle(pickle.LONG1, s),
489 proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000490
491 def test_long4(self):
492 x = 12345678910111213141516178920L << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +0000493 for proto in protocols:
494 s = self.dumps(x, proto)
495 y = self.loads(s)
496 self.assertEqual(x, y)
497 self.assertEqual(self.opcode_in_pickle(pickle.LONG4, s),
498 proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000499
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000500 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +0000501 # Map (proto, len(tuple)) to expected opcode.
502 expected_opcode = {(0, 0): pickle.TUPLE,
503 (0, 1): pickle.TUPLE,
504 (0, 2): pickle.TUPLE,
505 (0, 3): pickle.TUPLE,
506 (0, 4): pickle.TUPLE,
507
508 (1, 0): pickle.EMPTY_TUPLE,
509 (1, 1): pickle.TUPLE,
510 (1, 2): pickle.TUPLE,
511 (1, 3): pickle.TUPLE,
512 (1, 4): pickle.TUPLE,
513
514 (2, 0): pickle.EMPTY_TUPLE,
515 (2, 1): pickle.TUPLE1,
516 (2, 2): pickle.TUPLE2,
517 (2, 3): pickle.TUPLE3,
518 (2, 4): pickle.TUPLE,
519 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000520 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +0000521 b = (1,)
522 c = (1, 2)
523 d = (1, 2, 3)
524 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +0000525 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000526 for x in a, b, c, d, e:
527 s = self.dumps(x, proto)
528 y = self.loads(s)
529 self.assertEqual(x, y, (proto, x, s, y))
Tim Peters1d63c9f2003-02-02 20:29:39 +0000530 expected = expected_opcode[proto, len(x)]
Tim Peters61bf2572003-02-03 21:31:22 +0000531 self.assertEqual(self.opcode_in_pickle(expected, s), True)
Tim Peters1d63c9f2003-02-02 20:29:39 +0000532
Guido van Rossum7d97d312003-01-28 04:25:27 +0000533 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +0000534 # Map (proto, singleton) to expected opcode.
535 expected_opcode = {(0, None): pickle.NONE,
536 (1, None): pickle.NONE,
537 (2, None): pickle.NONE,
538
539 (0, True): pickle.INT,
540 (1, True): pickle.INT,
541 (2, True): pickle.NEWTRUE,
542
543 (0, False): pickle.INT,
544 (1, False): pickle.INT,
545 (2, False): pickle.NEWFALSE,
546 }
Tim Peters4190fb82003-02-02 16:09:05 +0000547 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +0000548 for x in None, False, True:
549 s = self.dumps(x, proto)
550 y = self.loads(s)
551 self.assert_(x is y, (proto, x, s, y))
Tim Peters61bf2572003-02-03 21:31:22 +0000552 expected = expected_opcode[proto, x]
553 self.assertEqual(self.opcode_in_pickle(expected, s), True)
Tim Peters3c67d792003-02-02 17:59:11 +0000554
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000555 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000556 x = MyTuple([1, 2, 3])
557 x.foo = 42
558 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000559 s = self.dumps(x, 2)
560 y = self.loads(s)
561 self.assertEqual(tuple(x), tuple(y))
562 self.assertEqual(x.__dict__, y.__dict__)
563
564 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000565 x = MyList([1, 2, 3])
566 x.foo = 42
567 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000568 s = self.dumps(x, 2)
569 y = self.loads(s)
570 self.assertEqual(list(x), list(y))
571 self.assertEqual(x.__dict__, y.__dict__)
572
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000573 def test_newobj_generic(self):
574 for proto in [0, 1, 2]:
575 for C in myclasses:
576 B = C.__base__
577 x = C(C.sample)
578 x.foo = 42
579 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000580 y = self.loads(s)
581 detail = (proto, C, B, x, y, type(y))
582 self.assertEqual(B(x), B(y), detail)
583 self.assertEqual(x.__dict__, y.__dict__, detail)
584
Tim Peters47a6b132003-01-28 22:34:11 +0000585# XXX Temporary hack, so long as the C implementation of pickle protocol
586# XXX 2 isn't ready. When it is, move the methods in TempAbstractPickleTests
587# XXX into AbstractPickleTests above, and get rid of TempAbstractPickleTests
588# XXX along with the references to it in test_pickle.py.
589class TempAbstractPickleTests(unittest.TestCase):
590
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000591 def test_newobj_list_slots(self):
592 x = SlotList([1, 2, 3])
593 x.foo = 42
594 x.bar = "hello"
595 s = self.dumps(x, 2)
596 y = self.loads(s)
597 self.assertEqual(list(x), list(y))
598 self.assertEqual(x.__dict__, y.__dict__)
599 self.assertEqual(x.foo, y.foo)
600 self.assertEqual(x.bar, y.bar)
601## import pickletools
602## print
603## pickletools.dis(s)
604
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000605 def test_global_ext1(self):
606 import copy_reg
607 copy_reg.add_extension(__name__, "MyList", 0xf0)
608 try:
609 x = MyList([1, 2, 3])
610 x.foo = 42
611 x.bar = "hello"
612
613 # Dump using protocol 1 for comparison
614 s1 = self.dumps(x, 1)
615 y = self.loads(s1)
616 self.assertEqual(list(x), list(y))
617 self.assertEqual(x.__dict__, y.__dict__)
618 self.assert_(s1.find(__name__) >= 0)
619 self.assert_(s1.find("MyList") >= 0)
620## import pickletools
621## print
622## pickletools.dis(s1)
623
624 # Dump using protocol 2 for test
625 s2 = self.dumps(x, 2)
626 self.assertEqual(s2.find(__name__), -1)
627 self.assertEqual(s2.find("MyList"), -1)
628 y = self.loads(s2)
629 self.assertEqual(list(x), list(y))
630 self.assertEqual(x.__dict__, y.__dict__)
631## import pickletools
632## print
633## pickletools.dis(s2)
634
635 finally:
636 copy_reg.remove_extension(__name__, "MyList", 0xf0)
637
638 def test_global_ext2(self):
639 import copy_reg
640 copy_reg.add_extension(__name__, "MyList", 0xfff0)
641 try:
642 x = MyList()
643 s2 = self.dumps(x, 2)
644 self.assertEqual(s2.find(__name__), -1)
645 self.assertEqual(s2.find("MyList"), -1)
646 y = self.loads(s2)
647 self.assertEqual(list(x), list(y))
648 self.assertEqual(x.__dict__, y.__dict__)
649 finally:
650 copy_reg.remove_extension(__name__, "MyList", 0xfff0)
651
652 def test_global_ext4(self):
653 import copy_reg
654 copy_reg.add_extension(__name__, "MyList", 0xfffff0)
655 try:
656 x = MyList()
657 s2 = self.dumps(x, 2)
658 self.assertEqual(s2.find(__name__), -1)
659 self.assertEqual(s2.find("MyList"), -1)
660 y = self.loads(s2)
661 self.assertEqual(list(x), list(y))
662 self.assertEqual(x.__dict__, y.__dict__)
663 finally:
664 copy_reg.remove_extension(__name__, "MyList", 0xfffff0)
665
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000666class MyInt(int):
667 sample = 1
668
669class MyLong(long):
670 sample = 1L
671
672class MyFloat(float):
673 sample = 1.0
674
675class MyComplex(complex):
676 sample = 1.0 + 0.0j
677
678class MyStr(str):
679 sample = "hello"
680
681class MyUnicode(unicode):
682 sample = u"hello \u1234"
683
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000684class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000685 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000686
687class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000688 sample = [1, 2, 3]
689
690class MyDict(dict):
691 sample = {"a": 1, "b": 2}
692
693myclasses = [MyInt, MyLong, MyFloat,
694 # MyComplex, # XXX complex somehow doesn't work here :-(
695 MyStr, MyUnicode,
696 MyTuple, MyList, MyDict]
697
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000698
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000699class SlotList(MyList):
700 __slots__ = ["foo"]
701
Jeremy Hylton66426532001-10-15 21:38:56 +0000702class AbstractPickleModuleTests(unittest.TestCase):
703
704 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000705 import os
706 f = open(TESTFN, "w")
707 try:
708 f.close()
709 self.assertRaises(ValueError, self.module.dump, 123, f)
710 finally:
711 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +0000712
713 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000714 import os
715 f = open(TESTFN, "w")
716 try:
717 f.close()
718 self.assertRaises(ValueError, self.module.dump, 123, f)
719 finally:
720 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +0000721
722class AbstractPersistentPicklerTests(unittest.TestCase):
723
724 # This class defines persistent_id() and persistent_load()
725 # functions that should be used by the pickler. All even integers
726 # are pickled using persistent ids.
727
728 def persistent_id(self, object):
729 if isinstance(object, int) and object % 2 == 0:
730 self.id_count += 1
731 return str(object)
732 else:
733 return None
734
735 def persistent_load(self, oid):
736 self.load_count += 1
737 object = int(oid)
738 assert object % 2 == 0
739 return object
740
741 def test_persistence(self):
742 self.id_count = 0
743 self.load_count = 0
744 L = range(10)
745 self.assertEqual(self.loads(self.dumps(L)), L)
746 self.assertEqual(self.id_count, 5)
747 self.assertEqual(self.load_count, 5)
748
749 def test_bin_persistence(self):
750 self.id_count = 0
751 self.load_count = 0
752 L = range(10)
753 self.assertEqual(self.loads(self.dumps(L, 1)), L)
754 self.assertEqual(self.id_count, 5)
755 self.assertEqual(self.load_count, 5)