blob: fe68b665c8bc71009ef6c312a427b99c722e0bee [file] [log] [blame]
Georg Brandl9dba5d92008-05-18 16:27:29 +00001import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002from test import support
Georg Brandl9dba5d92008-05-18 16:27:29 +00003from weakref import proxy, ref, WeakSet
4import operator
5import copy
6import string
7import os
8from random import randrange, shuffle
9import sys
10import warnings
11import collections
12from collections import UserString as ustr
Antoine Pitrouc1baa602010-01-08 17:54:23 +000013import gc
14import contextlib
Georg Brandl9dba5d92008-05-18 16:27:29 +000015
16
17class Foo:
18 pass
19
20
21class TestWeakSet(unittest.TestCase):
22
23 def setUp(self):
24 # need to keep references to them
25 self.items = [ustr(c) for c in ('a', 'b', 'c')]
26 self.items2 = [ustr(c) for c in ('x', 'y', 'z')]
27 self.letters = [ustr(c) for c in string.ascii_letters]
28 self.s = WeakSet(self.items)
29 self.d = dict.fromkeys(self.items)
30 self.obj = ustr('F')
31 self.fs = WeakSet([self.obj])
32
33 def test_methods(self):
34 weaksetmethods = dir(WeakSet)
35 for method in dir(set):
Georg Brandl02c0bbb2008-05-18 21:04:46 +000036 if method == 'test_c_api' or method.startswith('_'):
Georg Brandl9dba5d92008-05-18 16:27:29 +000037 continue
Ezio Melottib58e0bd2010-01-23 15:40:09 +000038 self.assertIn(method, weaksetmethods,
Georg Brandl19219702008-05-18 17:10:40 +000039 "WeakSet missing method " + method)
Georg Brandl9dba5d92008-05-18 16:27:29 +000040
41 def test_new_or_init(self):
42 self.assertRaises(TypeError, WeakSet, [], 2)
43
44 def test_len(self):
45 self.assertEqual(len(self.s), len(self.d))
46 self.assertEqual(len(self.fs), 1)
47 del self.obj
48 self.assertEqual(len(self.fs), 0)
49
50 def test_contains(self):
51 for c in self.letters:
52 self.assertEqual(c in self.s, c in self.d)
53 self.assertRaises(TypeError, self.s.__contains__, [[]])
Benjamin Peterson577473f2010-01-19 00:09:57 +000054 self.assertIn(self.obj, self.fs)
Georg Brandl9dba5d92008-05-18 16:27:29 +000055 del self.obj
Benjamin Peterson577473f2010-01-19 00:09:57 +000056 self.assertNotIn(ustr('F'), self.fs)
Georg Brandl9dba5d92008-05-18 16:27:29 +000057
58 def test_union(self):
59 u = self.s.union(self.items2)
60 for c in self.letters:
61 self.assertEqual(c in u, c in self.d or c in self.items2)
62 self.assertEqual(self.s, WeakSet(self.items))
63 self.assertEqual(type(u), WeakSet)
64 self.assertRaises(TypeError, self.s.union, [[]])
65 for C in set, frozenset, dict.fromkeys, list, tuple:
66 x = WeakSet(self.items + self.items2)
67 c = C(self.items2)
68 self.assertEqual(self.s.union(c), x)
69
70 def test_or(self):
71 i = self.s.union(self.items2)
72 self.assertEqual(self.s | set(self.items2), i)
73 self.assertEqual(self.s | frozenset(self.items2), i)
74
75 def test_intersection(self):
76 i = self.s.intersection(self.items2)
77 for c in self.letters:
78 self.assertEqual(c in i, c in self.d and c in self.items2)
79 self.assertEqual(self.s, WeakSet(self.items))
80 self.assertEqual(type(i), WeakSet)
81 for C in set, frozenset, dict.fromkeys, list, tuple:
82 x = WeakSet([])
83 self.assertEqual(self.s.intersection(C(self.items2)), x)
84
85 def test_isdisjoint(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000086 self.assertTrue(self.s.isdisjoint(WeakSet(self.items2)))
87 self.assertTrue(not self.s.isdisjoint(WeakSet(self.letters)))
Georg Brandl9dba5d92008-05-18 16:27:29 +000088
89 def test_and(self):
90 i = self.s.intersection(self.items2)
91 self.assertEqual(self.s & set(self.items2), i)
92 self.assertEqual(self.s & frozenset(self.items2), i)
93
94 def test_difference(self):
95 i = self.s.difference(self.items2)
96 for c in self.letters:
97 self.assertEqual(c in i, c in self.d and c not in self.items2)
98 self.assertEqual(self.s, WeakSet(self.items))
99 self.assertEqual(type(i), WeakSet)
100 self.assertRaises(TypeError, self.s.difference, [[]])
101
102 def test_sub(self):
103 i = self.s.difference(self.items2)
104 self.assertEqual(self.s - set(self.items2), i)
105 self.assertEqual(self.s - frozenset(self.items2), i)
106
107 def test_symmetric_difference(self):
108 i = self.s.symmetric_difference(self.items2)
109 for c in self.letters:
110 self.assertEqual(c in i, (c in self.d) ^ (c in self.items2))
111 self.assertEqual(self.s, WeakSet(self.items))
112 self.assertEqual(type(i), WeakSet)
113 self.assertRaises(TypeError, self.s.symmetric_difference, [[]])
114
115 def test_xor(self):
116 i = self.s.symmetric_difference(self.items2)
117 self.assertEqual(self.s ^ set(self.items2), i)
118 self.assertEqual(self.s ^ frozenset(self.items2), i)
119
120 def test_sub_and_super(self):
121 pl, ql, rl = map(lambda s: [ustr(c) for c in s], ['ab', 'abcde', 'def'])
122 p, q, r = map(WeakSet, (pl, ql, rl))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000123 self.assertTrue(p < q)
124 self.assertTrue(p <= q)
125 self.assertTrue(q <= q)
126 self.assertTrue(q > p)
127 self.assertTrue(q >= p)
128 self.assertFalse(q < r)
129 self.assertFalse(q <= r)
130 self.assertFalse(q > r)
131 self.assertFalse(q >= r)
132 self.assertTrue(set('a').issubset('abc'))
133 self.assertTrue(set('abc').issuperset('a'))
134 self.assertFalse(set('a').issubset('cbs'))
135 self.assertFalse(set('cbs').issuperset('a'))
Georg Brandl9dba5d92008-05-18 16:27:29 +0000136
137 def test_gc(self):
138 # Create a nest of cycles to exercise overall ref count check
Robert Schuppenies4ad1d6f2009-05-17 17:32:20 +0000139 s = WeakSet(Foo() for i in range(1000))
Georg Brandl9dba5d92008-05-18 16:27:29 +0000140 for elem in s:
141 elem.cycle = s
142 elem.sub = elem
Robert Schuppenies4ad1d6f2009-05-17 17:32:20 +0000143 elem.set = WeakSet([elem])
Georg Brandl9dba5d92008-05-18 16:27:29 +0000144
145 def test_subclass_with_custom_hash(self):
146 # Bug #1257731
147 class H(WeakSet):
148 def __hash__(self):
149 return int(id(self) & 0x7fffffff)
150 s=H()
151 f=set()
152 f.add(s)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000153 self.assertIn(s, f)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000154 f.remove(s)
155 f.add(s)
156 f.discard(s)
157
158 def test_init(self):
159 s = WeakSet()
160 s.__init__(self.items)
161 self.assertEqual(s, self.s)
162 s.__init__(self.items2)
163 self.assertEqual(s, WeakSet(self.items2))
164 self.assertRaises(TypeError, s.__init__, s, 2);
165 self.assertRaises(TypeError, s.__init__, 1);
166
167 def test_constructor_identity(self):
168 s = WeakSet(self.items)
169 t = WeakSet(s)
170 self.assertNotEqual(id(s), id(t))
171
Georg Brandl9dba5d92008-05-18 16:27:29 +0000172 def test_hash(self):
173 self.assertRaises(TypeError, hash, self.s)
174
175 def test_clear(self):
176 self.s.clear()
Robert Schuppenies4ad1d6f2009-05-17 17:32:20 +0000177 self.assertEqual(self.s, WeakSet([]))
Georg Brandl9dba5d92008-05-18 16:27:29 +0000178 self.assertEqual(len(self.s), 0)
179
180 def test_copy(self):
181 dup = self.s.copy()
182 self.assertEqual(self.s, dup)
183 self.assertNotEqual(id(self.s), id(dup))
184
185 def test_add(self):
186 x = ustr('Q')
187 self.s.add(x)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000188 self.assertIn(x, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000189 dup = self.s.copy()
190 self.s.add(x)
191 self.assertEqual(self.s, dup)
192 self.assertRaises(TypeError, self.s.add, [])
193 self.fs.add(Foo())
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000194 self.assertTrue(len(self.fs) == 1)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000195 self.fs.add(self.obj)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000196 self.assertTrue(len(self.fs) == 1)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000197
198 def test_remove(self):
199 x = ustr('a')
200 self.s.remove(x)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000201 self.assertNotIn(x, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000202 self.assertRaises(KeyError, self.s.remove, x)
203 self.assertRaises(TypeError, self.s.remove, [])
204
205 def test_discard(self):
206 a, q = ustr('a'), ustr('Q')
207 self.s.discard(a)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000208 self.assertNotIn(a, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000209 self.s.discard(q)
210 self.assertRaises(TypeError, self.s.discard, [])
211
212 def test_pop(self):
213 for i in range(len(self.s)):
214 elem = self.s.pop()
Benjamin Peterson577473f2010-01-19 00:09:57 +0000215 self.assertNotIn(elem, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000216 self.assertRaises(KeyError, self.s.pop)
217
218 def test_update(self):
219 retval = self.s.update(self.items2)
220 self.assertEqual(retval, None)
221 for c in (self.items + self.items2):
Benjamin Peterson577473f2010-01-19 00:09:57 +0000222 self.assertIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000223 self.assertRaises(TypeError, self.s.update, [[]])
224
225 def test_update_set(self):
226 self.s.update(set(self.items2))
227 for c in (self.items + self.items2):
Benjamin Peterson577473f2010-01-19 00:09:57 +0000228 self.assertIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000229
230 def test_ior(self):
231 self.s |= set(self.items2)
232 for c in (self.items + self.items2):
Benjamin Peterson577473f2010-01-19 00:09:57 +0000233 self.assertIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000234
235 def test_intersection_update(self):
236 retval = self.s.intersection_update(self.items2)
237 self.assertEqual(retval, None)
238 for c in (self.items + self.items2):
239 if c in self.items2 and c in self.items:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000240 self.assertIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000241 else:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000242 self.assertNotIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000243 self.assertRaises(TypeError, self.s.intersection_update, [[]])
244
245 def test_iand(self):
246 self.s &= set(self.items2)
247 for c in (self.items + self.items2):
248 if c in self.items2 and c in self.items:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000249 self.assertIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000250 else:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000251 self.assertNotIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000252
253 def test_difference_update(self):
254 retval = self.s.difference_update(self.items2)
255 self.assertEqual(retval, None)
256 for c in (self.items + self.items2):
257 if c in self.items and c not in self.items2:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000258 self.assertIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000259 else:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000260 self.assertNotIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000261 self.assertRaises(TypeError, self.s.difference_update, [[]])
262 self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
263
264 def test_isub(self):
265 self.s -= set(self.items2)
266 for c in (self.items + self.items2):
267 if c in self.items and c not in self.items2:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000268 self.assertIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000269 else:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000270 self.assertNotIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000271
272 def test_symmetric_difference_update(self):
273 retval = self.s.symmetric_difference_update(self.items2)
274 self.assertEqual(retval, None)
275 for c in (self.items + self.items2):
276 if (c in self.items) ^ (c in self.items2):
Benjamin Peterson577473f2010-01-19 00:09:57 +0000277 self.assertIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000278 else:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000279 self.assertNotIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000280 self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
281
282 def test_ixor(self):
283 self.s ^= set(self.items2)
284 for c in (self.items + self.items2):
285 if (c in self.items) ^ (c in self.items2):
Benjamin Peterson577473f2010-01-19 00:09:57 +0000286 self.assertIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000287 else:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000288 self.assertNotIn(c, self.s)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000289
290 def test_inplace_on_self(self):
291 t = self.s.copy()
292 t |= t
293 self.assertEqual(t, self.s)
294 t &= t
295 self.assertEqual(t, self.s)
296 t -= t
297 self.assertEqual(t, WeakSet())
298 t = self.s.copy()
299 t ^= t
300 self.assertEqual(t, WeakSet())
301
Robert Schuppenies4ad1d6f2009-05-17 17:32:20 +0000302 def test_eq(self):
303 # issue 5964
304 self.assertTrue(self.s == self.s)
305 self.assertTrue(self.s == WeakSet(self.items))
306 self.assertFalse(self.s == set(self.items))
307 self.assertFalse(self.s == list(self.items))
308 self.assertFalse(self.s == tuple(self.items))
309 self.assertFalse(self.s == WeakSet([Foo]))
310 self.assertFalse(self.s == 1)
311
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000312 def test_weak_destroy_while_iterating(self):
313 # Issue #7105: iterators shouldn't crash when a key is implicitly removed
314 # Create new items to be sure no-one else holds a reference
315 items = [ustr(c) for c in ('a', 'b', 'c')]
316 s = WeakSet(items)
317 it = iter(s)
318 next(it) # Trigger internal iteration
319 # Destroy an item
320 del items[-1]
321 gc.collect() # just in case
322 # We have removed either the first consumed items, or another one
323 self.assertIn(len(list(it)), [len(items), len(items) - 1])
324 del it
325 # The removal has been committed
326 self.assertEqual(len(s), len(items))
327
328 def test_weak_destroy_and_mutate_while_iterating(self):
329 # Issue #7105: iterators shouldn't crash when a key is implicitly removed
330 items = [ustr(c) for c in string.ascii_letters]
331 s = WeakSet(items)
332 @contextlib.contextmanager
333 def testcontext():
334 try:
335 it = iter(s)
336 next(it)
337 # Schedule an item for removal and recreate it
338 u = ustr(str(items.pop()))
339 gc.collect() # just in case
340 yield u
341 finally:
342 it = None # should commit all removals
343
344 with testcontext() as u:
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000345 self.assertNotIn(u, s)
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000346 with testcontext() as u:
347 self.assertRaises(KeyError, s.remove, u)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000348 self.assertNotIn(u, s)
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000349 with testcontext() as u:
350 s.add(u)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000351 self.assertIn(u, s)
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000352 t = s.copy()
353 with testcontext() as u:
354 s.update(t)
355 self.assertEqual(len(s), len(t))
356 with testcontext() as u:
357 s.clear()
358 self.assertEqual(len(s), 0)
359
Georg Brandl9dba5d92008-05-18 16:27:29 +0000360
361def test_main(verbose=None):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000362 support.run_unittest(TestWeakSet)
Georg Brandl9dba5d92008-05-18 16:27:29 +0000363
364if __name__ == "__main__":
365 test_main(verbose=True)