Esempio n. 1
0
def test_and(inputs, expected_result, falsey, truthy):
    inputs = resolve_inputs(inputs, falsey, truthy)
    expected_result = resolve_value(expected_result, falsey, truthy)

    f_inputs = [as_future(x) for x in inputs]
    future = f_and(*f_inputs)
    assert_future_equal(future, expected_result)
Esempio n. 2
0
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])
Esempio n. 3
0
def test_and_order_async():
    executor = Executors.thread_pool(max_workers=2)

    def delay_then(delay, value):
        time.sleep(delay)
        return value

    f_inputs = [
        executor.submit(delay_then, 0.1, 123),
        executor.submit(delay_then, 0.05, 456),
    ]

    future = f_and(*f_inputs)
    assert_future_equal(future, 123)
Esempio n. 4
0
def test_and_propagate_traceback():
    def inner_test_fn():
        raise RuntimeError("oops")

    def my_test_fn(inner_fn=None):
        if inner_fn:
            inner_fn()
        return True

    executor = Executors.thread_pool()
    futures = [
        executor.submit(my_test_fn),
        executor.submit(my_test_fn),
        executor.submit(my_test_fn, inner_fn=inner_test_fn),
        executor.submit(my_test_fn),
    ]
    future = f_and(*futures)
    assert_in_traceback(future, "inner_test_fn")
Esempio n. 5
0
def test_and_cancels():
    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)
    with executor:
        futures = [
            executor.submit(delayed_call, x) for x in (0.5, error, 0.2, 2.0, 3.0)
        ]

        future = f_and(*futures)

        exception = future.exception()

    # error should have been propagated
    assert exception is error

    # 0.5 definitely should have been invoked
    assert 0.5 in calls

    # up to 1 more of the calls might have succeeded,
    # but we can't say which.
    # Why: because the cancels race with the thread pool,
    # once 'error' completes then f_and and the thread pool
    # are both trying to grab the next futures ASAP,
    # and either cancel or run could win.
    assert len(calls) in (1, 2)

    # This could not have been cancelled since it was
    # submitted earlier than the terminal
    assert futures[0].done()

    # The future which terminated the and()
    assert futures[1].done()

    # at least 2 of the remaining futures should have been cancelled
    assert len([f for f in futures if f.cancelled()]) >= 2
Esempio n. 6
0
def test_and_error():
    with pytest.raises(TypeError):
        f_and("a", "b")
Esempio n. 7
0
def test_and_order_sync():
    f_inputs = [as_future(x) for x in [1, 2, 3]]

    future = f_and(*f_inputs)
    assert_future_equal(future, 3)
Esempio n. 8
0
def test_and_large():
    inputs = [f_return(True) for _ in range(0, 100000)]

    assert f_and(*inputs).result() is True