def test_or_with_nocancel(): calls = set() def delayed_call(delay): time.sleep(delay) calls.add(delay) return delay executor = Executors.thread_pool(max_workers=2) futures = [ executor.submit(delayed_call, x) for x in (0.5, 0.1, 0.2, 1.0, 1.1) ] futures = [f_nocancel(f) for f in futures] future = f_or(*futures) result = future.result() # Result comes from the future which completed first assert result == 0.1 # Only this calls should have completed so far assert calls == set([0.1]) # But if we wait on this... assert futures[-1].result() == 1.1 # Then they've all completed now, thanks to nocancel assert calls == set([0.1, 0.2, 0.5, 1.0, 1.1])
def test_timeout(): def sleep_then_return(x): time.sleep(x) return x with Executors.thread_pool(max_workers=2) as executor: futures = [ executor.submit(sleep_then_return, x) for x in [0.5, 0.5, 0.5, 0.5, 0.5] ] futures[3] = f_nocancel(futures[3]) futures = [f_timeout(f, 0.02) for f in futures] try: futures[-1].result() raise AssertionError("Should have failed") except CancelledError: # expected pass assert futures[0].result() == 0.5 assert futures[1].result() == 0.5 assert futures[2].cancelled() assert futures[3].result() == 0.5 assert futures[4].cancelled()
def test_and_with_nocancel(): calls = set() error = RuntimeError("simulated error") def delayed_call(delay): if delay is error: raise error time.sleep(delay) calls.add(delay) return delay executor = Executors.thread_pool(max_workers=2) futures = [ executor.submit(delayed_call, x) for x in (0.5, error, 0.2, 1.1, 1.2) ] futures = [f_nocancel(f) for f in futures] future = f_and(*futures) exception = future.exception() # error should have been propagated assert exception is error # nothing else has been called yet assert not calls # but if we wait on the last future... assert futures[-1].result() == 1.2 # then all calls were made thanks to nocancel assert calls == set([0.5, 0.2, 1.1, 1.2])
def test_nocancel(): executor = Executors.thread_pool(max_workers=2) futures = [f_nocancel(executor.submit(delay_then, x)) for x in [1, 2, 3, 4, 5]] for f in futures: # Should not be able to cancel it even though most # are not started yet assert not f.cancel() assert [f.result() for f in futures] == [1, 2, 3, 4, 5]
def test_nocancel(): with pytest.raises(TypeError): f_nocancel("a") with pytest.raises(TypeError): f_nocancel(future="a")