async def test_waiting_until_off_fails_when_not_turned_off(): toggle = Toggle(True) with pytest.raises(asyncio.TimeoutError): async with async_timeout.timeout(0.1) as timeout: await toggle.wait_for(False) assert toggle.is_on() assert timeout.expired
async def test_waiting_until_off_wakes_when_turned_off(timer): toggle = Toggle(True) async def delayed_turning_off(delay: float): await asyncio.sleep(delay) await toggle.turn_to(False) with timer: asyncio.create_task(delayed_turning_off(0.05)) await toggle.wait_for(False) assert toggle.is_off() assert timer.seconds < 0.5 # approx. 0.05 plus some code overhead
async def test_waiting_until_on_wakes_when_turned_on(timer): toggle = Toggle(False) async def delayed_turning_on(delay: float): await asyncio.sleep(delay) await toggle.turn_to(True) async with timer, async_timeout.timeout(1.0) as timeout: asyncio.create_task(delayed_turning_on(0.05)) await toggle.wait_for(True) assert toggle.is_on() assert not timeout.expired assert timer.seconds < 0.5 # approx. 0.05 plus some code overhead
async def test_preserved_on_ignored_errors(resource, settings, registry, memories, indexers, index, caplog, event_type, handlers): caplog.set_level(logging.DEBUG) body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}} memory = await memories.recall(raw_body=body) handlers.index_mock.side_effect = Exception("boo!") await process_resource_event( lifecycle=all_at_once, registry=registry, settings=settings, resource=resource, indexers=indexers, memories=memories, memobase=Memo(), raw_event={ 'type': event_type, 'object': body }, event_queue=asyncio.Queue(), resource_indexed=Toggle(), # used! only to enable indexing. ) assert set(index) == {None} assert set(index[None]) == {123} assert memory.indexing_memory.indexing_state is None
async def test_removed_and_remembered_on_temporary_errors( resource, settings, registry, memories, indexers, index, caplog, event_type, handlers, delay_kwargs, expected_delayed): caplog.set_level(logging.DEBUG) body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}} memory = await memories.recall(raw_body=body) handlers.index_mock.side_effect = TemporaryError("boo!", **delay_kwargs) await process_resource_event( lifecycle=all_at_once, registry=registry, settings=settings, resource=resource, indexers=indexers, memories=memories, memobase=Memo(), raw_event={ 'type': event_type, 'object': body }, event_queue=asyncio.Queue(), resource_indexed=Toggle(), # used! only to enable indexing. ) assert set(index) == set() assert memory.indexing_memory.indexing_state['index_fn'].finished == False assert memory.indexing_memory.indexing_state['index_fn'].failure == False assert memory.indexing_memory.indexing_state['index_fn'].success == False assert memory.indexing_memory.indexing_state['index_fn'].message == 'boo!' assert memory.indexing_memory.indexing_state[ 'index_fn'].delayed == expected_delayed
async def test_permanent_failures_are_not_reindexed(resource, settings, registry, memories, indexers, index, caplog, event_type, handlers): caplog.set_level(logging.DEBUG) body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}} memory = await memories.recall(raw_body=body) memory.indexing_memory.indexing_state = State( {'index_fn': HandlerState(failure=True)}) await process_resource_event( lifecycle=all_at_once, registry=registry, settings=settings, resource=resource, indexers=indexers, memories=memories, memobase=Memo(), raw_event={ 'type': event_type, 'object': body }, event_queue=asyncio.Queue(), resource_indexed=Toggle(), # used! only to enable indexing. ) assert handlers.index_mock.call_count == 0
async def test_created_empty(fn, expected): toggleset = ToggleSet(fn) assert len(toggleset) == 0 assert set(toggleset) == set() assert Toggle() not in toggleset assert toggleset.is_on() == expected assert toggleset.is_off() == (not expected)
async def test_successes_are_removed_from_the_indexing_state( resource, settings, registry, memories, indexers, caplog, event_type, handlers): caplog.set_level(logging.DEBUG) body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}} memory = await memories.recall(raw_body=body) memory.indexing_memory.indexing_state = State( {'unrelated': HandlerState(success=True)}) handlers.index_mock.side_effect = 123 await process_resource_event( lifecycle=all_at_once, registry=registry, settings=settings, resource=resource, indexers=indexers, memories=memories, memobase=Memo(), raw_event={ 'type': event_type, 'object': body }, event_queue=asyncio.Queue(), resource_indexed=Toggle(), # used! only to enable indexing. ) assert handlers.index_mock.call_count == 1 assert memory.indexing_memory.indexing_state is None
async def test_temporary_failures_with_expired_delays_are_reindexed( resource, settings, registry, memories, indexers, index, caplog, event_type, handlers): caplog.set_level(logging.DEBUG) body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}} delayed = datetime.datetime(2020, 12, 31, 23, 59, 59, 0) memory = await memories.recall(raw_body=body) memory.indexing_memory.indexing_state = State( {'index_fn': HandlerState(delayed=delayed)}) await process_resource_event( lifecycle=all_at_once, registry=registry, settings=settings, resource=resource, indexers=indexers, memories=memories, memobase=Memo(), raw_event={ 'type': event_type, 'object': body }, event_queue=asyncio.Queue(), resource_indexed=Toggle(), # used! only to enable indexing. ) assert handlers.index_mock.call_count == 1
async def test_removed_on_filters_mismatch(resource, settings, registry, indexers, index, caplog, event_type, handlers, mocker): # Simulate the indexing handler is gone out of scope (this is only one of the ways to do it): mocker.patch.object(registry._indexing, 'get_handlers', return_value=[]) caplog.set_level(logging.DEBUG) body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}} handlers.index_mock.return_value = 123 await process_resource_event( lifecycle=all_at_once, registry=registry, settings=settings, resource=resource, indexers=indexers, memories=ResourceMemories(), memobase=Memo(), raw_event={ 'type': event_type, 'object': body }, event_queue=asyncio.Queue(), resource_indexed=Toggle(), # used! only to enable indexing. ) assert set(index) == set()
async def test_preserved_on_logical_deletion(resource, settings, registry, indexers, index, caplog, event_type, handlers): caplog.set_level(logging.DEBUG) body = { 'metadata': { 'namespace': 'ns1', 'name': 'name1', 'deletionTimestamp': '...' } } handlers.index_mock.return_value = 456 await process_resource_event( lifecycle=all_at_once, registry=registry, settings=settings, resource=resource, indexers=indexers, memories=ResourceMemories(), memobase=Memo(), raw_event={ 'type': event_type, 'object': body }, event_queue=asyncio.Queue(), resource_indexed=Toggle(), # used! only to enable indexing. ) assert set(index) == {None} assert set(index[None]) == {456}
async def test_making_a_turned_on_toggle(fn): toggleset = ToggleSet(fn) toggle = await toggleset.make_toggle(True) assert len(toggleset) == 1 assert set(toggleset) == {toggle} assert toggle in toggleset assert Toggle() not in toggleset assert toggleset.is_on() == True assert toggleset.is_off() == False
async def test_dropping_an_unexistent_toggle(fn, expected): toggleset = ToggleSet(fn) toggle = Toggle() await toggleset.drop_toggle(toggle) assert len(toggleset) == 0 assert set(toggleset) == set() assert toggle not in toggleset assert toggleset.is_on() == expected assert toggleset.is_off() == (not expected)
async def test_dropping_multiple_toggles(fn, expected): toggleset = ToggleSet(fn) toggle1 = await toggleset.make_toggle(True) toggle2 = Toggle() await toggleset.drop_toggles([toggle1, toggle2]) assert len(toggleset) == 0 assert set(toggleset) == set() assert toggle1 not in toggleset assert toggle2 not in toggleset assert toggleset.is_on() == expected assert toggleset.is_off() == (not expected)
async def test_created_as_off(): toggle = Toggle() assert not toggle.is_on() assert toggle.is_off()
async def test_turning_off(): toggle = Toggle(True) await toggle.turn_to(False) assert not toggle.is_on() assert toggle.is_off()
async def test_initialised_as_on(): toggle = Toggle(True) assert toggle.is_on() assert not toggle.is_off()
async def test_repr_when_named_and_on(): toggle = Toggle(True, name='xyz') assert toggle.name == 'xyz' assert repr(toggle) == "<Toggle: xyz: on>"
async def test_repr_when_named_and_off(): toggle = Toggle(False, name='xyz') assert toggle.name == 'xyz' assert repr(toggle) == "<Toggle: xyz: off>"
async def test_repr_when_unnamed_and_on(): toggle = Toggle(True) assert toggle.name is None assert repr(toggle) == "<Toggle: on>"
async def test_secures_against_usage_as_a_boolean(): toggle = Toggle() with pytest.raises(NotImplementedError): bool(toggle)
async def test_repr_when_unnamed_and_off(): toggle = Toggle(False) assert toggle.name is None assert repr(toggle) == "<Toggle: off>"
async def test_waiting_until_off_fails_when_not_turned_off(): toggle = Toggle(True) with pytest.raises(asyncio.TimeoutError): await asyncio.wait_for(toggle.wait_for(False), timeout=0.1) assert toggle.is_on()