1import unittest, operator, copy, pickle, random
2from test import test_support
3
4test_support.import_module("sets", deprecated=True)
5from sets import Set, ImmutableSet
6
7empty_set = Set()
8
9#==============================================================================
10
11class TestBasicOps(unittest.TestCase):
12
13    def test_repr(self):
14        if self.repr is not None:
15            self.assertEqual(repr(self.set), self.repr)
16
17    def test_length(self):
18        self.assertEqual(len(self.set), self.length)
19
20    def test_self_equality(self):
21        self.assertEqual(self.set, self.set)
22
23    def test_equivalent_equality(self):
24        self.assertEqual(self.set, self.dup)
25
26    def test_copy(self):
27        self.assertEqual(self.set.copy(), self.dup)
28
29    def test_self_union(self):
30        result = self.set | self.set
31        self.assertEqual(result, self.dup)
32
33    def test_empty_union(self):
34        result = self.set | empty_set
35        self.assertEqual(result, self.dup)
36
37    def test_union_empty(self):
38        result = empty_set | self.set
39        self.assertEqual(result, self.dup)
40
41    def test_self_intersection(self):
42        result = self.set & self.set
43        self.assertEqual(result, self.dup)
44
45    def test_empty_intersection(self):
46        result = self.set & empty_set
47        self.assertEqual(result, empty_set)
48
49    def test_intersection_empty(self):
50        result = empty_set & self.set
51        self.assertEqual(result, empty_set)
52
53    def test_self_symmetric_difference(self):
54        result = self.set ^ self.set
55        self.assertEqual(result, empty_set)
56
57    def checkempty_symmetric_difference(self):
58        result = self.set ^ empty_set
59        self.assertEqual(result, self.set)
60
61    def test_self_difference(self):
62        result = self.set - self.set
63        self.assertEqual(result, empty_set)
64
65    def test_empty_difference(self):
66        result = self.set - empty_set
67        self.assertEqual(result, self.dup)
68
69    def test_empty_difference_rev(self):
70        result = empty_set - self.set
71        self.assertEqual(result, empty_set)
72
73    def test_iteration(self):
74        for v in self.set:
75            self.assertIn(v, self.values)
76
77    def test_pickling(self):
78        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
79            p = pickle.dumps(self.set, proto)
80            copy = pickle.loads(p)
81            self.assertEqual(self.set, copy,
82                             "%s != %s" % (self.set, copy))
83
84#------------------------------------------------------------------------------
85
86class TestBasicOpsEmpty(TestBasicOps):
87    def setUp(self):
88        self.case   = "empty set"
89        self.values = []
90        self.set    = Set(self.values)
91        self.dup    = Set(self.values)
92        self.length = 0
93        self.repr   = "Set([])"
94
95#------------------------------------------------------------------------------
96
97class TestBasicOpsSingleton(TestBasicOps):
98    def setUp(self):
99        self.case   = "unit set (number)"
100        self.values = [3]
101        self.set    = Set(self.values)
102        self.dup    = Set(self.values)
103        self.length = 1
104        self.repr   = "Set([3])"
105
106    def test_in(self):
107        self.assertTrue(3 in self.set)
108
109    def test_not_in(self):
110        self.assertTrue(2 not in self.set)
111
112#------------------------------------------------------------------------------
113
114class TestBasicOpsTuple(TestBasicOps):
115    def setUp(self):
116        self.case   = "unit set (tuple)"
117        self.values = [(0, "zero")]
118        self.set    = Set(self.values)
119        self.dup    = Set(self.values)
120        self.length = 1
121        self.repr   = "Set([(0, 'zero')])"
122
123    def test_in(self):
124        self.assertTrue((0, "zero") in self.set)
125
126    def test_not_in(self):
127        self.assertTrue(9 not in self.set)
128
129#------------------------------------------------------------------------------
130
131class TestBasicOpsTriple(TestBasicOps):
132    def setUp(self):
133        self.case   = "triple set"
134        self.values = [0, "zero", operator.add]
135        self.set    = Set(self.values)
136        self.dup    = Set(self.values)
137        self.length = 3
138        self.repr   = None
139
140#==============================================================================
141
142def baditer():
143    raise TypeError
144    yield True
145
146def gooditer():
147    yield True
148
149class TestExceptionPropagation(unittest.TestCase):
150    """SF 628246:  Set constructor should not trap iterator TypeErrors"""
151
152    def test_instanceWithException(self):
153        self.assertRaises(TypeError, Set, baditer())
154
155    def test_instancesWithoutException(self):
156        # All of these iterables should load without exception.
157        Set([1,2,3])
158        Set((1,2,3))
159        Set({'one':1, 'two':2, 'three':3})
160        Set(xrange(3))
161        Set('abc')
162        Set(gooditer())
163
164#==============================================================================
165
166class TestSetOfSets(unittest.TestCase):
167    def test_constructor(self):
168        inner = Set([1])
169        outer = Set([inner])
170        element = outer.pop()
171        self.assertEqual(type(element), ImmutableSet)
172        outer.add(inner)        # Rebuild set of sets with .add method
173        outer.remove(inner)
174        self.assertEqual(outer, Set())   # Verify that remove worked
175        outer.discard(inner)    # Absence of KeyError indicates working fine
176
177#==============================================================================
178
179class TestBinaryOps(unittest.TestCase):
180    def setUp(self):
181        self.set = Set((2, 4, 6))
182
183    def test_eq(self):              # SF bug 643115
184        self.assertEqual(self.set, Set({2:1,4:3,6:5}))
185
186    def test_union_subset(self):
187        result = self.set | Set([2])
188        self.assertEqual(result, Set((2, 4, 6)))
189
190    def test_union_superset(self):
191        result = self.set | Set([2, 4, 6, 8])
192        self.assertEqual(result, Set([2, 4, 6, 8]))
193
194    def test_union_overlap(self):
195        result = self.set | Set([3, 4, 5])
196        self.assertEqual(result, Set([2, 3, 4, 5, 6]))
197
198    def test_union_non_overlap(self):
199        result = self.set | Set([8])
200        self.assertEqual(result, Set([2, 4, 6, 8]))
201
202    def test_intersection_subset(self):
203        result = self.set & Set((2, 4))
204        self.assertEqual(result, Set((2, 4)))
205
206    def test_intersection_superset(self):
207        result = self.set & Set([2, 4, 6, 8])
208        self.assertEqual(result, Set([2, 4, 6]))
209
210    def test_intersection_overlap(self):
211        result = self.set & Set([3, 4, 5])
212        self.assertEqual(result, Set([4]))
213
214    def test_intersection_non_overlap(self):
215        result = self.set & Set([8])
216        self.assertEqual(result, empty_set)
217
218    def test_sym_difference_subset(self):
219        result = self.set ^ Set((2, 4))
220        self.assertEqual(result, Set([6]))
221
222    def test_sym_difference_superset(self):
223        result = self.set ^ Set((2, 4, 6, 8))
224        self.assertEqual(result, Set([8]))
225
226    def test_sym_difference_overlap(self):
227        result = self.set ^ Set((3, 4, 5))
228        self.assertEqual(result, Set([2, 3, 5, 6]))
229
230    def test_sym_difference_non_overlap(self):
231        result = self.set ^ Set([8])
232        self.assertEqual(result, Set([2, 4, 6, 8]))
233
234    def test_cmp(self):
235        a, b = Set('a'), Set('b')
236        self.assertRaises(TypeError, cmp, a, b)
237
238        # You can view this as a buglet:  cmp(a, a) does not raise TypeError,
239        # because __eq__ is tried before __cmp__, and a.__eq__(a) returns True,
240        # which Python thinks is good enough to synthesize a cmp() result
241        # without calling __cmp__.
242        self.assertEqual(cmp(a, a), 0)
243
244        self.assertRaises(TypeError, cmp, a, 12)
245        self.assertRaises(TypeError, cmp, "abc", a)
246
247    def test_inplace_on_self(self):
248        t = self.set.copy()
249        t |= t
250        self.assertEqual(t, self.set)
251        t &= t
252        self.assertEqual(t, self.set)
253        t -= t
254        self.assertEqual(len(t), 0)
255        t = self.set.copy()
256        t ^= t
257        self.assertEqual(len(t), 0)
258
259
260#==============================================================================
261
262class TestUpdateOps(unittest.TestCase):
263    def setUp(self):
264        self.set = Set((2, 4, 6))
265
266    def test_union_subset(self):
267        self.set |= Set([2])
268        self.assertEqual(self.set, Set((2, 4, 6)))
269
270    def test_union_superset(self):
271        self.set |= Set([2, 4, 6, 8])
272        self.assertEqual(self.set, Set([2, 4, 6, 8]))
273
274    def test_union_overlap(self):
275        self.set |= Set([3, 4, 5])
276        self.assertEqual(self.set, Set([2, 3, 4, 5, 6]))
277
278    def test_union_non_overlap(self):
279        self.set |= Set([8])
280        self.assertEqual(self.set, Set([2, 4, 6, 8]))
281
282    def test_union_method_call(self):
283        self.set.union_update(Set([3, 4, 5]))
284        self.assertEqual(self.set, Set([2, 3, 4, 5, 6]))
285
286    def test_intersection_subset(self):
287        self.set &= Set((2, 4))
288        self.assertEqual(self.set, Set((2, 4)))
289
290    def test_intersection_superset(self):
291        self.set &= Set([2, 4, 6, 8])
292        self.assertEqual(self.set, Set([2, 4, 6]))
293
294    def test_intersection_overlap(self):
295        self.set &= Set([3, 4, 5])
296        self.assertEqual(self.set, Set([4]))
297
298    def test_intersection_non_overlap(self):
299        self.set &= Set([8])
300        self.assertEqual(self.set, empty_set)
301
302    def test_intersection_method_call(self):
303        self.set.intersection_update(Set([3, 4, 5]))
304        self.assertEqual(self.set, Set([4]))
305
306    def test_sym_difference_subset(self):
307        self.set ^= Set((2, 4))
308        self.assertEqual(self.set, Set([6]))
309
310    def test_sym_difference_superset(self):
311        self.set ^= Set((2, 4, 6, 8))
312        self.assertEqual(self.set, Set([8]))
313
314    def test_sym_difference_overlap(self):
315        self.set ^= Set((3, 4, 5))
316        self.assertEqual(self.set, Set([2, 3, 5, 6]))
317
318    def test_sym_difference_non_overlap(self):
319        self.set ^= Set([8])
320        self.assertEqual(self.set, Set([2, 4, 6, 8]))
321
322    def test_sym_difference_method_call(self):
323        self.set.symmetric_difference_update(Set([3, 4, 5]))
324        self.assertEqual(self.set, Set([2, 3, 5, 6]))
325
326    def test_difference_subset(self):
327        self.set -= Set((2, 4))
328        self.assertEqual(self.set, Set([6]))
329
330    def test_difference_superset(self):
331        self.set -= Set((2, 4, 6, 8))
332        self.assertEqual(self.set, Set([]))
333
334    def test_difference_overlap(self):
335        self.set -= Set((3, 4, 5))
336        self.assertEqual(self.set, Set([2, 6]))
337
338    def test_difference_non_overlap(self):
339        self.set -= Set([8])
340        self.assertEqual(self.set, Set([2, 4, 6]))
341
342    def test_difference_method_call(self):
343        self.set.difference_update(Set([3, 4, 5]))
344        self.assertEqual(self.set, Set([2, 6]))
345
346#==============================================================================
347
348class TestMutate(unittest.TestCase):
349    def setUp(self):
350        self.values = ["a", "b", "c"]
351        self.set = Set(self.values)
352
353    def test_add_present(self):
354        self.set.add("c")
355        self.assertEqual(self.set, Set("abc"))
356
357    def test_add_absent(self):
358        self.set.add("d")
359        self.assertEqual(self.set, Set("abcd"))
360
361    def test_add_until_full(self):
362        tmp = Set()
363        expected_len = 0
364        for v in self.values:
365            tmp.add(v)
366            expected_len += 1
367            self.assertEqual(len(tmp), expected_len)
368        self.assertEqual(tmp, self.set)
369
370    def test_remove_present(self):
371        self.set.remove("b")
372        self.assertEqual(self.set, Set("ac"))
373
374    def test_remove_absent(self):
375        try:
376            self.set.remove("d")
377            self.fail("Removing missing element should have raised LookupError")
378        except LookupError:
379            pass
380
381    def test_remove_until_empty(self):
382        expected_len = len(self.set)
383        for v in self.values:
384            self.set.remove(v)
385            expected_len -= 1
386            self.assertEqual(len(self.set), expected_len)
387
388    def test_discard_present(self):
389        self.set.discard("c")
390        self.assertEqual(self.set, Set("ab"))
391
392    def test_discard_absent(self):
393        self.set.discard("d")
394        self.assertEqual(self.set, Set("abc"))
395
396    def test_clear(self):
397        self.set.clear()
398        self.assertEqual(len(self.set), 0)
399
400    def test_pop(self):
401        popped = {}
402        while self.set:
403            popped[self.set.pop()] = None
404        self.assertEqual(len(popped), len(self.values))
405        for v in self.values:
406            self.assertIn(v, popped)
407
408    def test_update_empty_tuple(self):
409        self.set.union_update(())
410        self.assertEqual(self.set, Set(self.values))
411
412    def test_update_unit_tuple_overlap(self):
413        self.set.union_update(("a",))
414        self.assertEqual(self.set, Set(self.values))
415
416    def test_update_unit_tuple_non_overlap(self):
417        self.set.union_update(("a", "z"))
418        self.assertEqual(self.set, Set(self.values + ["z"]))
419
420#==============================================================================
421
422class TestSubsets(unittest.TestCase):
423
424    case2method = {"<=": "issubset",
425                   ">=": "issuperset",
426                  }
427
428    reverse = {"==": "==",
429               "!=": "!=",
430               "<":  ">",
431               ">":  "<",
432               "<=": ">=",
433               ">=": "<=",
434              }
435
436    def test_issubset(self):
437        x = self.left
438        y = self.right
439        for case in "!=", "==", "<", "<=", ">", ">=":
440            expected = case in self.cases
441            # Test the binary infix spelling.
442            result = eval("x" + case + "y", locals())
443            self.assertEqual(result, expected)
444            # Test the "friendly" method-name spelling, if one exists.
445            if case in TestSubsets.case2method:
446                method = getattr(x, TestSubsets.case2method[case])
447                result = method(y)
448                self.assertEqual(result, expected)
449
450            # Now do the same for the operands reversed.
451            rcase = TestSubsets.reverse[case]
452            result = eval("y" + rcase + "x", locals())
453            self.assertEqual(result, expected)
454            if rcase in TestSubsets.case2method:
455                method = getattr(y, TestSubsets.case2method[rcase])
456                result = method(x)
457                self.assertEqual(result, expected)
458#------------------------------------------------------------------------------
459
460class TestSubsetEqualEmpty(TestSubsets):
461    left  = Set()
462    right = Set()
463    name  = "both empty"
464    cases = "==", "<=", ">="
465
466#------------------------------------------------------------------------------
467
468class TestSubsetEqualNonEmpty(TestSubsets):
469    left  = Set([1, 2])
470    right = Set([1, 2])
471    name  = "equal pair"
472    cases = "==", "<=", ">="
473
474#------------------------------------------------------------------------------
475
476class TestSubsetEmptyNonEmpty(TestSubsets):
477    left  = Set()
478    right = Set([1, 2])
479    name  = "one empty, one non-empty"
480    cases = "!=", "<", "<="
481
482#------------------------------------------------------------------------------
483
484class TestSubsetPartial(TestSubsets):
485    left  = Set([1])
486    right = Set([1, 2])
487    name  = "one a non-empty proper subset of other"
488    cases = "!=", "<", "<="
489
490#------------------------------------------------------------------------------
491
492class TestSubsetNonOverlap(TestSubsets):
493    left  = Set([1])
494    right = Set([2])
495    name  = "neither empty, neither contains"
496    cases = "!="
497
498#==============================================================================
499
500class TestOnlySetsInBinaryOps(unittest.TestCase):
501
502    def test_eq_ne(self):
503        # Unlike the others, this is testing that == and != *are* allowed.
504        self.assertEqual(self.other == self.set, False)
505        self.assertEqual(self.set == self.other, False)
506        self.assertEqual(self.other != self.set, True)
507        self.assertEqual(self.set != self.other, True)
508
509    def test_ge_gt_le_lt(self):
510        self.assertRaises(TypeError, lambda: self.set < self.other)
511        self.assertRaises(TypeError, lambda: self.set <= self.other)
512        self.assertRaises(TypeError, lambda: self.set > self.other)
513        self.assertRaises(TypeError, lambda: self.set >= self.other)
514
515        self.assertRaises(TypeError, lambda: self.other < self.set)
516        self.assertRaises(TypeError, lambda: self.other <= self.set)
517        self.assertRaises(TypeError, lambda: self.other > self.set)
518        self.assertRaises(TypeError, lambda: self.other >= self.set)
519
520    def test_union_update_operator(self):
521        try:
522            self.set |= self.other
523        except TypeError:
524            pass
525        else:
526            self.fail("expected TypeError")
527
528    def test_union_update(self):
529        if self.otherIsIterable:
530            self.set.union_update(self.other)
531        else:
532            self.assertRaises(TypeError, self.set.union_update, self.other)
533
534    def test_union(self):
535        self.assertRaises(TypeError, lambda: self.set | self.other)
536        self.assertRaises(TypeError, lambda: self.other | self.set)
537        if self.otherIsIterable:
538            self.set.union(self.other)
539        else:
540            self.assertRaises(TypeError, self.set.union, self.other)
541
542    def test_intersection_update_operator(self):
543        try:
544            self.set &= self.other
545        except TypeError:
546            pass
547        else:
548            self.fail("expected TypeError")
549
550    def test_intersection_update(self):
551        if self.otherIsIterable:
552            self.set.intersection_update(self.other)
553        else:
554            self.assertRaises(TypeError,
555                              self.set.intersection_update,
556                              self.other)
557
558    def test_intersection(self):
559        self.assertRaises(TypeError, lambda: self.set & self.other)
560        self.assertRaises(TypeError, lambda: self.other & self.set)
561        if self.otherIsIterable:
562            self.set.intersection(self.other)
563        else:
564            self.assertRaises(TypeError, self.set.intersection, self.other)
565
566    def test_sym_difference_update_operator(self):
567        try:
568            self.set ^= self.other
569        except TypeError:
570            pass
571        else:
572            self.fail("expected TypeError")
573
574    def test_sym_difference_update(self):
575        if self.otherIsIterable:
576            self.set.symmetric_difference_update(self.other)
577        else:
578            self.assertRaises(TypeError,
579                              self.set.symmetric_difference_update,
580                              self.other)
581
582    def test_sym_difference(self):
583        self.assertRaises(TypeError, lambda: self.set ^ self.other)
584        self.assertRaises(TypeError, lambda: self.other ^ self.set)
585        if self.otherIsIterable:
586            self.set.symmetric_difference(self.other)
587        else:
588            self.assertRaises(TypeError, self.set.symmetric_difference, self.other)
589
590    def test_difference_update_operator(self):
591        try:
592            self.set -= self.other
593        except TypeError:
594            pass
595        else:
596            self.fail("expected TypeError")
597
598    def test_difference_update(self):
599        if self.otherIsIterable:
600            self.set.difference_update(self.other)
601        else:
602            self.assertRaises(TypeError,
603                              self.set.difference_update,
604                              self.other)
605
606    def test_difference(self):
607        self.assertRaises(TypeError, lambda: self.set - self.other)
608        self.assertRaises(TypeError, lambda: self.other - self.set)
609        if self.otherIsIterable:
610            self.set.difference(self.other)
611        else:
612            self.assertRaises(TypeError, self.set.difference, self.other)
613
614#------------------------------------------------------------------------------
615
616class TestOnlySetsNumeric(TestOnlySetsInBinaryOps):
617    def setUp(self):
618        self.set   = Set((1, 2, 3))
619        self.other = 19
620        self.otherIsIterable = False
621
622#------------------------------------------------------------------------------
623
624class TestOnlySetsDict(TestOnlySetsInBinaryOps):
625    def setUp(self):
626        self.set   = Set((1, 2, 3))
627        self.other = {1:2, 3:4}
628        self.otherIsIterable = True
629
630#------------------------------------------------------------------------------
631
632class TestOnlySetsOperator(TestOnlySetsInBinaryOps):
633    def setUp(self):
634        self.set   = Set((1, 2, 3))
635        self.other = operator.add
636        self.otherIsIterable = False
637
638    def test_ge_gt_le_lt(self):
639        with test_support.check_py3k_warnings():
640            super(TestOnlySetsOperator, self).test_ge_gt_le_lt()
641
642#------------------------------------------------------------------------------
643
644class TestOnlySetsTuple(TestOnlySetsInBinaryOps):
645    def setUp(self):
646        self.set   = Set((1, 2, 3))
647        self.other = (2, 4, 6)
648        self.otherIsIterable = True
649
650#------------------------------------------------------------------------------
651
652class TestOnlySetsString(TestOnlySetsInBinaryOps):
653    def setUp(self):
654        self.set   = Set((1, 2, 3))
655        self.other = 'abc'
656        self.otherIsIterable = True
657
658#------------------------------------------------------------------------------
659
660class TestOnlySetsGenerator(TestOnlySetsInBinaryOps):
661    def setUp(self):
662        def gen():
663            for i in xrange(0, 10, 2):
664                yield i
665        self.set   = Set((1, 2, 3))
666        self.other = gen()
667        self.otherIsIterable = True
668
669#------------------------------------------------------------------------------
670
671class TestOnlySetsofSets(TestOnlySetsInBinaryOps):
672    def setUp(self):
673        self.set   = Set((1, 2, 3))
674        self.other = [Set('ab'), ImmutableSet('cd')]
675        self.otherIsIterable = True
676
677#==============================================================================
678
679class TestCopying(unittest.TestCase):
680
681    def test_copy(self):
682        dup = self.set.copy()
683        self.assertEqual(len(dup), len(self.set))
684        dup_list = sorted(dup)
685        set_list = sorted(self.set)
686        self.assertEqual(len(dup_list), len(set_list))
687        for i, el in enumerate(dup_list):
688            self.assertIs(el, set_list[i])
689
690    def test_deep_copy(self):
691        dup = copy.deepcopy(self.set)
692        self.assertSetEqual(dup, self.set)
693
694#------------------------------------------------------------------------------
695
696class TestCopyingEmpty(TestCopying):
697    def setUp(self):
698        self.set = Set()
699
700#------------------------------------------------------------------------------
701
702class TestCopyingSingleton(TestCopying):
703    def setUp(self):
704        self.set = Set(["hello"])
705
706#------------------------------------------------------------------------------
707
708class TestCopyingTriple(TestCopying):
709    def setUp(self):
710        self.set = Set(["zero", 0, None])
711
712    def test_copy(self):
713        with test_support.check_py3k_warnings():
714            super(TestCopyingTriple, self).test_copy()
715
716#------------------------------------------------------------------------------
717
718class TestCopyingTuple(TestCopying):
719    def setUp(self):
720        self.set = Set([(1, 2)])
721
722#------------------------------------------------------------------------------
723
724class TestCopyingNested(TestCopying):
725    def setUp(self):
726        self.set = Set([((1, 2), (3, 4))])
727
728#==============================================================================
729
730class TestIdentities(unittest.TestCase):
731    def setUp(self):
732        self.a = Set([random.randrange(100) for i in xrange(50)])
733        self.b = Set([random.randrange(100) for i in xrange(50)])
734
735    def test_binopsVsSubsets(self):
736        a, b = self.a, self.b
737        self.assertTrue(a - b <= a)
738        self.assertTrue(b - a <= b)
739        self.assertTrue(a & b <= a)
740        self.assertTrue(a & b <= b)
741        self.assertTrue(a | b >= a)
742        self.assertTrue(a | b >= b)
743        self.assertTrue(a ^ b <= a | b)
744
745    def test_commutativity(self):
746        a, b = self.a, self.b
747        self.assertEqual(a&b, b&a)
748        self.assertEqual(a|b, b|a)
749        self.assertEqual(a^b, b^a)
750        if a != b:
751            self.assertNotEqual(a-b, b-a)
752
753    def test_reflexsive_relations(self):
754        a, zero = self.a, Set()
755        self.assertEqual(a ^ a, zero)
756        self.assertEqual(a - a, zero)
757        self.assertEqual(a | a, a)
758        self.assertEqual(a & a, a)
759        self.assertTrue(a <= a)
760        self.assertTrue(a >= a)
761        self.assertTrue(a == a)
762
763    def test_summations(self):
764        # check that sums of parts equal the whole
765        a, b = self.a, self.b
766        self.assertEqual((a-b)|(a&b)|(b-a), a|b)
767        self.assertEqual((a&b)|(a^b), a|b)
768        self.assertEqual(a|(b-a), a|b)
769        self.assertEqual((a-b)|b, a|b)
770        self.assertEqual((a-b)|(a&b), a)
771        self.assertEqual((b-a)|(a&b), b)
772        self.assertEqual((a-b)|(b-a), a^b)
773
774    def test_exclusion(self):
775        # check that inverse operations do not overlap
776        a, b, zero = self.a, self.b, Set()
777        self.assertEqual((a-b)&b, zero)
778        self.assertEqual((b-a)&a, zero)
779        self.assertEqual((a&b)&(a^b), zero)
780
781    def test_cardinality_relations(self):
782        a, b = self.a, self.b
783        self.assertEqual(len(a), len(a-b) + len(a&b))
784        self.assertEqual(len(b), len(b-a) + len(a&b))
785        self.assertEqual(len(a^b), len(a-b) + len(b-a))
786        self.assertEqual(len(a|b), len(a-b) + len(a&b) + len(b-a))
787        self.assertEqual(len(a^b) + len(a&b), len(a|b))
788
789#==============================================================================
790
791libreftest = """
792Example from the Library Reference:  Doc/lib/libsets.tex
793
794>>> from sets import Set as Base  # override _repr to get sorted output
795>>> class Set(Base):
796...     def _repr(self):
797...         return Base._repr(self, sorted=True)
798>>> engineers = Set(['John', 'Jane', 'Jack', 'Janice'])
799>>> programmers = Set(['Jack', 'Sam', 'Susan', 'Janice'])
800>>> managers = Set(['Jane', 'Jack', 'Susan', 'Zack'])
801>>> employees = engineers | programmers | managers           # union
802>>> engineering_management = engineers & managers            # intersection
803>>> fulltime_management = managers - engineers - programmers # difference
804>>> engineers.add('Marvin')
805>>> print engineers
806Set(['Jack', 'Jane', 'Janice', 'John', 'Marvin'])
807>>> employees.issuperset(engineers)           # superset test
808False
809>>> employees.union_update(engineers)         # update from another set
810>>> employees.issuperset(engineers)
811True
812>>> for group in [engineers, programmers, managers, employees]:
813...     group.discard('Susan')                # unconditionally remove element
814...     print group
815...
816Set(['Jack', 'Jane', 'Janice', 'John', 'Marvin'])
817Set(['Jack', 'Janice', 'Sam'])
818Set(['Jack', 'Jane', 'Zack'])
819Set(['Jack', 'Jane', 'Janice', 'John', 'Marvin', 'Sam', 'Zack'])
820"""
821
822#==============================================================================
823
824__test__ = {'libreftest' : libreftest}
825
826def test_main(verbose=None):
827    import doctest
828    from test import test_sets
829    test_support.run_unittest(
830        TestSetOfSets,
831        TestExceptionPropagation,
832        TestBasicOpsEmpty,
833        TestBasicOpsSingleton,
834        TestBasicOpsTuple,
835        TestBasicOpsTriple,
836        TestBinaryOps,
837        TestUpdateOps,
838        TestMutate,
839        TestSubsetEqualEmpty,
840        TestSubsetEqualNonEmpty,
841        TestSubsetEmptyNonEmpty,
842        TestSubsetPartial,
843        TestSubsetNonOverlap,
844        TestOnlySetsNumeric,
845        TestOnlySetsDict,
846        TestOnlySetsOperator,
847        TestOnlySetsTuple,
848        TestOnlySetsString,
849        TestOnlySetsGenerator,
850        TestOnlySetsofSets,
851        TestCopyingEmpty,
852        TestCopyingSingleton,
853        TestCopyingTriple,
854        TestCopyingTuple,
855        TestCopyingNested,
856        TestIdentities,
857        doctest.DocTestSuite(test_sets),
858    )
859
860if __name__ == "__main__":
861    test_main(verbose=True)
862