-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
gh-128364: Fix flaky test_concurrent_futures.test_wait tests
#130742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
eff5d73
f3cc50f
8eeaf63
0a94b54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,5 @@ | ||
| import sys | ||
| import threading | ||
| import time | ||
| import unittest | ||
| from concurrent import futures | ||
| from test import support | ||
|
|
@@ -16,24 +15,25 @@ | |
| def mul(x, y): | ||
| return x * y | ||
|
|
||
| def sleep_and_raise(t): | ||
| time.sleep(t) | ||
| def wait_and_raise(e): | ||
| e.wait() | ||
| raise Exception('this is an exception') | ||
|
|
||
|
|
||
| class WaitTests: | ||
| def test_20369(self): | ||
| # See https://bugs.python.org/issue20369 | ||
| future = self.executor.submit(time.sleep, 1.5) | ||
| future = self.executor.submit(mul, 1, 2) | ||
| done, not_done = futures.wait([future, future], | ||
| return_when=futures.ALL_COMPLETED) | ||
| self.assertEqual({future}, done) | ||
| self.assertEqual(set(), not_done) | ||
|
|
||
|
|
||
| def test_first_completed(self): | ||
| event = self.create_event() | ||
| future1 = self.executor.submit(mul, 21, 2) | ||
| future2 = self.executor.submit(time.sleep, 1.5) | ||
| future2 = self.executor.submit(event.wait) | ||
|
|
||
| done, not_done = futures.wait( | ||
| [CANCELLED_FUTURE, future1, future2], | ||
|
|
@@ -42,8 +42,12 @@ def test_first_completed(self): | |
| self.assertEqual(set([future1]), done) | ||
| self.assertEqual(set([CANCELLED_FUTURE, future2]), not_done) | ||
|
|
||
| event.set() | ||
| future2.result() # wait for job to finish | ||
|
|
||
| def test_first_completed_some_already_completed(self): | ||
| future1 = self.executor.submit(time.sleep, 1.5) | ||
| event = self.create_event() | ||
| future1 = self.executor.submit(event.wait) | ||
|
|
||
| finished, pending = futures.wait( | ||
| [CANCELLED_AND_NOTIFIED_FUTURE, SUCCESSFUL_FUTURE, future1], | ||
|
|
@@ -54,11 +58,24 @@ def test_first_completed_some_already_completed(self): | |
| finished) | ||
| self.assertEqual(set([future1]), pending) | ||
|
|
||
| @support.requires_resource('walltime') | ||
| event.set() | ||
| future1.result() # wait for job to finish | ||
|
|
||
| def test_first_exception(self): | ||
picnixz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| event1 = self.create_event() | ||
| event2 = self.create_event() | ||
|
|
||
| future1 = self.executor.submit(mul, 2, 21) | ||
| future2 = self.executor.submit(sleep_and_raise, 1.5) | ||
| future3 = self.executor.submit(time.sleep, 3) | ||
| future2 = self.executor.submit(wait_and_raise, event1) | ||
| future3 = self.executor.submit(event2.wait) | ||
|
|
||
| # Ensure that future1 is completed before future2 finishes | ||
| def wait_for_future1(): | ||
| future1.result() | ||
| event1.set() | ||
|
|
||
| t = threading.Thread(target=wait_for_future1) | ||
| t.start() | ||
|
|
||
| finished, pending = futures.wait( | ||
| [future1, future2, future3], | ||
|
|
@@ -67,9 +84,14 @@ def test_first_exception(self): | |
| self.assertEqual(set([future1, future2]), finished) | ||
| self.assertEqual(set([future3]), pending) | ||
|
|
||
| t.join() | ||
|
||
| event2.set() | ||
| future3.result() # wait for job to finish | ||
|
|
||
| def test_first_exception_some_already_complete(self): | ||
| event = self.create_event() | ||
| future1 = self.executor.submit(divmod, 21, 0) | ||
| future2 = self.executor.submit(time.sleep, 1.5) | ||
| future2 = self.executor.submit(event.wait) | ||
|
|
||
| finished, pending = futures.wait( | ||
| [SUCCESSFUL_FUTURE, | ||
|
|
@@ -83,8 +105,12 @@ def test_first_exception_some_already_complete(self): | |
| future1]), finished) | ||
| self.assertEqual(set([CANCELLED_FUTURE, future2]), pending) | ||
|
|
||
| event.set() | ||
| future2.result() # wait for job to finish | ||
|
|
||
| def test_first_exception_one_already_failed(self): | ||
| future1 = self.executor.submit(time.sleep, 2) | ||
| event = self.create_event() | ||
| future1 = self.executor.submit(event.wait) | ||
|
Comment on lines
+118
to
+119
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if it could be more helpful, but what about using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cleanup functions are called too late. They run after There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh right.. |
||
|
|
||
| finished, pending = futures.wait( | ||
| [EXCEPTION_FUTURE, future1], | ||
|
|
@@ -93,6 +119,9 @@ def test_first_exception_one_already_failed(self): | |
| self.assertEqual(set([EXCEPTION_FUTURE]), finished) | ||
| self.assertEqual(set([future1]), pending) | ||
|
|
||
| event.set() | ||
| future1.result() # wait for job to finish | ||
|
|
||
| def test_all_completed(self): | ||
| future1 = self.executor.submit(divmod, 2, 0) | ||
| future2 = self.executor.submit(mul, 2, 21) | ||
|
|
@@ -114,9 +143,9 @@ def test_all_completed(self): | |
|
|
||
| def test_timeout(self): | ||
| short_timeout = 0.050 | ||
| long_timeout = short_timeout * 10 | ||
|
|
||
| future = self.executor.submit(time.sleep, long_timeout) | ||
| event = self.create_event() | ||
| future = self.executor.submit(event.wait) | ||
|
|
||
| finished, pending = futures.wait( | ||
| [CANCELLED_AND_NOTIFIED_FUTURE, | ||
|
|
@@ -132,6 +161,10 @@ def test_timeout(self): | |
| finished) | ||
| self.assertEqual(set([future]), pending) | ||
|
|
||
| # Set the event to allow the future to complete | ||
| event.set() | ||
| future.result() # wait for job to finish | ||
|
|
||
|
|
||
| class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests, BaseTestCase): | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use maybe try/finally to unblock the task on test failure? Same remark for other tests.