def test_first_completed_with_exception(self): future1 = concurrent.Future() future2 = concurrent.Future() # Mark future1 as completed with an exception. self.assertTrue(future1.set_running_or_notify_cancel()) future1.set_exception(AssertionError()) # Here, wait should return immediately even without timeout. done, not_done = concurrent.wait([future1, future2], return_when=concurrent.FIRST_COMPLETED) self.assertEqual({future1}, done) self.assertEqual({future2}, not_done)
def test_first_exception_without_error(self): future1 = concurrent.Future() future2 = concurrent.Future() # Mark both futures as completed without any exceptions. self.assertTrue(future1.set_running_or_notify_cancel()) future1.set_result(WaitTest._DUMMY_RESULT) self.assertTrue(future2.set_running_or_notify_cancel()) future2.set_result(WaitTest._DUMMY_RESULT) # If all futures are completed, wait() should return immediately, # even if return_when is set to FIRST_EXCEPTION. done, not_done = concurrent.wait([future1, future2], return_when=concurrent.FIRST_EXCEPTION) self.assertEqual({future1, future2}, done) self.assertFalse(not_done) # Empty.
def test_simple_scenario(self): future = concurrent.Future() # Make sure the precondition. self.assertFalse(future.cancelled()) self.assertFalse(future.running()) self.assertFalse(future.done()) with self.assertRaises(concurrent.TimeoutError): future.result(timeout=0) # Start the task. self.assertTrue(future.set_running_or_notify_cancel()) self.assertFalse(future.cancelled()) self.assertTrue(future.running()) self.assertFalse(future.done()) with self.assertRaises(concurrent.TimeoutError): future.result(timeout=0) # Then finished. future.set_result(FutureTest._DUMMY_RESULT) self.assertFalse(future.cancelled()) self.assertFalse(future.running()) self.assertTrue(future.done()) # Expect that future.result() returns immediately. self.assertEquals(FutureTest._DUMMY_RESULT, future.result())
def test_callback_cancel(self): future = concurrent.Future() event = threading.Event() future.add_done_callback(lambda _: event.set()) self.assertFalse(event.is_set()) # Cancel the task, then the callback should be called. self.assertTrue(future.cancel()) self.assertTrue(event.is_set())
def test_all_completed_with_exception(self): future1 = concurrent.Future() self.assertTrue(future1.set_running_or_notify_cancel()) future1.set_exception(AssertionError()) # Finished with an exception is also considered as completed. done, not_done = concurrent.wait([future1]) self.assertEqual({future1}, done) self.assertFalse(not_done) # Empty.
def test_first_exception(self): future1 = concurrent.Future() future2 = concurrent.Future() # First of all, no futures are completed. done, not_done = concurrent.wait([future1, future2], timeout=0.01, return_when=concurrent.FIRST_EXCEPTION) self.assertFalse(done) # Empty. self.assertEqual({future1, future2}, not_done) # Mark future1 as completed with an exception. self.assertTrue(future1.set_running_or_notify_cancel()) future1.set_exception(AssertionError()) # Here, wait should return immediately even without timeout. done, not_done = concurrent.wait([future1, future2], return_when=concurrent.FIRST_EXCEPTION) self.assertEqual({future1}, done) self.assertEqual({future2}, not_done)
def test_first_completed(self): future1 = concurrent.Future() future2 = concurrent.Future() # First of all, no futures are completed. done, not_done = concurrent.wait([future1, future2], timeout=0.01, return_when=concurrent.FIRST_COMPLETED) self.assertFalse(done) # Empty. self.assertEqual({future1, future2}, not_done) # Mark future1 as completed. self.assertTrue(future1.set_running_or_notify_cancel()) future1.set_result(WaitTest._DUMMY_RESULT) # Here, wait should return immediately even without timeout. done, not_done = concurrent.wait([future1, future2], return_when=concurrent.FIRST_COMPLETED) self.assertEqual({future1}, done) self.assertEqual({future2}, not_done)
def test_cancel_failed(self): future = concurrent.Future() # Running task is not cancellable. self.assertTrue(future.set_running_or_notify_cancel()) self.assertFalse(future.cancel()) # Completed task is not cancellable, neither. future.set_result(FutureTest._DUMMY_RESULT) self.assertFalse(future.cancel())
def test_cancel_success(self): future = concurrent.Future() self.assertTrue(future.cancel()) self.assertTrue(future.cancelled()) self.assertFalse(future.running()) self.assertTrue(future.done()) # Expect that CancelledError is raised immediately. with self.assertRaises(concurrent.CancelledError): future.result()
def test_callback_done(self): future = concurrent.Future() # Mark the future as the task is completed. self.assertTrue(future.set_running_or_notify_cancel()) future.set_result(FutureTest._DUMMY_RESULT) self.assertTrue(future.done()) # Add the callback to the future in DONE state. The callback should be # called immediately. event = threading.Event() future.add_done_callback(lambda _: event.set()) self.assertTrue(event.is_set())
def test_exception_scenario(self): future = concurrent.Future() # Start the task and finish with an exception. self.assertTrue(future.set_running_or_notify_cancel()) future.set_exception(AssertionError()) self.assertFalse(future.cancelled()) self.assertFalse(future.running()) self.assertTrue(future.done()) # Expect that future.result() raises the exception immediately. with self.assertRaises(AssertionError): future.result()
def test_callback_exception(self): future = concurrent.Future() event = threading.Event() future.add_done_callback(lambda _: event.set()) self.assertFalse(event.is_set()) # Start the task and finish with an exception self.assertTrue(future.set_running_or_notify_cancel()) self.assertFalse(event.is_set()) # And finish it with an exception. The callback should be called then. future.set_exception(AssertionError()) self.assertTrue(event.is_set())
def test_callback(self): future = concurrent.Future() event = threading.Event() future.add_done_callback(lambda _: event.set()) self.assertFalse(event.is_set()) # Start the task. self.assertTrue(future.set_running_or_notify_cancel()) self.assertFalse(event.is_set()) # And finish it. The callback should be called then. future.set_result(FutureTest._DUMMY_RESULT) self.assertTrue(event.is_set())
def test_all_completed(self): future1 = concurrent.Future() future2 = concurrent.Future() # First of all, no futures are completed. done, not_done = concurrent.wait([future1, future2], timeout=0.01) self.assertFalse(done) # Empty. self.assertEqual({future1, future2}, not_done) # Mark future1 as completed. self.assertTrue(future1.set_running_or_notify_cancel()) future1.set_result(WaitTest._DUMMY_RESULT) done, not_done = concurrent.wait([future1, future2], timeout=0.01) self.assertEqual({future1}, done) self.assertEqual({future2}, not_done) # Mark future2 as completed, too. self.assertTrue(future2.set_running_or_notify_cancel()) future2.set_result(WaitTest._DUMMY_RESULT) # Now, wait should return immediately, even timeout is not set. done, not_done = concurrent.wait([future1, future2]) self.assertEqual({future1, future2}, done) self.assertFalse(not_done) # Empty.
def test_wait_result(self): def worker_run(future): future.set_running_or_notify_cancel() future.set_result(FutureTest._DUMMY_RESULT) # Note: unfortunately there is no reliable way to ensure set_result() # is called (on worker thread) after result() is called on the main thread. # However, even if the order is inverted, this test should pass # successfully. future = concurrent.Future() thread = threading.Thread(target=worker_run, args=(future,)) thread.daemon = True thread.start() self.assertEquals(FutureTest._DUMMY_RESULT, future.result()) self.assertEquals(None, future.exception()) thread.join()
def test_wait_exception(self): def worker_run(future): future.set_running_or_notify_cancel() future.set_exception(AssertionError()) # Note: unfortunately there is no reliable way to ensure set_exception() # is called (on worker thread) after result() is called on the main thread. # However, even if the order is inverted, this test should pass # successfully. future = concurrent.Future() thread = threading.Thread(target=worker_run, args=(future,)) thread.daemon = True thread.start() with self.assertRaises(AssertionError): future.result() self.assertIsInstance(future.exception(), AssertionError) thread.join()
def test_exception_traceback(self): future = concurrent.Future() self.assertTrue(future.set_running_or_notify_cancel()) # Set an exception inside the inner function. class TestException(Exception): pass def inner_function(future): try: raise TestException except TestException as e: future.set_exception(e) inner_function(future) # Then we expect the raised exception to be propagated, with the inner # function appearing in the stack traceback. with self.assertRaises(TestException): try: future.result() except TestException: self.assertTrue('inner_function' in traceback.format_exc()) raise