blob: 90ef3fae3eedf89c2f8b1fea9a6822f722bb7dac [file] [log] [blame]
Guido van Rossum581cb932003-02-06 17:52:15 +00001"""Unit tests for the copy module."""
2
3import sys
4import copy
5
6import unittest
7from test import test_support
8
9class TestCopy(unittest.TestCase):
10
11 # Attempt full line coverage of copy.py from top to bottom
12
13 def test_exceptions(self):
14 self.assert_(copy.Error is copy.error)
15 self.assert_(issubclass(copy.Error, Exception))
16
17 # The copy() method
18
19 def test_copy_basic(self):
20 x = 42
21 y = copy.copy(x)
22 self.assertEqual(x, y)
23
24 def test_copy_copy(self):
25 class C(object):
26 def __init__(self, foo):
27 self.foo = foo
28 def __copy__(self):
29 return C(self.foo)
30 x = C(42)
31 y = copy.copy(x)
32 self.assertEqual(y.__class__, x.__class__)
33 self.assertEqual(y.foo, x.foo)
34
35 def test_copy_reduce(self):
36 class C(object):
37 def __reduce__(self):
38 return ""
39 x = C()
40 y = copy.copy(x)
41 self.assert_(y is x)
42
43 def test_copy_cant(self):
44 class C(object):
45 def __getattribute__(self, name):
46 if name == "__reduce__":
47 raise AttributeError, name
48 return object.__getattribute__(self, name)
49 x = C()
50 self.assertRaises(copy.Error, copy.copy, x)
51
52 # Type-specific _copy_xxx() methods
53
54 def test_copy_atomic(self):
55 class Classic:
56 pass
57 class NewStyle(object):
58 pass
59 def f():
60 pass
61 tests = [None, 42, 2L**100, 3.14, True, False, 1j,
62 "hello", u"hello\u1234", f.func_code,
63 NewStyle, xrange(10), Classic]
64 for x in tests:
65 self.assert_(copy.copy(x) is x, `x`)
66
67 def test_copy_list(self):
68 x = [1, 2, 3]
69 self.assertEqual(copy.copy(x), x)
70
71 def test_copy_tuple(self):
72 x = (1, 2, 3)
73 self.assertEqual(copy.copy(x), x)
74
75 def test_copy_dict(self):
76 x = {"foo": 1, "bar": 2}
77 self.assertEqual(copy.copy(x), x)
78
79 def test_copy_inst_vanilla(self):
80 class C:
81 def __init__(self, foo):
82 self.foo = foo
83 def __cmp__(self, other):
84 return cmp(self.foo, other.foo)
85 x = C(42)
86 self.assertEqual(copy.copy(x), x)
87
88 def test_copy_inst_copy(self):
89 class C:
90 def __init__(self, foo):
91 self.foo = foo
92 def __copy__(self):
93 return C(self.foo)
94 def __cmp__(self, other):
95 return cmp(self.foo, other.foo)
96 x = C(42)
97 self.assertEqual(copy.copy(x), x)
98
99 def test_copy_inst_getinitargs(self):
100 class C:
101 def __init__(self, foo):
102 self.foo = foo
103 def __getinitargs__(self):
104 return (self.foo,)
105 def __cmp__(self, other):
106 return cmp(self.foo, other.foo)
107 x = C(42)
108 self.assertEqual(copy.copy(x), x)
109
110 def test_copy_inst_getstate(self):
111 class C:
112 def __init__(self, foo):
113 self.foo = foo
114 def __getstate__(self):
115 return {"foo": self.foo}
116 def __cmp__(self, other):
117 return cmp(self.foo, other.foo)
118 x = C(42)
119 self.assertEqual(copy.copy(x), x)
120
121 def test_copy_inst_setstate(self):
122 class C:
123 def __init__(self, foo):
124 self.foo = foo
125 def __setstate__(self, state):
126 self.foo = state["foo"]
127 def __cmp__(self, other):
128 return cmp(self.foo, other.foo)
129 x = C(42)
130 self.assertEqual(copy.copy(x), x)
131
132 def test_copy_inst_getstate_setstate(self):
133 class C:
134 def __init__(self, foo):
135 self.foo = foo
136 def __getstate__(self):
137 return self.foo
138 def __setstate__(self, state):
139 self.foo = state
140 def __cmp__(self, other):
141 return cmp(self.foo, other.foo)
142 x = C(42)
143 self.assertEqual(copy.copy(x), x)
144
145 # The deepcopy() method
146
147 def test_deepcopy_basic(self):
148 x = 42
149 y = copy.deepcopy(x)
150 self.assertEqual(y, x)
151
152 def test_deepcopy_memo(self):
153 x = []
154 x.append(x)
155 y = copy.deepcopy(x)
156 self.assertEqual(y, x)
157 self.assert_(y is not x)
158 self.assert_(y[0] is not x[0])
159 self.assert_(y is y[0])
160
161 def test_deepcopy_issubclass(self):
162 # XXX Note: there's no way to test the TypeError coming out of
163 # issubclass() -- this can only happen when an extension
164 # module defines a "type" that doesn't formally inherit from
165 # type.
166 class Meta(type):
167 pass
168 class C:
169 __metaclass__ = Meta
170 self.assertEqual(copy.deepcopy(C), C)
171
172 def test_deepcopy_deepcopy(self):
173 class C(object):
174 def __init__(self, foo):
175 self.foo = foo
176 def __deepcopy__(self, memo=None):
177 return C(self.foo)
178 x = C(42)
179 y = copy.deepcopy(x)
180 self.assertEqual(y.__class__, x.__class__)
181 self.assertEqual(y.foo, x.foo)
182
183 def test_deepcopy_reduce(self):
184 class C(object):
185 def __reduce__(self):
186 return ""
187 x = C()
188 y = copy.deepcopy(x)
189 self.assert_(y is x)
190
191 def test_deepcopy_cant(self):
192 class C(object):
193 def __getattribute__(self, name):
194 if name == "__reduce__":
195 raise AttributeError, name
196 return object.__getattribute__(self, name)
197 x = C()
198 self.assertRaises(copy.Error, copy.deepcopy, x)
199
200 # Type-specific _deepcopy_xxx() methods
201
202 def test_deepcopy_atomic(self):
203 class Classic:
204 pass
205 class NewStyle(object):
206 pass
207 def f():
208 pass
209 tests = [None, 42, 2L**100, 3.14, True, False, 1j,
210 "hello", u"hello\u1234", f.func_code,
211 NewStyle, xrange(10)]
212 for x in tests:
213 self.assert_(copy.deepcopy(x) is x, `x`)
214
215 def test_deepcopy_list(self):
216 x = [[1, 2], 3]
217 y = copy.deepcopy(x)
218 self.assertEqual(y, x)
219 self.assert_(x is not y)
220 self.assert_(x[0] is not y[0])
221
222 def test_deepcopy_tuple(self):
223 x = ([1, 2], 3)
224 y = copy.deepcopy(x)
225 self.assertEqual(y, x)
226 self.assert_(x is not y)
227 self.assert_(x[0] is not y[0])
228
229 def test_deepcopy_dict(self):
230 x = {"foo": [1, 2], "bar": 3}
231 y = copy.deepcopy(x)
232 self.assertEqual(y, x)
233 self.assert_(x is not y)
234 self.assert_(x["foo"] is not y["foo"])
235
236 def test_deepcopy_keepalive(self):
237 memo = {}
238 x = 42
239 y = copy.deepcopy(x, memo)
240 self.assert_(memo[id(x)] is x)
241
242 def test_deepcopy_inst_vanilla(self):
243 class C:
244 def __init__(self, foo):
245 self.foo = foo
246 def __cmp__(self, other):
247 return cmp(self.foo, other.foo)
248 x = C([42])
249 y = copy.deepcopy(x)
250 self.assertEqual(y, x)
251 self.assert_(y.foo is not x.foo)
252
253 def test_deepcopy_inst_deepcopy(self):
254 class C:
255 def __init__(self, foo):
256 self.foo = foo
257 def __deepcopy__(self, memo):
258 return C(copy.deepcopy(self.foo, memo))
259 def __cmp__(self, other):
260 return cmp(self.foo, other.foo)
261 x = C([42])
262 y = copy.deepcopy(x)
263 self.assertEqual(y, x)
264 self.assert_(y is not x)
265 self.assert_(y.foo is not x.foo)
266
267 def test_deepcopy_inst_getinitargs(self):
268 class C:
269 def __init__(self, foo):
270 self.foo = foo
271 def __getinitargs__(self):
272 return (self.foo,)
273 def __cmp__(self, other):
274 return cmp(self.foo, other.foo)
275 x = C([42])
276 y = copy.deepcopy(x)
277 self.assertEqual(y, x)
278 self.assert_(y is not x)
279 self.assert_(y.foo is not x.foo)
280
281 def test_deepcopy_inst_getstate(self):
282 class C:
283 def __init__(self, foo):
284 self.foo = foo
285 def __getstate__(self):
286 return {"foo": self.foo}
287 def __cmp__(self, other):
288 return cmp(self.foo, other.foo)
289 x = C([42])
290 y = copy.deepcopy(x)
291 self.assertEqual(y, x)
292 self.assert_(y is not x)
293 self.assert_(y.foo is not x.foo)
294
295 def test_deepcopy_inst_setstate(self):
296 class C:
297 def __init__(self, foo):
298 self.foo = foo
299 def __setstate__(self, state):
300 self.foo = state["foo"]
301 def __cmp__(self, other):
302 return cmp(self.foo, other.foo)
303 x = C([42])
304 y = copy.deepcopy(x)
305 self.assertEqual(y, x)
306 self.assert_(y is not x)
307 self.assert_(y.foo is not x.foo)
308
309 def test_deepcopy_inst_getstate_setstate(self):
310 class C:
311 def __init__(self, foo):
312 self.foo = foo
313 def __getstate__(self):
314 return self.foo
315 def __setstate__(self, state):
316 self.foo = state
317 def __cmp__(self, other):
318 return cmp(self.foo, other.foo)
319 x = C([42])
320 y = copy.deepcopy(x)
321 self.assertEqual(y, x)
322 self.assert_(y is not x)
323 self.assert_(y.foo is not x.foo)
324
325 # _reconstruct()
326
327 def test_reconstruct_string(self):
328 class C(object):
329 def __reduce__(self):
330 return ""
331 x = C()
332 y = copy.copy(x)
333 self.assert_(y is x)
334 y = copy.deepcopy(x)
335 self.assert_(y is x)
336
337 def test_reconstruct_nostate(self):
338 class C(object):
339 def __reduce__(self):
340 return (C, ())
341 x = C()
342 x.foo = 42
343 y = copy.copy(x)
344 self.assert_(y.__class__ is x.__class__)
345 y = copy.deepcopy(x)
346 self.assert_(y.__class__ is x.__class__)
347
348 def test_reconstruct_state(self):
349 class C(object):
350 def __reduce__(self):
351 return (C, (), self.__dict__)
352 def __cmp__(self, other):
353 return cmp(self.__dict__, other.__dict__)
354 x = C()
355 x.foo = [42]
356 y = copy.copy(x)
357 self.assertEqual(y, x)
358 y = copy.deepcopy(x)
359 self.assertEqual(y, x)
360 self.assert_(y.foo is not x.foo)
361
362 def test_reconstruct_state_setstate(self):
363 class C(object):
364 def __reduce__(self):
365 return (C, (), self.__dict__)
366 def __setstate__(self, state):
367 self.__dict__.update(state)
368 def __cmp__(self, other):
369 return cmp(self.__dict__, other.__dict__)
370 x = C()
371 x.foo = [42]
372 y = copy.copy(x)
373 self.assertEqual(y, x)
374 y = copy.deepcopy(x)
375 self.assertEqual(y, x)
376 self.assert_(y.foo is not x.foo)
377
378def test_main():
379 suite = unittest.TestSuite()
380 suite.addTest(unittest.makeSuite(TestCopy))
381 test_support.run_suite(suite)
382
383if __name__ == "__main__":
384 test_main()