blob: 6c621e5386f62889bc31c3b34d9c1ebaac395d69 [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
Tim Peters22e71712003-02-03 22:27:38 +000012
13# Return True if opcode code appears in the pickle, else False.
14def opcode_in_pickle(code, pickle):
15 for op, dummy, dummy in pickletools.genops(pickle):
16 if op.code == code:
17 return True
18 return False
19
Jeremy Hylton66426532001-10-15 21:38:56 +000020class C:
21 def __cmp__(self, other):
22 return cmp(self.__dict__, other.__dict__)
23
24import __main__
25__main__.C = C
26C.__module__ = "__main__"
27
28class myint(int):
29 def __init__(self, x):
30 self.str = str(x)
31
32class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +000033
Jeremy Hylton66426532001-10-15 21:38:56 +000034 def __init__(self, a, b):
35 self.a = a
36 self.b = b
37
38 def __getinitargs__(self):
39 return self.a, self.b
40
Guido van Rossum04a86612001-12-19 16:58:54 +000041class metaclass(type):
42 pass
43
44class use_metaclass(object):
45 __metaclass__ = metaclass
46
Tim Peters70b02d72003-02-02 17:26:40 +000047# DATA0 .. DATA2 are the pickles we expect under the various protocols, for
48# the object returned by create_data().
49# XXX DATA2 doesn't exist yet, as it's not fully implemented in cPickle.
Tim Petersee1a53c2003-02-02 02:57:53 +000050
Jeremy Hylton66426532001-10-15 21:38:56 +000051# break into multiple strings to avoid confusing font-lock-mode
Tim Peters70b02d72003-02-02 17:26:40 +000052DATA0 = """(lp1
Tim Peterse9358162001-01-22 22:05:20 +000053I0
54aL1L
Tim Peters461922a2001-04-09 20:07:05 +000055aF2
Tim Peterse9358162001-01-22 22:05:20 +000056ac__builtin__
57complex
Tim Peters461922a2001-04-09 20:07:05 +000058p2
59""" + \
60"""(F3
61F0
62tRp3
63aI1
64aI-1
65aI255
66aI-255
67aI-256
68aI65535
69aI-65535
70aI-65536
71aI2147483647
72aI-2147483647
73aI-2147483648
74a""" + \
75"""(S'abc'
Tim Peterse9358162001-01-22 22:05:20 +000076p4
77g4
Tim Peters461922a2001-04-09 20:07:05 +000078""" + \
Guido van Rossum42f92da2001-04-16 00:28:21 +000079"""(i__main__
Tim Peterse9358162001-01-22 22:05:20 +000080C
81p5
Tim Peters461922a2001-04-09 20:07:05 +000082""" + \
Tim Peterse9358162001-01-22 22:05:20 +000083"""(dp6
84S'foo'
85p7
86I1
87sS'bar'
88p8
89I2
90sbg5
91tp9
92ag9
93aI5
94a.
95"""
96
Tim Peters70b02d72003-02-02 17:26:40 +000097# Disassembly of DATA0.
98DATA0_DIS = """\
99 0: ( MARK
100 1: l LIST (MARK at 0)
101 2: p PUT 1
102 5: I INT 0
103 8: a APPEND
104 9: L LONG 1L
105 13: a APPEND
106 14: F FLOAT 2.0
107 17: a APPEND
108 18: c GLOBAL '__builtin__ complex'
109 39: p PUT 2
110 42: ( MARK
111 43: F FLOAT 3.0
112 46: F FLOAT 0.0
113 49: t TUPLE (MARK at 42)
114 50: R REDUCE
115 51: p PUT 3
116 54: a APPEND
117 55: I INT 1
118 58: a APPEND
119 59: I INT -1
120 63: a APPEND
121 64: I INT 255
122 69: a APPEND
123 70: I INT -255
124 76: a APPEND
125 77: I INT -256
126 83: a APPEND
127 84: I INT 65535
128 91: a APPEND
129 92: I INT -65535
130 100: a APPEND
131 101: I INT -65536
132 109: a APPEND
133 110: I INT 2147483647
134 122: a APPEND
135 123: I INT -2147483647
136 136: a APPEND
137 137: I INT -2147483648
138 150: a APPEND
139 151: ( MARK
140 152: S STRING 'abc'
141 159: p PUT 4
142 162: g GET 4
143 165: ( MARK
144 166: i INST '__main__ C' (MARK at 165)
145 178: p PUT 5
146 181: ( MARK
147 182: d DICT (MARK at 181)
148 183: p PUT 6
149 186: S STRING 'foo'
150 193: p PUT 7
151 196: I INT 1
152 199: s SETITEM
153 200: S STRING 'bar'
154 207: p PUT 8
155 210: I INT 2
156 213: s SETITEM
157 214: b BUILD
158 215: g GET 5
159 218: t TUPLE (MARK at 151)
160 219: p PUT 9
161 222: a APPEND
162 223: g GET 9
163 226: a APPEND
164 227: I INT 5
165 230: a APPEND
166 231: . STOP
167highest protocol among opcodes = 0
168"""
169
170DATA1 = (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00'
171 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00'
172 '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff'
173 '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff'
174 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00'
175 '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n'
176 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh'
177 '\x06tq\nh\nK\x05e.'
178 )
179
180# Disassembly of DATA1.
181DATA1_DIS = """\
182 0: ] EMPTY_LIST
183 1: q BINPUT 1
184 3: ( MARK
185 4: K BININT1 0
186 6: L LONG 1L
187 10: G BINFLOAT 2.0
188 19: c GLOBAL '__builtin__ complex'
189 40: q BINPUT 2
190 42: ( MARK
191 43: G BINFLOAT 3.0
192 52: G BINFLOAT 0.0
193 61: t TUPLE (MARK at 42)
194 62: R REDUCE
195 63: q BINPUT 3
196 65: K BININT1 1
197 67: J BININT -1
198 72: K BININT1 255
199 74: J BININT -255
200 79: J BININT -256
201 84: M BININT2 65535
202 87: J BININT -65535
203 92: J BININT -65536
204 97: J BININT 2147483647
205 102: J BININT -2147483647
206 107: J BININT -2147483648
207 112: ( MARK
208 113: U SHORT_BINSTRING 'abc'
209 118: q BINPUT 4
210 120: h BINGET 4
211 122: ( MARK
212 123: c GLOBAL '__main__ C'
213 135: q BINPUT 5
214 137: o OBJ (MARK at 122)
215 138: q BINPUT 6
216 140: } EMPTY_DICT
217 141: q BINPUT 7
218 143: ( MARK
219 144: U SHORT_BINSTRING 'foo'
220 149: q BINPUT 8
221 151: K BININT1 1
222 153: U SHORT_BINSTRING 'bar'
223 158: q BINPUT 9
224 160: K BININT1 2
225 162: u SETITEMS (MARK at 143)
226 163: b BUILD
227 164: h BINGET 6
228 166: t TUPLE (MARK at 112)
229 167: q BINPUT 10
230 169: h BINGET 10
231 171: K BININT1 5
232 173: e APPENDS (MARK at 3)
233 174: . STOP
234highest protocol among opcodes = 1
235"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000236
Jeremy Hylton66426532001-10-15 21:38:56 +0000237def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000238 c = C()
239 c.foo = 1
240 c.bar = 2
241 x = [0, 1L, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000242 # Append some integer test cases at cPickle.c's internal size
243 # cutoffs.
244 uint1max = 0xff
245 uint2max = 0xffff
246 int4max = 0x7fffffff
247 x.extend([1, -1,
248 uint1max, -uint1max, -uint1max-1,
249 uint2max, -uint2max, -uint2max-1,
250 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000251 y = ('abc', 'abc', c, c)
252 x.append(y)
253 x.append(y)
254 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000255 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000256
Jeremy Hylton66426532001-10-15 21:38:56 +0000257class AbstractPickleTests(unittest.TestCase):
Tim Peters70b02d72003-02-02 17:26:40 +0000258 # Subclass must define self.dumps, self.loads, self.error.
Tim Petersc58440f2001-04-09 17:16:31 +0000259
Jeremy Hylton66426532001-10-15 21:38:56 +0000260 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000261
Jeremy Hylton66426532001-10-15 21:38:56 +0000262 def setUp(self):
Tim Peterse9358162001-01-22 22:05:20 +0000263 pass
Tim Petersc58440f2001-04-09 17:16:31 +0000264
Jeremy Hylton66426532001-10-15 21:38:56 +0000265 def test_misc(self):
266 # test various datatypes not tested by testdata
Tim Peters70b02d72003-02-02 17:26:40 +0000267 for proto in protocols:
268 x = myint(4)
269 s = self.dumps(x, proto)
270 y = self.loads(s)
271 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000272
Tim Peters70b02d72003-02-02 17:26:40 +0000273 x = (1, ())
274 s = self.dumps(x, proto)
275 y = self.loads(s)
276 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000277
Tim Peters70b02d72003-02-02 17:26:40 +0000278 x = initarg(1, x)
279 s = self.dumps(x, proto)
280 y = self.loads(s)
281 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000282
Jeremy Hylton66426532001-10-15 21:38:56 +0000283 # XXX test __reduce__ protocol?
284
Tim Peters70b02d72003-02-02 17:26:40 +0000285 def test_roundtrip_equality(self):
286 expected = self._testdata
287 for proto in protocols:
288 s = self.dumps(expected, proto)
289 got = self.loads(s)
290 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000291
Tim Peters70b02d72003-02-02 17:26:40 +0000292 def test_load_from_canned_string(self):
293 expected = self._testdata
294 for canned in DATA0, DATA1:
295 got = self.loads(canned)
296 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000297
Tim Peters70b02d72003-02-02 17:26:40 +0000298 # There are gratuitous differences between pickles produced by
299 # pickle and cPickle, largely because cPickle starts PUT indices at
300 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
301 # there's a comment with an exclamation point there whose meaning
302 # is a mystery. cPickle also suppresses PUT for objects with a refcount
303 # of 1.
304 def dont_test_disassembly(self):
305 from cStringIO import StringIO
306 from pickletools import dis
307
308 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
309 s = self.dumps(self._testdata, proto)
310 filelike = StringIO()
311 dis(s, out=filelike)
312 got = filelike.getvalue()
313 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000314
315 def test_recursive_list(self):
316 l = []
317 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +0000318 for proto in protocols:
319 s = self.dumps(l, proto)
320 x = self.loads(s)
321 self.assertEqual(x, l)
322 self.assertEqual(x, x[0])
323 self.assertEqual(id(x), id(x[0]))
Jeremy Hylton66426532001-10-15 21:38:56 +0000324
325 def test_recursive_dict(self):
326 d = {}
327 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +0000328 for proto in protocols:
329 s = self.dumps(d, proto)
330 x = self.loads(s)
331 self.assertEqual(x, d)
332 self.assertEqual(x[1], x)
333 self.assertEqual(id(x[1]), id(x))
Jeremy Hylton66426532001-10-15 21:38:56 +0000334
335 def test_recursive_inst(self):
336 i = C()
337 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +0000338 for proto in protocols:
339 s = self.dumps(i, 2)
340 x = self.loads(s)
341 self.assertEqual(x, i)
342 self.assertEqual(x.attr, x)
343 self.assertEqual(id(x.attr), id(x))
Jeremy Hylton66426532001-10-15 21:38:56 +0000344
345 def test_recursive_multi(self):
346 l = []
347 d = {1:l}
348 i = C()
349 i.attr = d
350 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +0000351 for proto in protocols:
352 s = self.dumps(l, proto)
353 x = self.loads(s)
354 self.assertEqual(x, l)
355 self.assertEqual(x[0], i)
356 self.assertEqual(x[0].attr, d)
357 self.assertEqual(x[0].attr[1], x)
358 self.assertEqual(x[0].attr[1][0], i)
359 self.assertEqual(x[0].attr[1][0].attr, d)
Jeremy Hylton66426532001-10-15 21:38:56 +0000360
361 def test_garyp(self):
362 self.assertRaises(self.error, self.loads, 'garyp')
363
364 def test_insecure_strings(self):
365 insecure = ["abc", "2 + 2", # not quoted
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000366 #"'abc' + 'def'", # not a single quoted string
Jeremy Hylton66426532001-10-15 21:38:56 +0000367 "'abc", # quote is not closed
368 "'abc\"", # open quote and close quote don't match
369 "'abc' ?", # junk after close quote
Martin v. Löwiseb3f00a2002-08-14 08:22:50 +0000370 "'\\'", # trailing backslash
Jeremy Hylton66426532001-10-15 21:38:56 +0000371 # some tests of the quoting rules
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000372 #"'abc\"\''",
373 #"'\\\\a\'\'\'\\\'\\\\\''",
Jeremy Hylton66426532001-10-15 21:38:56 +0000374 ]
375 for s in insecure:
376 buf = "S" + s + "\012p0\012."
377 self.assertRaises(ValueError, self.loads, buf)
378
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000379 if have_unicode:
Jeremy Hylton66426532001-10-15 21:38:56 +0000380 def test_unicode(self):
381 endcases = [unicode(''), unicode('<\\u>'), unicode('<\\\u1234>'),
382 unicode('<\n>'), unicode('<\\>')]
Tim Petersee1a53c2003-02-02 02:57:53 +0000383 for proto in protocols:
384 for u in endcases:
385 p = self.dumps(u, proto)
386 u2 = self.loads(p)
387 self.assertEqual(u2, u)
Tim Peterse089c682001-04-10 03:41:41 +0000388
Jeremy Hylton66426532001-10-15 21:38:56 +0000389 def test_ints(self):
390 import sys
Tim Petersee1a53c2003-02-02 02:57:53 +0000391 for proto in protocols:
392 n = sys.maxint
393 while n:
394 for expected in (-n, n):
395 s = self.dumps(expected, proto)
396 n2 = self.loads(s)
397 self.assertEqual(expected, n2)
398 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +0000399
Jeremy Hylton66426532001-10-15 21:38:56 +0000400 def test_maxint64(self):
401 maxint64 = (1L << 63) - 1
402 data = 'I' + str(maxint64) + '\n.'
403 got = self.loads(data)
404 self.assertEqual(got, maxint64)
405
406 # Try too with a bogus literal.
407 data = 'I' + str(maxint64) + 'JUNK\n.'
408 self.assertRaises(ValueError, self.loads, data)
409
Tim Petersee1a53c2003-02-02 02:57:53 +0000410 def test_long(self):
411 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +0000412 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +0000413 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
414 nbase = 1L << nbits
415 for npos in nbase-1, nbase, nbase+1:
416 for n in npos, -npos:
417 pickle = self.dumps(n, proto)
418 got = self.loads(pickle)
419 self.assertEqual(n, got)
420 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
421 # bother with those.
Tim Petersee1a53c2003-02-02 02:57:53 +0000422 nbase = long("deadbeeffeedface", 16)
423 nbase += nbase << 1000000
424 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +0000425 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000426 got = self.loads(p)
Tim Petersee1a53c2003-02-02 02:57:53 +0000427 self.assertEqual(n, got)
428
Jeremy Hylton66426532001-10-15 21:38:56 +0000429 def test_reduce(self):
Tim Peters19ef62d2001-08-28 22:21:18 +0000430 pass
Jeremy Hylton66426532001-10-15 21:38:56 +0000431
432 def test_getinitargs(self):
433 pass
434
Guido van Rossum04a86612001-12-19 16:58:54 +0000435 def test_metaclass(self):
436 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +0000437 for proto in protocols:
438 s = self.dumps(a, proto)
439 b = self.loads(s)
440 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +0000441
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000442 def test_structseq(self):
443 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +0000444 import os
Tim Peters70b02d72003-02-02 17:26:40 +0000445
446 t = time.localtime()
447 for proto in protocols:
448 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +0000449 u = self.loads(s)
450 self.assertEqual(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000451 if hasattr(os, "stat"):
452 t = os.stat(os.curdir)
453 s = self.dumps(t, proto)
454 u = self.loads(s)
455 self.assertEqual(t, u)
456 if hasattr(os, "statvfs"):
457 t = os.statvfs(os.curdir)
458 s = self.dumps(t, proto)
459 u = self.loads(s)
460 self.assertEqual(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000461
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000462 # Tests for protocol 2
463
Tim Peters4190fb82003-02-02 16:09:05 +0000464 def test_proto(self):
465 build_none = pickle.NONE + pickle.STOP
466 for proto in protocols:
467 expected = build_none
468 if proto >= 2:
469 expected = pickle.PROTO + chr(proto) + expected
470 p = self.dumps(None, proto)
471 self.assertEqual(p, expected)
472
473 oob = protocols[-1] + 1 # a future protocol
474 badpickle = pickle.PROTO + chr(oob) + build_none
475 try:
476 self.loads(badpickle)
477 except ValueError, detail:
478 self.failUnless(str(detail).startswith(
479 "unsupported pickle protocol"))
480 else:
481 self.fail("expected bad protocol number to raise ValueError")
482
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000483 def test_long1(self):
484 x = 12345678910111213141516178920L
Tim Peters61bf2572003-02-03 21:31:22 +0000485 for proto in protocols:
486 s = self.dumps(x, proto)
487 y = self.loads(s)
488 self.assertEqual(x, y)
Tim Peters22e71712003-02-03 22:27:38 +0000489 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), 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)
Tim Peters22e71712003-02-03 22:27:38 +0000497 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000498
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000499 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +0000500 # Map (proto, len(tuple)) to expected opcode.
501 expected_opcode = {(0, 0): pickle.TUPLE,
502 (0, 1): pickle.TUPLE,
503 (0, 2): pickle.TUPLE,
504 (0, 3): pickle.TUPLE,
505 (0, 4): pickle.TUPLE,
506
507 (1, 0): pickle.EMPTY_TUPLE,
508 (1, 1): pickle.TUPLE,
509 (1, 2): pickle.TUPLE,
510 (1, 3): pickle.TUPLE,
511 (1, 4): pickle.TUPLE,
512
513 (2, 0): pickle.EMPTY_TUPLE,
514 (2, 1): pickle.TUPLE1,
515 (2, 2): pickle.TUPLE2,
516 (2, 3): pickle.TUPLE3,
517 (2, 4): pickle.TUPLE,
518 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000519 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +0000520 b = (1,)
521 c = (1, 2)
522 d = (1, 2, 3)
523 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +0000524 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000525 for x in a, b, c, d, e:
526 s = self.dumps(x, proto)
527 y = self.loads(s)
528 self.assertEqual(x, y, (proto, x, s, y))
Tim Peters1d63c9f2003-02-02 20:29:39 +0000529 expected = expected_opcode[proto, len(x)]
Tim Peters22e71712003-02-03 22:27:38 +0000530 self.assertEqual(opcode_in_pickle(expected, s), True)
Tim Peters1d63c9f2003-02-02 20:29:39 +0000531
Guido van Rossum7d97d312003-01-28 04:25:27 +0000532 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +0000533 # Map (proto, singleton) to expected opcode.
534 expected_opcode = {(0, None): pickle.NONE,
535 (1, None): pickle.NONE,
536 (2, None): pickle.NONE,
537
538 (0, True): pickle.INT,
539 (1, True): pickle.INT,
540 (2, True): pickle.NEWTRUE,
541
542 (0, False): pickle.INT,
543 (1, False): pickle.INT,
544 (2, False): pickle.NEWFALSE,
545 }
Tim Peters4190fb82003-02-02 16:09:05 +0000546 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +0000547 for x in None, False, True:
548 s = self.dumps(x, proto)
549 y = self.loads(s)
550 self.assert_(x is y, (proto, x, s, y))
Tim Peters61bf2572003-02-03 21:31:22 +0000551 expected = expected_opcode[proto, x]
Tim Peters22e71712003-02-03 22:27:38 +0000552 self.assertEqual(opcode_in_pickle(expected, s), True)
Tim Peters3c67d792003-02-02 17:59:11 +0000553
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000554 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000555 x = MyTuple([1, 2, 3])
556 x.foo = 42
557 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000558 s = self.dumps(x, 2)
559 y = self.loads(s)
560 self.assertEqual(tuple(x), tuple(y))
561 self.assertEqual(x.__dict__, y.__dict__)
562
563 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000564 x = MyList([1, 2, 3])
565 x.foo = 42
566 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000567 s = self.dumps(x, 2)
568 y = self.loads(s)
569 self.assertEqual(list(x), list(y))
570 self.assertEqual(x.__dict__, y.__dict__)
571
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000572 def test_newobj_generic(self):
573 for proto in [0, 1, 2]:
574 for C in myclasses:
575 B = C.__base__
576 x = C(C.sample)
577 x.foo = 42
578 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000579 y = self.loads(s)
580 detail = (proto, C, B, x, y, type(y))
581 self.assertEqual(B(x), B(y), detail)
582 self.assertEqual(x.__dict__, y.__dict__, detail)
583
Tim Peters47a6b132003-01-28 22:34:11 +0000584# XXX Temporary hack, so long as the C implementation of pickle protocol
585# XXX 2 isn't ready. When it is, move the methods in TempAbstractPickleTests
586# XXX into AbstractPickleTests above, and get rid of TempAbstractPickleTests
587# XXX along with the references to it in test_pickle.py.
588class TempAbstractPickleTests(unittest.TestCase):
589
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000590 def test_newobj_list_slots(self):
591 x = SlotList([1, 2, 3])
592 x.foo = 42
593 x.bar = "hello"
594 s = self.dumps(x, 2)
595 y = self.loads(s)
596 self.assertEqual(list(x), list(y))
597 self.assertEqual(x.__dict__, y.__dict__)
598 self.assertEqual(x.foo, y.foo)
599 self.assertEqual(x.bar, y.bar)
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000600
Tim Peters22e71712003-02-03 22:27:38 +0000601 # Register a type with copy_reg, with extension code extcode. Pickle
602 # an object of that type. Check that the resulting pickle uses opcode
603 # (EXT[124]) under proto 2, and not in proto 1.
604 def produce_global_ext(self, extcode, opcode):
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000605 import copy_reg
Tim Peters22e71712003-02-03 22:27:38 +0000606 copy_reg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000607 try:
608 x = MyList([1, 2, 3])
609 x.foo = 42
610 x.bar = "hello"
611
Tim Peters22e71712003-02-03 22:27:38 +0000612 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000613 s1 = self.dumps(x, 1)
614 y = self.loads(s1)
615 self.assertEqual(list(x), list(y))
616 self.assertEqual(x.__dict__, y.__dict__)
617 self.assert_(s1.find(__name__) >= 0)
618 self.assert_(s1.find("MyList") >= 0)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000619
Tim Peters22e71712003-02-03 22:27:38 +0000620 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000621 s2 = self.dumps(x, 2)
622 self.assertEqual(s2.find(__name__), -1)
623 self.assertEqual(s2.find("MyList"), -1)
624 y = self.loads(s2)
625 self.assertEqual(list(x), list(y))
626 self.assertEqual(x.__dict__, y.__dict__)
Tim Peters22e71712003-02-03 22:27:38 +0000627 self.assertEqual(opcode_in_pickle(opcode, s2), True)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000628
629 finally:
Tim Peters22e71712003-02-03 22:27:38 +0000630 copy_reg.remove_extension(__name__, "MyList", extcode)
631
632 def test_global_ext1(self):
633 self.produce_global_ext(0xf0, pickle.EXT1)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000634
635 def test_global_ext2(self):
Tim Peters22e71712003-02-03 22:27:38 +0000636 self.produce_global_ext(0xfff0, pickle.EXT2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000637
638 def test_global_ext4(self):
Tim Peters22e71712003-02-03 22:27:38 +0000639 self.produce_global_ext(0xffffff0, pickle.EXT4)
640
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000641
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000642class MyInt(int):
643 sample = 1
644
645class MyLong(long):
646 sample = 1L
647
648class MyFloat(float):
649 sample = 1.0
650
651class MyComplex(complex):
652 sample = 1.0 + 0.0j
653
654class MyStr(str):
655 sample = "hello"
656
657class MyUnicode(unicode):
658 sample = u"hello \u1234"
659
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000660class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000661 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000662
663class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000664 sample = [1, 2, 3]
665
666class MyDict(dict):
667 sample = {"a": 1, "b": 2}
668
669myclasses = [MyInt, MyLong, MyFloat,
670 # MyComplex, # XXX complex somehow doesn't work here :-(
671 MyStr, MyUnicode,
672 MyTuple, MyList, MyDict]
673
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000674
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000675class SlotList(MyList):
676 __slots__ = ["foo"]
677
Jeremy Hylton66426532001-10-15 21:38:56 +0000678class AbstractPickleModuleTests(unittest.TestCase):
679
680 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000681 import os
682 f = open(TESTFN, "w")
683 try:
684 f.close()
685 self.assertRaises(ValueError, self.module.dump, 123, f)
686 finally:
687 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +0000688
689 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000690 import os
691 f = open(TESTFN, "w")
692 try:
693 f.close()
694 self.assertRaises(ValueError, self.module.dump, 123, f)
695 finally:
696 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +0000697
698class AbstractPersistentPicklerTests(unittest.TestCase):
699
700 # This class defines persistent_id() and persistent_load()
701 # functions that should be used by the pickler. All even integers
702 # are pickled using persistent ids.
703
704 def persistent_id(self, object):
705 if isinstance(object, int) and object % 2 == 0:
706 self.id_count += 1
707 return str(object)
708 else:
709 return None
710
711 def persistent_load(self, oid):
712 self.load_count += 1
713 object = int(oid)
714 assert object % 2 == 0
715 return object
716
717 def test_persistence(self):
718 self.id_count = 0
719 self.load_count = 0
720 L = range(10)
721 self.assertEqual(self.loads(self.dumps(L)), L)
722 self.assertEqual(self.id_count, 5)
723 self.assertEqual(self.load_count, 5)
724
725 def test_bin_persistence(self):
726 self.id_count = 0
727 self.load_count = 0
728 L = range(10)
729 self.assertEqual(self.loads(self.dumps(L, 1)), L)
730 self.assertEqual(self.id_count, 5)
731 self.assertEqual(self.load_count, 5)