blob: 8211dcf58cf3ee395d0822d5205618d6fee1f894 [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
Jeremy Hylton66426532001-10-15 21:38:56 +000018 def __init__(self, a, b):
19 self.a = a
20 self.b = b
21
22 def __getinitargs__(self):
23 return self.a, self.b
24
Guido van Rossum04a86612001-12-19 16:58:54 +000025class metaclass(type):
26 pass
27
28class use_metaclass(object):
29 __metaclass__ = metaclass
30
Jeremy Hylton66426532001-10-15 21:38:56 +000031# break into multiple strings to avoid confusing font-lock-mode
Tim Peters461922a2001-04-09 20:07:05 +000032DATA = """(lp1
Tim Peterse9358162001-01-22 22:05:20 +000033I0
34aL1L
Tim Peters461922a2001-04-09 20:07:05 +000035aF2
Tim Peterse9358162001-01-22 22:05:20 +000036ac__builtin__
37complex
Tim Peters461922a2001-04-09 20:07:05 +000038p2
39""" + \
40"""(F3
41F0
42tRp3
43aI1
44aI-1
45aI255
46aI-255
47aI-256
48aI65535
49aI-65535
50aI-65536
51aI2147483647
52aI-2147483647
53aI-2147483648
54a""" + \
55"""(S'abc'
Tim Peterse9358162001-01-22 22:05:20 +000056p4
57g4
Tim Peters461922a2001-04-09 20:07:05 +000058""" + \
Guido van Rossum42f92da2001-04-16 00:28:21 +000059"""(i__main__
Tim Peterse9358162001-01-22 22:05:20 +000060C
61p5
Tim Peters461922a2001-04-09 20:07:05 +000062""" + \
Tim Peterse9358162001-01-22 22:05:20 +000063"""(dp6
64S'foo'
65p7
66I1
67sS'bar'
68p8
69I2
70sbg5
71tp9
72ag9
73aI5
74a.
75"""
76
Tim Peters461922a2001-04-09 20:07:05 +000077BINDATA = ']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00' + \
78 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00' + \
79 '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff' + \
80 '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff' + \
81 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00' + \
Guido van Rossum42f92da2001-04-16 00:28:21 +000082 '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n' + \
Tim Peters461922a2001-04-09 20:07:05 +000083 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh' + \
84 '\x06tq\nh\nK\x05e.'
Tim Peterse0c446b2001-10-18 21:57:37 +000085
Jeremy Hylton66426532001-10-15 21:38:56 +000086def create_data():
Tim Peterse9358162001-01-22 22:05:20 +000087 c = C()
88 c.foo = 1
89 c.bar = 2
90 x = [0, 1L, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +000091 # Append some integer test cases at cPickle.c's internal size
92 # cutoffs.
93 uint1max = 0xff
94 uint2max = 0xffff
95 int4max = 0x7fffffff
96 x.extend([1, -1,
97 uint1max, -uint1max, -uint1max-1,
98 uint2max, -uint2max, -uint2max-1,
99 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000100 y = ('abc', 'abc', c, c)
101 x.append(y)
102 x.append(y)
103 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000104 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000105
Jeremy Hylton66426532001-10-15 21:38:56 +0000106class AbstractPickleTests(unittest.TestCase):
Tim Petersc58440f2001-04-09 17:16:31 +0000107
Jeremy Hylton66426532001-10-15 21:38:56 +0000108 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000109
Jeremy Hylton66426532001-10-15 21:38:56 +0000110 def setUp(self):
111 # subclass must define self.dumps, self.loads, self.error
Tim Peterse9358162001-01-22 22:05:20 +0000112 pass
Tim Petersc58440f2001-04-09 17:16:31 +0000113
Jeremy Hylton66426532001-10-15 21:38:56 +0000114 def test_misc(self):
115 # test various datatypes not tested by testdata
116 x = myint(4)
117 s = self.dumps(x)
118 y = self.loads(s)
119 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000120
Jeremy Hylton66426532001-10-15 21:38:56 +0000121 x = (1, ())
122 s = self.dumps(x)
123 y = self.loads(s)
124 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000125
Jeremy Hylton66426532001-10-15 21:38:56 +0000126 x = initarg(1, x)
127 s = self.dumps(x)
128 y = self.loads(s)
129 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000130
Jeremy Hylton66426532001-10-15 21:38:56 +0000131 # XXX test __reduce__ protocol?
132
133 def test_identity(self):
134 s = self.dumps(self._testdata)
135 x = self.loads(s)
136 self.assertEqual(x, self._testdata)
137
138 def test_constant(self):
139 x = self.loads(DATA)
140 self.assertEqual(x, self._testdata)
141 x = self.loads(BINDATA)
142 self.assertEqual(x, self._testdata)
143
144 def test_binary(self):
145 s = self.dumps(self._testdata, 1)
146 x = self.loads(s)
147 self.assertEqual(x, self._testdata)
148
149 def test_recursive_list(self):
150 l = []
151 l.append(l)
152 s = self.dumps(l)
153 x = self.loads(s)
154 self.assertEqual(x, l)
155 self.assertEqual(x, x[0])
156 self.assertEqual(id(x), id(x[0]))
157
158 def test_recursive_dict(self):
159 d = {}
160 d[1] = d
161 s = self.dumps(d)
162 x = self.loads(s)
163 self.assertEqual(x, d)
164 self.assertEqual(x[1], x)
165 self.assertEqual(id(x[1]), id(x))
166
167 def test_recursive_inst(self):
168 i = C()
169 i.attr = i
170 s = self.dumps(i)
171 x = self.loads(s)
172 self.assertEqual(x, i)
173 self.assertEqual(x.attr, x)
174 self.assertEqual(id(x.attr), id(x))
175
176 def test_recursive_multi(self):
177 l = []
178 d = {1:l}
179 i = C()
180 i.attr = d
181 l.append(i)
182 s = self.dumps(l)
183 x = self.loads(s)
184 self.assertEqual(x, l)
185 self.assertEqual(x[0], i)
186 self.assertEqual(x[0].attr, d)
187 self.assertEqual(x[0].attr[1], x)
188 self.assertEqual(x[0].attr[1][0], i)
189 self.assertEqual(x[0].attr[1][0].attr, d)
190
191 def test_garyp(self):
192 self.assertRaises(self.error, self.loads, 'garyp')
193
194 def test_insecure_strings(self):
195 insecure = ["abc", "2 + 2", # not quoted
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000196 #"'abc' + 'def'", # not a single quoted string
Jeremy Hylton66426532001-10-15 21:38:56 +0000197 "'abc", # quote is not closed
198 "'abc\"", # open quote and close quote don't match
199 "'abc' ?", # junk after close quote
Martin v. Löwiseb3f00a2002-08-14 08:22:50 +0000200 "'\\'", # trailing backslash
Jeremy Hylton66426532001-10-15 21:38:56 +0000201 # some tests of the quoting rules
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000202 #"'abc\"\''",
203 #"'\\\\a\'\'\'\\\'\\\\\''",
Jeremy Hylton66426532001-10-15 21:38:56 +0000204 ]
205 for s in insecure:
206 buf = "S" + s + "\012p0\012."
207 self.assertRaises(ValueError, self.loads, buf)
208
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000209 if have_unicode:
Jeremy Hylton66426532001-10-15 21:38:56 +0000210 def test_unicode(self):
211 endcases = [unicode(''), unicode('<\\u>'), unicode('<\\\u1234>'),
212 unicode('<\n>'), unicode('<\\>')]
213 for u in endcases:
214 p = self.dumps(u)
215 u2 = self.loads(p)
216 self.assertEqual(u2, u)
Tim Peterse089c682001-04-10 03:41:41 +0000217
Jeremy Hylton66426532001-10-15 21:38:56 +0000218 def test_ints(self):
219 import sys
220 n = sys.maxint
221 while n:
222 for expected in (-n, n):
223 s = self.dumps(expected)
224 n2 = self.loads(s)
225 self.assertEqual(expected, n2)
226 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +0000227
Jeremy Hylton66426532001-10-15 21:38:56 +0000228 def test_maxint64(self):
229 maxint64 = (1L << 63) - 1
230 data = 'I' + str(maxint64) + '\n.'
231 got = self.loads(data)
232 self.assertEqual(got, maxint64)
233
234 # Try too with a bogus literal.
235 data = 'I' + str(maxint64) + 'JUNK\n.'
236 self.assertRaises(ValueError, self.loads, data)
237
238 def test_reduce(self):
Tim Peters19ef62d2001-08-28 22:21:18 +0000239 pass
Jeremy Hylton66426532001-10-15 21:38:56 +0000240
241 def test_getinitargs(self):
242 pass
243
Guido van Rossum04a86612001-12-19 16:58:54 +0000244 def test_metaclass(self):
245 a = use_metaclass()
246 s = self.dumps(a)
247 b = self.loads(s)
248 self.assertEqual(a.__class__, b.__class__)
249
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000250 def test_structseq(self):
251 import time
252 t = time.localtime()
253 s = self.dumps(t)
254 u = self.loads(s)
Tim Peters863ac442002-04-16 01:38:40 +0000255 self.assertEqual(t, u)
Michael W. Hudson0e025302002-03-06 17:11:18 +0000256 import os
257 if hasattr(os, "stat"):
258 t = os.stat(os.curdir)
259 s = self.dumps(t)
260 u = self.loads(s)
261 self.assertEqual(t, u)
262 if hasattr(os, "statvfs"):
263 t = os.statvfs(os.curdir)
264 s = self.dumps(t)
265 u = self.loads(s)
266 self.assertEqual(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000267
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000268 # Tests for protocol 2
269
270 def test_long1(self):
271 x = 12345678910111213141516178920L
272 s = self.dumps(x, 2)
273 y = self.loads(s)
274 self.assertEqual(x, y)
275
276 def test_long4(self):
277 x = 12345678910111213141516178920L << (256*8)
278 s = self.dumps(x, 2)
279 y = self.loads(s)
280 self.assertEqual(x, y)
281
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000282 def test_short_tuples(self):
283 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +0000284 b = (1,)
285 c = (1, 2)
286 d = (1, 2, 3)
287 e = (1, 2, 3, 4)
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000288 for proto in 0, 1, 2:
289 for x in a, b, c, d, e:
290 s = self.dumps(x, proto)
291 y = self.loads(s)
292 self.assertEqual(x, y, (proto, x, s, y))
293
Guido van Rossum7d97d312003-01-28 04:25:27 +0000294 def test_singletons(self):
295 for proto in 0, 1, 2:
296 for x in None, False, True:
297 s = self.dumps(x, proto)
298 y = self.loads(s)
299 self.assert_(x is y, (proto, x, s, y))
300
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000301 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000302 x = MyTuple([1, 2, 3])
303 x.foo = 42
304 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000305 s = self.dumps(x, 2)
306 y = self.loads(s)
307 self.assertEqual(tuple(x), tuple(y))
308 self.assertEqual(x.__dict__, y.__dict__)
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000309## import pickletools
310## print
311## pickletools.dis(s)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000312
313 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000314 x = MyList([1, 2, 3])
315 x.foo = 42
316 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000317 s = self.dumps(x, 2)
318 y = self.loads(s)
319 self.assertEqual(list(x), list(y))
320 self.assertEqual(x.__dict__, y.__dict__)
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000321## import pickletools
322## print
323## pickletools.dis(s)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000324
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000325 def test_newobj_generic(self):
326 for proto in [0, 1, 2]:
327 for C in myclasses:
328 B = C.__base__
329 x = C(C.sample)
330 x.foo = 42
331 s = self.dumps(x, proto)
332## import pickletools
333## print
334## pickletools.dis(s)
335 y = self.loads(s)
336 detail = (proto, C, B, x, y, type(y))
337 self.assertEqual(B(x), B(y), detail)
338 self.assertEqual(x.__dict__, y.__dict__, detail)
339
Tim Peters47a6b132003-01-28 22:34:11 +0000340# XXX Temporary hack, so long as the C implementation of pickle protocol
341# XXX 2 isn't ready. When it is, move the methods in TempAbstractPickleTests
342# XXX into AbstractPickleTests above, and get rid of TempAbstractPickleTests
343# XXX along with the references to it in test_pickle.py.
344class TempAbstractPickleTests(unittest.TestCase):
345
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000346 def test_newobj_list_slots(self):
347 x = SlotList([1, 2, 3])
348 x.foo = 42
349 x.bar = "hello"
350 s = self.dumps(x, 2)
351 y = self.loads(s)
352 self.assertEqual(list(x), list(y))
353 self.assertEqual(x.__dict__, y.__dict__)
354 self.assertEqual(x.foo, y.foo)
355 self.assertEqual(x.bar, y.bar)
356## import pickletools
357## print
358## pickletools.dis(s)
359
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000360 def test_global_ext1(self):
361 import copy_reg
362 copy_reg.add_extension(__name__, "MyList", 0xf0)
363 try:
364 x = MyList([1, 2, 3])
365 x.foo = 42
366 x.bar = "hello"
367
368 # Dump using protocol 1 for comparison
369 s1 = self.dumps(x, 1)
370 y = self.loads(s1)
371 self.assertEqual(list(x), list(y))
372 self.assertEqual(x.__dict__, y.__dict__)
373 self.assert_(s1.find(__name__) >= 0)
374 self.assert_(s1.find("MyList") >= 0)
375## import pickletools
376## print
377## pickletools.dis(s1)
378
379 # Dump using protocol 2 for test
380 s2 = self.dumps(x, 2)
381 self.assertEqual(s2.find(__name__), -1)
382 self.assertEqual(s2.find("MyList"), -1)
383 y = self.loads(s2)
384 self.assertEqual(list(x), list(y))
385 self.assertEqual(x.__dict__, y.__dict__)
386## import pickletools
387## print
388## pickletools.dis(s2)
389
390 finally:
391 copy_reg.remove_extension(__name__, "MyList", 0xf0)
392
393 def test_global_ext2(self):
394 import copy_reg
395 copy_reg.add_extension(__name__, "MyList", 0xfff0)
396 try:
397 x = MyList()
398 s2 = self.dumps(x, 2)
399 self.assertEqual(s2.find(__name__), -1)
400 self.assertEqual(s2.find("MyList"), -1)
401 y = self.loads(s2)
402 self.assertEqual(list(x), list(y))
403 self.assertEqual(x.__dict__, y.__dict__)
404 finally:
405 copy_reg.remove_extension(__name__, "MyList", 0xfff0)
406
407 def test_global_ext4(self):
408 import copy_reg
409 copy_reg.add_extension(__name__, "MyList", 0xfffff0)
410 try:
411 x = MyList()
412 s2 = self.dumps(x, 2)
413 self.assertEqual(s2.find(__name__), -1)
414 self.assertEqual(s2.find("MyList"), -1)
415 y = self.loads(s2)
416 self.assertEqual(list(x), list(y))
417 self.assertEqual(x.__dict__, y.__dict__)
418 finally:
419 copy_reg.remove_extension(__name__, "MyList", 0xfffff0)
420
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000421class MyInt(int):
422 sample = 1
423
424class MyLong(long):
425 sample = 1L
426
427class MyFloat(float):
428 sample = 1.0
429
430class MyComplex(complex):
431 sample = 1.0 + 0.0j
432
433class MyStr(str):
434 sample = "hello"
435
436class MyUnicode(unicode):
437 sample = u"hello \u1234"
438
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000439class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000440 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000441
442class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000443 sample = [1, 2, 3]
444
445class MyDict(dict):
446 sample = {"a": 1, "b": 2}
447
448myclasses = [MyInt, MyLong, MyFloat,
449 # MyComplex, # XXX complex somehow doesn't work here :-(
450 MyStr, MyUnicode,
451 MyTuple, MyList, MyDict]
452
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000453
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000454class SlotList(MyList):
455 __slots__ = ["foo"]
456
Jeremy Hylton66426532001-10-15 21:38:56 +0000457class AbstractPickleModuleTests(unittest.TestCase):
458
459 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000460 import os
461 f = open(TESTFN, "w")
462 try:
463 f.close()
464 self.assertRaises(ValueError, self.module.dump, 123, f)
465 finally:
466 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +0000467
468 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000469 import os
470 f = open(TESTFN, "w")
471 try:
472 f.close()
473 self.assertRaises(ValueError, self.module.dump, 123, f)
474 finally:
475 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +0000476
477class AbstractPersistentPicklerTests(unittest.TestCase):
478
479 # This class defines persistent_id() and persistent_load()
480 # functions that should be used by the pickler. All even integers
481 # are pickled using persistent ids.
482
483 def persistent_id(self, object):
484 if isinstance(object, int) and object % 2 == 0:
485 self.id_count += 1
486 return str(object)
487 else:
488 return None
489
490 def persistent_load(self, oid):
491 self.load_count += 1
492 object = int(oid)
493 assert object % 2 == 0
494 return object
495
496 def test_persistence(self):
497 self.id_count = 0
498 self.load_count = 0
499 L = range(10)
500 self.assertEqual(self.loads(self.dumps(L)), L)
501 self.assertEqual(self.id_count, 5)
502 self.assertEqual(self.load_count, 5)
503
504 def test_bin_persistence(self):
505 self.id_count = 0
506 self.load_count = 0
507 L = range(10)
508 self.assertEqual(self.loads(self.dumps(L, 1)), L)
509 self.assertEqual(self.id_count, 5)
510 self.assertEqual(self.load_count, 5)