blob: 8bbfdb11edbfd6dc7160c7def16daa2aea4962f1 [file] [log] [blame]
Brett Cannon66865d22008-03-13 20:27:00 +00001import os
2import unittest
Guido van Rossumb26a1b41998-05-20 17:05:52 +00003import random
Brett Cannon66865d22008-03-13 20:27:00 +00004from test import test_support
Guido van Rossumcc544171994-04-14 20:28:41 +00005import thread
6import time
7
Antoine Pitrouc747d3a2009-11-09 16:47:50 +00008from test import lock_tests
Guido van Rossumcc544171994-04-14 20:28:41 +00009
Brett Cannon66865d22008-03-13 20:27:00 +000010NUMTASKS = 10
11NUMTRIPS = 3
Guido van Rossumd3b68421994-05-23 12:17:36 +000012
Guido van Rossumcc544171994-04-14 20:28:41 +000013
Jeffrey Yasskina1458532008-03-18 04:56:06 +000014_print_mutex = thread.allocate_lock()
15
Brett Cannon66865d22008-03-13 20:27:00 +000016def verbose_print(arg):
17 """Helper function for printing out debugging output."""
18 if test_support.verbose:
Jeffrey Yasskina1458532008-03-18 04:56:06 +000019 with _print_mutex:
20 print arg
Guido van Rossumcc544171994-04-14 20:28:41 +000021
Guido van Rossumcc544171994-04-14 20:28:41 +000022
Brett Cannon66865d22008-03-13 20:27:00 +000023class BasicThreadTest(unittest.TestCase):
Guido van Rossumd3b68421994-05-23 12:17:36 +000024
Brett Cannon66865d22008-03-13 20:27:00 +000025 def setUp(self):
26 self.done_mutex = thread.allocate_lock()
27 self.done_mutex.acquire()
28 self.running_mutex = thread.allocate_lock()
29 self.random_mutex = thread.allocate_lock()
Antoine Pitrouf75774b2009-10-27 12:32:18 +000030 self.created = 0
Brett Cannon66865d22008-03-13 20:27:00 +000031 self.running = 0
32 self.next_ident = 0
33
34
35class ThreadRunningTests(BasicThreadTest):
36
37 def newtask(self):
38 with self.running_mutex:
39 self.next_ident += 1
40 verbose_print("creating task %s" % self.next_ident)
41 thread.start_new_thread(self.task, (self.next_ident,))
Antoine Pitrouf75774b2009-10-27 12:32:18 +000042 self.created += 1
Brett Cannon66865d22008-03-13 20:27:00 +000043 self.running += 1
44
45 def task(self, ident):
46 with self.random_mutex:
Jeffrey Yasskina1458532008-03-18 04:56:06 +000047 delay = random.random() / 10000.0
48 verbose_print("task %s will run for %sus" % (ident, round(delay*1e6)))
Brett Cannon66865d22008-03-13 20:27:00 +000049 time.sleep(delay)
50 verbose_print("task %s done" % ident)
51 with self.running_mutex:
52 self.running -= 1
Antoine Pitrouf75774b2009-10-27 12:32:18 +000053 if self.created == NUMTASKS and self.running == 0:
Brett Cannon66865d22008-03-13 20:27:00 +000054 self.done_mutex.release()
55
56 def test_starting_threads(self):
57 # Basic test for thread creation.
58 for i in range(NUMTASKS):
59 self.newtask()
60 verbose_print("waiting for tasks to complete...")
61 self.done_mutex.acquire()
62 verbose_print("all tasks done")
63
64 def test_stack_size(self):
65 # Various stack size tests.
66 self.assertEquals(thread.stack_size(), 0, "intial stack size is not 0")
67
68 thread.stack_size(0)
69 self.assertEquals(thread.stack_size(), 0, "stack_size not reset to default")
70
71 if os.name not in ("nt", "os2", "posix"):
72 return
73
74 tss_supported = True
75 try:
76 thread.stack_size(4096)
77 except ValueError:
78 verbose_print("caught expected ValueError setting "
79 "stack_size(4096)")
80 except thread.error:
81 tss_supported = False
82 verbose_print("platform does not support changing thread stack "
83 "size")
84
85 if tss_supported:
86 fail_msg = "stack_size(%d) failed - should succeed"
87 for tss in (262144, 0x100000, 0):
88 thread.stack_size(tss)
89 self.assertEquals(thread.stack_size(), tss, fail_msg % tss)
90 verbose_print("successfully set stack_size(%d)" % tss)
91
92 for tss in (262144, 0x100000):
93 verbose_print("trying stack_size = (%d)" % tss)
94 self.next_ident = 0
Antoine Pitrouf75774b2009-10-27 12:32:18 +000095 self.created = 0
Brett Cannon66865d22008-03-13 20:27:00 +000096 for i in range(NUMTASKS):
97 self.newtask()
98
99 verbose_print("waiting for all tasks to complete")
100 self.done_mutex.acquire()
101 verbose_print("all tasks done")
102
103 thread.stack_size(0)
104
105
106class Barrier:
107 def __init__(self, num_threads):
108 self.num_threads = num_threads
Fred Drake004d5e62000-10-23 17:22:08 +0000109 self.waiting = 0
Brett Cannon66865d22008-03-13 20:27:00 +0000110 self.checkin_mutex = thread.allocate_lock()
111 self.checkout_mutex = thread.allocate_lock()
112 self.checkout_mutex.acquire()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000113
Fred Drake004d5e62000-10-23 17:22:08 +0000114 def enter(self):
Brett Cannon66865d22008-03-13 20:27:00 +0000115 self.checkin_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000116 self.waiting = self.waiting + 1
Brett Cannon66865d22008-03-13 20:27:00 +0000117 if self.waiting == self.num_threads:
118 self.waiting = self.num_threads - 1
119 self.checkout_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000120 return
Brett Cannon66865d22008-03-13 20:27:00 +0000121 self.checkin_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000122
Brett Cannon66865d22008-03-13 20:27:00 +0000123 self.checkout_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000124 self.waiting = self.waiting - 1
125 if self.waiting == 0:
Brett Cannon66865d22008-03-13 20:27:00 +0000126 self.checkin_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000127 return
Brett Cannon66865d22008-03-13 20:27:00 +0000128 self.checkout_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000129
Guido van Rossumd3b68421994-05-23 12:17:36 +0000130
Brett Cannon66865d22008-03-13 20:27:00 +0000131class BarrierTest(BasicThreadTest):
Andrew MacIntyre92913322006-06-13 15:04:24 +0000132
Brett Cannon66865d22008-03-13 20:27:00 +0000133 def test_barrier(self):
134 self.bar = Barrier(NUMTASKS)
135 self.running = NUMTASKS
136 for i in range(NUMTASKS):
137 thread.start_new_thread(self.task2, (i,))
138 verbose_print("waiting for tasks to end")
139 self.done_mutex.acquire()
140 verbose_print("tasks done")
Andrew MacIntyre92913322006-06-13 15:04:24 +0000141
Brett Cannon66865d22008-03-13 20:27:00 +0000142 def task2(self, ident):
143 for i in range(NUMTRIPS):
144 if ident == 0:
145 # give it a good chance to enter the next
146 # barrier before the others are all out
147 # of the current one
Jeffrey Yasskina1458532008-03-18 04:56:06 +0000148 delay = 0
Brett Cannon66865d22008-03-13 20:27:00 +0000149 else:
150 with self.random_mutex:
Jeffrey Yasskina1458532008-03-18 04:56:06 +0000151 delay = random.random() / 10000.0
152 verbose_print("task %s will run for %sus" %
153 (ident, round(delay * 1e6)))
Brett Cannon66865d22008-03-13 20:27:00 +0000154 time.sleep(delay)
155 verbose_print("task %s entering %s" % (ident, i))
156 self.bar.enter()
157 verbose_print("task %s leaving barrier" % ident)
158 with self.running_mutex:
159 self.running -= 1
160 # Must release mutex before releasing done, else the main thread can
161 # exit and set mutex to None as part of global teardown; then
162 # mutex.release() raises AttributeError.
163 finished = self.running == 0
164 if finished:
165 self.done_mutex.release()
Andrew MacIntyre92913322006-06-13 15:04:24 +0000166
Andrew MacIntyre92913322006-06-13 15:04:24 +0000167
Antoine Pitrouc747d3a2009-11-09 16:47:50 +0000168class LockTests(lock_tests.LockTests):
169 locktype = thread.allocate_lock
170
171
Brett Cannon66865d22008-03-13 20:27:00 +0000172def test_main():
Antoine Pitrouc747d3a2009-11-09 16:47:50 +0000173 test_support.run_unittest(ThreadRunningTests, BarrierTest, LockTests)
Andrew MacIntyre92913322006-06-13 15:04:24 +0000174
Brett Cannon66865d22008-03-13 20:27:00 +0000175if __name__ == "__main__":
176 test_main()