def test_subscribe_emit_assign(factory): hub = Hub(topic_factory=factory) mock_sink = mock.Mock() mock_sink2 = mock.Mock() disposable = hub['value1'] | op.Sink(mock_sink) mock_sink.assert_not_called() assert len(hub['value1']._subscriptions) == 1 hub['value1'].emit(1) hub['value1'].emit(2) mock_sink.assert_not_called() disposable.dispose() assert len(hub['value1']._subscriptions) == 0 hub['value1'] | op.Sink(mock_sink) hub['value1'] | op.Sink(mock_sink2) value = Value(0) hub['value1'].assign(value) mock_sink.calls(mock.call(0), mock.call(1), mock.call(2))
def test_assign_subscribe_emit(factory): hub = Hub(topic_factory=factory) # assign, subscribe and emit value1 = Value(0) assert not hub['value1'].assigned assert hub['value1'].subject is None hub['value1'].assign(value1) with pytest.raises(ValueError): hub['value1'].assign(value1) assert hub['value1'].path == 'value1' assert hub['value1'].assigned assert 'value1' in hub assert hub['value1'] is not value1 assert hub['value1'].subject is value1 assert len(value1._subscriptions) == 0 assert len(hub['value1']._subscriptions) == 0 value2 = Subject() hub['value2'].assign(value2) mock_sink1 = mock.Mock() mock_sink2 = mock.Mock() dispose_value1 = hub['value1'] | op.Sink(mock_sink1) dispose_value2 = hub['value2'] | op.Sink(mock_sink2) assert len(value1._subscriptions) == 1 assert len(hub['value1']._subscriptions) == 1 mock_sink1.assert_called_once_with(0) assert len(value1._subscriptions) == 1 assert len(hub['value1']._subscriptions) == 1 mock_sink2.assert_not_called() mock_sink1.reset_mock() mock_sink2.reset_mock() hub['value1'].emit(1) hub['value2'].emit(1) mock_sink1.assert_called_once_with(1) mock_sink2.assert_called_once_with(1) assert value1.get() == 1 mock_sink1b = mock.Mock() dispose_value1b = hub['value1'] | op.Sink(mock_sink1b) mock_sink1b.assert_called_once_with(1) dispose_value1.dispose() dispose_value1b.dispose() mock_sink2b = mock.Mock() hub['value2'] | op.Sink(mock_sink2b) mock_sink2b.assert_not_called() assert len(value1._subscriptions) == 0 assert len(hub['value1']._subscriptions) == 0
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()
def test_freeze(): hub = Hub() hub['value1'].assign(StatefulPublisher(0)) assert 'value1' in hub hub.freeze() assert len(tuple(hub)) == 1 hub.freeze(False) hub['value2'] | op.Sink() hub['value3'].emit(1) assert 'value2' in hub assert 'value3' in hub with pytest.raises(ValueError): hub.freeze() hub['value2'].assign(Value(0)) hub['value3'].assign(Value(0)) hub.freeze() with pytest.raises(ValueError): hub['value4'].assign(StatefulPublisher(0)) with pytest.raises(ValueError): hub['value5'] | op.Sink() with pytest.raises(ValueError): hub['value6'].emit(1) assert len(tuple(hub)) == 3 hub.freeze(False) hub['value4'] | op.Sink() hub['value5'].assign(StatefulPublisher(0)) hub['value6'].emit(1) assert 'value4' in hub assert 'value5' in hub assert 'value6' in hub assert len(tuple(hub)) == 6
def test_operator_with_constant_r(): v1 = 1 v2 = Value(0) o = v1 - v2 assert isinstance(o, Publisher) assert o.get() == 1 v2.emit(1) assert o.get() == 0 assert len(o.subscriptions) == 0 mock_sink = mock.Mock() o | op.Sink(mock_sink) assert len(o.subscriptions) == 1 mock_sink.assert_called_once_with(0) mock_sink.reset_mock() v2.emit(3) mock_sink.assert_called_once_with(-2) with pytest.raises(ValueError): Value(1) | o with pytest.raises(ValueError): o.emit_op(0, who=Publisher())
def test_getattr_attribute(): p = StatefulPublisher() class Foo: a = None def __init__(self, a=5): self.a = a p.inherit_type(Foo) dut = p.a m = mock.Mock() dut | op.Sink(m) with pytest.raises(ValueError): dut.get() m.assert_not_called() p.notify(Foo(3)) assert dut.get() == 3 m.assert_called_once_with(3) with pytest.raises(ValueError): dut.emit_op(0, who=Publisher()) with pytest.raises(AttributeError): dut.assnign(5)
def test_operator_with_publishers(): v1 = Value(0) v2 = Value(0) o = v1 + v2 assert isinstance(o, Publisher) assert not isinstance(o, Subscriber) assert o.get() == 0 v1.emit(1) assert o.get() == 1 assert len(o.subscriptions) == 0 mock_sink = mock.Mock() o | op.Sink(mock_sink) assert len(o.subscriptions) == 1 mock_sink.assert_called_once_with(1) mock_sink.reset_mock() v2.emit(3) mock_sink.assert_called_once_with(4) with pytest.raises(ValueError): o.emit_op(0, who=Publisher()) with pytest.raises(AttributeError): Value(1) | o
def test_inherit_with_operators(): p = StatefulPublisher() p.inherit_type(str) dut = op.Len(('abc' + p + 'ghi').upper()) m = mock.Mock() dut | op.Sink(m) p.notify('def') m.assert_called_once_with(9)
def test_inherit_getattr(): p = StatefulPublisher() p.inherit_type(str) dut = p.lower().split(' ') m = mock.Mock() dut | op.Sink(m) p.notify('This is a TEST') m.assert_called_once_with(['this', 'is', 'a', 'test'])
def test_getattr_method(): p = StatefulPublisher() p.inherit_type(str) dut1 = p.split() dut2 = p.split(',') dut3 = p.split(sep='!') mock1 = mock.Mock() mock2 = mock.Mock() mock3 = mock.Mock() dut1 | op.Sink(mock1) dut2 | op.Sink(mock2) dut3 | op.Sink(mock3) with pytest.raises(ValueError): dut1.get() with pytest.raises(ValueError): dut2.get() with pytest.raises(ValueError): dut3.get() mock1.assert_not_called() mock2.assert_not_called() mock3.assert_not_called() p.notify('This is just a test, honestly!') assert dut1.get() == ['This', 'is', 'just', 'a', 'test,', 'honestly!'] assert dut2.get() == ['This is just a test', ' honestly!'] assert dut3.get() == ['This is just a test, honestly', ''] mock1.assert_called_once_with( ['This', 'is', 'just', 'a', 'test,', 'honestly!']) mock2.assert_called_once_with(['This is just a test', ' honestly!']) mock3.assert_called_once_with(['This is just a test, honestly', ''])
def test_type_checks(factory): hub = Hub(topic_factory=factory) # test unassigned topic .get with pytest.raises(ValueError): hub['value1'].get() # test subscribing to a subscriber hub['value2'].assign(op.Sink()) with pytest.raises(TypeError): hub['value2'] | op.Sink() # test emiting to a publisher hub['value3'].assign(Publisher()) with pytest.raises(TypeError): hub['value3'].emit(0) # test assigning of non Publisher or Subscriber with pytest.raises(TypeError): hub['value4'].assign(None)
def test_unary_operators(operator, value, result): v = StatefulPublisher(value) try: value_applied = operator(v).get() except Exception as e: assert isinstance(e, result) else: assert value_applied == result cb = mock.Mock() try: operator(v) | op.Sink(cb) except Exception as e: assert isinstance(e, result) else: assert cb.mock_called_once_with(result) with pytest.raises(ValueError): Value(1) | operator(v) with pytest.raises(ValueError): operator(v).emit_op(0, who=Publisher())
def test_stateful_publisher(): p = StatefulPublisher() v = Value(0) with pytest.raises(ValueError): p.get() mock_sink = mock.Mock() disposable = p | v v | op.Sink(mock_sink) mock_sink.assert_called_once_with(0) mock_sink.reset_mock() p.notify(1) mock_sink.assert_called_once_with(1) assert p.get() == 1 mock_sink.reset_mock() p.notify(1) assert p.get() == 1 mock_sink.assert_not_called() p.notify(2) assert p.get() == 2 mock_sink.assert_called_once_with(2) p.reset_state() with pytest.raises(ValueError): p.get() p.reset_state(3) assert p.get() == 3
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)
import asyncio import subprocess import operator from broqer import op (op.FromPolling(1, subprocess.check_output, 'uptime') | op.Map(str, encoding='utf - 8') | op.Map(str.split, sep=', ') | op.Map(lambda v: v[0]) | op.Sink(print)) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.sleep(10))
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)
def test_with_publisher(operator, l_value, r_value, result): vl = Value(l_value) vr = Value(r_value) pl = Publisher() pr = Publisher() cl = l_value cr = r_value o1 = operator(vl, vr) o2 = operator(vl, cr) o3 = operator(vl, pr) o4 = operator(pl, vr) o5 = operator(pl, cr) o6 = operator(pl, pr) o7 = operator(cl, vr) try: o8 = operator(cl, cr) except Exception as e: assert isinstance(e, result) o8 = result # to pass the following test o9 = operator(cl, pr) mock_sink_o3 = mock.Mock() mock_sink_o4 = mock.Mock() mock_sink_o5 = mock.Mock() mock_sink_o6 = mock.Mock() mock_sink_o9 = mock.Mock() o3 | op.Sink(mock_sink_o3) o4 | op.Sink(mock_sink_o4) o5 | op.Sink(mock_sink_o5) o6 | op.Sink(mock_sink_o6) o9 | op.Sink(mock_sink_o9) for output in (o1, o2, o3, o4, o5, o6, o7, o9): assert isinstance(output, Publisher) assert o8 == result for output in (o1, o2, o7): try: assert output.get() == result except Exception as e: assert isinstance(e, result) for output in (o3, o4, o5, o6, o9): with pytest.raises(ValueError): output.get() mock_sink_o3.assert_not_called() mock_sink_o4.assert_not_called() mock_sink_o5.assert_not_called() mock_sink_o6.assert_not_called() mock_sink_o9.assert_not_called() try: pl.notify(l_value) except Exception as e: assert isinstance(e, result) else: mock_sink_o3.assert_not_called() mock_sink_o4.assert_called_once_with(result) mock_sink_o5.assert_called_once_with(result) mock_sink_o6.assert_not_called() mock_sink_o9.assert_not_called() try: pr.notify(r_value) except Exception as e: assert isinstance(e, result) else: mock_sink_o3.assert_called_once_with(result) mock_sink_o4.assert_called_once_with(result) mock_sink_o5.assert_called_once_with(result) mock_sink_o6.assert_called_once_with(result) mock_sink_o9.assert_called_once_with(result)