blob: 37a085cf77c8e7256f7764ae10a761f3dc15c441 [file] [log] [blame]
Raymond Hettingera690a992003-11-16 16:17:49 +00001import unittest
2from test import test_support
Raymond Hettinger691d8052004-05-30 07:26:47 +00003from weakref import proxy
Raymond Hettingera690a992003-11-16 16:17:49 +00004import operator
5import copy
6import pickle
Raymond Hettingereae05de2004-07-09 04:51:24 +00007import os
Raymond Hettinger82cb9a22005-07-05 05:34:43 +00008from random import randrange, shuffle
Raymond Hettingerc47e01d2005-08-16 10:44:15 +00009import sys
Raymond Hettinger61708742008-01-24 21:23:58 +000010import collections
Raymond Hettingera690a992003-11-16 16:17:49 +000011
12class PassThru(Exception):
13 pass
14
15def check_pass_thru():
16 raise PassThru
17 yield 1
18
Raymond Hettinger9bda1d62005-09-16 07:14:21 +000019class BadCmp:
20 def __hash__(self):
21 return 1
22 def __cmp__(self, other):
23 raise RuntimeError
24
Raymond Hettinger53999102006-12-30 04:01:17 +000025class ReprWrapper:
26 'Used to test self-referential repr() calls'
27 def __repr__(self):
28 return repr(self.value)
29
Raymond Hettingerd6fc72a2007-02-19 02:03:19 +000030class HashCountingInt(int):
31 'int-like object that counts the number of times __hash__ is called'
32 def __init__(self, *args):
33 self.hash_count = 0
34 def __hash__(self):
35 self.hash_count += 1
36 return int.__hash__(self)
37
Raymond Hettingera690a992003-11-16 16:17:49 +000038class TestJointOps(unittest.TestCase):
39 # Tests common to both set and frozenset
40
41 def setUp(self):
42 self.word = word = 'simsalabim'
43 self.otherword = 'madagascar'
44 self.letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
45 self.s = self.thetype(word)
46 self.d = dict.fromkeys(word)
47
Raymond Hettinger6429a472004-09-28 01:51:35 +000048 def test_new_or_init(self):
49 self.assertRaises(TypeError, self.thetype, [], 2)
50
Raymond Hettingera690a992003-11-16 16:17:49 +000051 def test_uniquification(self):
Raymond Hettinger64958a12003-12-17 20:43:33 +000052 actual = sorted(self.s)
53 expected = sorted(self.d)
Raymond Hettingera690a992003-11-16 16:17:49 +000054 self.assertEqual(actual, expected)
55 self.assertRaises(PassThru, self.thetype, check_pass_thru())
56 self.assertRaises(TypeError, self.thetype, [[]])
57
58 def test_len(self):
59 self.assertEqual(len(self.s), len(self.d))
60
61 def test_contains(self):
62 for c in self.letters:
63 self.assertEqual(c in self.s, c in self.d)
64 self.assertRaises(TypeError, self.s.__contains__, [[]])
Raymond Hettinger19c2d772003-11-21 18:36:54 +000065 s = self.thetype([frozenset(self.letters)])
66 self.assert_(self.thetype(self.letters) in s)
Raymond Hettingera690a992003-11-16 16:17:49 +000067
Raymond Hettingera690a992003-11-16 16:17:49 +000068 def test_union(self):
69 u = self.s.union(self.otherword)
70 for c in self.letters:
71 self.assertEqual(c in u, c in self.d or c in self.otherword)
Raymond Hettinger49ba4c32003-11-23 02:49:05 +000072 self.assertEqual(self.s, self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +000073 self.assertEqual(type(u), self.thetype)
74 self.assertRaises(PassThru, self.s.union, check_pass_thru())
75 self.assertRaises(TypeError, self.s.union, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +000076 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
77 self.assertEqual(self.thetype('abcba').union(C('cdc')), set('abcd'))
78 self.assertEqual(self.thetype('abcba').union(C('efgfe')), set('abcefg'))
79 self.assertEqual(self.thetype('abcba').union(C('ccb')), set('abc'))
80 self.assertEqual(self.thetype('abcba').union(C('ef')), set('abcef'))
Raymond Hettingeree4bcad2008-06-09 08:33:37 +000081 self.assertEqual(self.thetype('abcba').union(C('ef'), C('fg')), set('abcefg'))
Raymond Hettingera690a992003-11-16 16:17:49 +000082
83 def test_or(self):
84 i = self.s.union(self.otherword)
85 self.assertEqual(self.s | set(self.otherword), i)
86 self.assertEqual(self.s | frozenset(self.otherword), i)
87 try:
88 self.s | self.otherword
89 except TypeError:
90 pass
91 else:
92 self.fail("s|t did not screen-out general iterables")
93
94 def test_intersection(self):
95 i = self.s.intersection(self.otherword)
96 for c in self.letters:
97 self.assertEqual(c in i, c in self.d and c in self.otherword)
Raymond Hettinger49ba4c32003-11-23 02:49:05 +000098 self.assertEqual(self.s, self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +000099 self.assertEqual(type(i), self.thetype)
100 self.assertRaises(PassThru, self.s.intersection, check_pass_thru())
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000101 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
102 self.assertEqual(self.thetype('abcba').intersection(C('cdc')), set('cc'))
103 self.assertEqual(self.thetype('abcba').intersection(C('efgfe')), set(''))
104 self.assertEqual(self.thetype('abcba').intersection(C('ccb')), set('bc'))
105 self.assertEqual(self.thetype('abcba').intersection(C('ef')), set(''))
Raymond Hettingera690a992003-11-16 16:17:49 +0000106
Raymond Hettinger1760c8a2007-11-08 02:52:43 +0000107 def test_isdisjoint(self):
108 def f(s1, s2):
109 'Pure python equivalent of isdisjoint()'
110 return not set(s1).intersection(s2)
111 for larg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef':
112 s1 = self.thetype(larg)
113 for rarg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef':
114 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
115 s2 = C(rarg)
116 actual = s1.isdisjoint(s2)
117 expected = f(s1, s2)
118 self.assertEqual(actual, expected)
119 self.assert_(actual is True or actual is False)
120
Raymond Hettingera690a992003-11-16 16:17:49 +0000121 def test_and(self):
122 i = self.s.intersection(self.otherword)
123 self.assertEqual(self.s & set(self.otherword), i)
124 self.assertEqual(self.s & frozenset(self.otherword), i)
125 try:
126 self.s & self.otherword
127 except TypeError:
128 pass
129 else:
130 self.fail("s&t did not screen-out general iterables")
131
132 def test_difference(self):
133 i = self.s.difference(self.otherword)
134 for c in self.letters:
135 self.assertEqual(c in i, c in self.d and c not in self.otherword)
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000136 self.assertEqual(self.s, self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +0000137 self.assertEqual(type(i), self.thetype)
138 self.assertRaises(PassThru, self.s.difference, check_pass_thru())
139 self.assertRaises(TypeError, self.s.difference, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000140 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
141 self.assertEqual(self.thetype('abcba').difference(C('cdc')), set('ab'))
142 self.assertEqual(self.thetype('abcba').difference(C('efgfe')), set('abc'))
143 self.assertEqual(self.thetype('abcba').difference(C('ccb')), set('a'))
144 self.assertEqual(self.thetype('abcba').difference(C('ef')), set('abc'))
Raymond Hettingera690a992003-11-16 16:17:49 +0000145
146 def test_sub(self):
147 i = self.s.difference(self.otherword)
148 self.assertEqual(self.s - set(self.otherword), i)
149 self.assertEqual(self.s - frozenset(self.otherword), i)
150 try:
151 self.s - self.otherword
152 except TypeError:
153 pass
154 else:
155 self.fail("s-t did not screen-out general iterables")
156
157 def test_symmetric_difference(self):
158 i = self.s.symmetric_difference(self.otherword)
159 for c in self.letters:
160 self.assertEqual(c in i, (c in self.d) ^ (c in self.otherword))
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000161 self.assertEqual(self.s, self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +0000162 self.assertEqual(type(i), self.thetype)
163 self.assertRaises(PassThru, self.s.symmetric_difference, check_pass_thru())
164 self.assertRaises(TypeError, self.s.symmetric_difference, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000165 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
166 self.assertEqual(self.thetype('abcba').symmetric_difference(C('cdc')), set('abd'))
167 self.assertEqual(self.thetype('abcba').symmetric_difference(C('efgfe')), set('abcefg'))
168 self.assertEqual(self.thetype('abcba').symmetric_difference(C('ccb')), set('a'))
169 self.assertEqual(self.thetype('abcba').symmetric_difference(C('ef')), set('abcef'))
Raymond Hettingera690a992003-11-16 16:17:49 +0000170
171 def test_xor(self):
172 i = self.s.symmetric_difference(self.otherword)
173 self.assertEqual(self.s ^ set(self.otherword), i)
174 self.assertEqual(self.s ^ frozenset(self.otherword), i)
175 try:
176 self.s ^ self.otherword
177 except TypeError:
178 pass
179 else:
180 self.fail("s^t did not screen-out general iterables")
181
182 def test_equality(self):
183 self.assertEqual(self.s, set(self.word))
184 self.assertEqual(self.s, frozenset(self.word))
185 self.assertEqual(self.s == self.word, False)
186 self.assertNotEqual(self.s, set(self.otherword))
187 self.assertNotEqual(self.s, frozenset(self.otherword))
188 self.assertEqual(self.s != self.word, True)
189
190 def test_setOfFrozensets(self):
191 t = map(frozenset, ['abcdef', 'bcd', 'bdcb', 'fed', 'fedccba'])
192 s = self.thetype(t)
193 self.assertEqual(len(s), 3)
194
195 def test_compare(self):
196 self.assertRaises(TypeError, self.s.__cmp__, self.s)
197
198 def test_sub_and_super(self):
199 p, q, r = map(self.thetype, ['ab', 'abcde', 'def'])
200 self.assert_(p < q)
201 self.assert_(p <= q)
202 self.assert_(q <= q)
203 self.assert_(q > p)
204 self.assert_(q >= p)
205 self.failIf(q < r)
206 self.failIf(q <= r)
207 self.failIf(q > r)
208 self.failIf(q >= r)
Raymond Hettinger3fbec702003-11-21 07:56:36 +0000209 self.assert_(set('a').issubset('abc'))
210 self.assert_(set('abc').issuperset('a'))
211 self.failIf(set('a').issubset('cbs'))
212 self.failIf(set('cbs').issuperset('a'))
Raymond Hettingera690a992003-11-16 16:17:49 +0000213
214 def test_pickling(self):
Raymond Hettinger15056a52004-11-09 07:25:31 +0000215 for i in (0, 1, 2):
216 p = pickle.dumps(self.s, i)
217 dup = pickle.loads(p)
218 self.assertEqual(self.s, dup, "%s != %s" % (self.s, dup))
219 if type(self.s) not in (set, frozenset):
220 self.s.x = 10
221 p = pickle.dumps(self.s)
222 dup = pickle.loads(p)
223 self.assertEqual(self.s.x, dup.x)
Raymond Hettingera690a992003-11-16 16:17:49 +0000224
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000225 def test_deepcopy(self):
226 class Tracer:
227 def __init__(self, value):
228 self.value = value
229 def __hash__(self):
Tim Peters58eb11c2004-01-18 20:29:55 +0000230 return self.value
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000231 def __deepcopy__(self, memo=None):
232 return Tracer(self.value + 1)
233 t = Tracer(10)
234 s = self.thetype([t])
235 dup = copy.deepcopy(s)
236 self.assertNotEqual(id(s), id(dup))
237 for elem in dup:
238 newt = elem
239 self.assertNotEqual(id(t), id(newt))
240 self.assertEqual(t.value + 1, newt.value)
241
Raymond Hettingerbb999b52005-06-18 21:00:26 +0000242 def test_gc(self):
243 # Create a nest of cycles to exercise overall ref count check
244 class A:
245 pass
246 s = set(A() for i in xrange(1000))
247 for elem in s:
248 elem.cycle = s
249 elem.sub = elem
250 elem.set = set([elem])
251
Raymond Hettinger97979dd2005-08-12 23:58:22 +0000252 def test_subclass_with_custom_hash(self):
253 # Bug #1257731
254 class H(self.thetype):
255 def __hash__(self):
Tim Peters6902b442006-04-11 00:43:27 +0000256 return int(id(self) & 0x7fffffff)
Raymond Hettinger97979dd2005-08-12 23:58:22 +0000257 s=H()
258 f=set()
259 f.add(s)
260 self.assert_(s in f)
261 f.remove(s)
262 f.add(s)
263 f.discard(s)
264
Raymond Hettinger9bda1d62005-09-16 07:14:21 +0000265 def test_badcmp(self):
266 s = self.thetype([BadCmp()])
267 # Detect comparison errors during insertion and lookup
268 self.assertRaises(RuntimeError, self.thetype, [BadCmp(), BadCmp()])
269 self.assertRaises(RuntimeError, s.__contains__, BadCmp())
270 # Detect errors during mutating operations
271 if hasattr(s, 'add'):
272 self.assertRaises(RuntimeError, s.add, BadCmp())
273 self.assertRaises(RuntimeError, s.discard, BadCmp())
274 self.assertRaises(RuntimeError, s.remove, BadCmp())
275
Raymond Hettinger53999102006-12-30 04:01:17 +0000276 def test_cyclical_repr(self):
277 w = ReprWrapper()
278 s = self.thetype([w])
279 w.value = s
280 name = repr(s).partition('(')[0] # strip class name from repr string
281 self.assertEqual(repr(s), '%s([%s(...)])' % (name, name))
282
283 def test_cyclical_print(self):
284 w = ReprWrapper()
285 s = self.thetype([w])
286 w.value = s
Neal Norwitzbe9160b2008-03-25 06:35:10 +0000287 fo = open(test_support.TESTFN, "wb")
Raymond Hettinger53999102006-12-30 04:01:17 +0000288 try:
Raymond Hettinger53999102006-12-30 04:01:17 +0000289 print >> fo, s,
290 fo.close()
291 fo = open(test_support.TESTFN, "rb")
292 self.assertEqual(fo.read(), repr(s))
293 finally:
294 fo.close()
Neal Norwitzbe9160b2008-03-25 06:35:10 +0000295 test_support.unlink(test_support.TESTFN)
Raymond Hettinger53999102006-12-30 04:01:17 +0000296
Raymond Hettingerd6fc72a2007-02-19 02:03:19 +0000297 def test_do_not_rehash_dict_keys(self):
298 n = 10
299 d = dict.fromkeys(map(HashCountingInt, xrange(n)))
300 self.assertEqual(sum(elem.hash_count for elem in d), n)
301 s = self.thetype(d)
302 self.assertEqual(sum(elem.hash_count for elem in d), n)
303 s.difference(d)
Tim Petersea5962f2007-03-12 18:07:52 +0000304 self.assertEqual(sum(elem.hash_count for elem in d), n)
Raymond Hettingerd6fc72a2007-02-19 02:03:19 +0000305 if hasattr(s, 'symmetric_difference_update'):
306 s.symmetric_difference_update(d)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000307 self.assertEqual(sum(elem.hash_count for elem in d), n)
Raymond Hettinger0bbbfc42007-03-20 21:27:24 +0000308 d2 = dict.fromkeys(set(d))
309 self.assertEqual(sum(elem.hash_count for elem in d), n)
310 d3 = dict.fromkeys(frozenset(d))
Tim Petersea5962f2007-03-12 18:07:52 +0000311 self.assertEqual(sum(elem.hash_count for elem in d), n)
Raymond Hettingere3146f52007-03-21 20:33:57 +0000312 d3 = dict.fromkeys(frozenset(d), 123)
313 self.assertEqual(sum(elem.hash_count for elem in d), n)
314 self.assertEqual(d3, dict.fromkeys(d, 123))
Raymond Hettingerd6fc72a2007-02-19 02:03:19 +0000315
Raymond Hettingera690a992003-11-16 16:17:49 +0000316class TestSet(TestJointOps):
317 thetype = set
318
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000319 def test_init(self):
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000320 s = self.thetype()
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000321 s.__init__(self.word)
322 self.assertEqual(s, set(self.word))
323 s.__init__(self.otherword)
324 self.assertEqual(s, set(self.otherword))
Raymond Hettingereae05de2004-07-09 04:51:24 +0000325 self.assertRaises(TypeError, s.__init__, s, 2);
326 self.assertRaises(TypeError, s.__init__, 1);
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000327
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000328 def test_constructor_identity(self):
329 s = self.thetype(range(3))
330 t = self.thetype(s)
331 self.assertNotEqual(id(s), id(t))
332
Raymond Hettingera690a992003-11-16 16:17:49 +0000333 def test_hash(self):
334 self.assertRaises(TypeError, hash, self.s)
335
336 def test_clear(self):
337 self.s.clear()
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000338 self.assertEqual(self.s, set())
339 self.assertEqual(len(self.s), 0)
Raymond Hettingera690a992003-11-16 16:17:49 +0000340
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000341 def test_copy(self):
342 dup = self.s.copy()
343 self.assertEqual(self.s, dup)
344 self.assertNotEqual(id(self.s), id(dup))
345
Raymond Hettingera690a992003-11-16 16:17:49 +0000346 def test_add(self):
347 self.s.add('Q')
348 self.assert_('Q' in self.s)
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000349 dup = self.s.copy()
350 self.s.add('Q')
351 self.assertEqual(self.s, dup)
Raymond Hettingera690a992003-11-16 16:17:49 +0000352 self.assertRaises(TypeError, self.s.add, [])
353
354 def test_remove(self):
355 self.s.remove('a')
356 self.assert_('a' not in self.s)
357 self.assertRaises(KeyError, self.s.remove, 'Q')
358 self.assertRaises(TypeError, self.s.remove, [])
Raymond Hettingerbfd334a2003-11-22 03:55:23 +0000359 s = self.thetype([frozenset(self.word)])
360 self.assert_(self.thetype(self.word) in s)
361 s.remove(self.thetype(self.word))
362 self.assert_(self.thetype(self.word) not in s)
363 self.assertRaises(KeyError, self.s.remove, self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +0000364
Raymond Hettingerc789f342006-12-08 17:35:25 +0000365 def test_remove_keyerror_unpacking(self):
366 # bug: www.python.org/sf/1576657
367 for v1 in ['Q', (1,)]:
368 try:
369 self.s.remove(v1)
370 except KeyError, e:
371 v2 = e.args[0]
372 self.assertEqual(v1, v2)
373 else:
374 self.fail()
375
Raymond Hettingera690a992003-11-16 16:17:49 +0000376 def test_discard(self):
377 self.s.discard('a')
378 self.assert_('a' not in self.s)
379 self.s.discard('Q')
380 self.assertRaises(TypeError, self.s.discard, [])
Raymond Hettingerbfd334a2003-11-22 03:55:23 +0000381 s = self.thetype([frozenset(self.word)])
382 self.assert_(self.thetype(self.word) in s)
383 s.discard(self.thetype(self.word))
384 self.assert_(self.thetype(self.word) not in s)
385 s.discard(self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +0000386
387 def test_pop(self):
388 for i in xrange(len(self.s)):
389 elem = self.s.pop()
390 self.assert_(elem not in self.s)
391 self.assertRaises(KeyError, self.s.pop)
392
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000393 def test_update(self):
394 retval = self.s.update(self.otherword)
Raymond Hettingera690a992003-11-16 16:17:49 +0000395 self.assertEqual(retval, None)
396 for c in (self.word + self.otherword):
397 self.assert_(c in self.s)
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000398 self.assertRaises(PassThru, self.s.update, check_pass_thru())
399 self.assertRaises(TypeError, self.s.update, [[]])
400 for p, q in (('cdc', 'abcd'), ('efgfe', 'abcefg'), ('ccb', 'abc'), ('ef', 'abcef')):
401 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
402 s = self.thetype('abcba')
403 self.assertEqual(s.update(C(p)), None)
404 self.assertEqual(s, set(q))
Raymond Hettingeree4bcad2008-06-09 08:33:37 +0000405 for p in ('cdc', 'efgfe', 'ccb', 'ef', 'abcda'):
406 q = 'ahi'
407 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
408 s = self.thetype('abcba')
409 self.assertEqual(s.update(C(p), C(q)), None)
410 self.assertEqual(s, set(s) | set(p) | set(q))
Raymond Hettingera690a992003-11-16 16:17:49 +0000411
412 def test_ior(self):
413 self.s |= set(self.otherword)
414 for c in (self.word + self.otherword):
415 self.assert_(c in self.s)
416
417 def test_intersection_update(self):
418 retval = self.s.intersection_update(self.otherword)
419 self.assertEqual(retval, None)
420 for c in (self.word + self.otherword):
421 if c in self.otherword and c in self.word:
422 self.assert_(c in self.s)
423 else:
424 self.assert_(c not in self.s)
425 self.assertRaises(PassThru, self.s.intersection_update, check_pass_thru())
426 self.assertRaises(TypeError, self.s.intersection_update, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000427 for p, q in (('cdc', 'c'), ('efgfe', ''), ('ccb', 'bc'), ('ef', '')):
428 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
429 s = self.thetype('abcba')
430 self.assertEqual(s.intersection_update(C(p)), None)
431 self.assertEqual(s, set(q))
Raymond Hettingera690a992003-11-16 16:17:49 +0000432
433 def test_iand(self):
434 self.s &= set(self.otherword)
435 for c in (self.word + self.otherword):
436 if c in self.otherword and c in self.word:
437 self.assert_(c in self.s)
438 else:
439 self.assert_(c not in self.s)
440
441 def test_difference_update(self):
442 retval = self.s.difference_update(self.otherword)
443 self.assertEqual(retval, None)
444 for c in (self.word + self.otherword):
445 if c in self.word and c not in self.otherword:
446 self.assert_(c in self.s)
447 else:
448 self.assert_(c not in self.s)
449 self.assertRaises(PassThru, self.s.difference_update, check_pass_thru())
450 self.assertRaises(TypeError, self.s.difference_update, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000451 self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
452 for p, q in (('cdc', 'ab'), ('efgfe', 'abc'), ('ccb', 'a'), ('ef', 'abc')):
453 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
454 s = self.thetype('abcba')
455 self.assertEqual(s.difference_update(C(p)), None)
456 self.assertEqual(s, set(q))
Raymond Hettingera690a992003-11-16 16:17:49 +0000457
458 def test_isub(self):
459 self.s -= set(self.otherword)
460 for c in (self.word + self.otherword):
461 if c in self.word and c not in self.otherword:
462 self.assert_(c in self.s)
463 else:
464 self.assert_(c not in self.s)
465
466 def test_symmetric_difference_update(self):
467 retval = self.s.symmetric_difference_update(self.otherword)
468 self.assertEqual(retval, None)
469 for c in (self.word + self.otherword):
470 if (c in self.word) ^ (c in self.otherword):
471 self.assert_(c in self.s)
472 else:
473 self.assert_(c not in self.s)
474 self.assertRaises(PassThru, self.s.symmetric_difference_update, check_pass_thru())
475 self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000476 for p, q in (('cdc', 'abd'), ('efgfe', 'abcefg'), ('ccb', 'a'), ('ef', 'abcef')):
477 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
478 s = self.thetype('abcba')
479 self.assertEqual(s.symmetric_difference_update(C(p)), None)
480 self.assertEqual(s, set(q))
Raymond Hettingera690a992003-11-16 16:17:49 +0000481
482 def test_ixor(self):
483 self.s ^= set(self.otherword)
484 for c in (self.word + self.otherword):
485 if (c in self.word) ^ (c in self.otherword):
486 self.assert_(c in self.s)
487 else:
488 self.assert_(c not in self.s)
489
Raymond Hettingerc991db22005-08-11 07:58:45 +0000490 def test_inplace_on_self(self):
491 t = self.s.copy()
492 t |= t
493 self.assertEqual(t, self.s)
494 t &= t
495 self.assertEqual(t, self.s)
496 t -= t
497 self.assertEqual(t, self.thetype())
498 t = self.s.copy()
499 t ^= t
500 self.assertEqual(t, self.thetype())
501
Raymond Hettinger691d8052004-05-30 07:26:47 +0000502 def test_weakref(self):
503 s = self.thetype('gallahad')
504 p = proxy(s)
505 self.assertEqual(str(p), str(s))
506 s = None
507 self.assertRaises(ReferenceError, str, p)
508
Raymond Hettingerc47e01d2005-08-16 10:44:15 +0000509 # C API test only available in a debug build
Barry Warsaw176014f2006-03-30 22:45:35 +0000510 if hasattr(set, "test_c_api"):
Raymond Hettingerc47e01d2005-08-16 10:44:15 +0000511 def test_c_api(self):
512 self.assertEqual(set('abc').test_c_api(), True)
513
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000514class SetSubclass(set):
515 pass
516
517class TestSetSubclass(TestSet):
518 thetype = SetSubclass
Raymond Hettingera690a992003-11-16 16:17:49 +0000519
Raymond Hettinger9fdfadb2007-01-11 18:22:55 +0000520class SetSubclassWithKeywordArgs(set):
521 def __init__(self, iterable=[], newarg=None):
522 set.__init__(self, iterable)
523
524class TestSetSubclassWithKeywordArgs(TestSet):
Tim Petersf733abb2007-01-30 03:03:46 +0000525
Raymond Hettinger9fdfadb2007-01-11 18:22:55 +0000526 def test_keywords_in_subclass(self):
527 'SF bug #1486663 -- this used to erroneously raise a TypeError'
528 SetSubclassWithKeywordArgs(newarg=1)
529
Raymond Hettingera690a992003-11-16 16:17:49 +0000530class TestFrozenSet(TestJointOps):
531 thetype = frozenset
532
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000533 def test_init(self):
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000534 s = self.thetype(self.word)
535 s.__init__(self.otherword)
536 self.assertEqual(s, set(self.word))
537
Raymond Hettingerd7946662005-08-01 21:39:29 +0000538 def test_singleton_empty_frozenset(self):
539 f = frozenset()
540 efs = [frozenset(), frozenset([]), frozenset(()), frozenset(''),
541 frozenset(), frozenset([]), frozenset(()), frozenset(''),
542 frozenset(xrange(0)), frozenset(frozenset()),
543 frozenset(f), f]
544 # All of the empty frozensets should have just one id()
545 self.assertEqual(len(set(map(id, efs))), 1)
546
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000547 def test_constructor_identity(self):
548 s = self.thetype(range(3))
549 t = self.thetype(s)
550 self.assertEqual(id(s), id(t))
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000551
Raymond Hettingera690a992003-11-16 16:17:49 +0000552 def test_hash(self):
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000553 self.assertEqual(hash(self.thetype('abcdeb')),
554 hash(self.thetype('ebecda')))
555
Raymond Hettinger82cb9a22005-07-05 05:34:43 +0000556 # make sure that all permutations give the same hash value
557 n = 100
558 seq = [randrange(n) for i in xrange(n)]
559 results = set()
560 for i in xrange(200):
561 shuffle(seq)
562 results.add(hash(self.thetype(seq)))
563 self.assertEqual(len(results), 1)
564
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000565 def test_copy(self):
566 dup = self.s.copy()
567 self.assertEqual(id(self.s), id(dup))
Raymond Hettingera690a992003-11-16 16:17:49 +0000568
569 def test_frozen_as_dictkey(self):
570 seq = range(10) + list('abcdefg') + ['apple']
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000571 key1 = self.thetype(seq)
572 key2 = self.thetype(reversed(seq))
Raymond Hettingera690a992003-11-16 16:17:49 +0000573 self.assertEqual(key1, key2)
574 self.assertNotEqual(id(key1), id(key2))
575 d = {}
576 d[key1] = 42
577 self.assertEqual(d[key2], 42)
578
579 def test_hash_caching(self):
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000580 f = self.thetype('abcdcda')
Raymond Hettingera690a992003-11-16 16:17:49 +0000581 self.assertEqual(hash(f), hash(f))
582
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000583 def test_hash_effectiveness(self):
584 n = 13
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000585 hashvalues = set()
Raymond Hettinger6e70acc2003-12-31 02:01:33 +0000586 addhashvalue = hashvalues.add
587 elemmasks = [(i+1, 1<<i) for i in range(n)]
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000588 for i in xrange(2**n):
Raymond Hettinger6e70acc2003-12-31 02:01:33 +0000589 addhashvalue(hash(frozenset([e for e, m in elemmasks if m&i])))
590 self.assertEqual(len(hashvalues), 2**n)
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000591
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000592class FrozenSetSubclass(frozenset):
593 pass
594
595class TestFrozenSetSubclass(TestFrozenSet):
596 thetype = FrozenSetSubclass
597
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000598 def test_constructor_identity(self):
599 s = self.thetype(range(3))
600 t = self.thetype(s)
601 self.assertNotEqual(id(s), id(t))
602
603 def test_copy(self):
604 dup = self.s.copy()
605 self.assertNotEqual(id(self.s), id(dup))
606
607 def test_nested_empty_constructor(self):
608 s = self.thetype()
609 t = self.thetype(s)
610 self.assertEqual(s, t)
611
Raymond Hettingerd7946662005-08-01 21:39:29 +0000612 def test_singleton_empty_frozenset(self):
613 Frozenset = self.thetype
614 f = frozenset()
615 F = Frozenset()
616 efs = [Frozenset(), Frozenset([]), Frozenset(()), Frozenset(''),
617 Frozenset(), Frozenset([]), Frozenset(()), Frozenset(''),
618 Frozenset(xrange(0)), Frozenset(Frozenset()),
619 Frozenset(frozenset()), f, F, Frozenset(f), Frozenset(F)]
620 # All empty frozenset subclass instances should have different ids
621 self.assertEqual(len(set(map(id, efs))), len(efs))
622
Raymond Hettingera690a992003-11-16 16:17:49 +0000623# Tests taken from test_sets.py =============================================
624
625empty_set = set()
626
627#==============================================================================
628
629class TestBasicOps(unittest.TestCase):
630
631 def test_repr(self):
632 if self.repr is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000633 self.assertEqual(repr(self.set), self.repr)
Raymond Hettingera690a992003-11-16 16:17:49 +0000634
Raymond Hettingereae05de2004-07-09 04:51:24 +0000635 def test_print(self):
Neal Norwitzbe9160b2008-03-25 06:35:10 +0000636 fo = open(test_support.TESTFN, "wb")
Raymond Hettingereae05de2004-07-09 04:51:24 +0000637 try:
Raymond Hettingereae05de2004-07-09 04:51:24 +0000638 print >> fo, self.set,
639 fo.close()
640 fo = open(test_support.TESTFN, "rb")
641 self.assertEqual(fo.read(), repr(self.set))
642 finally:
643 fo.close()
Neal Norwitzbe9160b2008-03-25 06:35:10 +0000644 test_support.unlink(test_support.TESTFN)
Raymond Hettingereae05de2004-07-09 04:51:24 +0000645
Raymond Hettingera690a992003-11-16 16:17:49 +0000646 def test_length(self):
647 self.assertEqual(len(self.set), self.length)
648
649 def test_self_equality(self):
650 self.assertEqual(self.set, self.set)
651
652 def test_equivalent_equality(self):
653 self.assertEqual(self.set, self.dup)
654
655 def test_copy(self):
656 self.assertEqual(self.set.copy(), self.dup)
657
658 def test_self_union(self):
659 result = self.set | self.set
660 self.assertEqual(result, self.dup)
661
662 def test_empty_union(self):
663 result = self.set | empty_set
664 self.assertEqual(result, self.dup)
665
666 def test_union_empty(self):
667 result = empty_set | self.set
668 self.assertEqual(result, self.dup)
669
670 def test_self_intersection(self):
671 result = self.set & self.set
672 self.assertEqual(result, self.dup)
673
674 def test_empty_intersection(self):
675 result = self.set & empty_set
676 self.assertEqual(result, empty_set)
677
678 def test_intersection_empty(self):
679 result = empty_set & self.set
680 self.assertEqual(result, empty_set)
681
Raymond Hettinger1760c8a2007-11-08 02:52:43 +0000682 def test_self_isdisjoint(self):
683 result = self.set.isdisjoint(self.set)
684 self.assertEqual(result, not self.set)
685
686 def test_empty_isdisjoint(self):
687 result = self.set.isdisjoint(empty_set)
688 self.assertEqual(result, True)
689
690 def test_isdisjoint_empty(self):
691 result = empty_set.isdisjoint(self.set)
692 self.assertEqual(result, True)
693
Raymond Hettingera690a992003-11-16 16:17:49 +0000694 def test_self_symmetric_difference(self):
695 result = self.set ^ self.set
696 self.assertEqual(result, empty_set)
697
698 def checkempty_symmetric_difference(self):
699 result = self.set ^ empty_set
700 self.assertEqual(result, self.set)
701
702 def test_self_difference(self):
703 result = self.set - self.set
704 self.assertEqual(result, empty_set)
705
706 def test_empty_difference(self):
707 result = self.set - empty_set
708 self.assertEqual(result, self.dup)
709
710 def test_empty_difference_rev(self):
711 result = empty_set - self.set
712 self.assertEqual(result, empty_set)
713
714 def test_iteration(self):
715 for v in self.set:
716 self.assert_(v in self.values)
Neal Norwitzfcf44352005-11-27 20:37:43 +0000717 setiter = iter(self.set)
Armin Rigof5b3e362006-02-11 21:32:43 +0000718 # note: __length_hint__ is an internal undocumented API,
719 # don't rely on it in your own programs
720 self.assertEqual(setiter.__length_hint__(), len(self.set))
Raymond Hettingera690a992003-11-16 16:17:49 +0000721
722 def test_pickling(self):
723 p = pickle.dumps(self.set)
724 copy = pickle.loads(p)
725 self.assertEqual(self.set, copy,
726 "%s != %s" % (self.set, copy))
727
728#------------------------------------------------------------------------------
729
730class TestBasicOpsEmpty(TestBasicOps):
731 def setUp(self):
732 self.case = "empty set"
733 self.values = []
734 self.set = set(self.values)
735 self.dup = set(self.values)
736 self.length = 0
737 self.repr = "set([])"
738
739#------------------------------------------------------------------------------
740
741class TestBasicOpsSingleton(TestBasicOps):
742 def setUp(self):
743 self.case = "unit set (number)"
744 self.values = [3]
745 self.set = set(self.values)
746 self.dup = set(self.values)
747 self.length = 1
748 self.repr = "set([3])"
749
750 def test_in(self):
751 self.failUnless(3 in self.set)
752
753 def test_not_in(self):
754 self.failUnless(2 not in self.set)
755
756#------------------------------------------------------------------------------
757
758class TestBasicOpsTuple(TestBasicOps):
759 def setUp(self):
760 self.case = "unit set (tuple)"
761 self.values = [(0, "zero")]
762 self.set = set(self.values)
763 self.dup = set(self.values)
764 self.length = 1
765 self.repr = "set([(0, 'zero')])"
766
767 def test_in(self):
768 self.failUnless((0, "zero") in self.set)
769
770 def test_not_in(self):
771 self.failUnless(9 not in self.set)
772
773#------------------------------------------------------------------------------
774
775class TestBasicOpsTriple(TestBasicOps):
776 def setUp(self):
777 self.case = "triple set"
778 self.values = [0, "zero", operator.add]
779 self.set = set(self.values)
780 self.dup = set(self.values)
781 self.length = 3
782 self.repr = None
783
784#==============================================================================
785
786def baditer():
787 raise TypeError
788 yield True
789
790def gooditer():
791 yield True
792
793class TestExceptionPropagation(unittest.TestCase):
794 """SF 628246: Set constructor should not trap iterator TypeErrors"""
795
796 def test_instanceWithException(self):
797 self.assertRaises(TypeError, set, baditer())
798
799 def test_instancesWithoutException(self):
800 # All of these iterables should load without exception.
801 set([1,2,3])
802 set((1,2,3))
803 set({'one':1, 'two':2, 'three':3})
804 set(xrange(3))
805 set('abc')
806 set(gooditer())
807
Neal Norwitzfcf44352005-11-27 20:37:43 +0000808 def test_changingSizeWhileIterating(self):
809 s = set([1,2,3])
810 try:
811 for i in s:
812 s.update([4])
813 except RuntimeError:
814 pass
815 else:
816 self.fail("no exception when changing size during iteration")
817
Raymond Hettingera690a992003-11-16 16:17:49 +0000818#==============================================================================
819
820class TestSetOfSets(unittest.TestCase):
821 def test_constructor(self):
822 inner = frozenset([1])
823 outer = set([inner])
824 element = outer.pop()
825 self.assertEqual(type(element), frozenset)
826 outer.add(inner) # Rebuild set of sets with .add method
827 outer.remove(inner)
828 self.assertEqual(outer, set()) # Verify that remove worked
829 outer.discard(inner) # Absence of KeyError indicates working fine
830
831#==============================================================================
832
833class TestBinaryOps(unittest.TestCase):
834 def setUp(self):
835 self.set = set((2, 4, 6))
836
837 def test_eq(self): # SF bug 643115
838 self.assertEqual(self.set, set({2:1,4:3,6:5}))
839
840 def test_union_subset(self):
841 result = self.set | set([2])
842 self.assertEqual(result, set((2, 4, 6)))
843
844 def test_union_superset(self):
845 result = self.set | set([2, 4, 6, 8])
846 self.assertEqual(result, set([2, 4, 6, 8]))
847
848 def test_union_overlap(self):
849 result = self.set | set([3, 4, 5])
850 self.assertEqual(result, set([2, 3, 4, 5, 6]))
851
852 def test_union_non_overlap(self):
853 result = self.set | set([8])
854 self.assertEqual(result, set([2, 4, 6, 8]))
855
856 def test_intersection_subset(self):
857 result = self.set & set((2, 4))
858 self.assertEqual(result, set((2, 4)))
859
860 def test_intersection_superset(self):
861 result = self.set & set([2, 4, 6, 8])
862 self.assertEqual(result, set([2, 4, 6]))
863
864 def test_intersection_overlap(self):
865 result = self.set & set([3, 4, 5])
866 self.assertEqual(result, set([4]))
867
868 def test_intersection_non_overlap(self):
869 result = self.set & set([8])
870 self.assertEqual(result, empty_set)
871
Raymond Hettinger1760c8a2007-11-08 02:52:43 +0000872 def test_isdisjoint_subset(self):
873 result = self.set.isdisjoint(set((2, 4)))
874 self.assertEqual(result, False)
875
876 def test_isdisjoint_superset(self):
877 result = self.set.isdisjoint(set([2, 4, 6, 8]))
878 self.assertEqual(result, False)
879
880 def test_isdisjoint_overlap(self):
881 result = self.set.isdisjoint(set([3, 4, 5]))
882 self.assertEqual(result, False)
883
884 def test_isdisjoint_non_overlap(self):
885 result = self.set.isdisjoint(set([8]))
886 self.assertEqual(result, True)
887
Raymond Hettingera690a992003-11-16 16:17:49 +0000888 def test_sym_difference_subset(self):
889 result = self.set ^ set((2, 4))
890 self.assertEqual(result, set([6]))
891
892 def test_sym_difference_superset(self):
893 result = self.set ^ set((2, 4, 6, 8))
894 self.assertEqual(result, set([8]))
895
896 def test_sym_difference_overlap(self):
897 result = self.set ^ set((3, 4, 5))
898 self.assertEqual(result, set([2, 3, 5, 6]))
899
900 def test_sym_difference_non_overlap(self):
901 result = self.set ^ set([8])
902 self.assertEqual(result, set([2, 4, 6, 8]))
903
904 def test_cmp(self):
905 a, b = set('a'), set('b')
906 self.assertRaises(TypeError, cmp, a, b)
907
908 # You can view this as a buglet: cmp(a, a) does not raise TypeError,
909 # because __eq__ is tried before __cmp__, and a.__eq__(a) returns True,
910 # which Python thinks is good enough to synthesize a cmp() result
911 # without calling __cmp__.
912 self.assertEqual(cmp(a, a), 0)
913
914 self.assertRaises(TypeError, cmp, a, 12)
915 self.assertRaises(TypeError, cmp, "abc", a)
916
917#==============================================================================
918
919class TestUpdateOps(unittest.TestCase):
920 def setUp(self):
921 self.set = set((2, 4, 6))
922
923 def test_union_subset(self):
924 self.set |= set([2])
925 self.assertEqual(self.set, set((2, 4, 6)))
926
927 def test_union_superset(self):
928 self.set |= set([2, 4, 6, 8])
929 self.assertEqual(self.set, set([2, 4, 6, 8]))
930
931 def test_union_overlap(self):
932 self.set |= set([3, 4, 5])
933 self.assertEqual(self.set, set([2, 3, 4, 5, 6]))
934
935 def test_union_non_overlap(self):
936 self.set |= set([8])
937 self.assertEqual(self.set, set([2, 4, 6, 8]))
938
939 def test_union_method_call(self):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000940 self.set.update(set([3, 4, 5]))
Raymond Hettingera690a992003-11-16 16:17:49 +0000941 self.assertEqual(self.set, set([2, 3, 4, 5, 6]))
942
943 def test_intersection_subset(self):
944 self.set &= set((2, 4))
945 self.assertEqual(self.set, set((2, 4)))
946
947 def test_intersection_superset(self):
948 self.set &= set([2, 4, 6, 8])
949 self.assertEqual(self.set, set([2, 4, 6]))
950
951 def test_intersection_overlap(self):
952 self.set &= set([3, 4, 5])
953 self.assertEqual(self.set, set([4]))
954
955 def test_intersection_non_overlap(self):
956 self.set &= set([8])
957 self.assertEqual(self.set, empty_set)
958
959 def test_intersection_method_call(self):
960 self.set.intersection_update(set([3, 4, 5]))
961 self.assertEqual(self.set, set([4]))
962
963 def test_sym_difference_subset(self):
964 self.set ^= set((2, 4))
965 self.assertEqual(self.set, set([6]))
966
967 def test_sym_difference_superset(self):
968 self.set ^= set((2, 4, 6, 8))
969 self.assertEqual(self.set, set([8]))
970
971 def test_sym_difference_overlap(self):
972 self.set ^= set((3, 4, 5))
973 self.assertEqual(self.set, set([2, 3, 5, 6]))
974
975 def test_sym_difference_non_overlap(self):
976 self.set ^= set([8])
977 self.assertEqual(self.set, set([2, 4, 6, 8]))
978
979 def test_sym_difference_method_call(self):
980 self.set.symmetric_difference_update(set([3, 4, 5]))
981 self.assertEqual(self.set, set([2, 3, 5, 6]))
982
983 def test_difference_subset(self):
984 self.set -= set((2, 4))
985 self.assertEqual(self.set, set([6]))
986
987 def test_difference_superset(self):
988 self.set -= set((2, 4, 6, 8))
989 self.assertEqual(self.set, set([]))
990
991 def test_difference_overlap(self):
992 self.set -= set((3, 4, 5))
993 self.assertEqual(self.set, set([2, 6]))
994
995 def test_difference_non_overlap(self):
996 self.set -= set([8])
997 self.assertEqual(self.set, set([2, 4, 6]))
998
999 def test_difference_method_call(self):
1000 self.set.difference_update(set([3, 4, 5]))
1001 self.assertEqual(self.set, set([2, 6]))
1002
1003#==============================================================================
1004
1005class TestMutate(unittest.TestCase):
1006 def setUp(self):
1007 self.values = ["a", "b", "c"]
1008 self.set = set(self.values)
1009
1010 def test_add_present(self):
1011 self.set.add("c")
1012 self.assertEqual(self.set, set("abc"))
1013
1014 def test_add_absent(self):
1015 self.set.add("d")
1016 self.assertEqual(self.set, set("abcd"))
1017
1018 def test_add_until_full(self):
1019 tmp = set()
1020 expected_len = 0
1021 for v in self.values:
1022 tmp.add(v)
1023 expected_len += 1
1024 self.assertEqual(len(tmp), expected_len)
1025 self.assertEqual(tmp, self.set)
1026
1027 def test_remove_present(self):
1028 self.set.remove("b")
1029 self.assertEqual(self.set, set("ac"))
1030
1031 def test_remove_absent(self):
1032 try:
1033 self.set.remove("d")
1034 self.fail("Removing missing element should have raised LookupError")
1035 except LookupError:
1036 pass
1037
1038 def test_remove_until_empty(self):
1039 expected_len = len(self.set)
1040 for v in self.values:
1041 self.set.remove(v)
1042 expected_len -= 1
1043 self.assertEqual(len(self.set), expected_len)
1044
1045 def test_discard_present(self):
1046 self.set.discard("c")
1047 self.assertEqual(self.set, set("ab"))
1048
1049 def test_discard_absent(self):
1050 self.set.discard("d")
1051 self.assertEqual(self.set, set("abc"))
1052
1053 def test_clear(self):
1054 self.set.clear()
1055 self.assertEqual(len(self.set), 0)
1056
1057 def test_pop(self):
1058 popped = {}
1059 while self.set:
1060 popped[self.set.pop()] = None
1061 self.assertEqual(len(popped), len(self.values))
1062 for v in self.values:
1063 self.failUnless(v in popped)
1064
1065 def test_update_empty_tuple(self):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001066 self.set.update(())
Raymond Hettingera690a992003-11-16 16:17:49 +00001067 self.assertEqual(self.set, set(self.values))
1068
1069 def test_update_unit_tuple_overlap(self):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001070 self.set.update(("a",))
Raymond Hettingera690a992003-11-16 16:17:49 +00001071 self.assertEqual(self.set, set(self.values))
1072
1073 def test_update_unit_tuple_non_overlap(self):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001074 self.set.update(("a", "z"))
Raymond Hettingera690a992003-11-16 16:17:49 +00001075 self.assertEqual(self.set, set(self.values + ["z"]))
1076
1077#==============================================================================
1078
1079class TestSubsets(unittest.TestCase):
1080
1081 case2method = {"<=": "issubset",
1082 ">=": "issuperset",
1083 }
1084
1085 reverse = {"==": "==",
1086 "!=": "!=",
1087 "<": ">",
1088 ">": "<",
1089 "<=": ">=",
1090 ">=": "<=",
1091 }
1092
1093 def test_issubset(self):
1094 x = self.left
1095 y = self.right
1096 for case in "!=", "==", "<", "<=", ">", ">=":
1097 expected = case in self.cases
1098 # Test the binary infix spelling.
1099 result = eval("x" + case + "y", locals())
1100 self.assertEqual(result, expected)
1101 # Test the "friendly" method-name spelling, if one exists.
1102 if case in TestSubsets.case2method:
1103 method = getattr(x, TestSubsets.case2method[case])
1104 result = method(y)
1105 self.assertEqual(result, expected)
1106
1107 # Now do the same for the operands reversed.
1108 rcase = TestSubsets.reverse[case]
1109 result = eval("y" + rcase + "x", locals())
1110 self.assertEqual(result, expected)
1111 if rcase in TestSubsets.case2method:
1112 method = getattr(y, TestSubsets.case2method[rcase])
1113 result = method(x)
1114 self.assertEqual(result, expected)
1115#------------------------------------------------------------------------------
1116
1117class TestSubsetEqualEmpty(TestSubsets):
1118 left = set()
1119 right = set()
1120 name = "both empty"
1121 cases = "==", "<=", ">="
1122
1123#------------------------------------------------------------------------------
1124
1125class TestSubsetEqualNonEmpty(TestSubsets):
1126 left = set([1, 2])
1127 right = set([1, 2])
1128 name = "equal pair"
1129 cases = "==", "<=", ">="
1130
1131#------------------------------------------------------------------------------
1132
1133class TestSubsetEmptyNonEmpty(TestSubsets):
1134 left = set()
1135 right = set([1, 2])
1136 name = "one empty, one non-empty"
1137 cases = "!=", "<", "<="
1138
1139#------------------------------------------------------------------------------
1140
1141class TestSubsetPartial(TestSubsets):
1142 left = set([1])
1143 right = set([1, 2])
1144 name = "one a non-empty proper subset of other"
1145 cases = "!=", "<", "<="
1146
1147#------------------------------------------------------------------------------
1148
1149class TestSubsetNonOverlap(TestSubsets):
1150 left = set([1])
1151 right = set([2])
1152 name = "neither empty, neither contains"
1153 cases = "!="
1154
1155#==============================================================================
1156
1157class TestOnlySetsInBinaryOps(unittest.TestCase):
1158
1159 def test_eq_ne(self):
1160 # Unlike the others, this is testing that == and != *are* allowed.
1161 self.assertEqual(self.other == self.set, False)
1162 self.assertEqual(self.set == self.other, False)
1163 self.assertEqual(self.other != self.set, True)
1164 self.assertEqual(self.set != self.other, True)
1165
1166 def test_ge_gt_le_lt(self):
1167 self.assertRaises(TypeError, lambda: self.set < self.other)
1168 self.assertRaises(TypeError, lambda: self.set <= self.other)
1169 self.assertRaises(TypeError, lambda: self.set > self.other)
1170 self.assertRaises(TypeError, lambda: self.set >= self.other)
1171
1172 self.assertRaises(TypeError, lambda: self.other < self.set)
1173 self.assertRaises(TypeError, lambda: self.other <= self.set)
1174 self.assertRaises(TypeError, lambda: self.other > self.set)
1175 self.assertRaises(TypeError, lambda: self.other >= self.set)
1176
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001177 def test_update_operator(self):
Raymond Hettingera690a992003-11-16 16:17:49 +00001178 try:
1179 self.set |= self.other
1180 except TypeError:
1181 pass
1182 else:
1183 self.fail("expected TypeError")
1184
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001185 def test_update(self):
Raymond Hettingera690a992003-11-16 16:17:49 +00001186 if self.otherIsIterable:
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001187 self.set.update(self.other)
Raymond Hettingera690a992003-11-16 16:17:49 +00001188 else:
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001189 self.assertRaises(TypeError, self.set.update, self.other)
Raymond Hettingera690a992003-11-16 16:17:49 +00001190
1191 def test_union(self):
1192 self.assertRaises(TypeError, lambda: self.set | self.other)
1193 self.assertRaises(TypeError, lambda: self.other | self.set)
1194 if self.otherIsIterable:
1195 self.set.union(self.other)
1196 else:
1197 self.assertRaises(TypeError, self.set.union, self.other)
1198
1199 def test_intersection_update_operator(self):
1200 try:
1201 self.set &= self.other
1202 except TypeError:
1203 pass
1204 else:
1205 self.fail("expected TypeError")
1206
1207 def test_intersection_update(self):
1208 if self.otherIsIterable:
1209 self.set.intersection_update(self.other)
1210 else:
1211 self.assertRaises(TypeError,
1212 self.set.intersection_update,
1213 self.other)
1214
1215 def test_intersection(self):
1216 self.assertRaises(TypeError, lambda: self.set & self.other)
1217 self.assertRaises(TypeError, lambda: self.other & self.set)
1218 if self.otherIsIterable:
1219 self.set.intersection(self.other)
1220 else:
1221 self.assertRaises(TypeError, self.set.intersection, self.other)
1222
1223 def test_sym_difference_update_operator(self):
1224 try:
1225 self.set ^= self.other
1226 except TypeError:
1227 pass
1228 else:
1229 self.fail("expected TypeError")
1230
1231 def test_sym_difference_update(self):
1232 if self.otherIsIterable:
1233 self.set.symmetric_difference_update(self.other)
1234 else:
1235 self.assertRaises(TypeError,
1236 self.set.symmetric_difference_update,
1237 self.other)
1238
1239 def test_sym_difference(self):
1240 self.assertRaises(TypeError, lambda: self.set ^ self.other)
1241 self.assertRaises(TypeError, lambda: self.other ^ self.set)
1242 if self.otherIsIterable:
1243 self.set.symmetric_difference(self.other)
1244 else:
1245 self.assertRaises(TypeError, self.set.symmetric_difference, self.other)
1246
1247 def test_difference_update_operator(self):
1248 try:
1249 self.set -= self.other
1250 except TypeError:
1251 pass
1252 else:
1253 self.fail("expected TypeError")
1254
1255 def test_difference_update(self):
1256 if self.otherIsIterable:
1257 self.set.difference_update(self.other)
1258 else:
1259 self.assertRaises(TypeError,
1260 self.set.difference_update,
1261 self.other)
1262
1263 def test_difference(self):
1264 self.assertRaises(TypeError, lambda: self.set - self.other)
1265 self.assertRaises(TypeError, lambda: self.other - self.set)
1266 if self.otherIsIterable:
1267 self.set.difference(self.other)
1268 else:
1269 self.assertRaises(TypeError, self.set.difference, self.other)
1270
1271#------------------------------------------------------------------------------
1272
1273class TestOnlySetsNumeric(TestOnlySetsInBinaryOps):
1274 def setUp(self):
1275 self.set = set((1, 2, 3))
1276 self.other = 19
1277 self.otherIsIterable = False
1278
1279#------------------------------------------------------------------------------
1280
1281class TestOnlySetsDict(TestOnlySetsInBinaryOps):
1282 def setUp(self):
1283 self.set = set((1, 2, 3))
1284 self.other = {1:2, 3:4}
1285 self.otherIsIterable = True
1286
1287#------------------------------------------------------------------------------
1288
1289class TestOnlySetsOperator(TestOnlySetsInBinaryOps):
1290 def setUp(self):
1291 self.set = set((1, 2, 3))
1292 self.other = operator.add
1293 self.otherIsIterable = False
1294
1295#------------------------------------------------------------------------------
1296
1297class TestOnlySetsTuple(TestOnlySetsInBinaryOps):
1298 def setUp(self):
1299 self.set = set((1, 2, 3))
1300 self.other = (2, 4, 6)
1301 self.otherIsIterable = True
1302
1303#------------------------------------------------------------------------------
1304
1305class TestOnlySetsString(TestOnlySetsInBinaryOps):
1306 def setUp(self):
1307 self.set = set((1, 2, 3))
1308 self.other = 'abc'
1309 self.otherIsIterable = True
1310
1311#------------------------------------------------------------------------------
1312
1313class TestOnlySetsGenerator(TestOnlySetsInBinaryOps):
1314 def setUp(self):
1315 def gen():
1316 for i in xrange(0, 10, 2):
1317 yield i
1318 self.set = set((1, 2, 3))
1319 self.other = gen()
1320 self.otherIsIterable = True
1321
1322#==============================================================================
1323
1324class TestCopying(unittest.TestCase):
1325
1326 def test_copy(self):
1327 dup = self.set.copy()
1328 dup_list = list(dup); dup_list.sort()
1329 set_list = list(self.set); set_list.sort()
1330 self.assertEqual(len(dup_list), len(set_list))
1331 for i in range(len(dup_list)):
1332 self.failUnless(dup_list[i] is set_list[i])
1333
1334 def test_deep_copy(self):
1335 dup = copy.deepcopy(self.set)
Walter Dörwald70a6b492004-02-12 17:35:32 +00001336 ##print type(dup), repr(dup)
Raymond Hettingera690a992003-11-16 16:17:49 +00001337 dup_list = list(dup); dup_list.sort()
1338 set_list = list(self.set); set_list.sort()
1339 self.assertEqual(len(dup_list), len(set_list))
1340 for i in range(len(dup_list)):
1341 self.assertEqual(dup_list[i], set_list[i])
1342
1343#------------------------------------------------------------------------------
1344
1345class TestCopyingEmpty(TestCopying):
1346 def setUp(self):
1347 self.set = set()
1348
1349#------------------------------------------------------------------------------
1350
1351class TestCopyingSingleton(TestCopying):
1352 def setUp(self):
1353 self.set = set(["hello"])
1354
1355#------------------------------------------------------------------------------
1356
1357class TestCopyingTriple(TestCopying):
1358 def setUp(self):
1359 self.set = set(["zero", 0, None])
1360
1361#------------------------------------------------------------------------------
1362
1363class TestCopyingTuple(TestCopying):
1364 def setUp(self):
1365 self.set = set([(1, 2)])
1366
1367#------------------------------------------------------------------------------
1368
1369class TestCopyingNested(TestCopying):
1370 def setUp(self):
1371 self.set = set([((1, 2), (3, 4))])
1372
1373#==============================================================================
1374
1375class TestIdentities(unittest.TestCase):
1376 def setUp(self):
1377 self.a = set('abracadabra')
1378 self.b = set('alacazam')
1379
1380 def test_binopsVsSubsets(self):
1381 a, b = self.a, self.b
1382 self.assert_(a - b < a)
1383 self.assert_(b - a < b)
1384 self.assert_(a & b < a)
1385 self.assert_(a & b < b)
1386 self.assert_(a | b > a)
1387 self.assert_(a | b > b)
1388 self.assert_(a ^ b < a | b)
1389
1390 def test_commutativity(self):
1391 a, b = self.a, self.b
1392 self.assertEqual(a&b, b&a)
1393 self.assertEqual(a|b, b|a)
1394 self.assertEqual(a^b, b^a)
1395 if a != b:
1396 self.assertNotEqual(a-b, b-a)
1397
1398 def test_summations(self):
1399 # check that sums of parts equal the whole
1400 a, b = self.a, self.b
1401 self.assertEqual((a-b)|(a&b)|(b-a), a|b)
1402 self.assertEqual((a&b)|(a^b), a|b)
1403 self.assertEqual(a|(b-a), a|b)
1404 self.assertEqual((a-b)|b, a|b)
1405 self.assertEqual((a-b)|(a&b), a)
1406 self.assertEqual((b-a)|(a&b), b)
1407 self.assertEqual((a-b)|(b-a), a^b)
1408
1409 def test_exclusion(self):
1410 # check that inverse operations show non-overlap
1411 a, b, zero = self.a, self.b, set()
1412 self.assertEqual((a-b)&b, zero)
1413 self.assertEqual((b-a)&a, zero)
1414 self.assertEqual((a&b)&(a^b), zero)
1415
1416# Tests derived from test_itertools.py =======================================
1417
1418def R(seqn):
1419 'Regular generator'
1420 for i in seqn:
1421 yield i
1422
1423class G:
1424 'Sequence using __getitem__'
1425 def __init__(self, seqn):
1426 self.seqn = seqn
1427 def __getitem__(self, i):
1428 return self.seqn[i]
1429
1430class I:
1431 'Sequence using iterator protocol'
1432 def __init__(self, seqn):
1433 self.seqn = seqn
1434 self.i = 0
1435 def __iter__(self):
1436 return self
1437 def next(self):
1438 if self.i >= len(self.seqn): raise StopIteration
1439 v = self.seqn[self.i]
1440 self.i += 1
1441 return v
1442
1443class Ig:
1444 'Sequence using iterator protocol defined with a generator'
1445 def __init__(self, seqn):
1446 self.seqn = seqn
1447 self.i = 0
1448 def __iter__(self):
1449 for val in self.seqn:
1450 yield val
1451
1452class X:
1453 'Missing __getitem__ and __iter__'
1454 def __init__(self, seqn):
1455 self.seqn = seqn
1456 self.i = 0
1457 def next(self):
1458 if self.i >= len(self.seqn): raise StopIteration
1459 v = self.seqn[self.i]
1460 self.i += 1
1461 return v
1462
1463class N:
1464 'Iterator missing next()'
1465 def __init__(self, seqn):
1466 self.seqn = seqn
1467 self.i = 0
1468 def __iter__(self):
1469 return self
1470
1471class E:
1472 'Test propagation of exceptions'
1473 def __init__(self, seqn):
1474 self.seqn = seqn
1475 self.i = 0
1476 def __iter__(self):
1477 return self
1478 def next(self):
Raymond Hettingerffdb8bb2004-09-27 15:29:05 +00001479 3 // 0
Raymond Hettingera690a992003-11-16 16:17:49 +00001480
1481class S:
1482 'Test immediate stop'
1483 def __init__(self, seqn):
1484 pass
1485 def __iter__(self):
1486 return self
1487 def next(self):
1488 raise StopIteration
1489
1490from itertools import chain, imap
1491def L(seqn):
1492 'Test multiple tiers of iterators'
1493 return chain(imap(lambda x:x, R(Ig(G(seqn)))))
1494
1495class TestVariousIteratorArgs(unittest.TestCase):
1496
1497 def test_constructor(self):
1498 for cons in (set, frozenset):
1499 for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)):
1500 for g in (G, I, Ig, S, L, R):
Raymond Hettinger64958a12003-12-17 20:43:33 +00001501 self.assertEqual(sorted(cons(g(s))), sorted(g(s)))
Raymond Hettingera690a992003-11-16 16:17:49 +00001502 self.assertRaises(TypeError, cons , X(s))
1503 self.assertRaises(TypeError, cons , N(s))
1504 self.assertRaises(ZeroDivisionError, cons , E(s))
1505
1506 def test_inline_methods(self):
1507 s = set('november')
1508 for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'):
Raymond Hettinger1760c8a2007-11-08 02:52:43 +00001509 for meth in (s.union, s.intersection, s.difference, s.symmetric_difference, s.isdisjoint):
Raymond Hettingera690a992003-11-16 16:17:49 +00001510 for g in (G, I, Ig, L, R):
1511 expected = meth(data)
1512 actual = meth(G(data))
Raymond Hettinger1760c8a2007-11-08 02:52:43 +00001513 if isinstance(expected, bool):
1514 self.assertEqual(actual, expected)
1515 else:
1516 self.assertEqual(sorted(actual), sorted(expected))
Raymond Hettingera690a992003-11-16 16:17:49 +00001517 self.assertRaises(TypeError, meth, X(s))
1518 self.assertRaises(TypeError, meth, N(s))
1519 self.assertRaises(ZeroDivisionError, meth, E(s))
1520
1521 def test_inplace_methods(self):
1522 for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001523 for methname in ('update', 'intersection_update',
Raymond Hettingera690a992003-11-16 16:17:49 +00001524 'difference_update', 'symmetric_difference_update'):
1525 for g in (G, I, Ig, S, L, R):
1526 s = set('january')
1527 t = s.copy()
1528 getattr(s, methname)(list(g(data)))
1529 getattr(t, methname)(g(data))
Raymond Hettinger64958a12003-12-17 20:43:33 +00001530 self.assertEqual(sorted(s), sorted(t))
Raymond Hettingera690a992003-11-16 16:17:49 +00001531
1532 self.assertRaises(TypeError, getattr(set('january'), methname), X(data))
1533 self.assertRaises(TypeError, getattr(set('january'), methname), N(data))
1534 self.assertRaises(ZeroDivisionError, getattr(set('january'), methname), E(data))
1535
Raymond Hettinger61708742008-01-24 21:23:58 +00001536# Application tests (based on David Eppstein's graph recipes ====================================
1537
1538def powerset(U):
1539 """Generates all subsets of a set or sequence U."""
1540 U = iter(U)
1541 try:
1542 x = frozenset([U.next()])
1543 for S in powerset(U):
1544 yield S
1545 yield S | x
1546 except StopIteration:
1547 yield frozenset()
1548
1549def cube(n):
1550 """Graph of n-dimensional hypercube."""
1551 singletons = [frozenset([x]) for x in range(n)]
1552 return dict([(x, frozenset([x^s for s in singletons]))
1553 for x in powerset(range(n))])
1554
1555def linegraph(G):
1556 """Graph, the vertices of which are edges of G,
1557 with two vertices being adjacent iff the corresponding
1558 edges share a vertex."""
1559 L = {}
1560 for x in G:
1561 for y in G[x]:
1562 nx = [frozenset([x,z]) for z in G[x] if z != y]
1563 ny = [frozenset([y,z]) for z in G[y] if z != x]
1564 L[frozenset([x,y])] = frozenset(nx+ny)
1565 return L
1566
1567def faces(G):
1568 'Return a set of faces in G. Where a face is a set of vertices on that face'
1569 # currently limited to triangles,squares, and pentagons
1570 f = set()
1571 for v1, edges in G.items():
1572 for v2 in edges:
1573 for v3 in G[v2]:
1574 if v1 == v3:
1575 continue
1576 if v1 in G[v3]:
1577 f.add(frozenset([v1, v2, v3]))
1578 else:
1579 for v4 in G[v3]:
1580 if v4 == v2:
1581 continue
1582 if v1 in G[v4]:
1583 f.add(frozenset([v1, v2, v3, v4]))
1584 else:
1585 for v5 in G[v4]:
1586 if v5 == v3 or v5 == v2:
1587 continue
1588 if v1 in G[v5]:
1589 f.add(frozenset([v1, v2, v3, v4, v5]))
1590 return f
1591
1592
1593class TestGraphs(unittest.TestCase):
1594
1595 def test_cube(self):
1596
1597 g = cube(3) # vert --> {v1, v2, v3}
1598 vertices1 = set(g)
1599 self.assertEqual(len(vertices1), 8) # eight vertices
1600 for edge in g.values():
1601 self.assertEqual(len(edge), 3) # each vertex connects to three edges
1602 vertices2 = set(v for edges in g.values() for v in edges)
1603 self.assertEqual(vertices1, vertices2) # edge vertices in original set
1604
1605 cubefaces = faces(g)
1606 self.assertEqual(len(cubefaces), 6) # six faces
1607 for face in cubefaces:
1608 self.assertEqual(len(face), 4) # each face is a square
1609
1610 def test_cuboctahedron(self):
1611
1612 # http://en.wikipedia.org/wiki/Cuboctahedron
1613 # 8 triangular faces and 6 square faces
1614 # 12 indentical vertices each connecting a triangle and square
1615
1616 g = cube(3)
1617 cuboctahedron = linegraph(g) # V( --> {V1, V2, V3, V4}
1618 self.assertEqual(len(cuboctahedron), 12)# twelve vertices
1619
1620 vertices = set(cuboctahedron)
1621 for edges in cuboctahedron.values():
1622 self.assertEqual(len(edges), 4) # each vertex connects to four other vertices
1623 othervertices = set(edge for edges in cuboctahedron.values() for edge in edges)
1624 self.assertEqual(vertices, othervertices) # edge vertices in original set
1625
1626 cubofaces = faces(cuboctahedron)
1627 facesizes = collections.defaultdict(int)
1628 for face in cubofaces:
1629 facesizes[len(face)] += 1
1630 self.assertEqual(facesizes[3], 8) # eight triangular faces
1631 self.assertEqual(facesizes[4], 6) # six square faces
1632
1633 for vertex in cuboctahedron:
1634 edge = vertex # Cuboctahedron vertices are edges in Cube
1635 self.assertEqual(len(edge), 2) # Two cube vertices define an edge
1636 for cubevert in edge:
1637 self.assert_(cubevert in g)
1638
1639
Raymond Hettingera690a992003-11-16 16:17:49 +00001640#==============================================================================
1641
1642def test_main(verbose=None):
Raymond Hettingera690a992003-11-16 16:17:49 +00001643 from test import test_sets
1644 test_classes = (
1645 TestSet,
Raymond Hettinger50a4bb32003-11-17 16:42:33 +00001646 TestSetSubclass,
Tim Petersf733abb2007-01-30 03:03:46 +00001647 TestSetSubclassWithKeywordArgs,
Raymond Hettingera690a992003-11-16 16:17:49 +00001648 TestFrozenSet,
Raymond Hettinger50a4bb32003-11-17 16:42:33 +00001649 TestFrozenSetSubclass,
Raymond Hettingera690a992003-11-16 16:17:49 +00001650 TestSetOfSets,
1651 TestExceptionPropagation,
1652 TestBasicOpsEmpty,
1653 TestBasicOpsSingleton,
1654 TestBasicOpsTuple,
1655 TestBasicOpsTriple,
1656 TestBinaryOps,
1657 TestUpdateOps,
1658 TestMutate,
1659 TestSubsetEqualEmpty,
1660 TestSubsetEqualNonEmpty,
1661 TestSubsetEmptyNonEmpty,
1662 TestSubsetPartial,
1663 TestSubsetNonOverlap,
1664 TestOnlySetsNumeric,
1665 TestOnlySetsDict,
1666 TestOnlySetsOperator,
1667 TestOnlySetsTuple,
1668 TestOnlySetsString,
1669 TestOnlySetsGenerator,
1670 TestCopyingEmpty,
1671 TestCopyingSingleton,
1672 TestCopyingTriple,
1673 TestCopyingTuple,
1674 TestCopyingNested,
1675 TestIdentities,
1676 TestVariousIteratorArgs,
Raymond Hettinger61708742008-01-24 21:23:58 +00001677 TestGraphs,
Raymond Hettingera690a992003-11-16 16:17:49 +00001678 )
1679
1680 test_support.run_unittest(*test_classes)
1681
1682 # verify reference counting
1683 if verbose and hasattr(sys, "gettotalrefcount"):
1684 import gc
1685 counts = [None] * 5
1686 for i in xrange(len(counts)):
1687 test_support.run_unittest(*test_classes)
1688 gc.collect()
1689 counts[i] = sys.gettotalrefcount()
1690 print counts
1691
1692if __name__ == "__main__":
1693 test_main(verbose=True)