diff options
author | Grzegorz Grzywacz <grzgrzgrz3@gmail.com> | 2017-09-01 16:54:00 (GMT) |
---|---|---|
committer | Antoine Pitrou <pitrou@free.fr> | 2017-09-01 16:54:00 (GMT) |
commit | 97e1b1c81458d2109b2ffed32ffa1eb643a6c3b9 (patch) | |
tree | e87029349aa808857ea5e2d1582f0f9f66f0cfad /Lib/test/test_concurrent_futures.py | |
parent | 16432beadb8eba079c9786cc0c0eaacfd9fd2f7b (diff) | |
download | cpython-97e1b1c81458d2109b2ffed32ffa1eb643a6c3b9.zip cpython-97e1b1c81458d2109b2ffed32ffa1eb643a6c3b9.tar.gz cpython-97e1b1c81458d2109b2ffed32ffa1eb643a6c3b9.tar.bz2 |
bpo-27144: concurrent.futures as_complete and map iterators do not keep reference to returned object (#1560)
* bpo-27144: concurrent.futures as_complie and map iterators do not keep
reference to returned object
* Some nits. Improve wordings in docstrings and comments, and avoid relying on
sys.getrefcount() in tests.
Diffstat (limited to 'Lib/test/test_concurrent_futures.py')
-rw-r--r-- | Lib/test/test_concurrent_futures.py | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index ebc30a4..f1226fe 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -59,6 +59,10 @@ class MyObject(object): pass +def make_dummy_object(_): + return MyObject() + + class BaseTestCase(unittest.TestCase): def setUp(self): self._thread_key = test.support.threading_setup() @@ -396,6 +400,38 @@ class AsCompletedTests: completed = [f for f in futures.as_completed([future1,future1])] self.assertEqual(len(completed), 1) + def test_free_reference_yielded_future(self): + # Issue #14406: Generator should not keep references + # to finished futures. + futures_list = [Future() for _ in range(8)] + futures_list.append(create_future(state=CANCELLED_AND_NOTIFIED)) + futures_list.append(create_future(state=SUCCESSFUL_FUTURE)) + + with self.assertRaises(futures.TimeoutError): + for future in futures.as_completed(futures_list, timeout=0): + futures_list.remove(future) + wr = weakref.ref(future) + del future + self.assertIsNone(wr()) + + futures_list[0].set_result("test") + for future in futures.as_completed(futures_list): + futures_list.remove(future) + wr = weakref.ref(future) + del future + self.assertIsNone(wr()) + if futures_list: + futures_list[0].set_result("test") + + def test_correct_timeout_exception_msg(self): + futures_list = [CANCELLED_AND_NOTIFIED_FUTURE, PENDING_FUTURE, + RUNNING_FUTURE, SUCCESSFUL_FUTURE] + + with self.assertRaises(futures.TimeoutError) as cm: + list(futures.as_completed(futures_list, timeout=0)) + + self.assertEqual(str(cm.exception), '2 (of 4) futures unfinished') + class ThreadPoolAsCompletedTests(ThreadPoolMixin, AsCompletedTests, BaseTestCase): pass @@ -421,6 +457,10 @@ class ExecutorTest: list(self.executor.map(pow, range(10), range(10))), list(map(pow, range(10), range(10)))) + self.assertEqual( + list(self.executor.map(pow, range(10), range(10), chunksize=3)), + list(map(pow, range(10), range(10)))) + def test_map_exception(self): i = self.executor.map(divmod, [1, 1, 1, 1], [2, 3, 0, 5]) self.assertEqual(i.__next__(), (0, 1)) @@ -471,6 +511,14 @@ class ExecutorTest: "than 0"): self.executor_type(max_workers=number) + def test_free_reference(self): + # Issue #14406: Result iterator should not keep an internal + # reference to result objects. + for obj in self.executor.map(make_dummy_object, range(10)): + wr = weakref.ref(obj) + del obj + self.assertIsNone(wr()) + class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest, BaseTestCase): def test_map_submits_without_iteration(self): |