async def test_throttle_errorhandler(event_loop): from broqer import default_error_handler p = Publisher() mock_sink = mock.Mock() mock_error_handler = mock.Mock() default_error_handler.set(mock_error_handler) throttle = p | op.Throttle(0.1) disposable = throttle.subscribe(Sink(mock_sink)) mock_sink.side_effect = (None, ZeroDivisionError('FAIL')) # test error_handler p.notify(1) await asyncio.sleep(0.05, loop=event_loop) mock_sink.assert_called_once_with(1) p.notify(2) await asyncio.sleep(0.1, loop=event_loop) mock_error_handler.assert_called_once_with(ZeroDivisionError, mock.ANY, mock.ANY) mock_sink.assert_has_calls((mock.call(1), mock.call(2))) mock_sink.reset_mock()
async def test_errorhandler(operator_cls, publisher, args, capsys): mock = Mock(side_effect=ZeroDivisionError) # test default error handler if publisher is not None: dut = publisher | operator_cls(*args) else: dut = operator_cls(*args) dut | op.Sink(mock) await asyncio.sleep(0.1) captured = capsys.readouterr() assert 'Traceback' in captured.err assert 'ZeroDivisionError' in captured.err # test custom default error handler mock_errorhandler = Mock() default_error_handler.set(mock_errorhandler) if publisher is not None: dut = publisher | operator_cls(*args) else: dut = operator_cls(*args) dut | op.Sink(mock) await asyncio.sleep(0.1) mock_errorhandler.assert_called_with(ZeroDivisionError, ANY, ANY) default_error_handler.reset() # test custom error handler mock_errorhandler_custom = Mock() if publisher is not None: dut = publisher | operator_cls(*args, error_callback=mock_errorhandler_custom) else: dut = operator_cls(*args, error_callback=mock_errorhandler_custom) dut | op.Sink(mock) await asyncio.sleep(0.1) mock_errorhandler_custom.assert_called_with(ZeroDivisionError, ANY, ANY) default_error_handler.reset()
async def test_sink_async(): p = Publisher() mock_error_handler = mock.Mock() default_error_handler.set(mock_error_handler) # test error_handler for map coroutine async def _fail(v): raise ValueError() p2 = Publisher() disposable = p2 | SinkAsync(_fail) p2.notify(2) await asyncio.sleep(0.01) print(mock_error_handler.mock_calls) mock_error_handler.assert_called_once_with(ValueError, mock.ANY, mock.ANY)
async def test_map_async(): p = Publisher() mock_sink = mock.Mock() mock_error_handler = mock.Mock() default_error_handler.set(mock_error_handler) async def _map(v): return v disposable = p | MapAsync(_map) | Sink(mock_sink) mock_sink.side_effect = ZeroDivisionError('FAIL') # test error_handler for notify p.notify(1) mock_error_handler.assert_not_called() await asyncio.sleep(0.01) mock_error_handler.assert_called_once_with(ZeroDivisionError, mock.ANY, mock.ANY) disposable.dispose() mock_error_handler.reset_mock() mock_sink.reset_mock() mock_sink.side_effect = None # test error_handler for map coroutine async def _fail(v): raise ValueError() p2 = Publisher() disposable = p2 | MapAsync(_fail) | Sink(mock_sink) p2.notify(2) await asyncio.sleep(0.01) print(mock_error_handler.mock_calls) mock_error_handler.assert_called_once_with(ValueError, mock.ANY, mock.ANY) mock_sink.assert_not_called()
async def test_throttle(): import asyncio from broqer import default_error_handler, Publisher, op p = Publisher() mock_sink = mock.Mock() mock_error_handler = mock.Mock() default_error_handler.set(mock_error_handler) disposable = p | op.Throttle(0.1) | op.Sink(mock_sink) mock_sink.side_effect = (None, ZeroDivisionError('FAIL')) # test error_handler p.notify(1) await asyncio.sleep(0.05) mock_sink.assert_called_once_with(1) p.notify(2) await asyncio.sleep(0.1) mock_error_handler.assert_called_once_with(ZeroDivisionError, mock.ANY, mock.ANY) mock_sink.reset_mock() # test unsubscribe p.notify(2) mock_sink.reset_mock() await asyncio.sleep(0.05) disposable.dispose() await asyncio.sleep(0.1) mock_sink.assert_called_once_with(2) # test reset mock_sink.reset_mock() mock_sink.side_effect = None throttle = p | op.Throttle(0.1) disposable = throttle | op.Sink(mock_sink) p.notify(1) mock_sink.reset_mock() await asyncio.sleep(0.05) throttle.reset() p.notify(2) await asyncio.sleep(0.05) mock_sink.assert_called_once_with(2) disposable.dispose() # test reset again mock_sink.reset_mock() mock_sink.side_effect = None throttle = p | op.Throttle(0.1) disposable = throttle | op.Sink(mock_sink) # resubscribe mock_sink.reset_mock() p.notify(1) await asyncio.sleep(0.05) mock_sink.assert_called_once_with(1) disposable.dispose() throttle | op.Sink() p.notify(2) await asyncio.sleep(0.05) p.notify(3) with pytest.raises(ValueError): throttle.get() assert await throttle == 3 mock_sink.assert_called_once_with(1) # reset when nothing is to be emitted disposable = throttle | op.Sink(mock_sink) mock_sink.reset_mock() await asyncio.sleep(0.15) throttle.reset() p.notify(4) mock_sink.assert_called_once_with(4)
async def test_debounce(): import asyncio from broqer import default_error_handler, Publisher, op p = Publisher() mock_sink = mock.Mock() mock_error_handler = mock.Mock() default_error_handler.set(mock_error_handler) disposable = p | op.Debounce(0.1) | op.Sink(mock_sink) mock_sink.side_effect = ZeroDivisionError('FAIL') # test error_handler p.notify(1) mock_error_handler.assert_not_called() await asyncio.sleep(0.05) mock_error_handler.assert_not_called() await asyncio.sleep(0.1) mock_error_handler.assert_called_once_with(ZeroDivisionError, mock.ANY, mock.ANY) mock_sink.assert_called_once_with(1) mock_sink.reset_mock() # test unsubscribe p.notify(2) await asyncio.sleep(0.05) disposable.dispose() await asyncio.sleep(0.1) mock_sink.assert_not_called() # test reset mock_sink.reset_mock() debounce = p | op.Debounce(0.1) disposable = debounce | op.Sink(mock_sink) p.notify(1) await asyncio.sleep(0.05) debounce.reset() await asyncio.sleep(0.1) mock_sink.assert_not_called() disposable.dispose() # test reset again mock_sink.reset_mock() mock_sink.side_effect = None debounce = p | op.Debounce(0, False) disposable = debounce | op.Sink(mock_sink) p.notify(True) await asyncio.sleep(0.05) debounce.reset() mock_sink.assert_has_calls( (mock.call(False), mock.call(True), mock.call(False))) # resubscribe mock_sink.reset_mock() p.notify(True) await asyncio.sleep(0.05) mock_sink.assert_called_once_with(True) disposable.dispose() debounce | op.Sink() p.notify(True) await asyncio.sleep(0.05) assert debounce.get() == True await debounce | op.True_() mock_sink.assert_called_once_with(True) # test argument check with pytest.raises(ValueError): op.Debounce(-1)