1
1
import sys
2
2
import threading
3
- import time
4
3
import unittest
5
4
from concurrent import futures
6
5
from test import support
6
+ from test .support import threading_helper
7
7
8
8
from .util import (
9
9
CANCELLED_FUTURE , CANCELLED_AND_NOTIFIED_FUTURE , EXCEPTION_FUTURE ,
16
16
def mul (x , y ):
17
17
return x * y
18
18
19
- def sleep_and_raise ( t ):
20
- time . sleep ( t )
19
+ def wait_and_raise ( e ):
20
+ e . wait ( )
21
21
raise Exception ('this is an exception' )
22
22
23
23
24
24
class WaitTests :
25
25
def test_20369 (self ):
26
26
# See https://bugs.python.org/issue20369
27
- future = self .executor .submit (time . sleep , 1.5 )
27
+ future = self .executor .submit (mul , 1 , 2 )
28
28
done , not_done = futures .wait ([future , future ],
29
29
return_when = futures .ALL_COMPLETED )
30
30
self .assertEqual ({future }, done )
31
31
self .assertEqual (set (), not_done )
32
32
33
33
34
34
def test_first_completed (self ):
35
+ event = self .create_event ()
35
36
future1 = self .executor .submit (mul , 21 , 2 )
36
- future2 = self .executor .submit (time . sleep , 1.5 )
37
+ future2 = self .executor .submit (event . wait )
37
38
38
- done , not_done = futures .wait (
39
- [CANCELLED_FUTURE , future1 , future2 ],
40
- return_when = futures .FIRST_COMPLETED )
39
+ try :
40
+ done , not_done = futures .wait (
41
+ [CANCELLED_FUTURE , future1 , future2 ],
42
+ return_when = futures .FIRST_COMPLETED )
41
43
42
- self .assertEqual (set ([future1 ]), done )
43
- self .assertEqual (set ([CANCELLED_FUTURE , future2 ]), not_done )
44
+ self .assertEqual (set ([future1 ]), done )
45
+ self .assertEqual (set ([CANCELLED_FUTURE , future2 ]), not_done )
46
+ finally :
47
+ event .set ()
48
+ future2 .result () # wait for job to finish
44
49
45
50
def test_first_completed_some_already_completed (self ):
46
- future1 = self .executor .submit (time .sleep , 1.5 )
47
-
48
- finished , pending = futures .wait (
49
- [CANCELLED_AND_NOTIFIED_FUTURE , SUCCESSFUL_FUTURE , future1 ],
50
- return_when = futures .FIRST_COMPLETED )
51
+ event = self .create_event ()
52
+ future1 = self .executor .submit (event .wait )
51
53
52
- self .assertEqual (
53
- set ([CANCELLED_AND_NOTIFIED_FUTURE , SUCCESSFUL_FUTURE ]),
54
- finished )
55
- self .assertEqual (set ([future1 ]), pending )
54
+ try :
55
+ finished , pending = futures .wait (
56
+ [CANCELLED_AND_NOTIFIED_FUTURE , SUCCESSFUL_FUTURE , future1 ],
57
+ return_when = futures .FIRST_COMPLETED )
58
+
59
+ self .assertEqual (
60
+ set ([CANCELLED_AND_NOTIFIED_FUTURE , SUCCESSFUL_FUTURE ]),
61
+ finished )
62
+ self .assertEqual (set ([future1 ]), pending )
63
+ finally :
64
+ event .set ()
65
+ future1 .result () # wait for job to finish
56
66
57
- @support .requires_resource ('walltime' )
58
67
def test_first_exception (self ):
59
- future1 = self .executor .submit (mul , 2 , 21 )
60
- future2 = self .executor .submit (sleep_and_raise , 1.5 )
61
- future3 = self .executor .submit (time .sleep , 3 )
68
+ event1 = self .create_event ()
69
+ event2 = self .create_event ()
70
+ try :
71
+ future1 = self .executor .submit (mul , 2 , 21 )
72
+ future2 = self .executor .submit (wait_and_raise , event1 )
73
+ future3 = self .executor .submit (event2 .wait )
62
74
63
- finished , pending = futures .wait (
64
- [future1 , future2 , future3 ],
65
- return_when = futures .FIRST_EXCEPTION )
75
+ # Ensure that future1 is completed before future2 finishes
76
+ def wait_for_future1 ():
77
+ future1 .result ()
78
+ event1 .set ()
79
+
80
+ t = threading .Thread (target = wait_for_future1 )
81
+ t .start ()
82
+
83
+ finished , pending = futures .wait (
84
+ [future1 , future2 , future3 ],
85
+ return_when = futures .FIRST_EXCEPTION )
66
86
67
- self .assertEqual (set ([future1 , future2 ]), finished )
68
- self .assertEqual (set ([future3 ]), pending )
87
+ self .assertEqual (set ([future1 , future2 ]), finished )
88
+ self .assertEqual (set ([future3 ]), pending )
89
+
90
+ threading_helper .join_thread (t )
91
+ finally :
92
+ event1 .set ()
93
+ event2 .set ()
94
+ future3 .result () # wait for job to finish
69
95
70
96
def test_first_exception_some_already_complete (self ):
97
+ event = self .create_event ()
71
98
future1 = self .executor .submit (divmod , 21 , 0 )
72
- future2 = self .executor .submit (time .sleep , 1.5 )
73
-
74
- finished , pending = futures .wait (
75
- [SUCCESSFUL_FUTURE ,
76
- CANCELLED_FUTURE ,
77
- CANCELLED_AND_NOTIFIED_FUTURE ,
78
- future1 , future2 ],
79
- return_when = futures .FIRST_EXCEPTION )
99
+ future2 = self .executor .submit (event .wait )
80
100
81
- self .assertEqual (set ([SUCCESSFUL_FUTURE ,
82
- CANCELLED_AND_NOTIFIED_FUTURE ,
83
- future1 ]), finished )
84
- self .assertEqual (set ([CANCELLED_FUTURE , future2 ]), pending )
101
+ try :
102
+ finished , pending = futures .wait (
103
+ [SUCCESSFUL_FUTURE ,
104
+ CANCELLED_FUTURE ,
105
+ CANCELLED_AND_NOTIFIED_FUTURE ,
106
+ future1 , future2 ],
107
+ return_when = futures .FIRST_EXCEPTION )
108
+
109
+ self .assertEqual (set ([SUCCESSFUL_FUTURE ,
110
+ CANCELLED_AND_NOTIFIED_FUTURE ,
111
+ future1 ]), finished )
112
+ self .assertEqual (set ([CANCELLED_FUTURE , future2 ]), pending )
113
+ finally :
114
+ event .set ()
115
+ future2 .result () # wait for job to finish
85
116
86
117
def test_first_exception_one_already_failed (self ):
87
- future1 = self .executor .submit (time .sleep , 2 )
118
+ event = self .create_event ()
119
+ future1 = self .executor .submit (event .wait )
88
120
89
- finished , pending = futures .wait (
90
- [EXCEPTION_FUTURE , future1 ],
91
- return_when = futures .FIRST_EXCEPTION )
121
+ try :
122
+ finished , pending = futures .wait (
123
+ [EXCEPTION_FUTURE , future1 ],
124
+ return_when = futures .FIRST_EXCEPTION )
92
125
93
- self .assertEqual (set ([EXCEPTION_FUTURE ]), finished )
94
- self .assertEqual (set ([future1 ]), pending )
126
+ self .assertEqual (set ([EXCEPTION_FUTURE ]), finished )
127
+ self .assertEqual (set ([future1 ]), pending )
128
+ finally :
129
+ event .set ()
130
+ future1 .result () # wait for job to finish
95
131
96
132
def test_all_completed (self ):
97
133
future1 = self .executor .submit (divmod , 2 , 0 )
@@ -114,23 +150,27 @@ def test_all_completed(self):
114
150
115
151
def test_timeout (self ):
116
152
short_timeout = 0.050
117
- long_timeout = short_timeout * 10
118
153
119
- future = self .executor .submit (time .sleep , long_timeout )
154
+ event = self .create_event ()
155
+ future = self .executor .submit (event .wait )
120
156
121
- finished , pending = futures .wait (
122
- [CANCELLED_AND_NOTIFIED_FUTURE ,
123
- EXCEPTION_FUTURE ,
124
- SUCCESSFUL_FUTURE ,
125
- future ],
126
- timeout = short_timeout ,
127
- return_when = futures .ALL_COMPLETED )
128
-
129
- self .assertEqual (set ([CANCELLED_AND_NOTIFIED_FUTURE ,
130
- EXCEPTION_FUTURE ,
131
- SUCCESSFUL_FUTURE ]),
132
- finished )
133
- self .assertEqual (set ([future ]), pending )
157
+ try :
158
+ finished , pending = futures .wait (
159
+ [CANCELLED_AND_NOTIFIED_FUTURE ,
160
+ EXCEPTION_FUTURE ,
161
+ SUCCESSFUL_FUTURE ,
162
+ future ],
163
+ timeout = short_timeout ,
164
+ return_when = futures .ALL_COMPLETED )
165
+
166
+ self .assertEqual (set ([CANCELLED_AND_NOTIFIED_FUTURE ,
167
+ EXCEPTION_FUTURE ,
168
+ SUCCESSFUL_FUTURE ]),
169
+ finished )
170
+ self .assertEqual (set ([future ]), pending )
171
+ finally :
172
+ event .set ()
173
+ future .result () # wait for job to finish
134
174
135
175
136
176
class ThreadPoolWaitTests (ThreadPoolMixin , WaitTests , BaseTestCase ):
0 commit comments