def test_clear(): import asyncgui as ag e1 = ag.Event() e2 = ag.Event() async def main(): nonlocal task_state task_state = 'A' await e1.wait() task_state = 'B' await e2.wait() task_state = 'C' await e1.wait() task_state = 'D' task_state = None ag.start(main()) assert task_state == 'A' e1.set() assert task_state == 'B' e1.clear() e2.set() assert task_state == 'C' e1.set() assert task_state == 'D'
def test_nested(set_immediately_1, set_immediately_2): import asyncgui as ag TS = ag.TaskState e1 = ag.Event() e2 = ag.Event() if set_immediately_1: e1.set() if set_immediately_2: e2.set() main_task = ag.Task(main(e1, e2)) ag.start(main_task) main_task.cancel() if set_immediately_1 and set_immediately_2: # 中断の機会を与えられずに終わる為 DONE assert main_task.state is TS.DONE return assert main_task.state is TS.STARTED if set_immediately_1 or set_immediately_2: e1.set() e2.set() assert main_task.state is TS.CANCELLED return e1.set() assert main_task.state is TS.STARTED e2.set() assert main_task.state is TS.CANCELLED
def test_complicated_case( starts_immediately, what_a_should_do, should_b_fail, should_c_fail, ): import asyncgui as ag TS = ag.TaskState ctx = { 'e_begin': ag.Event(), 'e': ag.Event(), 'what_a_should_do': what_a_should_do, 'should_b_fail': should_b_fail, 'should_c_fail': should_c_fail, } n_exceptions = 0 if what_a_should_do == 'fail': n_exceptions += 1 if should_b_fail: n_exceptions += 1 if should_c_fail: n_exceptions += 1 async def main(ctx): from asyncgui.structured_concurrency import and_ task_a = ag.Task(child_a(ctx)) task_b = ctx['task_b'] = ag.Task(child_b(ctx)) task_c = ag.Task(child_c(ctx)) if n_exceptions == 1: with pytest.raises(ZeroDivisionError): await and_(task_a, task_b, task_c) elif n_exceptions: with pytest.raises(ag.MultiError) as excinfo: await and_(task_a, task_b, task_c) assert [ZeroDivisionError, ] * n_exceptions == \ [type(e) for e in excinfo.value.exceptions] else: await and_(task_a, task_b, task_c) if starts_immediately: ctx['e_begin'].set() main_task = ag.start(main(ctx)) if not starts_immediately: ctx['e_begin'].set() if should_c_fail or should_b_fail or what_a_should_do != 'suspend': assert main_task.state is TS.DONE else: assert main_task.state is TS.STARTED main_task.cancel()
def test_nested_cancel_protection(): import asyncgui as ag async def outer_fn(e): async with ag.cancel_protection(): await inner_fn(e) await ag.sleep_forever() pytest.fail("Failed to cancel") async def inner_fn(e): assert task._cancel_protection == 1 async with ag.cancel_protection(): assert task._cancel_protection == 2 await e.wait() assert task._cancel_protection == 1 e = ag.Event() task = ag.Task(outer_fn(e)) assert task._cancel_protection == 0 ag.start(task) assert task._cancel_protection == 2 task.cancel() assert not task.cancelled assert not task._is_cancellable e.set() assert task._cancel_protection == 0 assert task.cancelled
def test_set_before_task_starts(): import asyncgui as ag e = ag.Event() e.set() async def main(): await e.wait() task = ag.start(main()) assert task.done
def test_pass_argument(): import asyncgui as ag e = ag.Event() async def main(e): assert await e.wait() == 'A' task = ag.start(main(e)) assert not task.done e.set('A') assert task.done
def test_multiple_tasks(): import asyncgui as ag TS = ag.TaskState e = ag.Event() task1 = ag.start(e.wait()) task2 = ag.start(e.wait()) assert task1.state is TS.STARTED assert task2.state is TS.STARTED e.set() assert task1.state is TS.DONE assert task2.state is TS.DONE
def test_one_child_fails_soon(): import asyncgui as ag from asyncgui.structured_concurrency import or_ async def main(e): with pytest.raises(ZeroDivisionError): await or_(fail_soon(e)) e = ag.Event() main_task = ag.start(main(e)) assert not main_task.done e.set() assert main_task.done
def test_multiple_children_finish_soon(): import asyncgui as ag from asyncgui.structured_concurrency import and_ async def main(e): tasks = await and_(finish_soon(e), finish_soon(e)) assert [True, True] == [task.done for task in tasks] e = ag.Event() main_task = ag.start(main(e)) assert not main_task.done e.set() assert main_task.done
def test_multiple_children_finish_soon(): import asyncgui as ag from asyncgui.structured_concurrency import or_ TS = ag.TaskState async def main(e): tasks = await or_(finish_soon(e), finish_soon(e)) assert [TS.DONE, TS.CANCELLED] == [task.state for task in tasks] e = ag.Event() main_task = ag.start(main(e)) assert not main_task.done e.set() assert main_task.done
def test_one_child_finishes_soon(): import asyncgui as ag from asyncgui.structured_concurrency import or_ async def main(e): tasks = await or_(finish_soon(e)) assert [ True, ] == [task.done for task in tasks] e = ag.Event() main_task = ag.start(main(e)) assert not main_task.done e.set() assert main_task.done
def test_other_child_fails(self, other_child): import asyncgui as ag from asyncgui.structured_concurrency import or_ async def main(e): with pytest.raises(ZeroDivisionError): await or_(finish_soon_but_protected(e), other_child(e)) e = ag.Event() main_task = ag.Task(main(e)) ag.start(main_task) assert not main_task.done main_task.cancel() assert not main_task.done e.set() assert main_task.done
def test_other_child_does_not_fail(self, other_child): import asyncgui as ag from asyncgui.structured_concurrency import and_ async def main(e): await and_(finish_soon_but_protected(e), other_child(e)) pytest.fail("Failed to cancel") e = ag.Event() main_task = ag.Task(main(e)) ag.start(main_task) assert not main_task.cancelled main_task.cancel() assert not main_task.cancelled e.set() assert main_task.cancelled
def test_multiple_children_fail_soon(): ''' MultiErrorが起こるように思えるが、1つ目の子で例外が起こるや否や2つ目 は即中断されるため、2つ目では例外は起こらない ''' import asyncgui as ag from asyncgui.structured_concurrency import or_ async def main(e): with pytest.raises(ZeroDivisionError): await or_(fail_soon(e), fail_soon(e)) e = ag.Event() main_task = ag.start(main(e)) assert not main_task.done e.set() assert main_task.done
def test_必ず例外を起こす子_を複数持つ親を中断(): import asyncgui as ag from asyncgui.structured_concurrency import or_ TS = ag.TaskState async def main(e): with pytest.raises(ag.MultiError) as excinfo: await or_(fail_on_cancel(), fail_on_cancel()) assert [ZeroDivisionError, ZeroDivisionError] == \ [type(e) for e in excinfo.value.exceptions] await e.wait() pytest.fail("Failed to cancel") e = ag.Event() main_task = ag.Task(main(e)) ag.start(main_task) assert main_task.state is TS.STARTED main_task.cancel() assert main_task.state is TS.CANCELLED
def test_multiple_children_fail(): ''' 1つ目の子で例外が起こる事で2つ目が中断される。その時2つ目でも例外が 起きるためMultiErrorが湧く。 ''' import asyncgui as ag from asyncgui.structured_concurrency import or_ async def main(e): with pytest.raises(ag.MultiError) as excinfo: await or_(fail_soon(e), fail_on_cancel()) assert [ZeroDivisionError, ZeroDivisionError] == \ [type(e) for e in excinfo.value.exceptions] e = ag.Event() main_task = ag.start(main(e)) assert not main_task.done e.set() assert main_task.done
def test_reset_value(): import asyncgui as ag e = ag.Event() async def job1(e): assert await e.wait() == 'A' e.clear() e.set('B') async def job2(e): assert await e.wait() == 'A' assert await e.wait() == 'B' task1 = ag.start(job1(e)) task2 = ag.start(job2(e)) assert not task1.done assert not task2.done e.set('A') assert task1.done assert task2.done
def test_callback(): import asyncgui as ag e = ag.Event() def callback(value): assert value == 'A' nonlocal done done = True # set after a callback is registered done = False e.add_callback(callback) assert not done e.set('A') assert done e.clear() # set before a callback is registered done = False e.set('A') assert not done e.add_callback(callback) assert done