def test_build(build_kwargs, ref_kwargs, exception): mock_cb = mock.Mock() ref_mock_cb = mock.Mock() publishers = (StatefulPublisher(0), StatefulPublisher(1), Publisher()) try: if build_kwargs is None: dut = build_combine_latest(mock_cb)(*publishers) else: dut = build_combine_latest(**build_kwargs)(mock_cb)(*publishers) except Exception as e: assert isinstance(e, exception) return else: assert exception is None reference = CombineLatest(*publishers, map_=ref_mock_cb, **ref_kwargs) assert dut._partial_state == reference._partial_state assert dut._missing == reference._missing assert dut._stateless == reference._stateless assert dut._index == reference._index assert dut._emit_on == reference._emit_on assert mock_cb.mock_calls == ref_mock_cb.mock_calls
def test_stateful_publisher(): p = StatefulPublisher(1) future = p | OnEmitFuture(timeout=1, loop=asyncio.get_event_loop()) assert future.result() == 1 p.notify(2) assert future.result() == 1
def test_getattr_without_inherit(): p = StatefulPublisher() class Foo: a = None def __init__(self, a=5): self.a = a with pytest.raises(AttributeError): dut = p.a with pytest.raises(AttributeError): p.assnign(5)
def test_stateless_map(): source1 = StatefulPublisher(0) source2 = Publisher() dut = CombineLatest(source1, source2, map_=lambda a, b: a + (0 if b is NONE else b), allow_stateless=True) collector = Collector() dut.subscribe(collector) with pytest.raises(ValueError): dut.get() assert collector.result_vector == () collector.reset() source1.notify(1) assert collector.result_vector == (1, ) source1.notify(1) assert collector.result_vector == (1, ) source1.notify(1.0) assert collector.result_vector == (1, ) source2.notify(0) assert collector.result_vector == (1, 1) source2.notify(1) assert collector.result_vector == (1, 1, 2) source2.notify(1) assert collector.result_vector == (1, 1, 2, 2)
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_build(build_kwargs, init_args, init_kwargs, ref_args, ref_kwargs, exception): mock_cb = mock.Mock() ref_mock_cb = mock.Mock() try: if build_kwargs is None: dut = build_filter(mock_cb)(*init_args, **init_kwargs) else: dut = build_filter(**build_kwargs)(mock_cb)(*init_args, **init_kwargs) except Exception as e: assert isinstance(e, exception) return else: assert exception is None reference = Filter(ref_mock_cb, *ref_args, **ref_kwargs) assert dut._unpack == reference._unpack v = StatefulPublisher((1, 2)) v | dut | Sink() v | reference | Sink() assert mock_cb.mock_calls == ref_mock_cb.mock_calls assert len(mock_cb.mock_calls) == 1
def test_build(build_kwargs, init_args, init_kwargs, ref_args, ref_kwargs, exception): mock_cb = mock.Mock(return_value=(0,0)) ref_mock_cb = mock.Mock(return_value=(0,0)) try: if build_kwargs is None: dut = build_reduce(mock_cb)(*init_args, **init_kwargs) else: dut = build_reduce(**build_kwargs)(mock_cb)(*init_args, **init_kwargs) except Exception as e: assert isinstance(e, exception) return else: assert exception is None reference = Reduce(ref_mock_cb, *ref_args, **ref_kwargs) assert dut._init == reference._init assert dut._state == reference._state assert dut._result == reference._result v = StatefulPublisher(1) v | dut | Sink() v | reference | Sink() assert mock_cb.mock_calls == ref_mock_cb.mock_calls assert len(mock_cb.mock_calls) == 1
def test_build(build_kwargs, init_args, init_kwargs, ref_args, ref_kwargs, exception): mock_cb = mock.Mock() ref_mock_cb = mock.Mock() async def mock_cb_coro(*args, **kwargs): mock_cb(*args, **kwargs) async def ref_mock_cb_coro(*args, **kwargs): ref_mock_cb(*args, **kwargs) try: if build_kwargs is None: dut = build_sink_async(mock_cb_coro)(*init_args, **init_kwargs) else: dut = build_sink_async(**build_kwargs)(mock_cb_coro)(*init_args, **init_kwargs) except Exception as e: assert isinstance(e, exception) return else: assert exception is None reference = SinkAsync(ref_mock_cb_coro, *ref_args, **ref_kwargs) assert dut._map_async._options[1:] == reference._map_async._options[ 1:] # don't compare coro v = StatefulPublisher((1, 2)) v | dut v | reference asyncio.get_event_loop().run_until_complete(asyncio.sleep(0.01)) assert mock_cb.mock_calls == ref_mock_cb.mock_calls assert len(mock_cb.mock_calls) == 1
def test_build(build_kwargs, init_args, init_kwargs, ref_args, ref_kwargs, exception): mock_cb = mock.Mock() ref_mock_cb = mock.Mock() try: if build_kwargs is None: dut = build_map_threaded(mock_cb)(*init_args, **init_kwargs) else: dut = build_map_threaded(**build_kwargs)(mock_cb)(*init_args, **init_kwargs) except Exception as e: assert isinstance(e, exception) return else: assert exception is None reference = MapThreaded(ref_mock_cb, *ref_args, **ref_kwargs) assert dut._options[1:] == reference._options[1:] # don't compare coro v = StatefulPublisher((1, 2)) v | dut | Sink() v | reference | Sink() asyncio.get_event_loop().run_until_complete(asyncio.sleep(0.01)) assert mock_cb.mock_calls == ref_mock_cb.mock_calls assert len(mock_cb.mock_calls) == 1
def test_allow_stateless_extensive(): source1 = StatefulPublisher(0) source2 = Publisher() source3 = StatefulPublisher(0) source4 = Publisher() dut = CombineLatest(source1, source2, source3, source4, allow_stateless=True, emit_on=(source2, source3)) with pytest.raises(ValueError): dut | Sink() # source4 is stateless but not in emit_on list def reverse(s1, s2, s3, s4): return (s4, s3, s2, s1) dut = CombineLatest(source1, source2, source3, source4, map_=reverse, allow_stateless=True, emit_on=(source2, source3, source4)) with pytest.raises(ValueError): dut.get() collector = Collector() dut.subscribe(collector) with pytest.raises(ValueError): dut.get() assert collector.result_vector == () collector.reset() source1.notify(1) source2.notify(2) with pytest.raises(ValueError): dut.get() assert collector.result_vector == ((NONE, 0, 2, 1), ) collector.reset() source3.notify(3) source4.notify(4) with pytest.raises(ValueError): dut.get() assert collector.result_vector == ( (NONE, 3, NONE, 1), (4, 3, NONE, 1), )
def test_allow_stateless_with_stateful_publishers(): source1 = StatefulPublisher(0) source2 = StatefulPublisher(0) dut = CombineLatest(source1, source2, allow_stateless=True) collector = Collector() dut.subscribe(collector) source1.notify(1) source2.notify(1) assert collector.result_vector == ((0, 0), (1, 0), (1, 1))
def test_mod_str(): v1 = StatefulPublisher('%.2f %d') v2 = Value((0, 0)) o = v1 % v2 assert isinstance(o, Publisher) assert o.get() == '0.00 0' v2.emit((1, 3)) assert o.get() == '1.00 3'
def test_concat(): v1 = StatefulPublisher((1, 2)) v2 = Value((0, 0)) o = v1 + v2 assert isinstance(o, Publisher) assert o.get() == (1, 2, 0, 0) v2.emit((1, 3)) assert o.get() == (1, 2, 1, 3)
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_subscribe_all(subscribe_all): p_select = StatefulPublisher('a') p1 = StatefulPublisher(0) p2 = StatefulPublisher(1) dut = Switch({'a': p1, 'b': p2, 'c': 2}, subscribe_all=subscribe_all) assert not p_select.subscriptions assert not p1.subscriptions assert not p2.subscriptions assert not dut.subscriptions mock_cb = mock.Mock() disposable = p_select | dut | Sink(mock_cb) assert len(dut.subscriptions) == 1 assert len(p_select.subscriptions) == 1 assert len(p1.subscriptions) == 1 assert len(p2.subscriptions) == (1 if subscribe_all else 0) p_select.notify('b') assert len(dut.subscriptions) == 1 assert len(p_select.subscriptions) == 1 assert len(p1.subscriptions) == (1 if subscribe_all else 0) assert len(p2.subscriptions) == 1 disposable.dispose() assert not p_select.subscriptions assert not p1.subscriptions assert not p2.subscriptions assert not dut.subscriptions
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_allow_stateless(): source1 = StatefulPublisher(0) source2 = Publisher() dut = CombineLatest(source1, source2, allow_stateless=True) with pytest.raises(ValueError): dut.get() collector = Collector() disposable = dut.subscribe(collector) with pytest.raises(ValueError): dut.get() assert collector.result_vector == () source1.notify(1) source2.notify(True) source1.notify(2) source2.notify(False) assert collector.result_vector == ((1, NONE), (1, True), (2, NONE), (2, False)) # combine latest should also emit when stateless publisher is emitting collector.reset() source2.notify(False) assert collector.result_vector == ((2, False), ) source2.notify(False) assert collector.result_vector == ((2, False), (2, False)) source1.notify(0) assert collector.result_vector == ((2, False), (2, False), (0, NONE)) disposable.dispose() assert len(dut.subscriptions) == 0 source3 = StatefulPublisher(0) dut2 = CombineLatest(dut, source3) with pytest.raises(ValueError): dut2.get()
def test_operator_concat(): DUT = OperatorConcat(Map(lambda v: v / 2), Reduce(lambda s, v: s + v, init=0)) mock_cb = mock.Mock() p = StatefulPublisher(0) p | DUT assert DUT.get() == 0 DUT | Sink(mock_cb) for v in range(5): p.notify(v) mock_cb.assert_has_calls([ mock.call(0), mock.call(0.5), mock.call(1.5), mock.call(3), mock.call(5) ]) assert DUT.get() == 5
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_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_uninitialised_with_stateful(): source = StatefulPublisher(1) dut = source | Cache() cb = mock.Mock() dut | Sink(cb) cb.assert_called_once_with(1) source.notify(1) cb.assert_called_once_with(1) cb.reset_mock() source.notify(2) cb.assert_called_once_with(2)
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
import pytest from unittest import mock from broqer import StatefulPublisher, NONE from broqer.op import Switch, Sink from .helper import check_single_operator @pytest.mark.parametrize('mapping, kwargs, input_vector, output_vector', [ ({ 0: StatefulPublisher('a'), 1: StatefulPublisher('b'), 2: StatefulPublisher('c') }, {}, (0, 1, 2, 2, 1, 3), ('a', 'b', 'c', NONE, 'b', ValueError)), ({ 'a': 0, 'b': StatefulPublisher(1) }, { 'default': 2 }, ('a', 'b', 'a', 'b', 'c', 'a', 'a', 'b'), (0, 1, 0, 1, 2, 0, NONE, 1)), (['No', 'Yes'], { 'default': 'Unknown' }, (False, True, 1, -1, -5, True, 5.8), ('No', 'Yes', NONE, NONE, 'Unknown', 'Yes', 'Unknown')), (['No', 'Yes'], { 'default': 'Unknown' }, (4, 0), ('Unknown', 'No')), (['No', 'Yes'], {}, (0, 4, 1), ('No', ValueError, 'Yes')), ]) def test_with_publisher(mapping, kwargs, input_vector, output_vector):
def __init__(self, init): StatefulPublisher.__init__(self, init) Subscriber.__init__(self)
@pytest.yield_fixture() def event_loop(): loop = VirtualTimeEventLoop() yield loop loop.close() async def _foo_coro(v): return v @pytest.mark.parametrize( 'operator_cls, publisher, args', [ (op.Debounce, StatefulPublisher(True), (0, )), (op.Delay, StatefulPublisher(True), (0, )), (op.MapAsync, StatefulPublisher(True), (_foo_coro, )), # (op.MapThreaded, (StatefulPublisher(True), lambda v:None)), # run_in_executor is not implemented in VirtualTimeEventLoop (op.FromPolling, None, (0.1, lambda: None)), (op.Sample, StatefulPublisher(True), (0.1, )), (op.Throttle, StatefulPublisher(True), (0.1, )), ]) @pytest.mark.asyncio 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:
def test_multi_operators(operator, values, result): sources = [StatefulPublisher(v) for v in values] dut = operator(*sources) assert dut.get() == result