blob: e1a88b6b5861dd15140cd5133b11c046dd0901c6 [file] [log] [blame]
Jeremy Hyltonbe467e52000-09-15 15:14:51 +00001import pickle
Guido van Rossumcfe5f202007-05-08 21:26:54 +00002import io
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003import collections
Serhiy Storchaka5bbd2312014-12-16 19:39:08 +02004import struct
5import sys
Tim Peters47a6b132003-01-28 22:34:11 +00006
Serhiy Storchaka5bbd2312014-12-16 19:39:08 +02007import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00008from test import support
Jeremy Hylton66426532001-10-15 21:38:56 +00009
Tim Peters47a6b132003-01-28 22:34:11 +000010from test.pickletester import AbstractPickleTests
Tim Peters47a6b132003-01-28 22:34:11 +000011from test.pickletester import AbstractPickleModuleTests
12from test.pickletester import AbstractPersistentPicklerTests
Collin Winter771d8342009-04-16 03:18:06 +000013from test.pickletester import AbstractPicklerUnpicklerObjectTests
Antoine Pitrou8d3c2902012-03-04 18:31:48 +010014from test.pickletester import AbstractDispatchTableTests
Antoine Pitrou82be19f2011-08-29 23:09:33 +020015from test.pickletester import BigmemPickleTests
Tim Peters47a6b132003-01-28 22:34:11 +000016
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000017try:
18 import _pickle
19 has_c_implementation = True
20except ImportError:
21 has_c_implementation = False
Jeremy Hylton66426532001-10-15 21:38:56 +000022
Guido van Rossum98297ee2007-11-06 21:34:58 +000023
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000024class PickleTests(AbstractPickleModuleTests):
25 pass
Guido van Rossum5d9113d2003-01-29 17:58:45 +000026
Tim Peterse0c446b2001-10-18 21:57:37 +000027
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000028class PyPicklerTests(AbstractPickleTests):
Jeremy Hylton66426532001-10-15 21:38:56 +000029
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000030 pickler = pickle._Pickler
31 unpickler = pickle._Unpickler
Jeremy Hylton66426532001-10-15 21:38:56 +000032
Guido van Rossumf4169812008-03-17 22:56:06 +000033 def dumps(self, arg, proto=None):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000034 f = io.BytesIO()
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000035 p = self.pickler(f, proto)
Jeremy Hylton66426532001-10-15 21:38:56 +000036 p.dump(arg)
37 f.seek(0)
Guido van Rossumcfe5f202007-05-08 21:26:54 +000038 return bytes(f.read())
Jeremy Hylton66426532001-10-15 21:38:56 +000039
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000040 def loads(self, buf, **kwds):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000041 f = io.BytesIO(buf)
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000042 u = self.unpickler(f, **kwds)
Jeremy Hylton66426532001-10-15 21:38:56 +000043 return u.load()
44
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000045
Antoine Pitrou82be19f2011-08-29 23:09:33 +020046class InMemoryPickleTests(AbstractPickleTests, BigmemPickleTests):
Antoine Pitrouea99c5c2010-09-09 18:33:21 +000047
48 pickler = pickle._Pickler
49 unpickler = pickle._Unpickler
50
Antoine Pitrou82be19f2011-08-29 23:09:33 +020051 def dumps(self, arg, protocol=None):
52 return pickle.dumps(arg, protocol)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +000053
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000054 def loads(self, buf, **kwds):
55 return pickle.loads(buf, **kwds)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +000056
57
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000058class PyPersPicklerTests(AbstractPersistentPicklerTests):
59
60 pickler = pickle._Pickler
61 unpickler = pickle._Unpickler
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000062
Guido van Rossumf4169812008-03-17 22:56:06 +000063 def dumps(self, arg, proto=None):
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000064 class PersPickler(self.pickler):
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000065 def persistent_id(subself, obj):
66 return self.persistent_id(obj)
Guido van Rossumcfe5f202007-05-08 21:26:54 +000067 f = io.BytesIO()
Guido van Rossum9d32bb12003-01-28 03:51:53 +000068 p = PersPickler(f, proto)
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000069 p.dump(arg)
70 f.seek(0)
71 return f.read()
72
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000073 def loads(self, buf, **kwds):
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000074 class PersUnpickler(self.unpickler):
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000075 def persistent_load(subself, obj):
76 return self.persistent_load(obj)
Guido van Rossumcfe5f202007-05-08 21:26:54 +000077 f = io.BytesIO(buf)
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000078 u = PersUnpickler(f, **kwds)
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000079 return u.load()
80
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000081
Collin Winter771d8342009-04-16 03:18:06 +000082class PyPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests):
83
84 pickler_class = pickle._Pickler
85 unpickler_class = pickle._Unpickler
86
87
Antoine Pitrou8d3c2902012-03-04 18:31:48 +010088class PyDispatchTableTests(AbstractDispatchTableTests):
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -080089
Antoine Pitrou8d3c2902012-03-04 18:31:48 +010090 pickler_class = pickle._Pickler
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -080091
Antoine Pitrou8d3c2902012-03-04 18:31:48 +010092 def get_dispatch_table(self):
93 return pickle.dispatch_table.copy()
94
95
96class PyChainDispatchTableTests(AbstractDispatchTableTests):
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -080097
Antoine Pitrou8d3c2902012-03-04 18:31:48 +010098 pickler_class = pickle._Pickler
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -080099
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100100 def get_dispatch_table(self):
101 return collections.ChainMap({}, pickle.dispatch_table)
102
103
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000104if has_c_implementation:
105 class CPicklerTests(PyPicklerTests):
106 pickler = _pickle.Pickler
107 unpickler = _pickle.Unpickler
108
109 class CPersPicklerTests(PyPersPicklerTests):
110 pickler = _pickle.Pickler
111 unpickler = _pickle.Unpickler
112
Collin Winter771d8342009-04-16 03:18:06 +0000113 class CDumpPickle_LoadPickle(PyPicklerTests):
114 pickler = _pickle.Pickler
115 unpickler = pickle._Unpickler
116
117 class DumpPickle_CLoadPickle(PyPicklerTests):
118 pickler = pickle._Pickler
119 unpickler = _pickle.Unpickler
120
121 class CPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests):
122 pickler_class = _pickle.Pickler
123 unpickler_class = _pickle.Unpickler
124
Christian Heimesa24b4d22013-07-01 15:17:45 +0200125 def test_issue18339(self):
126 unpickler = self.unpickler_class(io.BytesIO())
Christian Heimes21782482013-07-01 23:00:13 +0200127 with self.assertRaises(TypeError):
128 unpickler.memo = object
Christian Heimesa24b4d22013-07-01 15:17:45 +0200129 # used to cause a segfault
Christian Heimes21782482013-07-01 23:00:13 +0200130 with self.assertRaises(ValueError):
131 unpickler.memo = {-1: None}
Christian Heimesa24b4d22013-07-01 15:17:45 +0200132 unpickler.memo = {1: None}
133
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100134 class CDispatchTableTests(AbstractDispatchTableTests):
135 pickler_class = pickle.Pickler
136 def get_dispatch_table(self):
137 return pickle.dispatch_table.copy()
138
139 class CChainDispatchTableTests(AbstractDispatchTableTests):
140 pickler_class = pickle.Pickler
141 def get_dispatch_table(self):
142 return collections.ChainMap({}, pickle.dispatch_table)
143
Serhiy Storchaka5bbd2312014-12-16 19:39:08 +0200144 @support.cpython_only
145 class SizeofTests(unittest.TestCase):
146 check_sizeof = support.check_sizeof
147
148 def test_pickler(self):
149 basesize = support.calcobjsize('5P2n3i2n3iP')
150 p = _pickle.Pickler(io.BytesIO())
151 self.assertEqual(object.__sizeof__(p), basesize)
152 MT_size = struct.calcsize('3nP0n')
153 ME_size = struct.calcsize('Pn0P')
154 check = self.check_sizeof
155 check(p, basesize +
156 MT_size + 8 * ME_size + # Minimal memo table size.
157 sys.getsizeof(b'x'*4096)) # Minimal write buffer size.
158 for i in range(6):
159 p.dump(chr(i))
160 check(p, basesize +
161 MT_size + 32 * ME_size + # Size of memo table required to
162 # save references to 6 objects.
163 0) # Write buffer is cleared after every dump().
164
165 def test_unpickler(self):
166 basesize = support.calcobjsize('2Pn2P 2P2n2i5P 2P3n6P2n2i')
167 unpickler = _pickle.Unpickler
168 P = struct.calcsize('P') # Size of memo table entry.
169 n = struct.calcsize('n') # Size of mark table entry.
170 check = self.check_sizeof
171 for encoding in 'ASCII', 'UTF-16', 'latin-1':
172 for errors in 'strict', 'replace':
173 u = unpickler(io.BytesIO(),
174 encoding=encoding, errors=errors)
175 self.assertEqual(object.__sizeof__(u), basesize)
176 check(u, basesize +
177 32 * P + # Minimal memo table size.
178 len(encoding) + 1 + len(errors) + 1)
179
180 stdsize = basesize + len('ASCII') + 1 + len('strict') + 1
181 def check_unpickler(data, memo_size, marks_size):
182 dump = pickle.dumps(data)
183 u = unpickler(io.BytesIO(dump),
184 encoding='ASCII', errors='strict')
185 u.load()
186 check(u, stdsize + memo_size * P + marks_size * n)
187
188 check_unpickler(0, 32, 0)
189 # 20 is minimal non-empty mark stack size.
190 check_unpickler([0] * 100, 32, 20)
191 # 128 is memo table size required to save references to 100 objects.
192 check_unpickler([chr(i) for i in range(100)], 128, 20)
193 def recurse(deep):
194 data = 0
195 for i in range(deep):
196 data = [data, data]
197 return data
198 check_unpickler(recurse(0), 32, 0)
199 check_unpickler(recurse(1), 32, 20)
200 check_unpickler(recurse(20), 32, 58)
201 check_unpickler(recurse(50), 64, 58)
202 check_unpickler(recurse(100), 128, 134)
203
204 u = unpickler(io.BytesIO(pickle.dumps('a', 0)),
205 encoding='ASCII', errors='strict')
206 u.load()
207 check(u, stdsize + 32 * P + 2 + 1)
208
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000209
Fred Drake694ed092001-12-19 16:42:15 +0000210def test_main():
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100211 tests = [PickleTests, PyPicklerTests, PyPersPicklerTests,
212 PyDispatchTableTests, PyChainDispatchTableTests]
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000213 if has_c_implementation:
Collin Winter771d8342009-04-16 03:18:06 +0000214 tests.extend([CPicklerTests, CPersPicklerTests,
215 CDumpPickle_LoadPickle, DumpPickle_CLoadPickle,
216 PyPicklerUnpicklerObjectTests,
Antoine Pitrouea99c5c2010-09-09 18:33:21 +0000217 CPicklerUnpicklerObjectTests,
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100218 CDispatchTableTests, CChainDispatchTableTests,
Serhiy Storchaka5bbd2312014-12-16 19:39:08 +0200219 InMemoryPickleTests, SizeofTests])
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000220 support.run_unittest(*tests)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000221 support.run_doctest(pickle)
Fred Drake694ed092001-12-19 16:42:15 +0000222
Jeremy Hylton66426532001-10-15 21:38:56 +0000223if __name__ == "__main__":
Fred Drake694ed092001-12-19 16:42:15 +0000224 test_main()