blob: 3d09d87fdb0e5d151cb0f59cc5cd74caac61dc75 [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 Hettingera690a992003-11-16 16:17:49 +000081
82 def test_or(self):
83 i = self.s.union(self.otherword)
84 self.assertEqual(self.s | set(self.otherword), i)
85 self.assertEqual(self.s | frozenset(self.otherword), i)
86 try:
87 self.s | self.otherword
88 except TypeError:
89 pass
90 else:
91 self.fail("s|t did not screen-out general iterables")
92
93 def test_intersection(self):
94 i = self.s.intersection(self.otherword)
95 for c in self.letters:
96 self.assertEqual(c in i, c in self.d and c in self.otherword)
Raymond Hettinger49ba4c32003-11-23 02:49:05 +000097 self.assertEqual(self.s, self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +000098 self.assertEqual(type(i), self.thetype)
99 self.assertRaises(PassThru, self.s.intersection, check_pass_thru())
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000100 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
101 self.assertEqual(self.thetype('abcba').intersection(C('cdc')), set('cc'))
102 self.assertEqual(self.thetype('abcba').intersection(C('efgfe')), set(''))
103 self.assertEqual(self.thetype('abcba').intersection(C('ccb')), set('bc'))
104 self.assertEqual(self.thetype('abcba').intersection(C('ef')), set(''))
Raymond Hettingera690a992003-11-16 16:17:49 +0000105
Raymond Hettinger1760c8a2007-11-08 02:52:43 +0000106 def test_isdisjoint(self):
107 def f(s1, s2):
108 'Pure python equivalent of isdisjoint()'
109 return not set(s1).intersection(s2)
110 for larg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef':
111 s1 = self.thetype(larg)
112 for rarg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef':
113 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
114 s2 = C(rarg)
115 actual = s1.isdisjoint(s2)
116 expected = f(s1, s2)
117 self.assertEqual(actual, expected)
118 self.assert_(actual is True or actual is False)
119
Raymond Hettingera690a992003-11-16 16:17:49 +0000120 def test_and(self):
121 i = self.s.intersection(self.otherword)
122 self.assertEqual(self.s & set(self.otherword), i)
123 self.assertEqual(self.s & frozenset(self.otherword), i)
124 try:
125 self.s & self.otherword
126 except TypeError:
127 pass
128 else:
129 self.fail("s&t did not screen-out general iterables")
130
131 def test_difference(self):
132 i = self.s.difference(self.otherword)
133 for c in self.letters:
134 self.assertEqual(c in i, c in self.d and c not in self.otherword)
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000135 self.assertEqual(self.s, self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +0000136 self.assertEqual(type(i), self.thetype)
137 self.assertRaises(PassThru, self.s.difference, check_pass_thru())
138 self.assertRaises(TypeError, self.s.difference, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000139 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
140 self.assertEqual(self.thetype('abcba').difference(C('cdc')), set('ab'))
141 self.assertEqual(self.thetype('abcba').difference(C('efgfe')), set('abc'))
142 self.assertEqual(self.thetype('abcba').difference(C('ccb')), set('a'))
143 self.assertEqual(self.thetype('abcba').difference(C('ef')), set('abc'))
Raymond Hettingera690a992003-11-16 16:17:49 +0000144
145 def test_sub(self):
146 i = self.s.difference(self.otherword)
147 self.assertEqual(self.s - set(self.otherword), i)
148 self.assertEqual(self.s - frozenset(self.otherword), i)
149 try:
150 self.s - self.otherword
151 except TypeError:
152 pass
153 else:
154 self.fail("s-t did not screen-out general iterables")
155
156 def test_symmetric_difference(self):
157 i = self.s.symmetric_difference(self.otherword)
158 for c in self.letters:
159 self.assertEqual(c in i, (c in self.d) ^ (c in self.otherword))
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000160 self.assertEqual(self.s, self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +0000161 self.assertEqual(type(i), self.thetype)
162 self.assertRaises(PassThru, self.s.symmetric_difference, check_pass_thru())
163 self.assertRaises(TypeError, self.s.symmetric_difference, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000164 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
165 self.assertEqual(self.thetype('abcba').symmetric_difference(C('cdc')), set('abd'))
166 self.assertEqual(self.thetype('abcba').symmetric_difference(C('efgfe')), set('abcefg'))
167 self.assertEqual(self.thetype('abcba').symmetric_difference(C('ccb')), set('a'))
168 self.assertEqual(self.thetype('abcba').symmetric_difference(C('ef')), set('abcef'))
Raymond Hettingera690a992003-11-16 16:17:49 +0000169
170 def test_xor(self):
171 i = self.s.symmetric_difference(self.otherword)
172 self.assertEqual(self.s ^ set(self.otherword), i)
173 self.assertEqual(self.s ^ frozenset(self.otherword), i)
174 try:
175 self.s ^ self.otherword
176 except TypeError:
177 pass
178 else:
179 self.fail("s^t did not screen-out general iterables")
180
181 def test_equality(self):
182 self.assertEqual(self.s, set(self.word))
183 self.assertEqual(self.s, frozenset(self.word))
184 self.assertEqual(self.s == self.word, False)
185 self.assertNotEqual(self.s, set(self.otherword))
186 self.assertNotEqual(self.s, frozenset(self.otherword))
187 self.assertEqual(self.s != self.word, True)
188
189 def test_setOfFrozensets(self):
190 t = map(frozenset, ['abcdef', 'bcd', 'bdcb', 'fed', 'fedccba'])
191 s = self.thetype(t)
192 self.assertEqual(len(s), 3)
193
194 def test_compare(self):
195 self.assertRaises(TypeError, self.s.__cmp__, self.s)
196
197 def test_sub_and_super(self):
198 p, q, r = map(self.thetype, ['ab', 'abcde', 'def'])
199 self.assert_(p < q)
200 self.assert_(p <= q)
201 self.assert_(q <= q)
202 self.assert_(q > p)
203 self.assert_(q >= p)
204 self.failIf(q < r)
205 self.failIf(q <= r)
206 self.failIf(q > r)
207 self.failIf(q >= r)
Raymond Hettinger3fbec702003-11-21 07:56:36 +0000208 self.assert_(set('a').issubset('abc'))
209 self.assert_(set('abc').issuperset('a'))
210 self.failIf(set('a').issubset('cbs'))
211 self.failIf(set('cbs').issuperset('a'))
Raymond Hettingera690a992003-11-16 16:17:49 +0000212
213 def test_pickling(self):
Raymond Hettinger15056a52004-11-09 07:25:31 +0000214 for i in (0, 1, 2):
215 p = pickle.dumps(self.s, i)
216 dup = pickle.loads(p)
217 self.assertEqual(self.s, dup, "%s != %s" % (self.s, dup))
218 if type(self.s) not in (set, frozenset):
219 self.s.x = 10
220 p = pickle.dumps(self.s)
221 dup = pickle.loads(p)
222 self.assertEqual(self.s.x, dup.x)
Raymond Hettingera690a992003-11-16 16:17:49 +0000223
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000224 def test_deepcopy(self):
225 class Tracer:
226 def __init__(self, value):
227 self.value = value
228 def __hash__(self):
Tim Peters58eb11c2004-01-18 20:29:55 +0000229 return self.value
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000230 def __deepcopy__(self, memo=None):
231 return Tracer(self.value + 1)
232 t = Tracer(10)
233 s = self.thetype([t])
234 dup = copy.deepcopy(s)
235 self.assertNotEqual(id(s), id(dup))
236 for elem in dup:
237 newt = elem
238 self.assertNotEqual(id(t), id(newt))
239 self.assertEqual(t.value + 1, newt.value)
240
Raymond Hettingerbb999b52005-06-18 21:00:26 +0000241 def test_gc(self):
242 # Create a nest of cycles to exercise overall ref count check
243 class A:
244 pass
245 s = set(A() for i in xrange(1000))
246 for elem in s:
247 elem.cycle = s
248 elem.sub = elem
249 elem.set = set([elem])
250
Raymond Hettinger97979dd2005-08-12 23:58:22 +0000251 def test_subclass_with_custom_hash(self):
252 # Bug #1257731
253 class H(self.thetype):
254 def __hash__(self):
Tim Peters6902b442006-04-11 00:43:27 +0000255 return int(id(self) & 0x7fffffff)
Raymond Hettinger97979dd2005-08-12 23:58:22 +0000256 s=H()
257 f=set()
258 f.add(s)
259 self.assert_(s in f)
260 f.remove(s)
261 f.add(s)
262 f.discard(s)
263
Raymond Hettinger9bda1d62005-09-16 07:14:21 +0000264 def test_badcmp(self):
265 s = self.thetype([BadCmp()])
266 # Detect comparison errors during insertion and lookup
267 self.assertRaises(RuntimeError, self.thetype, [BadCmp(), BadCmp()])
268 self.assertRaises(RuntimeError, s.__contains__, BadCmp())
269 # Detect errors during mutating operations
270 if hasattr(s, 'add'):
271 self.assertRaises(RuntimeError, s.add, BadCmp())
272 self.assertRaises(RuntimeError, s.discard, BadCmp())
273 self.assertRaises(RuntimeError, s.remove, BadCmp())
274
Raymond Hettinger53999102006-12-30 04:01:17 +0000275 def test_cyclical_repr(self):
276 w = ReprWrapper()
277 s = self.thetype([w])
278 w.value = s
279 name = repr(s).partition('(')[0] # strip class name from repr string
280 self.assertEqual(repr(s), '%s([%s(...)])' % (name, name))
281
282 def test_cyclical_print(self):
283 w = ReprWrapper()
284 s = self.thetype([w])
285 w.value = s
286 try:
287 fo = open(test_support.TESTFN, "wb")
288 print >> fo, s,
289 fo.close()
290 fo = open(test_support.TESTFN, "rb")
291 self.assertEqual(fo.read(), repr(s))
292 finally:
293 fo.close()
294 os.remove(test_support.TESTFN)
295
Raymond Hettingerd6fc72a2007-02-19 02:03:19 +0000296 def test_do_not_rehash_dict_keys(self):
297 n = 10
298 d = dict.fromkeys(map(HashCountingInt, xrange(n)))
299 self.assertEqual(sum(elem.hash_count for elem in d), n)
300 s = self.thetype(d)
301 self.assertEqual(sum(elem.hash_count for elem in d), n)
302 s.difference(d)
Tim Petersea5962f2007-03-12 18:07:52 +0000303 self.assertEqual(sum(elem.hash_count for elem in d), n)
Raymond Hettingerd6fc72a2007-02-19 02:03:19 +0000304 if hasattr(s, 'symmetric_difference_update'):
305 s.symmetric_difference_update(d)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000306 self.assertEqual(sum(elem.hash_count for elem in d), n)
Raymond Hettinger0bbbfc42007-03-20 21:27:24 +0000307 d2 = dict.fromkeys(set(d))
308 self.assertEqual(sum(elem.hash_count for elem in d), n)
309 d3 = dict.fromkeys(frozenset(d))
Tim Petersea5962f2007-03-12 18:07:52 +0000310 self.assertEqual(sum(elem.hash_count for elem in d), n)
Raymond Hettingere3146f52007-03-21 20:33:57 +0000311 d3 = dict.fromkeys(frozenset(d), 123)
312 self.assertEqual(sum(elem.hash_count for elem in d), n)
313 self.assertEqual(d3, dict.fromkeys(d, 123))
Raymond Hettingerd6fc72a2007-02-19 02:03:19 +0000314
Raymond Hettingera690a992003-11-16 16:17:49 +0000315class TestSet(TestJointOps):
316 thetype = set
317
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000318 def test_init(self):
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000319 s = self.thetype()
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000320 s.__init__(self.word)
321 self.assertEqual(s, set(self.word))
322 s.__init__(self.otherword)
323 self.assertEqual(s, set(self.otherword))
Raymond Hettingereae05de2004-07-09 04:51:24 +0000324 self.assertRaises(TypeError, s.__init__, s, 2);
325 self.assertRaises(TypeError, s.__init__, 1);
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000326
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000327 def test_constructor_identity(self):
328 s = self.thetype(range(3))
329 t = self.thetype(s)
330 self.assertNotEqual(id(s), id(t))
331
Raymond Hettingera690a992003-11-16 16:17:49 +0000332 def test_hash(self):
333 self.assertRaises(TypeError, hash, self.s)
334
335 def test_clear(self):
336 self.s.clear()
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000337 self.assertEqual(self.s, set())
338 self.assertEqual(len(self.s), 0)
Raymond Hettingera690a992003-11-16 16:17:49 +0000339
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000340 def test_copy(self):
341 dup = self.s.copy()
342 self.assertEqual(self.s, dup)
343 self.assertNotEqual(id(self.s), id(dup))
344
Raymond Hettingera690a992003-11-16 16:17:49 +0000345 def test_add(self):
346 self.s.add('Q')
347 self.assert_('Q' in self.s)
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000348 dup = self.s.copy()
349 self.s.add('Q')
350 self.assertEqual(self.s, dup)
Raymond Hettingera690a992003-11-16 16:17:49 +0000351 self.assertRaises(TypeError, self.s.add, [])
352
353 def test_remove(self):
354 self.s.remove('a')
355 self.assert_('a' not in self.s)
356 self.assertRaises(KeyError, self.s.remove, 'Q')
357 self.assertRaises(TypeError, self.s.remove, [])
Raymond Hettingerbfd334a2003-11-22 03:55:23 +0000358 s = self.thetype([frozenset(self.word)])
359 self.assert_(self.thetype(self.word) in s)
360 s.remove(self.thetype(self.word))
361 self.assert_(self.thetype(self.word) not in s)
362 self.assertRaises(KeyError, self.s.remove, self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +0000363
Raymond Hettingerc789f342006-12-08 17:35:25 +0000364 def test_remove_keyerror_unpacking(self):
365 # bug: www.python.org/sf/1576657
366 for v1 in ['Q', (1,)]:
367 try:
368 self.s.remove(v1)
369 except KeyError, e:
370 v2 = e.args[0]
371 self.assertEqual(v1, v2)
372 else:
373 self.fail()
374
Raymond Hettingera690a992003-11-16 16:17:49 +0000375 def test_discard(self):
376 self.s.discard('a')
377 self.assert_('a' not in self.s)
378 self.s.discard('Q')
379 self.assertRaises(TypeError, self.s.discard, [])
Raymond Hettingerbfd334a2003-11-22 03:55:23 +0000380 s = self.thetype([frozenset(self.word)])
381 self.assert_(self.thetype(self.word) in s)
382 s.discard(self.thetype(self.word))
383 self.assert_(self.thetype(self.word) not in s)
384 s.discard(self.thetype(self.word))
Raymond Hettingera690a992003-11-16 16:17:49 +0000385
386 def test_pop(self):
387 for i in xrange(len(self.s)):
388 elem = self.s.pop()
389 self.assert_(elem not in self.s)
390 self.assertRaises(KeyError, self.s.pop)
391
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000392 def test_update(self):
393 retval = self.s.update(self.otherword)
Raymond Hettingera690a992003-11-16 16:17:49 +0000394 self.assertEqual(retval, None)
395 for c in (self.word + self.otherword):
396 self.assert_(c in self.s)
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000397 self.assertRaises(PassThru, self.s.update, check_pass_thru())
398 self.assertRaises(TypeError, self.s.update, [[]])
399 for p, q in (('cdc', 'abcd'), ('efgfe', 'abcefg'), ('ccb', 'abc'), ('ef', 'abcef')):
400 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
401 s = self.thetype('abcba')
402 self.assertEqual(s.update(C(p)), None)
403 self.assertEqual(s, set(q))
Raymond Hettingera690a992003-11-16 16:17:49 +0000404
405 def test_ior(self):
406 self.s |= set(self.otherword)
407 for c in (self.word + self.otherword):
408 self.assert_(c in self.s)
409
410 def test_intersection_update(self):
411 retval = self.s.intersection_update(self.otherword)
412 self.assertEqual(retval, None)
413 for c in (self.word + self.otherword):
414 if c in self.otherword and c in self.word:
415 self.assert_(c in self.s)
416 else:
417 self.assert_(c not in self.s)
418 self.assertRaises(PassThru, self.s.intersection_update, check_pass_thru())
419 self.assertRaises(TypeError, self.s.intersection_update, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000420 for p, q in (('cdc', 'c'), ('efgfe', ''), ('ccb', 'bc'), ('ef', '')):
421 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
422 s = self.thetype('abcba')
423 self.assertEqual(s.intersection_update(C(p)), None)
424 self.assertEqual(s, set(q))
Raymond Hettingera690a992003-11-16 16:17:49 +0000425
426 def test_iand(self):
427 self.s &= set(self.otherword)
428 for c in (self.word + self.otherword):
429 if c in self.otherword and c in self.word:
430 self.assert_(c in self.s)
431 else:
432 self.assert_(c not in self.s)
433
434 def test_difference_update(self):
435 retval = self.s.difference_update(self.otherword)
436 self.assertEqual(retval, None)
437 for c in (self.word + self.otherword):
438 if c in self.word and c not in self.otherword:
439 self.assert_(c in self.s)
440 else:
441 self.assert_(c not in self.s)
442 self.assertRaises(PassThru, self.s.difference_update, check_pass_thru())
443 self.assertRaises(TypeError, self.s.difference_update, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000444 self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
445 for p, q in (('cdc', 'ab'), ('efgfe', 'abc'), ('ccb', 'a'), ('ef', 'abc')):
446 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
447 s = self.thetype('abcba')
448 self.assertEqual(s.difference_update(C(p)), None)
449 self.assertEqual(s, set(q))
Raymond Hettingera690a992003-11-16 16:17:49 +0000450
451 def test_isub(self):
452 self.s -= set(self.otherword)
453 for c in (self.word + self.otherword):
454 if c in self.word and c not in self.otherword:
455 self.assert_(c in self.s)
456 else:
457 self.assert_(c not in self.s)
458
459 def test_symmetric_difference_update(self):
460 retval = self.s.symmetric_difference_update(self.otherword)
461 self.assertEqual(retval, None)
462 for c in (self.word + self.otherword):
463 if (c in self.word) ^ (c in self.otherword):
464 self.assert_(c in self.s)
465 else:
466 self.assert_(c not in self.s)
467 self.assertRaises(PassThru, self.s.symmetric_difference_update, check_pass_thru())
468 self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000469 for p, q in (('cdc', 'abd'), ('efgfe', 'abcefg'), ('ccb', 'a'), ('ef', 'abcef')):
470 for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
471 s = self.thetype('abcba')
472 self.assertEqual(s.symmetric_difference_update(C(p)), None)
473 self.assertEqual(s, set(q))
Raymond Hettingera690a992003-11-16 16:17:49 +0000474
475 def test_ixor(self):
476 self.s ^= set(self.otherword)
477 for c in (self.word + self.otherword):
478 if (c in self.word) ^ (c in self.otherword):
479 self.assert_(c in self.s)
480 else:
481 self.assert_(c not in self.s)
482
Raymond Hettingerc991db22005-08-11 07:58:45 +0000483 def test_inplace_on_self(self):
484 t = self.s.copy()
485 t |= t
486 self.assertEqual(t, self.s)
487 t &= t
488 self.assertEqual(t, self.s)
489 t -= t
490 self.assertEqual(t, self.thetype())
491 t = self.s.copy()
492 t ^= t
493 self.assertEqual(t, self.thetype())
494
Raymond Hettinger691d8052004-05-30 07:26:47 +0000495 def test_weakref(self):
496 s = self.thetype('gallahad')
497 p = proxy(s)
498 self.assertEqual(str(p), str(s))
499 s = None
500 self.assertRaises(ReferenceError, str, p)
501
Raymond Hettingerc47e01d2005-08-16 10:44:15 +0000502 # C API test only available in a debug build
Barry Warsaw176014f2006-03-30 22:45:35 +0000503 if hasattr(set, "test_c_api"):
Raymond Hettingerc47e01d2005-08-16 10:44:15 +0000504 def test_c_api(self):
505 self.assertEqual(set('abc').test_c_api(), True)
506
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000507class SetSubclass(set):
508 pass
509
510class TestSetSubclass(TestSet):
511 thetype = SetSubclass
Raymond Hettingera690a992003-11-16 16:17:49 +0000512
Raymond Hettinger9fdfadb2007-01-11 18:22:55 +0000513class SetSubclassWithKeywordArgs(set):
514 def __init__(self, iterable=[], newarg=None):
515 set.__init__(self, iterable)
516
517class TestSetSubclassWithKeywordArgs(TestSet):
Tim Petersf733abb2007-01-30 03:03:46 +0000518
Raymond Hettinger9fdfadb2007-01-11 18:22:55 +0000519 def test_keywords_in_subclass(self):
520 'SF bug #1486663 -- this used to erroneously raise a TypeError'
521 SetSubclassWithKeywordArgs(newarg=1)
522
Raymond Hettingera690a992003-11-16 16:17:49 +0000523class TestFrozenSet(TestJointOps):
524 thetype = frozenset
525
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000526 def test_init(self):
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000527 s = self.thetype(self.word)
528 s.__init__(self.otherword)
529 self.assertEqual(s, set(self.word))
530
Raymond Hettingerd7946662005-08-01 21:39:29 +0000531 def test_singleton_empty_frozenset(self):
532 f = frozenset()
533 efs = [frozenset(), frozenset([]), frozenset(()), frozenset(''),
534 frozenset(), frozenset([]), frozenset(()), frozenset(''),
535 frozenset(xrange(0)), frozenset(frozenset()),
536 frozenset(f), f]
537 # All of the empty frozensets should have just one id()
538 self.assertEqual(len(set(map(id, efs))), 1)
539
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000540 def test_constructor_identity(self):
541 s = self.thetype(range(3))
542 t = self.thetype(s)
543 self.assertEqual(id(s), id(t))
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000544
Raymond Hettingera690a992003-11-16 16:17:49 +0000545 def test_hash(self):
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000546 self.assertEqual(hash(self.thetype('abcdeb')),
547 hash(self.thetype('ebecda')))
548
Raymond Hettinger82cb9a22005-07-05 05:34:43 +0000549 # make sure that all permutations give the same hash value
550 n = 100
551 seq = [randrange(n) for i in xrange(n)]
552 results = set()
553 for i in xrange(200):
554 shuffle(seq)
555 results.add(hash(self.thetype(seq)))
556 self.assertEqual(len(results), 1)
557
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000558 def test_copy(self):
559 dup = self.s.copy()
560 self.assertEqual(id(self.s), id(dup))
Raymond Hettingera690a992003-11-16 16:17:49 +0000561
562 def test_frozen_as_dictkey(self):
563 seq = range(10) + list('abcdefg') + ['apple']
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000564 key1 = self.thetype(seq)
565 key2 = self.thetype(reversed(seq))
Raymond Hettingera690a992003-11-16 16:17:49 +0000566 self.assertEqual(key1, key2)
567 self.assertNotEqual(id(key1), id(key2))
568 d = {}
569 d[key1] = 42
570 self.assertEqual(d[key2], 42)
571
572 def test_hash_caching(self):
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000573 f = self.thetype('abcdcda')
Raymond Hettingera690a992003-11-16 16:17:49 +0000574 self.assertEqual(hash(f), hash(f))
575
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000576 def test_hash_effectiveness(self):
577 n = 13
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000578 hashvalues = set()
Raymond Hettinger6e70acc2003-12-31 02:01:33 +0000579 addhashvalue = hashvalues.add
580 elemmasks = [(i+1, 1<<i) for i in range(n)]
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000581 for i in xrange(2**n):
Raymond Hettinger6e70acc2003-12-31 02:01:33 +0000582 addhashvalue(hash(frozenset([e for e, m in elemmasks if m&i])))
583 self.assertEqual(len(hashvalues), 2**n)
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000584
Raymond Hettinger50a4bb32003-11-17 16:42:33 +0000585class FrozenSetSubclass(frozenset):
586 pass
587
588class TestFrozenSetSubclass(TestFrozenSet):
589 thetype = FrozenSetSubclass
590
Raymond Hettinger49ba4c32003-11-23 02:49:05 +0000591 def test_constructor_identity(self):
592 s = self.thetype(range(3))
593 t = self.thetype(s)
594 self.assertNotEqual(id(s), id(t))
595
596 def test_copy(self):
597 dup = self.s.copy()
598 self.assertNotEqual(id(self.s), id(dup))
599
600 def test_nested_empty_constructor(self):
601 s = self.thetype()
602 t = self.thetype(s)
603 self.assertEqual(s, t)
604
Raymond Hettingerd7946662005-08-01 21:39:29 +0000605 def test_singleton_empty_frozenset(self):
606 Frozenset = self.thetype
607 f = frozenset()
608 F = Frozenset()
609 efs = [Frozenset(), Frozenset([]), Frozenset(()), Frozenset(''),
610 Frozenset(), Frozenset([]), Frozenset(()), Frozenset(''),
611 Frozenset(xrange(0)), Frozenset(Frozenset()),
612 Frozenset(frozenset()), f, F, Frozenset(f), Frozenset(F)]
613 # All empty frozenset subclass instances should have different ids
614 self.assertEqual(len(set(map(id, efs))), len(efs))
615
Raymond Hettingera690a992003-11-16 16:17:49 +0000616# Tests taken from test_sets.py =============================================
617
618empty_set = set()
619
620#==============================================================================
621
622class TestBasicOps(unittest.TestCase):
623
624 def test_repr(self):
625 if self.repr is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000626 self.assertEqual(repr(self.set), self.repr)
Raymond Hettingera690a992003-11-16 16:17:49 +0000627
Raymond Hettingereae05de2004-07-09 04:51:24 +0000628 def test_print(self):
629 try:
630 fo = open(test_support.TESTFN, "wb")
631 print >> fo, self.set,
632 fo.close()
633 fo = open(test_support.TESTFN, "rb")
634 self.assertEqual(fo.read(), repr(self.set))
635 finally:
636 fo.close()
637 os.remove(test_support.TESTFN)
638
Raymond Hettingera690a992003-11-16 16:17:49 +0000639 def test_length(self):
640 self.assertEqual(len(self.set), self.length)
641
642 def test_self_equality(self):
643 self.assertEqual(self.set, self.set)
644
645 def test_equivalent_equality(self):
646 self.assertEqual(self.set, self.dup)
647
648 def test_copy(self):
649 self.assertEqual(self.set.copy(), self.dup)
650
651 def test_self_union(self):
652 result = self.set | self.set
653 self.assertEqual(result, self.dup)
654
655 def test_empty_union(self):
656 result = self.set | empty_set
657 self.assertEqual(result, self.dup)
658
659 def test_union_empty(self):
660 result = empty_set | self.set
661 self.assertEqual(result, self.dup)
662
663 def test_self_intersection(self):
664 result = self.set & self.set
665 self.assertEqual(result, self.dup)
666
667 def test_empty_intersection(self):
668 result = self.set & empty_set
669 self.assertEqual(result, empty_set)
670
671 def test_intersection_empty(self):
672 result = empty_set & self.set
673 self.assertEqual(result, empty_set)
674
Raymond Hettinger1760c8a2007-11-08 02:52:43 +0000675 def test_self_isdisjoint(self):
676 result = self.set.isdisjoint(self.set)
677 self.assertEqual(result, not self.set)
678
679 def test_empty_isdisjoint(self):
680 result = self.set.isdisjoint(empty_set)
681 self.assertEqual(result, True)
682
683 def test_isdisjoint_empty(self):
684 result = empty_set.isdisjoint(self.set)
685 self.assertEqual(result, True)
686
Raymond Hettingera690a992003-11-16 16:17:49 +0000687 def test_self_symmetric_difference(self):
688 result = self.set ^ self.set
689 self.assertEqual(result, empty_set)
690
691 def checkempty_symmetric_difference(self):
692 result = self.set ^ empty_set
693 self.assertEqual(result, self.set)
694
695 def test_self_difference(self):
696 result = self.set - self.set
697 self.assertEqual(result, empty_set)
698
699 def test_empty_difference(self):
700 result = self.set - empty_set
701 self.assertEqual(result, self.dup)
702
703 def test_empty_difference_rev(self):
704 result = empty_set - self.set
705 self.assertEqual(result, empty_set)
706
707 def test_iteration(self):
708 for v in self.set:
709 self.assert_(v in self.values)
Neal Norwitzfcf44352005-11-27 20:37:43 +0000710 setiter = iter(self.set)
Armin Rigof5b3e362006-02-11 21:32:43 +0000711 # note: __length_hint__ is an internal undocumented API,
712 # don't rely on it in your own programs
713 self.assertEqual(setiter.__length_hint__(), len(self.set))
Raymond Hettingera690a992003-11-16 16:17:49 +0000714
715 def test_pickling(self):
716 p = pickle.dumps(self.set)
717 copy = pickle.loads(p)
718 self.assertEqual(self.set, copy,
719 "%s != %s" % (self.set, copy))
720
721#------------------------------------------------------------------------------
722
723class TestBasicOpsEmpty(TestBasicOps):
724 def setUp(self):
725 self.case = "empty set"
726 self.values = []
727 self.set = set(self.values)
728 self.dup = set(self.values)
729 self.length = 0
730 self.repr = "set([])"
731
732#------------------------------------------------------------------------------
733
734class TestBasicOpsSingleton(TestBasicOps):
735 def setUp(self):
736 self.case = "unit set (number)"
737 self.values = [3]
738 self.set = set(self.values)
739 self.dup = set(self.values)
740 self.length = 1
741 self.repr = "set([3])"
742
743 def test_in(self):
744 self.failUnless(3 in self.set)
745
746 def test_not_in(self):
747 self.failUnless(2 not in self.set)
748
749#------------------------------------------------------------------------------
750
751class TestBasicOpsTuple(TestBasicOps):
752 def setUp(self):
753 self.case = "unit set (tuple)"
754 self.values = [(0, "zero")]
755 self.set = set(self.values)
756 self.dup = set(self.values)
757 self.length = 1
758 self.repr = "set([(0, 'zero')])"
759
760 def test_in(self):
761 self.failUnless((0, "zero") in self.set)
762
763 def test_not_in(self):
764 self.failUnless(9 not in self.set)
765
766#------------------------------------------------------------------------------
767
768class TestBasicOpsTriple(TestBasicOps):
769 def setUp(self):
770 self.case = "triple set"
771 self.values = [0, "zero", operator.add]
772 self.set = set(self.values)
773 self.dup = set(self.values)
774 self.length = 3
775 self.repr = None
776
777#==============================================================================
778
779def baditer():
780 raise TypeError
781 yield True
782
783def gooditer():
784 yield True
785
786class TestExceptionPropagation(unittest.TestCase):
787 """SF 628246: Set constructor should not trap iterator TypeErrors"""
788
789 def test_instanceWithException(self):
790 self.assertRaises(TypeError, set, baditer())
791
792 def test_instancesWithoutException(self):
793 # All of these iterables should load without exception.
794 set([1,2,3])
795 set((1,2,3))
796 set({'one':1, 'two':2, 'three':3})
797 set(xrange(3))
798 set('abc')
799 set(gooditer())
800
Neal Norwitzfcf44352005-11-27 20:37:43 +0000801 def test_changingSizeWhileIterating(self):
802 s = set([1,2,3])
803 try:
804 for i in s:
805 s.update([4])
806 except RuntimeError:
807 pass
808 else:
809 self.fail("no exception when changing size during iteration")
810
Raymond Hettingera690a992003-11-16 16:17:49 +0000811#==============================================================================
812
813class TestSetOfSets(unittest.TestCase):
814 def test_constructor(self):
815 inner = frozenset([1])
816 outer = set([inner])
817 element = outer.pop()
818 self.assertEqual(type(element), frozenset)
819 outer.add(inner) # Rebuild set of sets with .add method
820 outer.remove(inner)
821 self.assertEqual(outer, set()) # Verify that remove worked
822 outer.discard(inner) # Absence of KeyError indicates working fine
823
824#==============================================================================
825
826class TestBinaryOps(unittest.TestCase):
827 def setUp(self):
828 self.set = set((2, 4, 6))
829
830 def test_eq(self): # SF bug 643115
831 self.assertEqual(self.set, set({2:1,4:3,6:5}))
832
833 def test_union_subset(self):
834 result = self.set | set([2])
835 self.assertEqual(result, set((2, 4, 6)))
836
837 def test_union_superset(self):
838 result = self.set | set([2, 4, 6, 8])
839 self.assertEqual(result, set([2, 4, 6, 8]))
840
841 def test_union_overlap(self):
842 result = self.set | set([3, 4, 5])
843 self.assertEqual(result, set([2, 3, 4, 5, 6]))
844
845 def test_union_non_overlap(self):
846 result = self.set | set([8])
847 self.assertEqual(result, set([2, 4, 6, 8]))
848
849 def test_intersection_subset(self):
850 result = self.set & set((2, 4))
851 self.assertEqual(result, set((2, 4)))
852
853 def test_intersection_superset(self):
854 result = self.set & set([2, 4, 6, 8])
855 self.assertEqual(result, set([2, 4, 6]))
856
857 def test_intersection_overlap(self):
858 result = self.set & set([3, 4, 5])
859 self.assertEqual(result, set([4]))
860
861 def test_intersection_non_overlap(self):
862 result = self.set & set([8])
863 self.assertEqual(result, empty_set)
864
Raymond Hettinger1760c8a2007-11-08 02:52:43 +0000865 def test_isdisjoint_subset(self):
866 result = self.set.isdisjoint(set((2, 4)))
867 self.assertEqual(result, False)
868
869 def test_isdisjoint_superset(self):
870 result = self.set.isdisjoint(set([2, 4, 6, 8]))
871 self.assertEqual(result, False)
872
873 def test_isdisjoint_overlap(self):
874 result = self.set.isdisjoint(set([3, 4, 5]))
875 self.assertEqual(result, False)
876
877 def test_isdisjoint_non_overlap(self):
878 result = self.set.isdisjoint(set([8]))
879 self.assertEqual(result, True)
880
Raymond Hettingera690a992003-11-16 16:17:49 +0000881 def test_sym_difference_subset(self):
882 result = self.set ^ set((2, 4))
883 self.assertEqual(result, set([6]))
884
885 def test_sym_difference_superset(self):
886 result = self.set ^ set((2, 4, 6, 8))
887 self.assertEqual(result, set([8]))
888
889 def test_sym_difference_overlap(self):
890 result = self.set ^ set((3, 4, 5))
891 self.assertEqual(result, set([2, 3, 5, 6]))
892
893 def test_sym_difference_non_overlap(self):
894 result = self.set ^ set([8])
895 self.assertEqual(result, set([2, 4, 6, 8]))
896
897 def test_cmp(self):
898 a, b = set('a'), set('b')
899 self.assertRaises(TypeError, cmp, a, b)
900
901 # You can view this as a buglet: cmp(a, a) does not raise TypeError,
902 # because __eq__ is tried before __cmp__, and a.__eq__(a) returns True,
903 # which Python thinks is good enough to synthesize a cmp() result
904 # without calling __cmp__.
905 self.assertEqual(cmp(a, a), 0)
906
907 self.assertRaises(TypeError, cmp, a, 12)
908 self.assertRaises(TypeError, cmp, "abc", a)
909
910#==============================================================================
911
912class TestUpdateOps(unittest.TestCase):
913 def setUp(self):
914 self.set = set((2, 4, 6))
915
916 def test_union_subset(self):
917 self.set |= set([2])
918 self.assertEqual(self.set, set((2, 4, 6)))
919
920 def test_union_superset(self):
921 self.set |= set([2, 4, 6, 8])
922 self.assertEqual(self.set, set([2, 4, 6, 8]))
923
924 def test_union_overlap(self):
925 self.set |= set([3, 4, 5])
926 self.assertEqual(self.set, set([2, 3, 4, 5, 6]))
927
928 def test_union_non_overlap(self):
929 self.set |= set([8])
930 self.assertEqual(self.set, set([2, 4, 6, 8]))
931
932 def test_union_method_call(self):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +0000933 self.set.update(set([3, 4, 5]))
Raymond Hettingera690a992003-11-16 16:17:49 +0000934 self.assertEqual(self.set, set([2, 3, 4, 5, 6]))
935
936 def test_intersection_subset(self):
937 self.set &= set((2, 4))
938 self.assertEqual(self.set, set((2, 4)))
939
940 def test_intersection_superset(self):
941 self.set &= set([2, 4, 6, 8])
942 self.assertEqual(self.set, set([2, 4, 6]))
943
944 def test_intersection_overlap(self):
945 self.set &= set([3, 4, 5])
946 self.assertEqual(self.set, set([4]))
947
948 def test_intersection_non_overlap(self):
949 self.set &= set([8])
950 self.assertEqual(self.set, empty_set)
951
952 def test_intersection_method_call(self):
953 self.set.intersection_update(set([3, 4, 5]))
954 self.assertEqual(self.set, set([4]))
955
956 def test_sym_difference_subset(self):
957 self.set ^= set((2, 4))
958 self.assertEqual(self.set, set([6]))
959
960 def test_sym_difference_superset(self):
961 self.set ^= set((2, 4, 6, 8))
962 self.assertEqual(self.set, set([8]))
963
964 def test_sym_difference_overlap(self):
965 self.set ^= set((3, 4, 5))
966 self.assertEqual(self.set, set([2, 3, 5, 6]))
967
968 def test_sym_difference_non_overlap(self):
969 self.set ^= set([8])
970 self.assertEqual(self.set, set([2, 4, 6, 8]))
971
972 def test_sym_difference_method_call(self):
973 self.set.symmetric_difference_update(set([3, 4, 5]))
974 self.assertEqual(self.set, set([2, 3, 5, 6]))
975
976 def test_difference_subset(self):
977 self.set -= set((2, 4))
978 self.assertEqual(self.set, set([6]))
979
980 def test_difference_superset(self):
981 self.set -= set((2, 4, 6, 8))
982 self.assertEqual(self.set, set([]))
983
984 def test_difference_overlap(self):
985 self.set -= set((3, 4, 5))
986 self.assertEqual(self.set, set([2, 6]))
987
988 def test_difference_non_overlap(self):
989 self.set -= set([8])
990 self.assertEqual(self.set, set([2, 4, 6]))
991
992 def test_difference_method_call(self):
993 self.set.difference_update(set([3, 4, 5]))
994 self.assertEqual(self.set, set([2, 6]))
995
996#==============================================================================
997
998class TestMutate(unittest.TestCase):
999 def setUp(self):
1000 self.values = ["a", "b", "c"]
1001 self.set = set(self.values)
1002
1003 def test_add_present(self):
1004 self.set.add("c")
1005 self.assertEqual(self.set, set("abc"))
1006
1007 def test_add_absent(self):
1008 self.set.add("d")
1009 self.assertEqual(self.set, set("abcd"))
1010
1011 def test_add_until_full(self):
1012 tmp = set()
1013 expected_len = 0
1014 for v in self.values:
1015 tmp.add(v)
1016 expected_len += 1
1017 self.assertEqual(len(tmp), expected_len)
1018 self.assertEqual(tmp, self.set)
1019
1020 def test_remove_present(self):
1021 self.set.remove("b")
1022 self.assertEqual(self.set, set("ac"))
1023
1024 def test_remove_absent(self):
1025 try:
1026 self.set.remove("d")
1027 self.fail("Removing missing element should have raised LookupError")
1028 except LookupError:
1029 pass
1030
1031 def test_remove_until_empty(self):
1032 expected_len = len(self.set)
1033 for v in self.values:
1034 self.set.remove(v)
1035 expected_len -= 1
1036 self.assertEqual(len(self.set), expected_len)
1037
1038 def test_discard_present(self):
1039 self.set.discard("c")
1040 self.assertEqual(self.set, set("ab"))
1041
1042 def test_discard_absent(self):
1043 self.set.discard("d")
1044 self.assertEqual(self.set, set("abc"))
1045
1046 def test_clear(self):
1047 self.set.clear()
1048 self.assertEqual(len(self.set), 0)
1049
1050 def test_pop(self):
1051 popped = {}
1052 while self.set:
1053 popped[self.set.pop()] = None
1054 self.assertEqual(len(popped), len(self.values))
1055 for v in self.values:
1056 self.failUnless(v in popped)
1057
1058 def test_update_empty_tuple(self):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001059 self.set.update(())
Raymond Hettingera690a992003-11-16 16:17:49 +00001060 self.assertEqual(self.set, set(self.values))
1061
1062 def test_update_unit_tuple_overlap(self):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001063 self.set.update(("a",))
Raymond Hettingera690a992003-11-16 16:17:49 +00001064 self.assertEqual(self.set, set(self.values))
1065
1066 def test_update_unit_tuple_non_overlap(self):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001067 self.set.update(("a", "z"))
Raymond Hettingera690a992003-11-16 16:17:49 +00001068 self.assertEqual(self.set, set(self.values + ["z"]))
1069
1070#==============================================================================
1071
1072class TestSubsets(unittest.TestCase):
1073
1074 case2method = {"<=": "issubset",
1075 ">=": "issuperset",
1076 }
1077
1078 reverse = {"==": "==",
1079 "!=": "!=",
1080 "<": ">",
1081 ">": "<",
1082 "<=": ">=",
1083 ">=": "<=",
1084 }
1085
1086 def test_issubset(self):
1087 x = self.left
1088 y = self.right
1089 for case in "!=", "==", "<", "<=", ">", ">=":
1090 expected = case in self.cases
1091 # Test the binary infix spelling.
1092 result = eval("x" + case + "y", locals())
1093 self.assertEqual(result, expected)
1094 # Test the "friendly" method-name spelling, if one exists.
1095 if case in TestSubsets.case2method:
1096 method = getattr(x, TestSubsets.case2method[case])
1097 result = method(y)
1098 self.assertEqual(result, expected)
1099
1100 # Now do the same for the operands reversed.
1101 rcase = TestSubsets.reverse[case]
1102 result = eval("y" + rcase + "x", locals())
1103 self.assertEqual(result, expected)
1104 if rcase in TestSubsets.case2method:
1105 method = getattr(y, TestSubsets.case2method[rcase])
1106 result = method(x)
1107 self.assertEqual(result, expected)
1108#------------------------------------------------------------------------------
1109
1110class TestSubsetEqualEmpty(TestSubsets):
1111 left = set()
1112 right = set()
1113 name = "both empty"
1114 cases = "==", "<=", ">="
1115
1116#------------------------------------------------------------------------------
1117
1118class TestSubsetEqualNonEmpty(TestSubsets):
1119 left = set([1, 2])
1120 right = set([1, 2])
1121 name = "equal pair"
1122 cases = "==", "<=", ">="
1123
1124#------------------------------------------------------------------------------
1125
1126class TestSubsetEmptyNonEmpty(TestSubsets):
1127 left = set()
1128 right = set([1, 2])
1129 name = "one empty, one non-empty"
1130 cases = "!=", "<", "<="
1131
1132#------------------------------------------------------------------------------
1133
1134class TestSubsetPartial(TestSubsets):
1135 left = set([1])
1136 right = set([1, 2])
1137 name = "one a non-empty proper subset of other"
1138 cases = "!=", "<", "<="
1139
1140#------------------------------------------------------------------------------
1141
1142class TestSubsetNonOverlap(TestSubsets):
1143 left = set([1])
1144 right = set([2])
1145 name = "neither empty, neither contains"
1146 cases = "!="
1147
1148#==============================================================================
1149
1150class TestOnlySetsInBinaryOps(unittest.TestCase):
1151
1152 def test_eq_ne(self):
1153 # Unlike the others, this is testing that == and != *are* allowed.
1154 self.assertEqual(self.other == self.set, False)
1155 self.assertEqual(self.set == self.other, False)
1156 self.assertEqual(self.other != self.set, True)
1157 self.assertEqual(self.set != self.other, True)
1158
1159 def test_ge_gt_le_lt(self):
1160 self.assertRaises(TypeError, lambda: self.set < self.other)
1161 self.assertRaises(TypeError, lambda: self.set <= self.other)
1162 self.assertRaises(TypeError, lambda: self.set > self.other)
1163 self.assertRaises(TypeError, lambda: self.set >= self.other)
1164
1165 self.assertRaises(TypeError, lambda: self.other < self.set)
1166 self.assertRaises(TypeError, lambda: self.other <= self.set)
1167 self.assertRaises(TypeError, lambda: self.other > self.set)
1168 self.assertRaises(TypeError, lambda: self.other >= self.set)
1169
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001170 def test_update_operator(self):
Raymond Hettingera690a992003-11-16 16:17:49 +00001171 try:
1172 self.set |= self.other
1173 except TypeError:
1174 pass
1175 else:
1176 self.fail("expected TypeError")
1177
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001178 def test_update(self):
Raymond Hettingera690a992003-11-16 16:17:49 +00001179 if self.otherIsIterable:
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001180 self.set.update(self.other)
Raymond Hettingera690a992003-11-16 16:17:49 +00001181 else:
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001182 self.assertRaises(TypeError, self.set.update, self.other)
Raymond Hettingera690a992003-11-16 16:17:49 +00001183
1184 def test_union(self):
1185 self.assertRaises(TypeError, lambda: self.set | self.other)
1186 self.assertRaises(TypeError, lambda: self.other | self.set)
1187 if self.otherIsIterable:
1188 self.set.union(self.other)
1189 else:
1190 self.assertRaises(TypeError, self.set.union, self.other)
1191
1192 def test_intersection_update_operator(self):
1193 try:
1194 self.set &= self.other
1195 except TypeError:
1196 pass
1197 else:
1198 self.fail("expected TypeError")
1199
1200 def test_intersection_update(self):
1201 if self.otherIsIterable:
1202 self.set.intersection_update(self.other)
1203 else:
1204 self.assertRaises(TypeError,
1205 self.set.intersection_update,
1206 self.other)
1207
1208 def test_intersection(self):
1209 self.assertRaises(TypeError, lambda: self.set & self.other)
1210 self.assertRaises(TypeError, lambda: self.other & self.set)
1211 if self.otherIsIterable:
1212 self.set.intersection(self.other)
1213 else:
1214 self.assertRaises(TypeError, self.set.intersection, self.other)
1215
1216 def test_sym_difference_update_operator(self):
1217 try:
1218 self.set ^= self.other
1219 except TypeError:
1220 pass
1221 else:
1222 self.fail("expected TypeError")
1223
1224 def test_sym_difference_update(self):
1225 if self.otherIsIterable:
1226 self.set.symmetric_difference_update(self.other)
1227 else:
1228 self.assertRaises(TypeError,
1229 self.set.symmetric_difference_update,
1230 self.other)
1231
1232 def test_sym_difference(self):
1233 self.assertRaises(TypeError, lambda: self.set ^ self.other)
1234 self.assertRaises(TypeError, lambda: self.other ^ self.set)
1235 if self.otherIsIterable:
1236 self.set.symmetric_difference(self.other)
1237 else:
1238 self.assertRaises(TypeError, self.set.symmetric_difference, self.other)
1239
1240 def test_difference_update_operator(self):
1241 try:
1242 self.set -= self.other
1243 except TypeError:
1244 pass
1245 else:
1246 self.fail("expected TypeError")
1247
1248 def test_difference_update(self):
1249 if self.otherIsIterable:
1250 self.set.difference_update(self.other)
1251 else:
1252 self.assertRaises(TypeError,
1253 self.set.difference_update,
1254 self.other)
1255
1256 def test_difference(self):
1257 self.assertRaises(TypeError, lambda: self.set - self.other)
1258 self.assertRaises(TypeError, lambda: self.other - self.set)
1259 if self.otherIsIterable:
1260 self.set.difference(self.other)
1261 else:
1262 self.assertRaises(TypeError, self.set.difference, self.other)
1263
1264#------------------------------------------------------------------------------
1265
1266class TestOnlySetsNumeric(TestOnlySetsInBinaryOps):
1267 def setUp(self):
1268 self.set = set((1, 2, 3))
1269 self.other = 19
1270 self.otherIsIterable = False
1271
1272#------------------------------------------------------------------------------
1273
1274class TestOnlySetsDict(TestOnlySetsInBinaryOps):
1275 def setUp(self):
1276 self.set = set((1, 2, 3))
1277 self.other = {1:2, 3:4}
1278 self.otherIsIterable = True
1279
1280#------------------------------------------------------------------------------
1281
1282class TestOnlySetsOperator(TestOnlySetsInBinaryOps):
1283 def setUp(self):
1284 self.set = set((1, 2, 3))
1285 self.other = operator.add
1286 self.otherIsIterable = False
1287
1288#------------------------------------------------------------------------------
1289
1290class TestOnlySetsTuple(TestOnlySetsInBinaryOps):
1291 def setUp(self):
1292 self.set = set((1, 2, 3))
1293 self.other = (2, 4, 6)
1294 self.otherIsIterable = True
1295
1296#------------------------------------------------------------------------------
1297
1298class TestOnlySetsString(TestOnlySetsInBinaryOps):
1299 def setUp(self):
1300 self.set = set((1, 2, 3))
1301 self.other = 'abc'
1302 self.otherIsIterable = True
1303
1304#------------------------------------------------------------------------------
1305
1306class TestOnlySetsGenerator(TestOnlySetsInBinaryOps):
1307 def setUp(self):
1308 def gen():
1309 for i in xrange(0, 10, 2):
1310 yield i
1311 self.set = set((1, 2, 3))
1312 self.other = gen()
1313 self.otherIsIterable = True
1314
1315#==============================================================================
1316
1317class TestCopying(unittest.TestCase):
1318
1319 def test_copy(self):
1320 dup = self.set.copy()
1321 dup_list = list(dup); dup_list.sort()
1322 set_list = list(self.set); set_list.sort()
1323 self.assertEqual(len(dup_list), len(set_list))
1324 for i in range(len(dup_list)):
1325 self.failUnless(dup_list[i] is set_list[i])
1326
1327 def test_deep_copy(self):
1328 dup = copy.deepcopy(self.set)
Walter Dörwald70a6b492004-02-12 17:35:32 +00001329 ##print type(dup), repr(dup)
Raymond Hettingera690a992003-11-16 16:17:49 +00001330 dup_list = list(dup); dup_list.sort()
1331 set_list = list(self.set); set_list.sort()
1332 self.assertEqual(len(dup_list), len(set_list))
1333 for i in range(len(dup_list)):
1334 self.assertEqual(dup_list[i], set_list[i])
1335
1336#------------------------------------------------------------------------------
1337
1338class TestCopyingEmpty(TestCopying):
1339 def setUp(self):
1340 self.set = set()
1341
1342#------------------------------------------------------------------------------
1343
1344class TestCopyingSingleton(TestCopying):
1345 def setUp(self):
1346 self.set = set(["hello"])
1347
1348#------------------------------------------------------------------------------
1349
1350class TestCopyingTriple(TestCopying):
1351 def setUp(self):
1352 self.set = set(["zero", 0, None])
1353
1354#------------------------------------------------------------------------------
1355
1356class TestCopyingTuple(TestCopying):
1357 def setUp(self):
1358 self.set = set([(1, 2)])
1359
1360#------------------------------------------------------------------------------
1361
1362class TestCopyingNested(TestCopying):
1363 def setUp(self):
1364 self.set = set([((1, 2), (3, 4))])
1365
1366#==============================================================================
1367
1368class TestIdentities(unittest.TestCase):
1369 def setUp(self):
1370 self.a = set('abracadabra')
1371 self.b = set('alacazam')
1372
1373 def test_binopsVsSubsets(self):
1374 a, b = self.a, self.b
1375 self.assert_(a - b < a)
1376 self.assert_(b - a < b)
1377 self.assert_(a & b < a)
1378 self.assert_(a & b < b)
1379 self.assert_(a | b > a)
1380 self.assert_(a | b > b)
1381 self.assert_(a ^ b < a | b)
1382
1383 def test_commutativity(self):
1384 a, b = self.a, self.b
1385 self.assertEqual(a&b, b&a)
1386 self.assertEqual(a|b, b|a)
1387 self.assertEqual(a^b, b^a)
1388 if a != b:
1389 self.assertNotEqual(a-b, b-a)
1390
1391 def test_summations(self):
1392 # check that sums of parts equal the whole
1393 a, b = self.a, self.b
1394 self.assertEqual((a-b)|(a&b)|(b-a), a|b)
1395 self.assertEqual((a&b)|(a^b), a|b)
1396 self.assertEqual(a|(b-a), a|b)
1397 self.assertEqual((a-b)|b, a|b)
1398 self.assertEqual((a-b)|(a&b), a)
1399 self.assertEqual((b-a)|(a&b), b)
1400 self.assertEqual((a-b)|(b-a), a^b)
1401
1402 def test_exclusion(self):
1403 # check that inverse operations show non-overlap
1404 a, b, zero = self.a, self.b, set()
1405 self.assertEqual((a-b)&b, zero)
1406 self.assertEqual((b-a)&a, zero)
1407 self.assertEqual((a&b)&(a^b), zero)
1408
1409# Tests derived from test_itertools.py =======================================
1410
1411def R(seqn):
1412 'Regular generator'
1413 for i in seqn:
1414 yield i
1415
1416class G:
1417 'Sequence using __getitem__'
1418 def __init__(self, seqn):
1419 self.seqn = seqn
1420 def __getitem__(self, i):
1421 return self.seqn[i]
1422
1423class I:
1424 'Sequence using iterator protocol'
1425 def __init__(self, seqn):
1426 self.seqn = seqn
1427 self.i = 0
1428 def __iter__(self):
1429 return self
1430 def next(self):
1431 if self.i >= len(self.seqn): raise StopIteration
1432 v = self.seqn[self.i]
1433 self.i += 1
1434 return v
1435
1436class Ig:
1437 'Sequence using iterator protocol defined with a generator'
1438 def __init__(self, seqn):
1439 self.seqn = seqn
1440 self.i = 0
1441 def __iter__(self):
1442 for val in self.seqn:
1443 yield val
1444
1445class X:
1446 'Missing __getitem__ and __iter__'
1447 def __init__(self, seqn):
1448 self.seqn = seqn
1449 self.i = 0
1450 def next(self):
1451 if self.i >= len(self.seqn): raise StopIteration
1452 v = self.seqn[self.i]
1453 self.i += 1
1454 return v
1455
1456class N:
1457 'Iterator missing next()'
1458 def __init__(self, seqn):
1459 self.seqn = seqn
1460 self.i = 0
1461 def __iter__(self):
1462 return self
1463
1464class E:
1465 'Test propagation of exceptions'
1466 def __init__(self, seqn):
1467 self.seqn = seqn
1468 self.i = 0
1469 def __iter__(self):
1470 return self
1471 def next(self):
Raymond Hettingerffdb8bb2004-09-27 15:29:05 +00001472 3 // 0
Raymond Hettingera690a992003-11-16 16:17:49 +00001473
1474class S:
1475 'Test immediate stop'
1476 def __init__(self, seqn):
1477 pass
1478 def __iter__(self):
1479 return self
1480 def next(self):
1481 raise StopIteration
1482
1483from itertools import chain, imap
1484def L(seqn):
1485 'Test multiple tiers of iterators'
1486 return chain(imap(lambda x:x, R(Ig(G(seqn)))))
1487
1488class TestVariousIteratorArgs(unittest.TestCase):
1489
1490 def test_constructor(self):
1491 for cons in (set, frozenset):
1492 for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)):
1493 for g in (G, I, Ig, S, L, R):
Raymond Hettinger64958a12003-12-17 20:43:33 +00001494 self.assertEqual(sorted(cons(g(s))), sorted(g(s)))
Raymond Hettingera690a992003-11-16 16:17:49 +00001495 self.assertRaises(TypeError, cons , X(s))
1496 self.assertRaises(TypeError, cons , N(s))
1497 self.assertRaises(ZeroDivisionError, cons , E(s))
1498
1499 def test_inline_methods(self):
1500 s = set('november')
1501 for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'):
Raymond Hettinger1760c8a2007-11-08 02:52:43 +00001502 for meth in (s.union, s.intersection, s.difference, s.symmetric_difference, s.isdisjoint):
Raymond Hettingera690a992003-11-16 16:17:49 +00001503 for g in (G, I, Ig, L, R):
1504 expected = meth(data)
1505 actual = meth(G(data))
Raymond Hettinger1760c8a2007-11-08 02:52:43 +00001506 if isinstance(expected, bool):
1507 self.assertEqual(actual, expected)
1508 else:
1509 self.assertEqual(sorted(actual), sorted(expected))
Raymond Hettingera690a992003-11-16 16:17:49 +00001510 self.assertRaises(TypeError, meth, X(s))
1511 self.assertRaises(TypeError, meth, N(s))
1512 self.assertRaises(ZeroDivisionError, meth, E(s))
1513
1514 def test_inplace_methods(self):
1515 for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'):
Raymond Hettingerf5f41bf2003-11-24 02:57:33 +00001516 for methname in ('update', 'intersection_update',
Raymond Hettingera690a992003-11-16 16:17:49 +00001517 'difference_update', 'symmetric_difference_update'):
1518 for g in (G, I, Ig, S, L, R):
1519 s = set('january')
1520 t = s.copy()
1521 getattr(s, methname)(list(g(data)))
1522 getattr(t, methname)(g(data))
Raymond Hettinger64958a12003-12-17 20:43:33 +00001523 self.assertEqual(sorted(s), sorted(t))
Raymond Hettingera690a992003-11-16 16:17:49 +00001524
1525 self.assertRaises(TypeError, getattr(set('january'), methname), X(data))
1526 self.assertRaises(TypeError, getattr(set('january'), methname), N(data))
1527 self.assertRaises(ZeroDivisionError, getattr(set('january'), methname), E(data))
1528
Raymond Hettinger61708742008-01-24 21:23:58 +00001529# Application tests (based on David Eppstein's graph recipes ====================================
1530
1531def powerset(U):
1532 """Generates all subsets of a set or sequence U."""
1533 U = iter(U)
1534 try:
1535 x = frozenset([U.next()])
1536 for S in powerset(U):
1537 yield S
1538 yield S | x
1539 except StopIteration:
1540 yield frozenset()
1541
1542def cube(n):
1543 """Graph of n-dimensional hypercube."""
1544 singletons = [frozenset([x]) for x in range(n)]
1545 return dict([(x, frozenset([x^s for s in singletons]))
1546 for x in powerset(range(n))])
1547
1548def linegraph(G):
1549 """Graph, the vertices of which are edges of G,
1550 with two vertices being adjacent iff the corresponding
1551 edges share a vertex."""
1552 L = {}
1553 for x in G:
1554 for y in G[x]:
1555 nx = [frozenset([x,z]) for z in G[x] if z != y]
1556 ny = [frozenset([y,z]) for z in G[y] if z != x]
1557 L[frozenset([x,y])] = frozenset(nx+ny)
1558 return L
1559
1560def faces(G):
1561 'Return a set of faces in G. Where a face is a set of vertices on that face'
1562 # currently limited to triangles,squares, and pentagons
1563 f = set()
1564 for v1, edges in G.items():
1565 for v2 in edges:
1566 for v3 in G[v2]:
1567 if v1 == v3:
1568 continue
1569 if v1 in G[v3]:
1570 f.add(frozenset([v1, v2, v3]))
1571 else:
1572 for v4 in G[v3]:
1573 if v4 == v2:
1574 continue
1575 if v1 in G[v4]:
1576 f.add(frozenset([v1, v2, v3, v4]))
1577 else:
1578 for v5 in G[v4]:
1579 if v5 == v3 or v5 == v2:
1580 continue
1581 if v1 in G[v5]:
1582 f.add(frozenset([v1, v2, v3, v4, v5]))
1583 return f
1584
1585
1586class TestGraphs(unittest.TestCase):
1587
1588 def test_cube(self):
1589
1590 g = cube(3) # vert --> {v1, v2, v3}
1591 vertices1 = set(g)
1592 self.assertEqual(len(vertices1), 8) # eight vertices
1593 for edge in g.values():
1594 self.assertEqual(len(edge), 3) # each vertex connects to three edges
1595 vertices2 = set(v for edges in g.values() for v in edges)
1596 self.assertEqual(vertices1, vertices2) # edge vertices in original set
1597
1598 cubefaces = faces(g)
1599 self.assertEqual(len(cubefaces), 6) # six faces
1600 for face in cubefaces:
1601 self.assertEqual(len(face), 4) # each face is a square
1602
1603 def test_cuboctahedron(self):
1604
1605 # http://en.wikipedia.org/wiki/Cuboctahedron
1606 # 8 triangular faces and 6 square faces
1607 # 12 indentical vertices each connecting a triangle and square
1608
1609 g = cube(3)
1610 cuboctahedron = linegraph(g) # V( --> {V1, V2, V3, V4}
1611 self.assertEqual(len(cuboctahedron), 12)# twelve vertices
1612
1613 vertices = set(cuboctahedron)
1614 for edges in cuboctahedron.values():
1615 self.assertEqual(len(edges), 4) # each vertex connects to four other vertices
1616 othervertices = set(edge for edges in cuboctahedron.values() for edge in edges)
1617 self.assertEqual(vertices, othervertices) # edge vertices in original set
1618
1619 cubofaces = faces(cuboctahedron)
1620 facesizes = collections.defaultdict(int)
1621 for face in cubofaces:
1622 facesizes[len(face)] += 1
1623 self.assertEqual(facesizes[3], 8) # eight triangular faces
1624 self.assertEqual(facesizes[4], 6) # six square faces
1625
1626 for vertex in cuboctahedron:
1627 edge = vertex # Cuboctahedron vertices are edges in Cube
1628 self.assertEqual(len(edge), 2) # Two cube vertices define an edge
1629 for cubevert in edge:
1630 self.assert_(cubevert in g)
1631
1632
Raymond Hettingera690a992003-11-16 16:17:49 +00001633#==============================================================================
1634
1635def test_main(verbose=None):
Raymond Hettingera690a992003-11-16 16:17:49 +00001636 from test import test_sets
1637 test_classes = (
1638 TestSet,
Raymond Hettinger50a4bb32003-11-17 16:42:33 +00001639 TestSetSubclass,
Tim Petersf733abb2007-01-30 03:03:46 +00001640 TestSetSubclassWithKeywordArgs,
Raymond Hettingera690a992003-11-16 16:17:49 +00001641 TestFrozenSet,
Raymond Hettinger50a4bb32003-11-17 16:42:33 +00001642 TestFrozenSetSubclass,
Raymond Hettingera690a992003-11-16 16:17:49 +00001643 TestSetOfSets,
1644 TestExceptionPropagation,
1645 TestBasicOpsEmpty,
1646 TestBasicOpsSingleton,
1647 TestBasicOpsTuple,
1648 TestBasicOpsTriple,
1649 TestBinaryOps,
1650 TestUpdateOps,
1651 TestMutate,
1652 TestSubsetEqualEmpty,
1653 TestSubsetEqualNonEmpty,
1654 TestSubsetEmptyNonEmpty,
1655 TestSubsetPartial,
1656 TestSubsetNonOverlap,
1657 TestOnlySetsNumeric,
1658 TestOnlySetsDict,
1659 TestOnlySetsOperator,
1660 TestOnlySetsTuple,
1661 TestOnlySetsString,
1662 TestOnlySetsGenerator,
1663 TestCopyingEmpty,
1664 TestCopyingSingleton,
1665 TestCopyingTriple,
1666 TestCopyingTuple,
1667 TestCopyingNested,
1668 TestIdentities,
1669 TestVariousIteratorArgs,
Raymond Hettinger61708742008-01-24 21:23:58 +00001670 TestGraphs,
Raymond Hettingera690a992003-11-16 16:17:49 +00001671 )
1672
1673 test_support.run_unittest(*test_classes)
1674
1675 # verify reference counting
1676 if verbose and hasattr(sys, "gettotalrefcount"):
1677 import gc
1678 counts = [None] * 5
1679 for i in xrange(len(counts)):
1680 test_support.run_unittest(*test_classes)
1681 gc.collect()
1682 counts[i] = sys.gettotalrefcount()
1683 print counts
1684
1685if __name__ == "__main__":
1686 test_main(verbose=True)