11import unittest
2- from threading import Thread , Barrier , Event
2+
3+ from threading import Thread , Barrier
4+ from unittest import TestCase
5+
36from test .support import threading_helper
47
58
6- class TestSetRepr (unittest .TestCase ):
9+ @threading_helper .requires_working_threading ()
10+ class TestSet (TestCase ):
711 def test_repr_clear (self ):
812 """Test repr() of a set while another thread is calling clear()"""
913 NUM_ITERS = 10
1014 NUM_REPR_THREADS = 10
11- barrier = Barrier (NUM_REPR_THREADS + 1 , timeout = 2 )
15+ barrier = Barrier (NUM_REPR_THREADS + 1 )
1216 s = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }
1317
1418 def clear_set ():
@@ -33,131 +37,5 @@ def repr_set():
3337 self .assertIn (set_repr , ("set()" , "{1, 2, 3, 4, 5, 6, 7, 8}" ))
3438
3539
36- class RaceTestBase :
37- def test_contains_mutate (self ):
38- """Test set contains operation combined with mutation."""
39- barrier = Barrier (2 , timeout = 2 )
40- s = set ()
41- done = Event ()
42-
43- NUM_LOOPS = 1000
44-
45- def read_set ():
46- barrier .wait ()
47- while not done .is_set ():
48- for i in range (self .SET_SIZE ):
49- item = i >> 1
50- result = item in s
51-
52- def mutate_set ():
53- barrier .wait ()
54- for i in range (NUM_LOOPS ):
55- s .clear ()
56- for j in range (self .SET_SIZE ):
57- s .add (j )
58- for j in range (self .SET_SIZE ):
59- s .discard (j )
60- # executes the set_swap_bodies() function
61- s .__iand__ (set (k for k in range (10 , 20 )))
62- done .set ()
63-
64- threads = [Thread (target = read_set ), Thread (target = mutate_set )]
65- for t in threads :
66- t .start ()
67- for t in threads :
68- t .join ()
69-
70- def test_contains_frozenset (self ):
71- barrier = Barrier (3 , timeout = 2 )
72- done = Event ()
73-
74- NUM_LOOPS = 1_000
75-
76- # This mutates the key used for contains test, not the container
77- # itself. This works because frozenset allows the key to be a set().
78- s = set ()
79-
80- def mutate_set ():
81- barrier .wait ()
82- while not done .is_set ():
83- s .add (0 )
84- s .add (1 )
85- s .clear ()
86-
87- def read_set ():
88- barrier .wait ()
89- container = frozenset ([frozenset ([0 ])])
90- self .assertTrue (set ([0 ]) in container )
91- for _ in range (NUM_LOOPS ):
92- # Will return True when {0} is the key and False otherwise
93- result = s in container
94- done .set ()
95-
96- threads = [
97- Thread (target = read_set ),
98- Thread (target = read_set ),
99- Thread (target = mutate_set ),
100- ]
101- for t in threads :
102- t .start ()
103- for t in threads :
104- t .join ()
105-
106- def test_contains_hash_mutate (self ):
107- """Test set contains operation with mutating hash method."""
108- barrier = Barrier (2 , timeout = 2 )
109-
110- NUM_LOOPS = 1_000
111- SET_SIZE = self .SET_SIZE
112-
113- s = set (range (SET_SIZE ))
114-
115- class Key :
116- def __init__ (self ):
117- self .count = 0
118- self .value = 0
119-
120- def __hash__ (self ):
121- self .count += 1
122- # This intends to trigger the SET_LOOKKEY_CHANGED case
123- # of set_lookkey_threadsafe() since calling clear()
124- # will cause the 'table' pointer to change.
125- if self .count % 2 == 0 :
126- s .clear ()
127- else :
128- s .update (range (SET_SIZE ))
129- return hash (self .value )
130-
131- def __eq__ (self , other ):
132- return self .value == other
133-
134- key = Key ()
135- self .assertTrue (key in s )
136- self .assertFalse (key in s )
137- self .assertTrue (key in s )
138- self .assertFalse (key in s )
139-
140- def read_set ():
141- barrier .wait ()
142- for i in range (NUM_LOOPS ):
143- result = key in s
144-
145- threads = [Thread (target = read_set ), Thread (target = read_set )]
146- for t in threads :
147- t .start ()
148- for t in threads :
149- t .join ()
150-
151-
152- @threading_helper .requires_working_threading ()
153- class SmallSetTest (RaceTestBase , unittest .TestCase ):
154- SET_SIZE = 6 # smaller than PySet_MINSIZE
155-
156-
157- @threading_helper .requires_working_threading ()
158- class LargeSetTest (RaceTestBase , unittest .TestCase ):
159- SET_SIZE = 20 # larger than PySet_MINSIZE
160-
161-
16240if __name__ == "__main__" :
16341 unittest .main ()
0 commit comments