Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 1 | # |
| 2 | # A test file for the `multiprocessing` package |
| 3 | # |
Benjamin Peterson | 4469d0c | 2008-11-30 22:46:23 +0000 | [diff] [blame] | 4 | # Copyright (c) 2006-2008, R Oudkerk |
| 5 | # All rights reserved. |
| 6 | # |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 7 | |
| 8 | import time, sys, random |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 9 | from queue import Empty |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 10 | |
| 11 | import multiprocessing # may get overwritten |
| 12 | |
| 13 | |
| 14 | #### TEST_VALUE |
| 15 | |
| 16 | def value_func(running, mutex): |
| 17 | random.seed() |
| 18 | time.sleep(random.random()*4) |
| 19 | |
| 20 | mutex.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 21 | print('\n\t\t\t' + str(multiprocessing.current_process()) + ' has finished') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 22 | running.value -= 1 |
| 23 | mutex.release() |
| 24 | |
| 25 | def test_value(): |
| 26 | TASKS = 10 |
| 27 | running = multiprocessing.Value('i', TASKS) |
| 28 | mutex = multiprocessing.Lock() |
| 29 | |
| 30 | for i in range(TASKS): |
| 31 | p = multiprocessing.Process(target=value_func, args=(running, mutex)) |
| 32 | p.start() |
| 33 | |
| 34 | while running.value > 0: |
| 35 | time.sleep(0.08) |
| 36 | mutex.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 37 | print(running.value, end=' ') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 38 | sys.stdout.flush() |
| 39 | mutex.release() |
| 40 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 41 | print() |
| 42 | print('No more running processes') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 43 | |
| 44 | |
| 45 | #### TEST_QUEUE |
| 46 | |
| 47 | def queue_func(queue): |
| 48 | for i in range(30): |
| 49 | time.sleep(0.5 * random.random()) |
| 50 | queue.put(i*i) |
| 51 | queue.put('STOP') |
| 52 | |
| 53 | def test_queue(): |
| 54 | q = multiprocessing.Queue() |
| 55 | |
| 56 | p = multiprocessing.Process(target=queue_func, args=(q,)) |
| 57 | p.start() |
| 58 | |
| 59 | o = None |
| 60 | while o != 'STOP': |
| 61 | try: |
| 62 | o = q.get(timeout=0.3) |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 63 | print(o, end=' ') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 64 | sys.stdout.flush() |
| 65 | except Empty: |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 66 | print('TIMEOUT') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 67 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 68 | print() |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 69 | |
| 70 | |
| 71 | #### TEST_CONDITION |
| 72 | |
| 73 | def condition_func(cond): |
| 74 | cond.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 75 | print('\t' + str(cond)) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 76 | time.sleep(2) |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 77 | print('\tchild is notifying') |
| 78 | print('\t' + str(cond)) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 79 | cond.notify() |
| 80 | cond.release() |
| 81 | |
| 82 | def test_condition(): |
| 83 | cond = multiprocessing.Condition() |
| 84 | |
| 85 | p = multiprocessing.Process(target=condition_func, args=(cond,)) |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 86 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 87 | |
| 88 | cond.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 89 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 90 | cond.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 91 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 92 | |
| 93 | p.start() |
| 94 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 95 | print('main is waiting') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 96 | cond.wait() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 97 | print('main has woken up') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 98 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 99 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 100 | cond.release() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 101 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 102 | cond.release() |
| 103 | |
| 104 | p.join() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 105 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 106 | |
| 107 | |
| 108 | #### TEST_SEMAPHORE |
| 109 | |
| 110 | def semaphore_func(sema, mutex, running): |
| 111 | sema.acquire() |
| 112 | |
| 113 | mutex.acquire() |
| 114 | running.value += 1 |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 115 | print(running.value, 'tasks are running') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 116 | mutex.release() |
| 117 | |
| 118 | random.seed() |
| 119 | time.sleep(random.random()*2) |
| 120 | |
| 121 | mutex.acquire() |
| 122 | running.value -= 1 |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 123 | print('%s has finished' % multiprocessing.current_process()) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 124 | mutex.release() |
| 125 | |
| 126 | sema.release() |
| 127 | |
| 128 | def test_semaphore(): |
| 129 | sema = multiprocessing.Semaphore(3) |
| 130 | mutex = multiprocessing.RLock() |
| 131 | running = multiprocessing.Value('i', 0) |
| 132 | |
| 133 | processes = [ |
| 134 | multiprocessing.Process(target=semaphore_func, |
| 135 | args=(sema, mutex, running)) |
| 136 | for i in range(10) |
| 137 | ] |
| 138 | |
| 139 | for p in processes: |
| 140 | p.start() |
| 141 | |
| 142 | for p in processes: |
| 143 | p.join() |
| 144 | |
| 145 | |
| 146 | #### TEST_JOIN_TIMEOUT |
| 147 | |
| 148 | def join_timeout_func(): |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 149 | print('\tchild sleeping') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 150 | time.sleep(5.5) |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 151 | print('\n\tchild terminating') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 152 | |
| 153 | def test_join_timeout(): |
| 154 | p = multiprocessing.Process(target=join_timeout_func) |
| 155 | p.start() |
| 156 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 157 | print('waiting for process to finish') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 158 | |
| 159 | while 1: |
| 160 | p.join(timeout=1) |
| 161 | if not p.is_alive(): |
| 162 | break |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 163 | print('.', end=' ') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 164 | sys.stdout.flush() |
| 165 | |
| 166 | |
| 167 | #### TEST_EVENT |
| 168 | |
| 169 | def event_func(event): |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 170 | print('\t%r is waiting' % multiprocessing.current_process()) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 171 | event.wait() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 172 | print('\t%r has woken up' % multiprocessing.current_process()) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 173 | |
| 174 | def test_event(): |
| 175 | event = multiprocessing.Event() |
| 176 | |
| 177 | processes = [multiprocessing.Process(target=event_func, args=(event,)) |
| 178 | for i in range(5)] |
| 179 | |
| 180 | for p in processes: |
| 181 | p.start() |
| 182 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 183 | print('main is sleeping') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 184 | time.sleep(2) |
| 185 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 186 | print('main is setting event') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 187 | event.set() |
| 188 | |
| 189 | for p in processes: |
| 190 | p.join() |
| 191 | |
| 192 | |
| 193 | #### TEST_SHAREDVALUES |
| 194 | |
| 195 | def sharedvalues_func(values, arrays, shared_values, shared_arrays): |
| 196 | for i in range(len(values)): |
| 197 | v = values[i][1] |
| 198 | sv = shared_values[i].value |
| 199 | assert v == sv |
| 200 | |
| 201 | for i in range(len(values)): |
| 202 | a = arrays[i][1] |
| 203 | sa = list(shared_arrays[i][:]) |
| 204 | assert a == sa |
| 205 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 206 | print('Tests passed') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 207 | |
| 208 | def test_sharedvalues(): |
| 209 | values = [ |
| 210 | ('i', 10), |
| 211 | ('h', -2), |
| 212 | ('d', 1.25) |
| 213 | ] |
| 214 | arrays = [ |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 215 | ('i', list(range(100))), |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 216 | ('d', [0.25 * i for i in range(100)]), |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 217 | ('H', list(range(1000))) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 218 | ] |
| 219 | |
| 220 | shared_values = [multiprocessing.Value(id, v) for id, v in values] |
| 221 | shared_arrays = [multiprocessing.Array(id, a) for id, a in arrays] |
| 222 | |
| 223 | p = multiprocessing.Process( |
| 224 | target=sharedvalues_func, |
| 225 | args=(values, arrays, shared_values, shared_arrays) |
| 226 | ) |
| 227 | p.start() |
| 228 | p.join() |
| 229 | |
Benjamin Peterson | 58ea9fe | 2008-08-19 19:17:39 +0000 | [diff] [blame] | 230 | assert p.exitcode == 0 |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 231 | |
| 232 | |
| 233 | #### |
| 234 | |
| 235 | def test(namespace=multiprocessing): |
| 236 | global multiprocessing |
| 237 | |
| 238 | multiprocessing = namespace |
| 239 | |
| 240 | for func in [ test_value, test_queue, test_condition, |
| 241 | test_semaphore, test_join_timeout, test_event, |
| 242 | test_sharedvalues ]: |
| 243 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 244 | print('\n\t######## %s\n' % func.__name__) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 245 | func() |
| 246 | |
| 247 | ignore = multiprocessing.active_children() # cleanup any old processes |
| 248 | if hasattr(multiprocessing, '_debug_info'): |
| 249 | info = multiprocessing._debug_info() |
| 250 | if info: |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 251 | print(info) |
| 252 | raise ValueError('there should be no positive refcounts left') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 253 | |
| 254 | |
| 255 | if __name__ == '__main__': |
| 256 | multiprocessing.freeze_support() |
| 257 | |
| 258 | assert len(sys.argv) in (1, 2) |
| 259 | |
| 260 | if len(sys.argv) == 1 or sys.argv[1] == 'processes': |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 261 | print(' Using processes '.center(79, '-')) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 262 | namespace = multiprocessing |
| 263 | elif sys.argv[1] == 'manager': |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 264 | print(' Using processes and a manager '.center(79, '-')) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 265 | namespace = multiprocessing.Manager() |
| 266 | namespace.Process = multiprocessing.Process |
| 267 | namespace.current_process = multiprocessing.current_process |
| 268 | namespace.active_children = multiprocessing.active_children |
| 269 | elif sys.argv[1] == 'threads': |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 270 | print(' Using threads '.center(79, '-')) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 271 | import multiprocessing.dummy as namespace |
| 272 | else: |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 273 | print('Usage:\n\t%s [processes | manager | threads]' % sys.argv[0]) |
| 274 | raise SystemExit(2) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 275 | |
| 276 | test(namespace) |