1
- """Generic thread tests.
2
-
3
- Meant to be used by dummy_thread and thread. To allow for different modules
4
- to be used, test_main() can be called with the module to use as the thread
5
- implementation as its sole argument.
6
-
7
- """
8
1
import _dummy_thread as _thread
9
2
import time
10
3
import queue
11
4
import random
12
5
import unittest
13
6
from test import support
7
+ from unittest import mock
8
+
9
+ DELAY = 0
14
10
15
- DELAY = 0 # Set > 0 when testing a module other than _dummy_thread, such as
16
- # the '_thread' module.
17
11
18
12
class LockTests (unittest .TestCase ):
19
13
"""Test lock objects."""
@@ -34,6 +28,12 @@ def test_release(self):
34
28
self .assertFalse (self .lock .locked (),
35
29
"Lock object did not release properly." )
36
30
31
+ def test_LockType_context_manager (self ):
32
+ with _thread .LockType ():
33
+ pass
34
+ self .assertFalse (self .lock .locked (),
35
+ "Acquired Lock was not released" )
36
+
37
37
def test_improper_release (self ):
38
38
#Make sure release of an unlocked thread raises RuntimeError
39
39
self .assertRaises (RuntimeError , self .lock .release )
@@ -83,39 +83,72 @@ def delay_unlock(to_unlock, delay):
83
83
self .assertGreaterEqual (end_time - start_time , DELAY ,
84
84
"Blocking by unconditional acquiring failed." )
85
85
86
+ @mock .patch ('time.sleep' )
87
+ def test_acquire_timeout (self , mock_sleep ):
88
+ """Test invoking acquire() with a positive timeout when the lock is
89
+ already acquired. Ensure that time.sleep() is invoked with the given
90
+ timeout and that False is returned."""
91
+
92
+ self .lock .acquire ()
93
+ retval = self .lock .acquire (waitflag = 0 , timeout = 1 )
94
+ self .assertTrue (mock_sleep .called )
95
+ mock_sleep .assert_called_once_with (1 )
96
+ self .assertEqual (retval , False )
97
+
98
+ def test_lock_representation (self ):
99
+ self .lock .acquire ()
100
+ self .assertIn ("locked" , repr (self .lock ))
101
+ self .lock .release ()
102
+ self .assertIn ("unlocked" , repr (self .lock ))
103
+
104
+
86
105
class MiscTests (unittest .TestCase ):
87
106
"""Miscellaneous tests."""
88
107
89
108
def test_exit (self ):
90
- #Make sure _thread.exit() raises SystemExit
91
109
self .assertRaises (SystemExit , _thread .exit )
92
110
93
111
def test_ident (self ):
94
- #Test sanity of _thread.get_ident()
95
112
self .assertIsInstance (_thread .get_ident (), int ,
96
113
"_thread.get_ident() returned a non-integer" )
97
114
self .assertNotEqual (_thread .get_ident (), 0 ,
98
115
"_thread.get_ident() returned 0" )
99
116
100
117
def test_LockType (self ):
101
- #Make sure _thread.LockType is the same type as _thread.allocate_locke()
102
118
self .assertIsInstance (_thread .allocate_lock (), _thread .LockType ,
103
119
"_thread.LockType is not an instance of what "
104
120
"is returned by _thread.allocate_lock()" )
105
121
122
+ def test_set_sentinel (self ):
123
+ self .assertIsInstance (_thread ._set_sentinel (), _thread .LockType ,
124
+ "_thread._set_sentinel() did not return a "
125
+ "LockType instance." )
126
+
106
127
def test_interrupt_main (self ):
107
128
#Calling start_new_thread with a function that executes interrupt_main
108
129
# should raise KeyboardInterrupt upon completion.
109
130
def call_interrupt ():
110
131
_thread .interrupt_main ()
111
- self .assertRaises (KeyboardInterrupt , _thread .start_new_thread ,
112
- call_interrupt , tuple ())
132
+
133
+ self .assertRaises (KeyboardInterrupt ,
134
+ _thread .start_new_thread ,
135
+ call_interrupt ,
136
+ tuple ())
113
137
114
138
def test_interrupt_in_main (self ):
115
- # Make sure that if interrupt_main is called in main threat that
116
- # KeyboardInterrupt is raised instantly.
117
139
self .assertRaises (KeyboardInterrupt , _thread .interrupt_main )
118
140
141
+ def test_stack_size_None (self ):
142
+ retval = _thread .stack_size (None )
143
+ self .assertEqual (retval , 0 )
144
+
145
+ def test_stack_size_not_None (self ):
146
+ with self .assertRaises (_thread .error ) as cm :
147
+ _thread .stack_size ("" )
148
+ self .assertEqual (cm .exception .args [0 ],
149
+ "setting thread stack size not supported" )
150
+
151
+
119
152
class ThreadTests (unittest .TestCase ):
120
153
"""Test thread creation."""
121
154
@@ -129,31 +162,43 @@ def arg_tester(queue, arg1=False, arg2=False):
129
162
_thread .start_new_thread (arg_tester , (testing_queue , True , True ))
130
163
result = testing_queue .get ()
131
164
self .assertTrue (result [0 ] and result [1 ],
132
- "Argument passing for thread creation using tuple failed" )
133
- _thread .start_new_thread (arg_tester , tuple (), {'queue' :testing_queue ,
134
- 'arg1' :True , 'arg2' :True })
165
+ "Argument passing for thread creation "
166
+ "using tuple failed" )
167
+
168
+ _thread .start_new_thread (
169
+ arg_tester ,
170
+ tuple (),
171
+ {'queue' :testing_queue , 'arg1' :True , 'arg2' :True })
172
+
135
173
result = testing_queue .get ()
136
174
self .assertTrue (result [0 ] and result [1 ],
137
- "Argument passing for thread creation using kwargs failed" )
138
- _thread .start_new_thread (arg_tester , (testing_queue , True ), {'arg2' :True })
175
+ "Argument passing for thread creation "
176
+ "using kwargs failed" )
177
+
178
+ _thread .start_new_thread (
179
+ arg_tester ,
180
+ (testing_queue , True ),
181
+ {'arg2' :True })
182
+
139
183
result = testing_queue .get ()
140
184
self .assertTrue (result [0 ] and result [1 ],
141
185
"Argument passing for thread creation using both tuple"
142
186
" and kwargs failed" )
143
187
144
- def test_multi_creation (self ):
145
- #Make sure multiple threads can be created.
188
+ def test_multi_thread_creation (self ):
146
189
def queue_mark (queue , delay ):
147
- """Wait for ``delay`` seconds and then put something into ``queue``"""
148
190
time .sleep (delay )
149
191
queue .put (_thread .get_ident ())
150
192
151
193
thread_count = 5
152
194
testing_queue = queue .Queue (thread_count )
195
+
153
196
if support .verbose :
154
197
print ()
155
- print ("*** Testing multiple thread creation " \
156
- "(will take approx. %s to %s sec.) ***" % (DELAY , thread_count ))
198
+ print ("*** Testing multiple thread creation "
199
+ "(will take approx. %s to %s sec.) ***" % (
200
+ DELAY , thread_count ))
201
+
157
202
for count in range (thread_count ):
158
203
if DELAY :
159
204
local_delay = round (random .random (), 1 )
@@ -165,18 +210,47 @@ def queue_mark(queue, delay):
165
210
if support .verbose :
166
211
print ('done' )
167
212
self .assertEqual (testing_queue .qsize (), thread_count ,
168
- "Not all %s threads executed properly after %s sec." %
169
- (thread_count , DELAY ))
170
-
171
- def test_main (imported_module = None ):
172
- global _thread , DELAY
173
- if imported_module :
174
- _thread = imported_module
175
- DELAY = 2
176
- if support .verbose :
177
- print ()
178
- print ("*** Using %s as _thread module ***" % _thread )
179
- support .run_unittest (LockTests , MiscTests , ThreadTests )
180
-
181
- if __name__ == '__main__' :
182
- test_main ()
213
+ "Not all %s threads executed properly "
214
+ "after %s sec." % (thread_count , DELAY ))
215
+
216
+ def test_args_not_tuple (self ):
217
+ """
218
+ Test invoking start_new_thread() with a non-tuple value for "args".
219
+ Expect TypeError with a meaningful error message to be raised.
220
+ """
221
+ with self .assertRaises (TypeError ) as cm :
222
+ _thread .start_new_thread (mock .Mock (), [])
223
+ self .assertEqual (cm .exception .args [0 ], "2nd arg must be a tuple" )
224
+
225
+ def test_kwargs_not_dict (self ):
226
+ """
227
+ Test invoking start_new_thread() with a non-dict value for "kwargs".
228
+ Expect TypeError with a meaningful error message to be raised.
229
+ """
230
+ with self .assertRaises (TypeError ) as cm :
231
+ _thread .start_new_thread (mock .Mock (), tuple (), kwargs = [])
232
+ self .assertEqual (cm .exception .args [0 ], "3rd arg must be a dict" )
233
+
234
+ def test_SystemExit (self ):
235
+ """
236
+ Test invoking start_new_thread() with a function that raises
237
+ SystemExit.
238
+ The exception should be discarded.
239
+ """
240
+ func = mock .Mock (side_effect = SystemExit ())
241
+ try :
242
+ _thread .start_new_thread (func , tuple ())
243
+ except SystemExit :
244
+ self .fail ("start_new_thread raised SystemExit." )
245
+
246
+ @mock .patch ('traceback.print_exc' )
247
+ def test_RaiseException (self , mock_print_exc ):
248
+ """
249
+ Test invoking start_new_thread() with a function that raises exception.
250
+
251
+ The exception should be discarded and the traceback should be printed
252
+ via traceback.print_exc()
253
+ """
254
+ func = mock .Mock (side_effect = Exception )
255
+ _thread .start_new_thread (func , tuple ())
256
+ self .assertTrue (mock_print_exc .called )
0 commit comments