blob: 33b96e54ef187243cacffb850b04c50740488a5c [file] [log] [blame]
Jeremy Hylton66426532001-10-15 21:38:56 +00001import unittest
Guido van Rossum3b0a3292002-08-09 16:38:32 +00002from test.test_support import TestFailed, have_unicode, TESTFN
Tim Peterse089c682001-04-10 03:41:41 +00003
Jeremy Hylton66426532001-10-15 21:38:56 +00004class C:
5 def __cmp__(self, other):
6 return cmp(self.__dict__, other.__dict__)
7
8import __main__
9__main__.C = C
10C.__module__ = "__main__"
11
12class myint(int):
13 def __init__(self, x):
14 self.str = str(x)
15
16class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +000017
18 __safe_for_unpickling__ = 1
19
Jeremy Hylton66426532001-10-15 21:38:56 +000020 def __init__(self, a, b):
21 self.a = a
22 self.b = b
23
24 def __getinitargs__(self):
25 return self.a, self.b
26
Guido van Rossum04a86612001-12-19 16:58:54 +000027class metaclass(type):
28 pass
29
30class use_metaclass(object):
31 __metaclass__ = metaclass
32
Jeremy Hylton66426532001-10-15 21:38:56 +000033# break into multiple strings to avoid confusing font-lock-mode
Tim Peters461922a2001-04-09 20:07:05 +000034DATA = """(lp1
Tim Peterse9358162001-01-22 22:05:20 +000035I0
36aL1L
Tim Peters461922a2001-04-09 20:07:05 +000037aF2
Tim Peterse9358162001-01-22 22:05:20 +000038ac__builtin__
39complex
Tim Peters461922a2001-04-09 20:07:05 +000040p2
41""" + \
42"""(F3
43F0
44tRp3
45aI1
46aI-1
47aI255
48aI-255
49aI-256
50aI65535
51aI-65535
52aI-65536
53aI2147483647
54aI-2147483647
55aI-2147483648
56a""" + \
57"""(S'abc'
Tim Peterse9358162001-01-22 22:05:20 +000058p4
59g4
Tim Peters461922a2001-04-09 20:07:05 +000060""" + \
Guido van Rossum42f92da2001-04-16 00:28:21 +000061"""(i__main__
Tim Peterse9358162001-01-22 22:05:20 +000062C
63p5
Tim Peters461922a2001-04-09 20:07:05 +000064""" + \
Tim Peterse9358162001-01-22 22:05:20 +000065"""(dp6
66S'foo'
67p7
68I1
69sS'bar'
70p8
71I2
72sbg5
73tp9
74ag9
75aI5
76a.
77"""
78
Tim Peters461922a2001-04-09 20:07:05 +000079BINDATA = ']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00' + \
80 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00' + \
81 '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff' + \
82 '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff' + \
83 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00' + \
Guido van Rossum42f92da2001-04-16 00:28:21 +000084 '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n' + \
Tim Peters461922a2001-04-09 20:07:05 +000085 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh' + \
86 '\x06tq\nh\nK\x05e.'
Tim Peterse0c446b2001-10-18 21:57:37 +000087
Jeremy Hylton66426532001-10-15 21:38:56 +000088def create_data():
Tim Peterse9358162001-01-22 22:05:20 +000089 c = C()
90 c.foo = 1
91 c.bar = 2
92 x = [0, 1L, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +000093 # Append some integer test cases at cPickle.c's internal size
94 # cutoffs.
95 uint1max = 0xff
96 uint2max = 0xffff
97 int4max = 0x7fffffff
98 x.extend([1, -1,
99 uint1max, -uint1max, -uint1max-1,
100 uint2max, -uint2max, -uint2max-1,
101 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000102 y = ('abc', 'abc', c, c)
103 x.append(y)
104 x.append(y)
105 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000106 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000107
Jeremy Hylton66426532001-10-15 21:38:56 +0000108class AbstractPickleTests(unittest.TestCase):
Tim Petersc58440f2001-04-09 17:16:31 +0000109
Jeremy Hylton66426532001-10-15 21:38:56 +0000110 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000111
Jeremy Hylton66426532001-10-15 21:38:56 +0000112 def setUp(self):
113 # subclass must define self.dumps, self.loads, self.error
Tim Peterse9358162001-01-22 22:05:20 +0000114 pass
Tim Petersc58440f2001-04-09 17:16:31 +0000115
Jeremy Hylton66426532001-10-15 21:38:56 +0000116 def test_misc(self):
117 # test various datatypes not tested by testdata
118 x = myint(4)
119 s = self.dumps(x)
120 y = self.loads(s)
121 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000122
Jeremy Hylton66426532001-10-15 21:38:56 +0000123 x = (1, ())
124 s = self.dumps(x)
125 y = self.loads(s)
126 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000127
Jeremy Hylton66426532001-10-15 21:38:56 +0000128 x = initarg(1, x)
129 s = self.dumps(x)
130 y = self.loads(s)
131 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000132
Jeremy Hylton66426532001-10-15 21:38:56 +0000133 # XXX test __reduce__ protocol?
134
135 def test_identity(self):
136 s = self.dumps(self._testdata)
137 x = self.loads(s)
138 self.assertEqual(x, self._testdata)
139
140 def test_constant(self):
141 x = self.loads(DATA)
142 self.assertEqual(x, self._testdata)
143 x = self.loads(BINDATA)
144 self.assertEqual(x, self._testdata)
145
146 def test_binary(self):
147 s = self.dumps(self._testdata, 1)
148 x = self.loads(s)
149 self.assertEqual(x, self._testdata)
150
151 def test_recursive_list(self):
152 l = []
153 l.append(l)
154 s = self.dumps(l)
155 x = self.loads(s)
156 self.assertEqual(x, l)
157 self.assertEqual(x, x[0])
158 self.assertEqual(id(x), id(x[0]))
159
160 def test_recursive_dict(self):
161 d = {}
162 d[1] = d
163 s = self.dumps(d)
164 x = self.loads(s)
165 self.assertEqual(x, d)
166 self.assertEqual(x[1], x)
167 self.assertEqual(id(x[1]), id(x))
168
169 def test_recursive_inst(self):
170 i = C()
171 i.attr = i
172 s = self.dumps(i)
173 x = self.loads(s)
174 self.assertEqual(x, i)
175 self.assertEqual(x.attr, x)
176 self.assertEqual(id(x.attr), id(x))
177
178 def test_recursive_multi(self):
179 l = []
180 d = {1:l}
181 i = C()
182 i.attr = d
183 l.append(i)
184 s = self.dumps(l)
185 x = self.loads(s)
186 self.assertEqual(x, l)
187 self.assertEqual(x[0], i)
188 self.assertEqual(x[0].attr, d)
189 self.assertEqual(x[0].attr[1], x)
190 self.assertEqual(x[0].attr[1][0], i)
191 self.assertEqual(x[0].attr[1][0].attr, d)
192
193 def test_garyp(self):
194 self.assertRaises(self.error, self.loads, 'garyp')
195
196 def test_insecure_strings(self):
197 insecure = ["abc", "2 + 2", # not quoted
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000198 #"'abc' + 'def'", # not a single quoted string
Jeremy Hylton66426532001-10-15 21:38:56 +0000199 "'abc", # quote is not closed
200 "'abc\"", # open quote and close quote don't match
201 "'abc' ?", # junk after close quote
Martin v. Löwiseb3f00a2002-08-14 08:22:50 +0000202 "'\\'", # trailing backslash
Jeremy Hylton66426532001-10-15 21:38:56 +0000203 # some tests of the quoting rules
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000204 #"'abc\"\''",
205 #"'\\\\a\'\'\'\\\'\\\\\''",
Jeremy Hylton66426532001-10-15 21:38:56 +0000206 ]
207 for s in insecure:
208 buf = "S" + s + "\012p0\012."
209 self.assertRaises(ValueError, self.loads, buf)
210
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000211 if have_unicode:
Jeremy Hylton66426532001-10-15 21:38:56 +0000212 def test_unicode(self):
213 endcases = [unicode(''), unicode('<\\u>'), unicode('<\\\u1234>'),
214 unicode('<\n>'), unicode('<\\>')]
215 for u in endcases:
216 p = self.dumps(u)
217 u2 = self.loads(p)
218 self.assertEqual(u2, u)
Tim Peterse089c682001-04-10 03:41:41 +0000219
Jeremy Hylton66426532001-10-15 21:38:56 +0000220 def test_ints(self):
221 import sys
222 n = sys.maxint
223 while n:
224 for expected in (-n, n):
225 s = self.dumps(expected)
226 n2 = self.loads(s)
227 self.assertEqual(expected, n2)
228 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +0000229
Jeremy Hylton66426532001-10-15 21:38:56 +0000230 def test_maxint64(self):
231 maxint64 = (1L << 63) - 1
232 data = 'I' + str(maxint64) + '\n.'
233 got = self.loads(data)
234 self.assertEqual(got, maxint64)
235
236 # Try too with a bogus literal.
237 data = 'I' + str(maxint64) + 'JUNK\n.'
238 self.assertRaises(ValueError, self.loads, data)
239
240 def test_reduce(self):
Tim Peters19ef62d2001-08-28 22:21:18 +0000241 pass
Jeremy Hylton66426532001-10-15 21:38:56 +0000242
243 def test_getinitargs(self):
244 pass
245
Guido van Rossum04a86612001-12-19 16:58:54 +0000246 def test_metaclass(self):
247 a = use_metaclass()
248 s = self.dumps(a)
249 b = self.loads(s)
250 self.assertEqual(a.__class__, b.__class__)
251
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000252 def test_structseq(self):
253 import time
254 t = time.localtime()
255 s = self.dumps(t)
256 u = self.loads(s)
Tim Peters863ac442002-04-16 01:38:40 +0000257 self.assertEqual(t, u)
Michael W. Hudson0e025302002-03-06 17:11:18 +0000258 import os
259 if hasattr(os, "stat"):
260 t = os.stat(os.curdir)
261 s = self.dumps(t)
262 u = self.loads(s)
263 self.assertEqual(t, u)
264 if hasattr(os, "statvfs"):
265 t = os.statvfs(os.curdir)
266 s = self.dumps(t)
267 u = self.loads(s)
268 self.assertEqual(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000269
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000270 # Tests for protocol 2
271
272 def test_long1(self):
273 x = 12345678910111213141516178920L
274 s = self.dumps(x, 2)
275 y = self.loads(s)
276 self.assertEqual(x, y)
277
278 def test_long4(self):
279 x = 12345678910111213141516178920L << (256*8)
280 s = self.dumps(x, 2)
281 y = self.loads(s)
282 self.assertEqual(x, y)
283
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000284 def test_short_tuples(self):
285 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +0000286 b = (1,)
287 c = (1, 2)
288 d = (1, 2, 3)
289 e = (1, 2, 3, 4)
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000290 for proto in 0, 1, 2:
291 for x in a, b, c, d, e:
292 s = self.dumps(x, proto)
293 y = self.loads(s)
294 self.assertEqual(x, y, (proto, x, s, y))
295
Guido van Rossum7d97d312003-01-28 04:25:27 +0000296 def test_singletons(self):
297 for proto in 0, 1, 2:
298 for x in None, False, True:
299 s = self.dumps(x, proto)
300 y = self.loads(s)
301 self.assert_(x is y, (proto, x, s, y))
302
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000303 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000304 x = MyTuple([1, 2, 3])
305 x.foo = 42
306 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000307 s = self.dumps(x, 2)
308 y = self.loads(s)
309 self.assertEqual(tuple(x), tuple(y))
310 self.assertEqual(x.__dict__, y.__dict__)
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000311## import pickletools
312## print
313## pickletools.dis(s)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000314
315 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000316 x = MyList([1, 2, 3])
317 x.foo = 42
318 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000319 s = self.dumps(x, 2)
320 y = self.loads(s)
321 self.assertEqual(list(x), list(y))
322 self.assertEqual(x.__dict__, y.__dict__)
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000323## import pickletools
324## print
325## pickletools.dis(s)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000326
Tim Peters47a6b132003-01-28 22:34:11 +0000327# XXX Temporary hack, so long as the C implementation of pickle protocol
328# XXX 2 isn't ready. When it is, move the methods in TempAbstractPickleTests
329# XXX into AbstractPickleTests above, and get rid of TempAbstractPickleTests
330# XXX along with the references to it in test_pickle.py.
331class TempAbstractPickleTests(unittest.TestCase):
332
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000333 def test_newobj_list_slots(self):
334 x = SlotList([1, 2, 3])
335 x.foo = 42
336 x.bar = "hello"
337 s = self.dumps(x, 2)
338 y = self.loads(s)
339 self.assertEqual(list(x), list(y))
340 self.assertEqual(x.__dict__, y.__dict__)
341 self.assertEqual(x.foo, y.foo)
342 self.assertEqual(x.bar, y.bar)
343## import pickletools
344## print
345## pickletools.dis(s)
346
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000347 def test_global_ext1(self):
348 import copy_reg
349 copy_reg.add_extension(__name__, "MyList", 0xf0)
350 try:
351 x = MyList([1, 2, 3])
352 x.foo = 42
353 x.bar = "hello"
354
355 # Dump using protocol 1 for comparison
356 s1 = self.dumps(x, 1)
357 y = self.loads(s1)
358 self.assertEqual(list(x), list(y))
359 self.assertEqual(x.__dict__, y.__dict__)
360 self.assert_(s1.find(__name__) >= 0)
361 self.assert_(s1.find("MyList") >= 0)
362## import pickletools
363## print
364## pickletools.dis(s1)
365
366 # Dump using protocol 2 for test
367 s2 = self.dumps(x, 2)
368 self.assertEqual(s2.find(__name__), -1)
369 self.assertEqual(s2.find("MyList"), -1)
370 y = self.loads(s2)
371 self.assertEqual(list(x), list(y))
372 self.assertEqual(x.__dict__, y.__dict__)
373## import pickletools
374## print
375## pickletools.dis(s2)
376
377 finally:
378 copy_reg.remove_extension(__name__, "MyList", 0xf0)
379
380 def test_global_ext2(self):
381 import copy_reg
382 copy_reg.add_extension(__name__, "MyList", 0xfff0)
383 try:
384 x = MyList()
385 s2 = self.dumps(x, 2)
386 self.assertEqual(s2.find(__name__), -1)
387 self.assertEqual(s2.find("MyList"), -1)
388 y = self.loads(s2)
389 self.assertEqual(list(x), list(y))
390 self.assertEqual(x.__dict__, y.__dict__)
391 finally:
392 copy_reg.remove_extension(__name__, "MyList", 0xfff0)
393
394 def test_global_ext4(self):
395 import copy_reg
396 copy_reg.add_extension(__name__, "MyList", 0xfffff0)
397 try:
398 x = MyList()
399 s2 = self.dumps(x, 2)
400 self.assertEqual(s2.find(__name__), -1)
401 self.assertEqual(s2.find("MyList"), -1)
402 y = self.loads(s2)
403 self.assertEqual(list(x), list(y))
404 self.assertEqual(x.__dict__, y.__dict__)
405 finally:
406 copy_reg.remove_extension(__name__, "MyList", 0xfffff0)
407
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000408class MyTuple(tuple):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000409 pass
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000410
411class MyList(list):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000412 pass
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000413
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000414class SlotList(MyList):
415 __slots__ = ["foo"]
416
Jeremy Hylton66426532001-10-15 21:38:56 +0000417class AbstractPickleModuleTests(unittest.TestCase):
418
419 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000420 import os
421 f = open(TESTFN, "w")
422 try:
423 f.close()
424 self.assertRaises(ValueError, self.module.dump, 123, f)
425 finally:
426 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +0000427
428 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000429 import os
430 f = open(TESTFN, "w")
431 try:
432 f.close()
433 self.assertRaises(ValueError, self.module.dump, 123, f)
434 finally:
435 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +0000436
437class AbstractPersistentPicklerTests(unittest.TestCase):
438
439 # This class defines persistent_id() and persistent_load()
440 # functions that should be used by the pickler. All even integers
441 # are pickled using persistent ids.
442
443 def persistent_id(self, object):
444 if isinstance(object, int) and object % 2 == 0:
445 self.id_count += 1
446 return str(object)
447 else:
448 return None
449
450 def persistent_load(self, oid):
451 self.load_count += 1
452 object = int(oid)
453 assert object % 2 == 0
454 return object
455
456 def test_persistence(self):
457 self.id_count = 0
458 self.load_count = 0
459 L = range(10)
460 self.assertEqual(self.loads(self.dumps(L)), L)
461 self.assertEqual(self.id_count, 5)
462 self.assertEqual(self.load_count, 5)
463
464 def test_bin_persistence(self):
465 self.id_count = 0
466 self.load_count = 0
467 L = range(10)
468 self.assertEqual(self.loads(self.dumps(L, 1)), L)
469 self.assertEqual(self.id_count, 5)
470 self.assertEqual(self.load_count, 5)