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- """
81import _dummy_thread as _thread
92import time
103import queue
114import random
125import unittest
136from test import support
7+ from unittest import mock
8+
9+ DELAY = 0
1410
15- DELAY = 0 # Set > 0 when testing a module other than _dummy_thread, such as
16- # the '_thread' module.
1711
1812class LockTests (unittest .TestCase ):
1913 """Test lock objects."""
@@ -34,6 +28,12 @@ def test_release(self):
3428 self .assertFalse (self .lock .locked (),
3529 "Lock object did not release properly." )
3630
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+
3737 def test_improper_release (self ):
3838 #Make sure release of an unlocked thread raises RuntimeError
3939 self .assertRaises (RuntimeError , self .lock .release )
@@ -83,39 +83,72 @@ def delay_unlock(to_unlock, delay):
8383 self .assertGreaterEqual (end_time - start_time , DELAY ,
8484 "Blocking by unconditional acquiring failed." )
8585
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+
86105class MiscTests (unittest .TestCase ):
87106 """Miscellaneous tests."""
88107
89108 def test_exit (self ):
90- #Make sure _thread.exit() raises SystemExit
91109 self .assertRaises (SystemExit , _thread .exit )
92110
93111 def test_ident (self ):
94- #Test sanity of _thread.get_ident()
95112 self .assertIsInstance (_thread .get_ident (), int ,
96113 "_thread.get_ident() returned a non-integer" )
97114 self .assertNotEqual (_thread .get_ident (), 0 ,
98115 "_thread.get_ident() returned 0" )
99116
100117 def test_LockType (self ):
101- #Make sure _thread.LockType is the same type as _thread.allocate_locke()
102118 self .assertIsInstance (_thread .allocate_lock (), _thread .LockType ,
103119 "_thread.LockType is not an instance of what "
104120 "is returned by _thread.allocate_lock()" )
105121
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+
106127 def test_interrupt_main (self ):
107128 #Calling start_new_thread with a function that executes interrupt_main
108129 # should raise KeyboardInterrupt upon completion.
109130 def call_interrupt ():
110131 _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 ())
113137
114138 def test_interrupt_in_main (self ):
115- # Make sure that if interrupt_main is called in main threat that
116- # KeyboardInterrupt is raised instantly.
117139 self .assertRaises (KeyboardInterrupt , _thread .interrupt_main )
118140
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+
119152class ThreadTests (unittest .TestCase ):
120153 """Test thread creation."""
121154
@@ -129,31 +162,43 @@ def arg_tester(queue, arg1=False, arg2=False):
129162 _thread .start_new_thread (arg_tester , (testing_queue , True , True ))
130163 result = testing_queue .get ()
131164 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+
135173 result = testing_queue .get ()
136174 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+
139183 result = testing_queue .get ()
140184 self .assertTrue (result [0 ] and result [1 ],
141185 "Argument passing for thread creation using both tuple"
142186 " and kwargs failed" )
143187
144- def test_multi_creation (self ):
145- #Make sure multiple threads can be created.
188+ def test_multi_thread_creation (self ):
146189 def queue_mark (queue , delay ):
147- """Wait for ``delay`` seconds and then put something into ``queue``"""
148190 time .sleep (delay )
149191 queue .put (_thread .get_ident ())
150192
151193 thread_count = 5
152194 testing_queue = queue .Queue (thread_count )
195+
153196 if support .verbose :
154197 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+
157202 for count in range (thread_count ):
158203 if DELAY :
159204 local_delay = round (random .random (), 1 )
@@ -165,18 +210,47 @@ def queue_mark(queue, delay):
165210 if support .verbose :
166211 print ('done' )
167212 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