blob: 4ffa7028400a2f08bf2849add229d783de84bb87 [file] [log] [blame]
Jeremy Hylton66426532001-10-15 21:38:56 +00001import unittest
Tim Peters4190fb82003-02-02 16:09:05 +00002import pickle
Tim Peters8587b3c2003-02-13 15:44:41 +00003import cPickle
Collin Winterf8089c72009-04-09 16:46:46 +00004import cStringIO
Tim Peters31f119e2003-02-03 16:20:13 +00005import pickletools
Georg Brandldffbf5f2008-05-20 07:49:57 +00006import copy_reg
Tim Peters4190fb82003-02-02 16:09:05 +00007
Collin Winterf8089c72009-04-09 16:46:46 +00008from test.test_support import TestFailed, have_unicode, TESTFN
Tim Peterse089c682001-04-10 03:41:41 +00009
Tim Petersee1a53c2003-02-02 02:57:53 +000010# Tests that try a number of pickle protocols should have a
11# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000012# kind of outer loop.
13assert pickle.HIGHEST_PROTOCOL == cPickle.HIGHEST_PROTOCOL == 2
14protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000015
Collin Winterf8089c72009-04-09 16:46:46 +000016# Copy of test.test_support.run_with_locale. This is needed to support Python
17# 2.4, which didn't include it. This is all to support test_xpickle, which
18# bounces pickled objects through older Python versions to test backwards
19# compatibility.
20def run_with_locale(catstr, *locales):
21 def decorator(func):
22 def inner(*args, **kwds):
23 try:
24 import locale
25 category = getattr(locale, catstr)
26 orig_locale = locale.setlocale(category)
27 except AttributeError:
28 # if the test author gives us an invalid category string
29 raise
30 except:
31 # cannot retrieve original locale, so do nothing
32 locale = orig_locale = None
33 else:
34 for loc in locales:
35 try:
36 locale.setlocale(category, loc)
37 break
38 except:
39 pass
40
41 # now run the function, resetting the locale on exceptions
42 try:
43 return func(*args, **kwds)
44 finally:
45 if locale and orig_locale:
46 locale.setlocale(category, orig_locale)
47 inner.func_name = func.func_name
48 inner.__doc__ = func.__doc__
49 return inner
50 return decorator
51
Tim Peters22e71712003-02-03 22:27:38 +000052
53# Return True if opcode code appears in the pickle, else False.
54def opcode_in_pickle(code, pickle):
55 for op, dummy, dummy in pickletools.genops(pickle):
56 if op.code == code:
57 return True
58 return False
59
Tim Peters8d2613a2003-02-11 16:40:16 +000060# Return the number of times opcode code appears in pickle.
61def count_opcode(code, pickle):
62 n = 0
63 for op, dummy, dummy in pickletools.genops(pickle):
64 if op.code == code:
65 n += 1
66 return n
67
Tim Peters3e667d52003-02-04 21:47:44 +000068# We can't very well test the extension registry without putting known stuff
69# in it, but we have to be careful to restore its original state. Code
70# should do this:
71#
72# e = ExtensionSaver(extension_code)
73# try:
74# fiddle w/ the extension registry's stuff for extension_code
75# finally:
76# e.restore()
77
78class ExtensionSaver:
79 # Remember current registration for code (if any), and remove it (if
80 # there is one).
81 def __init__(self, code):
82 self.code = code
Georg Brandldffbf5f2008-05-20 07:49:57 +000083 if code in copy_reg._inverted_registry:
84 self.pair = copy_reg._inverted_registry[code]
85 copy_reg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000086 else:
87 self.pair = None
88
89 # Restore previous registration for code.
90 def restore(self):
91 code = self.code
Georg Brandldffbf5f2008-05-20 07:49:57 +000092 curpair = copy_reg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +000093 if curpair is not None:
Georg Brandldffbf5f2008-05-20 07:49:57 +000094 copy_reg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000095 pair = self.pair
96 if pair is not None:
Georg Brandldffbf5f2008-05-20 07:49:57 +000097 copy_reg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000098
Jeremy Hylton66426532001-10-15 21:38:56 +000099class C:
100 def __cmp__(self, other):
101 return cmp(self.__dict__, other.__dict__)
102
103import __main__
104__main__.C = C
105C.__module__ = "__main__"
106
107class myint(int):
108 def __init__(self, x):
109 self.str = str(x)
110
111class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000112
Jeremy Hylton66426532001-10-15 21:38:56 +0000113 def __init__(self, a, b):
114 self.a = a
115 self.b = b
116
117 def __getinitargs__(self):
118 return self.a, self.b
119
Guido van Rossum04a86612001-12-19 16:58:54 +0000120class metaclass(type):
121 pass
122
123class use_metaclass(object):
124 __metaclass__ = metaclass
125
Tim Peters70b02d72003-02-02 17:26:40 +0000126# DATA0 .. DATA2 are the pickles we expect under the various protocols, for
127# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000128
Jeremy Hylton66426532001-10-15 21:38:56 +0000129# break into multiple strings to avoid confusing font-lock-mode
Tim Peters70b02d72003-02-02 17:26:40 +0000130DATA0 = """(lp1
Tim Peterse9358162001-01-22 22:05:20 +0000131I0
132aL1L
Tim Peters461922a2001-04-09 20:07:05 +0000133aF2
Tim Peterse9358162001-01-22 22:05:20 +0000134ac__builtin__
135complex
Tim Peters461922a2001-04-09 20:07:05 +0000136p2
137""" + \
138"""(F3
139F0
140tRp3
141aI1
142aI-1
143aI255
144aI-255
145aI-256
146aI65535
147aI-65535
148aI-65536
149aI2147483647
150aI-2147483647
151aI-2147483648
152a""" + \
153"""(S'abc'
Tim Peterse9358162001-01-22 22:05:20 +0000154p4
155g4
Tim Peters461922a2001-04-09 20:07:05 +0000156""" + \
Guido van Rossum42f92da2001-04-16 00:28:21 +0000157"""(i__main__
Tim Peterse9358162001-01-22 22:05:20 +0000158C
159p5
Tim Peters461922a2001-04-09 20:07:05 +0000160""" + \
Tim Peterse9358162001-01-22 22:05:20 +0000161"""(dp6
162S'foo'
163p7
164I1
165sS'bar'
166p8
167I2
168sbg5
169tp9
170ag9
171aI5
172a.
173"""
174
Tim Peters70b02d72003-02-02 17:26:40 +0000175# Disassembly of DATA0.
176DATA0_DIS = """\
177 0: ( MARK
178 1: l LIST (MARK at 0)
179 2: p PUT 1
180 5: I INT 0
181 8: a APPEND
182 9: L LONG 1L
183 13: a APPEND
184 14: F FLOAT 2.0
185 17: a APPEND
186 18: c GLOBAL '__builtin__ complex'
187 39: p PUT 2
188 42: ( MARK
189 43: F FLOAT 3.0
190 46: F FLOAT 0.0
191 49: t TUPLE (MARK at 42)
192 50: R REDUCE
193 51: p PUT 3
194 54: a APPEND
195 55: I INT 1
196 58: a APPEND
197 59: I INT -1
198 63: a APPEND
199 64: I INT 255
200 69: a APPEND
201 70: I INT -255
202 76: a APPEND
203 77: I INT -256
204 83: a APPEND
205 84: I INT 65535
206 91: a APPEND
207 92: I INT -65535
208 100: a APPEND
209 101: I INT -65536
210 109: a APPEND
211 110: I INT 2147483647
212 122: a APPEND
213 123: I INT -2147483647
214 136: a APPEND
215 137: I INT -2147483648
216 150: a APPEND
217 151: ( MARK
218 152: S STRING 'abc'
219 159: p PUT 4
220 162: g GET 4
221 165: ( MARK
222 166: i INST '__main__ C' (MARK at 165)
223 178: p PUT 5
224 181: ( MARK
225 182: d DICT (MARK at 181)
226 183: p PUT 6
227 186: S STRING 'foo'
228 193: p PUT 7
229 196: I INT 1
230 199: s SETITEM
231 200: S STRING 'bar'
232 207: p PUT 8
233 210: I INT 2
234 213: s SETITEM
235 214: b BUILD
236 215: g GET 5
237 218: t TUPLE (MARK at 151)
238 219: p PUT 9
239 222: a APPEND
240 223: g GET 9
241 226: a APPEND
242 227: I INT 5
243 230: a APPEND
244 231: . STOP
245highest protocol among opcodes = 0
246"""
247
248DATA1 = (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00'
249 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00'
250 '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff'
251 '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff'
252 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00'
253 '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n'
254 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh'
255 '\x06tq\nh\nK\x05e.'
256 )
257
258# Disassembly of DATA1.
259DATA1_DIS = """\
260 0: ] EMPTY_LIST
261 1: q BINPUT 1
262 3: ( MARK
263 4: K BININT1 0
264 6: L LONG 1L
265 10: G BINFLOAT 2.0
266 19: c GLOBAL '__builtin__ complex'
267 40: q BINPUT 2
268 42: ( MARK
269 43: G BINFLOAT 3.0
270 52: G BINFLOAT 0.0
271 61: t TUPLE (MARK at 42)
272 62: R REDUCE
273 63: q BINPUT 3
274 65: K BININT1 1
275 67: J BININT -1
276 72: K BININT1 255
277 74: J BININT -255
278 79: J BININT -256
279 84: M BININT2 65535
280 87: J BININT -65535
281 92: J BININT -65536
282 97: J BININT 2147483647
283 102: J BININT -2147483647
284 107: J BININT -2147483648
285 112: ( MARK
286 113: U SHORT_BINSTRING 'abc'
287 118: q BINPUT 4
288 120: h BINGET 4
289 122: ( MARK
290 123: c GLOBAL '__main__ C'
291 135: q BINPUT 5
292 137: o OBJ (MARK at 122)
293 138: q BINPUT 6
294 140: } EMPTY_DICT
295 141: q BINPUT 7
296 143: ( MARK
297 144: U SHORT_BINSTRING 'foo'
298 149: q BINPUT 8
299 151: K BININT1 1
300 153: U SHORT_BINSTRING 'bar'
301 158: q BINPUT 9
302 160: K BININT1 2
303 162: u SETITEMS (MARK at 143)
304 163: b BUILD
305 164: h BINGET 6
306 166: t TUPLE (MARK at 112)
307 167: q BINPUT 10
308 169: h BINGET 10
309 171: K BININT1 5
310 173: e APPENDS (MARK at 3)
311 174: . STOP
312highest protocol among opcodes = 1
313"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000314
Tim Petersfc273752003-03-02 04:54:24 +0000315DATA2 = ('\x80\x02]q\x01(K\x00\x8a\x01\x01G@\x00\x00\x00\x00\x00\x00\x00'
316 'c__builtin__\ncomplex\nq\x02G@\x08\x00\x00\x00\x00\x00\x00G\x00'
317 '\x00\x00\x00\x00\x00\x00\x00\x86Rq\x03K\x01J\xff\xff\xff\xffK'
318 '\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xff'
319 'J\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00'
320 '\x80(U\x03abcq\x04h\x04(c__main__\nC\nq\x05oq\x06}q\x07(U\x03foo'
321 'q\x08K\x01U\x03barq\tK\x02ubh\x06tq\nh\nK\x05e.')
322
323# Disassembly of DATA2.
324DATA2_DIS = """\
325 0: \x80 PROTO 2
326 2: ] EMPTY_LIST
327 3: q BINPUT 1
328 5: ( MARK
329 6: K BININT1 0
330 8: \x8a LONG1 1L
331 11: G BINFLOAT 2.0
332 20: c GLOBAL '__builtin__ complex'
333 41: q BINPUT 2
334 43: G BINFLOAT 3.0
335 52: G BINFLOAT 0.0
336 61: \x86 TUPLE2
337 62: R REDUCE
338 63: q BINPUT 3
339 65: K BININT1 1
340 67: J BININT -1
341 72: K BININT1 255
342 74: J BININT -255
343 79: J BININT -256
344 84: M BININT2 65535
345 87: J BININT -65535
346 92: J BININT -65536
347 97: J BININT 2147483647
348 102: J BININT -2147483647
349 107: J BININT -2147483648
350 112: ( MARK
351 113: U SHORT_BINSTRING 'abc'
352 118: q BINPUT 4
353 120: h BINGET 4
354 122: ( MARK
355 123: c GLOBAL '__main__ C'
356 135: q BINPUT 5
357 137: o OBJ (MARK at 122)
358 138: q BINPUT 6
359 140: } EMPTY_DICT
360 141: q BINPUT 7
361 143: ( MARK
362 144: U SHORT_BINSTRING 'foo'
363 149: q BINPUT 8
364 151: K BININT1 1
365 153: U SHORT_BINSTRING 'bar'
366 158: q BINPUT 9
367 160: K BININT1 2
368 162: u SETITEMS (MARK at 143)
369 163: b BUILD
370 164: h BINGET 6
371 166: t TUPLE (MARK at 112)
372 167: q BINPUT 10
373 169: h BINGET 10
374 171: K BININT1 5
375 173: e APPENDS (MARK at 5)
376 174: . STOP
377highest protocol among opcodes = 2
378"""
379
Jeremy Hylton66426532001-10-15 21:38:56 +0000380def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000381 c = C()
382 c.foo = 1
383 c.bar = 2
384 x = [0, 1L, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000385 # Append some integer test cases at cPickle.c's internal size
386 # cutoffs.
387 uint1max = 0xff
388 uint2max = 0xffff
389 int4max = 0x7fffffff
390 x.extend([1, -1,
391 uint1max, -uint1max, -uint1max-1,
392 uint2max, -uint2max, -uint2max-1,
393 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000394 y = ('abc', 'abc', c, c)
395 x.append(y)
396 x.append(y)
397 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000398 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000399
Jeremy Hylton66426532001-10-15 21:38:56 +0000400class AbstractPickleTests(unittest.TestCase):
Tim Peters70b02d72003-02-02 17:26:40 +0000401 # Subclass must define self.dumps, self.loads, self.error.
Tim Petersc58440f2001-04-09 17:16:31 +0000402
Jeremy Hylton66426532001-10-15 21:38:56 +0000403 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000404
Jeremy Hylton66426532001-10-15 21:38:56 +0000405 def setUp(self):
Tim Peterse9358162001-01-22 22:05:20 +0000406 pass
Tim Petersc58440f2001-04-09 17:16:31 +0000407
Jeremy Hylton66426532001-10-15 21:38:56 +0000408 def test_misc(self):
409 # test various datatypes not tested by testdata
Tim Peters70b02d72003-02-02 17:26:40 +0000410 for proto in protocols:
411 x = myint(4)
412 s = self.dumps(x, proto)
413 y = self.loads(s)
414 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000415
Tim Peters70b02d72003-02-02 17:26:40 +0000416 x = (1, ())
417 s = self.dumps(x, proto)
418 y = self.loads(s)
419 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000420
Tim Peters70b02d72003-02-02 17:26:40 +0000421 x = initarg(1, x)
422 s = self.dumps(x, proto)
423 y = self.loads(s)
424 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000425
Jeremy Hylton66426532001-10-15 21:38:56 +0000426 # XXX test __reduce__ protocol?
427
Tim Peters70b02d72003-02-02 17:26:40 +0000428 def test_roundtrip_equality(self):
429 expected = self._testdata
430 for proto in protocols:
431 s = self.dumps(expected, proto)
432 got = self.loads(s)
433 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000434
Tim Peters70b02d72003-02-02 17:26:40 +0000435 def test_load_from_canned_string(self):
436 expected = self._testdata
Tim Petersfc273752003-03-02 04:54:24 +0000437 for canned in DATA0, DATA1, DATA2:
Tim Peters70b02d72003-02-02 17:26:40 +0000438 got = self.loads(canned)
439 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000440
Tim Peters70b02d72003-02-02 17:26:40 +0000441 # There are gratuitous differences between pickles produced by
442 # pickle and cPickle, largely because cPickle starts PUT indices at
443 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
444 # there's a comment with an exclamation point there whose meaning
445 # is a mystery. cPickle also suppresses PUT for objects with a refcount
446 # of 1.
447 def dont_test_disassembly(self):
Tim Peters70b02d72003-02-02 17:26:40 +0000448 from pickletools import dis
449
450 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
451 s = self.dumps(self._testdata, proto)
Collin Winterf8089c72009-04-09 16:46:46 +0000452 filelike = cStringIO.StringIO()
Tim Peters70b02d72003-02-02 17:26:40 +0000453 dis(s, out=filelike)
454 got = filelike.getvalue()
455 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000456
457 def test_recursive_list(self):
458 l = []
459 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +0000460 for proto in protocols:
461 s = self.dumps(l, proto)
462 x = self.loads(s)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000463 self.assertEqual(len(x), 1)
464 self.assert_(x is x[0])
Jeremy Hylton66426532001-10-15 21:38:56 +0000465
466 def test_recursive_dict(self):
467 d = {}
468 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +0000469 for proto in protocols:
470 s = self.dumps(d, proto)
471 x = self.loads(s)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000472 self.assertEqual(x.keys(), [1])
473 self.assert_(x[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000474
475 def test_recursive_inst(self):
476 i = C()
477 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +0000478 for proto in protocols:
479 s = self.dumps(i, 2)
480 x = self.loads(s)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000481 self.assertEqual(dir(x), dir(i))
482 self.assert_(x.attr is x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000483
484 def test_recursive_multi(self):
485 l = []
486 d = {1:l}
487 i = C()
488 i.attr = d
489 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +0000490 for proto in protocols:
491 s = self.dumps(l, proto)
492 x = self.loads(s)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000493 self.assertEqual(len(x), 1)
494 self.assertEqual(dir(x[0]), dir(i))
495 self.assertEqual(x[0].attr.keys(), [1])
496 self.assert_(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000497
498 def test_garyp(self):
499 self.assertRaises(self.error, self.loads, 'garyp')
500
501 def test_insecure_strings(self):
502 insecure = ["abc", "2 + 2", # not quoted
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000503 #"'abc' + 'def'", # not a single quoted string
Jeremy Hylton66426532001-10-15 21:38:56 +0000504 "'abc", # quote is not closed
505 "'abc\"", # open quote and close quote don't match
506 "'abc' ?", # junk after close quote
Martin v. Löwiseb3f00a2002-08-14 08:22:50 +0000507 "'\\'", # trailing backslash
Jeremy Hylton66426532001-10-15 21:38:56 +0000508 # some tests of the quoting rules
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000509 #"'abc\"\''",
510 #"'\\\\a\'\'\'\\\'\\\\\''",
Jeremy Hylton66426532001-10-15 21:38:56 +0000511 ]
512 for s in insecure:
513 buf = "S" + s + "\012p0\012."
514 self.assertRaises(ValueError, self.loads, buf)
515
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000516 if have_unicode:
Jeremy Hylton66426532001-10-15 21:38:56 +0000517 def test_unicode(self):
Alexandre Vassalottie57e9992008-12-27 10:02:59 +0000518 endcases = [u'', u'<\\u>', u'<\\\u1234>', u'<\n>',
519 u'<\\>', u'<\\\U00012345>']
Tim Petersee1a53c2003-02-02 02:57:53 +0000520 for proto in protocols:
521 for u in endcases:
522 p = self.dumps(u, proto)
523 u2 = self.loads(p)
524 self.assertEqual(u2, u)
Tim Peterse089c682001-04-10 03:41:41 +0000525
Alexandre Vassalottif852bf92008-12-27 07:08:47 +0000526 def test_unicode_high_plane(self):
527 t = u'\U00012345'
528 for proto in protocols:
529 p = self.dumps(t, proto)
530 t2 = self.loads(p)
531 self.assertEqual(t2, t)
532
Jeremy Hylton66426532001-10-15 21:38:56 +0000533 def test_ints(self):
534 import sys
Tim Petersee1a53c2003-02-02 02:57:53 +0000535 for proto in protocols:
536 n = sys.maxint
537 while n:
538 for expected in (-n, n):
539 s = self.dumps(expected, proto)
540 n2 = self.loads(s)
541 self.assertEqual(expected, n2)
542 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +0000543
Jeremy Hylton66426532001-10-15 21:38:56 +0000544 def test_maxint64(self):
545 maxint64 = (1L << 63) - 1
546 data = 'I' + str(maxint64) + '\n.'
547 got = self.loads(data)
548 self.assertEqual(got, maxint64)
549
550 # Try too with a bogus literal.
551 data = 'I' + str(maxint64) + 'JUNK\n.'
552 self.assertRaises(ValueError, self.loads, data)
553
Tim Petersee1a53c2003-02-02 02:57:53 +0000554 def test_long(self):
555 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +0000556 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +0000557 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
558 nbase = 1L << nbits
559 for npos in nbase-1, nbase, nbase+1:
560 for n in npos, -npos:
561 pickle = self.dumps(n, proto)
562 got = self.loads(pickle)
563 self.assertEqual(n, got)
564 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
565 # bother with those.
Tim Petersee1a53c2003-02-02 02:57:53 +0000566 nbase = long("deadbeeffeedface", 16)
567 nbase += nbase << 1000000
568 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +0000569 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000570 got = self.loads(p)
Tim Petersee1a53c2003-02-02 02:57:53 +0000571 self.assertEqual(n, got)
572
Mark Dickinsona3ecd2c2009-01-24 16:40:29 +0000573 def test_float(self):
574 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
575 3.14, 263.44582062374053, 6.022e23, 1e30]
576 test_values = test_values + [-x for x in test_values]
577 for proto in protocols:
578 for value in test_values:
579 pickle = self.dumps(value, proto)
580 got = self.loads(pickle)
581 self.assertEqual(value, got)
582
Georg Brandlde9b6242006-04-30 11:13:56 +0000583 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
584 def test_float_format(self):
585 # make sure that floats are formatted locale independent
586 self.assertEqual(self.dumps(1.2)[0:3], 'F1.')
587
Jeremy Hylton66426532001-10-15 21:38:56 +0000588 def test_reduce(self):
Tim Peters19ef62d2001-08-28 22:21:18 +0000589 pass
Jeremy Hylton66426532001-10-15 21:38:56 +0000590
591 def test_getinitargs(self):
592 pass
593
Guido van Rossum04a86612001-12-19 16:58:54 +0000594 def test_metaclass(self):
595 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +0000596 for proto in protocols:
597 s = self.dumps(a, proto)
598 b = self.loads(s)
599 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +0000600
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000601 def test_structseq(self):
602 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +0000603 import os
Tim Peters70b02d72003-02-02 17:26:40 +0000604
605 t = time.localtime()
606 for proto in protocols:
607 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +0000608 u = self.loads(s)
609 self.assertEqual(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000610 if hasattr(os, "stat"):
611 t = os.stat(os.curdir)
612 s = self.dumps(t, proto)
613 u = self.loads(s)
614 self.assertEqual(t, u)
615 if hasattr(os, "statvfs"):
616 t = os.statvfs(os.curdir)
617 s = self.dumps(t, proto)
618 u = self.loads(s)
619 self.assertEqual(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000620
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000621 # Tests for protocol 2
622
Tim Peters4190fb82003-02-02 16:09:05 +0000623 def test_proto(self):
624 build_none = pickle.NONE + pickle.STOP
625 for proto in protocols:
626 expected = build_none
627 if proto >= 2:
628 expected = pickle.PROTO + chr(proto) + expected
629 p = self.dumps(None, proto)
630 self.assertEqual(p, expected)
631
632 oob = protocols[-1] + 1 # a future protocol
633 badpickle = pickle.PROTO + chr(oob) + build_none
634 try:
635 self.loads(badpickle)
636 except ValueError, detail:
637 self.failUnless(str(detail).startswith(
638 "unsupported pickle protocol"))
639 else:
640 self.fail("expected bad protocol number to raise ValueError")
641
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000642 def test_long1(self):
643 x = 12345678910111213141516178920L
Tim Peters61bf2572003-02-03 21:31:22 +0000644 for proto in protocols:
645 s = self.dumps(x, proto)
646 y = self.loads(s)
647 self.assertEqual(x, y)
Tim Peters22e71712003-02-03 22:27:38 +0000648 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000649
650 def test_long4(self):
651 x = 12345678910111213141516178920L << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +0000652 for proto in protocols:
653 s = self.dumps(x, proto)
654 y = self.loads(s)
655 self.assertEqual(x, y)
Tim Peters22e71712003-02-03 22:27:38 +0000656 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000657
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000658 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +0000659 # Map (proto, len(tuple)) to expected opcode.
660 expected_opcode = {(0, 0): pickle.TUPLE,
661 (0, 1): pickle.TUPLE,
662 (0, 2): pickle.TUPLE,
663 (0, 3): pickle.TUPLE,
664 (0, 4): pickle.TUPLE,
665
666 (1, 0): pickle.EMPTY_TUPLE,
667 (1, 1): pickle.TUPLE,
668 (1, 2): pickle.TUPLE,
669 (1, 3): pickle.TUPLE,
670 (1, 4): pickle.TUPLE,
671
672 (2, 0): pickle.EMPTY_TUPLE,
673 (2, 1): pickle.TUPLE1,
674 (2, 2): pickle.TUPLE2,
675 (2, 3): pickle.TUPLE3,
676 (2, 4): pickle.TUPLE,
677 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000678 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +0000679 b = (1,)
680 c = (1, 2)
681 d = (1, 2, 3)
682 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +0000683 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000684 for x in a, b, c, d, e:
685 s = self.dumps(x, proto)
686 y = self.loads(s)
687 self.assertEqual(x, y, (proto, x, s, y))
Tim Peters1d63c9f2003-02-02 20:29:39 +0000688 expected = expected_opcode[proto, len(x)]
Tim Peters22e71712003-02-03 22:27:38 +0000689 self.assertEqual(opcode_in_pickle(expected, s), True)
Tim Peters1d63c9f2003-02-02 20:29:39 +0000690
Guido van Rossum7d97d312003-01-28 04:25:27 +0000691 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +0000692 # Map (proto, singleton) to expected opcode.
693 expected_opcode = {(0, None): pickle.NONE,
694 (1, None): pickle.NONE,
695 (2, None): pickle.NONE,
696
697 (0, True): pickle.INT,
698 (1, True): pickle.INT,
699 (2, True): pickle.NEWTRUE,
700
701 (0, False): pickle.INT,
702 (1, False): pickle.INT,
703 (2, False): pickle.NEWFALSE,
704 }
Tim Peters4190fb82003-02-02 16:09:05 +0000705 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +0000706 for x in None, False, True:
707 s = self.dumps(x, proto)
708 y = self.loads(s)
709 self.assert_(x is y, (proto, x, s, y))
Tim Peters61bf2572003-02-03 21:31:22 +0000710 expected = expected_opcode[proto, x]
Tim Peters22e71712003-02-03 22:27:38 +0000711 self.assertEqual(opcode_in_pickle(expected, s), True)
Tim Peters3c67d792003-02-02 17:59:11 +0000712
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000713 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000714 x = MyTuple([1, 2, 3])
715 x.foo = 42
716 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +0000717 for proto in protocols:
718 s = self.dumps(x, proto)
719 y = self.loads(s)
720 self.assertEqual(tuple(x), tuple(y))
721 self.assertEqual(x.__dict__, y.__dict__)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000722
723 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000724 x = MyList([1, 2, 3])
725 x.foo = 42
726 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +0000727 for proto in protocols:
728 s = self.dumps(x, proto)
729 y = self.loads(s)
730 self.assertEqual(list(x), list(y))
731 self.assertEqual(x.__dict__, y.__dict__)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000732
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000733 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +0000734 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000735 for C in myclasses:
736 B = C.__base__
737 x = C(C.sample)
738 x.foo = 42
739 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000740 y = self.loads(s)
741 detail = (proto, C, B, x, y, type(y))
742 self.assertEqual(B(x), B(y), detail)
743 self.assertEqual(x.__dict__, y.__dict__, detail)
744
Georg Brandldffbf5f2008-05-20 07:49:57 +0000745 # Register a type with copy_reg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +0000746 # an object of that type. Check that the resulting pickle uses opcode
747 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +0000748
Tim Peters22e71712003-02-03 22:27:38 +0000749 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +0000750 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000751 try:
Georg Brandldffbf5f2008-05-20 07:49:57 +0000752 copy_reg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000753 x = MyList([1, 2, 3])
754 x.foo = 42
755 x.bar = "hello"
756
Tim Peters22e71712003-02-03 22:27:38 +0000757 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000758 s1 = self.dumps(x, 1)
Tim Peters3e667d52003-02-04 21:47:44 +0000759 self.assert_(__name__ in s1)
760 self.assert_("MyList" in s1)
761 self.assertEqual(opcode_in_pickle(opcode, s1), False)
762
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000763 y = self.loads(s1)
764 self.assertEqual(list(x), list(y))
765 self.assertEqual(x.__dict__, y.__dict__)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000766
Tim Peters22e71712003-02-03 22:27:38 +0000767 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000768 s2 = self.dumps(x, 2)
Tim Peters3e667d52003-02-04 21:47:44 +0000769 self.assert_(__name__ not in s2)
770 self.assert_("MyList" not in s2)
771 self.assertEqual(opcode_in_pickle(opcode, s2), True)
772
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000773 y = self.loads(s2)
774 self.assertEqual(list(x), list(y))
775 self.assertEqual(x.__dict__, y.__dict__)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000776
777 finally:
Tim Peters3e667d52003-02-04 21:47:44 +0000778 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +0000779
780 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +0000781 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
782 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000783
784 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +0000785 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
786 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
787 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000788
789 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +0000790 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
791 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
792 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
793
Tim Peters8d2613a2003-02-11 16:40:16 +0000794 def test_list_chunking(self):
795 n = 10 # too small to chunk
796 x = range(n)
797 for proto in protocols:
798 s = self.dumps(x, proto)
799 y = self.loads(s)
800 self.assertEqual(x, y)
801 num_appends = count_opcode(pickle.APPENDS, s)
802 self.assertEqual(num_appends, proto > 0)
803
804 n = 2500 # expect at least two chunks when proto > 0
805 x = range(n)
806 for proto in protocols:
807 s = self.dumps(x, proto)
808 y = self.loads(s)
809 self.assertEqual(x, y)
810 num_appends = count_opcode(pickle.APPENDS, s)
811 if proto == 0:
812 self.assertEqual(num_appends, 0)
813 else:
814 self.failUnless(num_appends >= 2)
815
816 def test_dict_chunking(self):
817 n = 10 # too small to chunk
818 x = dict.fromkeys(range(n))
819 for proto in protocols:
820 s = self.dumps(x, proto)
821 y = self.loads(s)
822 self.assertEqual(x, y)
823 num_setitems = count_opcode(pickle.SETITEMS, s)
824 self.assertEqual(num_setitems, proto > 0)
825
826 n = 2500 # expect at least two chunks when proto > 0
827 x = dict.fromkeys(range(n))
828 for proto in protocols:
829 s = self.dumps(x, proto)
830 y = self.loads(s)
831 self.assertEqual(x, y)
832 num_setitems = count_opcode(pickle.SETITEMS, s)
833 if proto == 0:
834 self.assertEqual(num_setitems, 0)
835 else:
836 self.failUnless(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000837
Tim Peterse9ef2032003-02-13 18:42:00 +0000838 def test_simple_newobj(self):
839 x = object.__new__(SimpleNewObj) # avoid __init__
840 x.abc = 666
841 for proto in protocols:
842 s = self.dumps(x, proto)
843 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s), proto >= 2)
844 y = self.loads(s) # will raise TypeError if __init__ called
845 self.assertEqual(y.abc, 666)
846 self.assertEqual(x.__dict__, y.__dict__)
847
Tim Peters42f08ac2003-02-11 22:43:24 +0000848 def test_newobj_list_slots(self):
849 x = SlotList([1, 2, 3])
850 x.foo = 42
851 x.bar = "hello"
852 s = self.dumps(x, 2)
853 y = self.loads(s)
854 self.assertEqual(list(x), list(y))
855 self.assertEqual(x.__dict__, y.__dict__)
856 self.assertEqual(x.foo, y.foo)
857 self.assertEqual(x.bar, y.bar)
858
Guido van Rossum2a30b212003-02-18 22:41:24 +0000859 def test_reduce_overrides_default_reduce_ex(self):
Collin Winterf8089c72009-04-09 16:46:46 +0000860 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +0000861 x = REX_one()
862 self.assertEqual(x._reduce_called, 0)
863 s = self.dumps(x, proto)
864 self.assertEqual(x._reduce_called, 1)
865 y = self.loads(s)
866 self.assertEqual(y._reduce_called, 0)
867
868 def test_reduce_ex_called(self):
Collin Winterf8089c72009-04-09 16:46:46 +0000869 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +0000870 x = REX_two()
871 self.assertEqual(x._proto, None)
872 s = self.dumps(x, proto)
873 self.assertEqual(x._proto, proto)
874 y = self.loads(s)
875 self.assertEqual(y._proto, None)
876
877 def test_reduce_ex_overrides_reduce(self):
Collin Winterf8089c72009-04-09 16:46:46 +0000878 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +0000879 x = REX_three()
880 self.assertEqual(x._proto, None)
881 s = self.dumps(x, proto)
882 self.assertEqual(x._proto, proto)
883 y = self.loads(s)
884 self.assertEqual(y._proto, None)
885
Žiga Seilnacht20f43d32007-03-15 11:44:55 +0000886 def test_reduce_ex_calls_base(self):
Collin Winterf8089c72009-04-09 16:46:46 +0000887 for proto in protocols:
Žiga Seilnacht20f43d32007-03-15 11:44:55 +0000888 x = REX_four()
889 self.assertEqual(x._proto, None)
890 s = self.dumps(x, proto)
891 self.assertEqual(x._proto, proto)
892 y = self.loads(s)
893 self.assertEqual(y._proto, proto)
894
895 def test_reduce_calls_base(self):
Collin Winterf8089c72009-04-09 16:46:46 +0000896 for proto in protocols:
Žiga Seilnacht20f43d32007-03-15 11:44:55 +0000897 x = REX_five()
898 self.assertEqual(x._reduce_called, 0)
899 s = self.dumps(x, proto)
900 self.assertEqual(x._reduce_called, 1)
901 y = self.loads(s)
902 self.assertEqual(y._reduce_called, 1)
903
Amaury Forgeot d'Arc69a9c5b2008-10-30 21:18:34 +0000904 def test_reduce_bad_iterator(self):
905 # Issue4176: crash when 4th and 5th items of __reduce__()
906 # are not iterators
907 class C(object):
908 def __reduce__(self):
909 # 4th item is not an iterator
910 return list, (), None, [], None
911 class D(object):
912 def __reduce__(self):
913 # 5th item is not an iterator
914 return dict, (), None, None, []
915
916 # Protocol 0 is less strict and also accept iterables.
Collin Winterf8089c72009-04-09 16:46:46 +0000917 for proto in protocols:
Amaury Forgeot d'Arc69a9c5b2008-10-30 21:18:34 +0000918 try:
919 self.dumps(C(), proto)
920 except (AttributeError, pickle.PickleError, cPickle.PickleError):
921 pass
922 try:
923 self.dumps(D(), proto)
924 except (AttributeError, pickle.PickleError, cPickle.PickleError):
925 pass
926
Collin Winterf8089c72009-04-09 16:46:46 +0000927 def test_many_puts_and_gets(self):
928 # Test that internal data structures correctly deal with lots of
929 # puts/gets.
930 keys = ("aaa" + str(i) for i in xrange(100))
931 large_dict = dict((k, [4, 5, 6]) for k in keys)
932 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
933
934 for proto in protocols:
935 dumped = self.dumps(obj, proto)
936 loaded = self.loads(dumped)
937 self.assertEqual(loaded, obj,
938 "Failed protocol %d: %r != %r"
939 % (proto, obj, loaded))
940
941
Guido van Rossum2a30b212003-02-18 22:41:24 +0000942# Test classes for reduce_ex
943
944class REX_one(object):
945 _reduce_called = 0
946 def __reduce__(self):
947 self._reduce_called = 1
948 return REX_one, ()
949 # No __reduce_ex__ here, but inheriting it from object
950
951class REX_two(object):
952 _proto = None
953 def __reduce_ex__(self, proto):
954 self._proto = proto
955 return REX_two, ()
956 # No __reduce__ here, but inheriting it from object
957
958class REX_three(object):
959 _proto = None
960 def __reduce_ex__(self, proto):
961 self._proto = proto
962 return REX_two, ()
963 def __reduce__(self):
964 raise TestFailed, "This __reduce__ shouldn't be called"
965
Žiga Seilnacht20f43d32007-03-15 11:44:55 +0000966class REX_four(object):
967 _proto = None
968 def __reduce_ex__(self, proto):
969 self._proto = proto
970 return object.__reduce_ex__(self, proto)
971 # Calling base class method should succeed
972
973class REX_five(object):
974 _reduce_called = 0
975 def __reduce__(self):
976 self._reduce_called = 1
977 return object.__reduce__(self)
978 # This one used to fail with infinite recursion
979
Guido van Rossum2a30b212003-02-18 22:41:24 +0000980# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +0000981
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000982class MyInt(int):
983 sample = 1
984
985class MyLong(long):
986 sample = 1L
987
988class MyFloat(float):
989 sample = 1.0
990
991class MyComplex(complex):
992 sample = 1.0 + 0.0j
993
994class MyStr(str):
995 sample = "hello"
996
997class MyUnicode(unicode):
998 sample = u"hello \u1234"
999
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001000class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001001 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001002
1003class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001004 sample = [1, 2, 3]
1005
1006class MyDict(dict):
1007 sample = {"a": 1, "b": 2}
1008
1009myclasses = [MyInt, MyLong, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00001010 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001011 MyStr, MyUnicode,
1012 MyTuple, MyList, MyDict]
1013
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001014
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00001015class SlotList(MyList):
1016 __slots__ = ["foo"]
1017
Tim Peterse9ef2032003-02-13 18:42:00 +00001018class SimpleNewObj(object):
1019 def __init__(self, a, b, c):
1020 # raise an error, to make sure this isn't called
1021 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
1022
Jeremy Hylton66426532001-10-15 21:38:56 +00001023class AbstractPickleModuleTests(unittest.TestCase):
1024
1025 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001026 import os
1027 f = open(TESTFN, "w")
1028 try:
1029 f.close()
1030 self.assertRaises(ValueError, self.module.dump, 123, f)
1031 finally:
1032 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00001033
1034 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001035 import os
1036 f = open(TESTFN, "w")
1037 try:
1038 f.close()
1039 self.assertRaises(ValueError, self.module.dump, 123, f)
1040 finally:
1041 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00001042
Collin Winterf8089c72009-04-09 16:46:46 +00001043 def test_load_from_and_dump_to_file(self):
1044 stream = cStringIO.StringIO()
1045 data = [123, {}, 124]
1046 self.module.dump(data, stream)
1047 stream.seek(0)
1048 unpickled = self.module.load(stream)
1049 self.assertEqual(unpickled, data)
1050
Tim Petersc0c93702003-02-13 19:30:57 +00001051 def test_highest_protocol(self):
1052 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
1053 self.assertEqual(self.module.HIGHEST_PROTOCOL, 2)
1054
Martin v. Löwis544f1192004-07-27 05:22:33 +00001055 def test_callapi(self):
Collin Winterf8089c72009-04-09 16:46:46 +00001056 f = cStringIO.StringIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00001057 # With and without keyword arguments
1058 self.module.dump(123, f, -1)
1059 self.module.dump(123, file=f, protocol=-1)
1060 self.module.dumps(123, -1)
1061 self.module.dumps(123, protocol=-1)
1062 self.module.Pickler(f, -1)
1063 self.module.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00001064
Jeremy Hylton4c8be852002-11-13 22:10:47 +00001065class AbstractPersistentPicklerTests(unittest.TestCase):
1066
1067 # This class defines persistent_id() and persistent_load()
1068 # functions that should be used by the pickler. All even integers
1069 # are pickled using persistent ids.
1070
1071 def persistent_id(self, object):
1072 if isinstance(object, int) and object % 2 == 0:
1073 self.id_count += 1
1074 return str(object)
1075 else:
1076 return None
1077
1078 def persistent_load(self, oid):
1079 self.load_count += 1
1080 object = int(oid)
1081 assert object % 2 == 0
1082 return object
1083
1084 def test_persistence(self):
1085 self.id_count = 0
1086 self.load_count = 0
1087 L = range(10)
1088 self.assertEqual(self.loads(self.dumps(L)), L)
1089 self.assertEqual(self.id_count, 5)
1090 self.assertEqual(self.load_count, 5)
1091
1092 def test_bin_persistence(self):
1093 self.id_count = 0
1094 self.load_count = 0
1095 L = range(10)
1096 self.assertEqual(self.loads(self.dumps(L, 1)), L)
1097 self.assertEqual(self.id_count, 5)
1098 self.assertEqual(self.load_count, 5)
Collin Winterf8089c72009-04-09 16:46:46 +00001099
1100class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
1101
1102 pickler_class = None
1103 unpickler_class = None
1104
1105 def setUp(self):
1106 assert self.pickler_class
1107 assert self.unpickler_class
1108
1109 def test_clear_pickler_memo(self):
1110 # To test whether clear_memo() has any effect, we pickle an object,
1111 # then pickle it again without clearing the memo; the two serialized
1112 # forms should be different. If we clear_memo() and then pickle the
1113 # object again, the third serialized form should be identical to the
1114 # first one we obtained.
1115 data = ["abcdefg", "abcdefg", 44]
1116 f = cStringIO.StringIO()
1117 pickler = self.pickler_class(f)
1118
1119 pickler.dump(data)
1120 first_pickled = f.getvalue()
1121
1122 # Reset StringIO object.
1123 f.seek(0)
1124 f.truncate()
1125
1126 pickler.dump(data)
1127 second_pickled = f.getvalue()
1128
1129 # Reset the Pickler and StringIO objects.
1130 pickler.clear_memo()
1131 f.seek(0)
1132 f.truncate()
1133
1134 pickler.dump(data)
1135 third_pickled = f.getvalue()
1136
1137 self.assertNotEqual(first_pickled, second_pickled)
1138 self.assertEqual(first_pickled, third_pickled)
1139
1140 def test_priming_pickler_memo(self):
1141 # Verify that we can set the Pickler's memo attribute.
1142 data = ["abcdefg", "abcdefg", 44]
1143 f = cStringIO.StringIO()
1144 pickler = self.pickler_class(f)
1145
1146 pickler.dump(data)
1147 first_pickled = f.getvalue()
1148
1149 f = cStringIO.StringIO()
1150 primed = self.pickler_class(f)
1151 primed.memo = pickler.memo
1152
1153 primed.dump(data)
1154 primed_pickled = f.getvalue()
1155
1156 self.assertNotEqual(first_pickled, primed_pickled)
1157
1158 def test_priming_unpickler_memo(self):
1159 # Verify that we can set the Unpickler's memo attribute.
1160 data = ["abcdefg", "abcdefg", 44]
1161 f = cStringIO.StringIO()
1162 pickler = self.pickler_class(f)
1163
1164 pickler.dump(data)
1165 first_pickled = f.getvalue()
1166
1167 f = cStringIO.StringIO()
1168 primed = self.pickler_class(f)
1169 primed.memo = pickler.memo
1170
1171 primed.dump(data)
1172 primed_pickled = f.getvalue()
1173
1174 unpickler = self.unpickler_class(cStringIO.StringIO(first_pickled))
1175 unpickled_data1 = unpickler.load()
1176
1177 self.assertEqual(unpickled_data1, data)
1178
1179 primed = self.unpickler_class(cStringIO.StringIO(primed_pickled))
1180 primed.memo = unpickler.memo
1181 unpickled_data2 = primed.load()
1182
1183 primed.memo.clear()
1184
1185 self.assertEqual(unpickled_data2, data)
1186 self.assertTrue(unpickled_data2 is unpickled_data1)
1187
1188 def test_reusing_unpickler_objects(self):
1189 data1 = ["abcdefg", "abcdefg", 44]
1190 f = cStringIO.StringIO()
1191 pickler = self.pickler_class(f)
1192 pickler.dump(data1)
1193 pickled1 = f.getvalue()
1194
1195 data2 = ["abcdefg", 44, 44]
1196 f = cStringIO.StringIO()
1197 pickler = self.pickler_class(f)
1198 pickler.dump(data2)
1199 pickled2 = f.getvalue()
1200
1201 f = cStringIO.StringIO()
1202 f.write(pickled1)
1203 f.seek(0)
1204 unpickler = self.unpickler_class(f)
1205 self.assertEqual(unpickler.load(), data1)
1206
1207 f.seek(0)
1208 f.truncate()
1209 f.write(pickled2)
1210 f.seek(0)
1211 self.assertEqual(unpickler.load(), data2)