예제 #1
0
def test_reset_state():
    """ Test .reset_state() """
    m = mock.Mock()
    p = Publisher()

    p.subscribe(Sink(m, 1))

    m.assert_not_called()

    # test .reset_state() before and after subscribing
    p.reset_state()
    assert p.get() == NONE

    p.subscribe(Sink(m, 2))

    m.assert_not_called()

    m.reset_mock()

    # test .reset_state() after notify
    p.notify('check')
    assert p.get() == 'check'
    m.assert_has_calls([mock.call(1, 'check'), mock.call(2, 'check')])
    m.reset_mock()

    # test no subscribers get notified
    p.reset_state()
    m.assert_not_called()

    assert p.get() == NONE
예제 #2
0
def check_dependencies(operator, *_):
    publishers = operator.dependencies

    for p in publishers:
        assert p.subscriptions == ()  # operator should not be subscribed yet

    assert operator.subscriptions == ()

    # subscribe to operator
    disposable1 = operator.subscribe(Sink())

    assert p.subscriptions == (operator, )  # operator should now be subscriped
    assert operator.subscriptions == (disposable1.subscriber, )

    # second subscribe to operator
    disposable2 = operator.subscribe(Sink(), prepend=True)

    assert p.subscriptions == (operator, )
    assert operator.subscriptions == (disposable2.subscriber,
                                      disposable1.subscriber)

    # remove first subscriber
    disposable1.dispose()

    assert p.subscriptions == (operator, )
    assert operator.subscriptions == (disposable2.subscriber, )

    # remove second subscriber
    disposable2.dispose()

    assert p.subscriptions == ()  # operator should now be subscriped
    assert operator.subscriptions == ()
예제 #3
0
def check_subscription(operator, input_vector, output_vector):
    m = mock.Mock()

    publishers = operator.dependencies

    # subscribe operator to publisher
    disposable = operator.subscribe(Sink(m))

    for p in publishers:
        assert p.subscriptions == (operator, )  # now it should be subscribed

    assert operator.dependencies == publishers

    # test emit on subscription
    if output_vector[0] is not NONE:
        m.assert_called_once_with(output_vector[0])

    m.reset_mock()

    # test input_vector
    for input_value, output_value in zip(input_vector[1:], output_vector[1:]):
        for p, v in zip(publishers, input_value):
            if v is not NONE:
                p.notify(v)

        if output_value is NONE:
            m.assert_not_called()
        else:
            m.assert_called_with(output_value)
        m.reset_mock()

    # test input_vector with unsubscriptions between
    disposable.dispose()

    assert operator.dependencies == publishers

    for p, v in zip(publishers, input_vector[0]):
        p.notify(v)

    disposable = operator.subscribe(Sink(m))

    for input_value, output_value in zip(input_vector, output_vector):
        m.reset_mock()

        for p, v in zip(publishers, input_value):
            if v is not NONE:
                p.notify(v)

        if output_value is NONE:
            m.assert_not_called()
        else:
            m.assert_called_with(output_value)
예제 #4
0
def test_operator_concat():
    DUT = Concat(Map(lambda v: v / 2), Map(lambda v: v + 1))
    mock_cb = mock.Mock()

    p = Publisher()

    o = p | DUT
    assert o.get() == NONE

    p.notify(0)
    assert o.get() == 1.0

    o.subscribe(Sink(mock_cb))

    for v in range(5):
        p.notify(v)

    mock_cb.assert_has_calls([
        mock.call(1.0),
        mock.call(1.5),
        mock.call(2.0),
        mock.call(2.5),
        mock.call(3.0)
    ])

    assert o.get() == 3.0
def test_emit_on(factory, flags):
    m = mock.Mock()

    publishers = [Publisher(None) for i in range(3)]

    emit_on = [p for p, f in zip(publishers, flags) if f]
    if len(emit_on) == 0:
        emit_on = None
    elif len(emit_on) == 1:
        emit_on = emit_on[0]

    operator = factory(*publishers, emit_on=emit_on)
    operator.subscribe(Sink(m))

    result = [None] * 3

    if flags.count(True) == 0:
        flags = [True] * 3

    for i, f in enumerate(flags):
        m.reset_mock()

        result[i] = i

        publishers[i].notify(i)

        if f:
            m.assert_called_once_with(tuple(result))
        else:
            m.assert_not_called()
def test_with_publisher(operator, l_value, r_value, result):
    vl = Value(l_value)
    vr = Value(r_value)
    cl = l_value
    cr = r_value

    o1 = operator(vl, vr)
    o2 = operator(vl, cr)
    o3 = operator(cl, vr)
    try:
        o4 = operator(cl, cr)
    except Exception as e:
        assert isinstance(e, result)
        o4 = result  # to pass the following test

    mock_sink_o3 = mock.Mock()

    try:
        o3.subscribe(Sink(mock_sink_o3))
    except Exception as e:
        assert isinstance(e, result)

    for output in (o1, o2, o3):
        assert isinstance(output, Publisher)

    assert o4 == result

    for output in (o1, o2, o3):
        try:
            assert output.get() == result
        except Exception as e:
            assert isinstance(e, result)
예제 #7
0
def test_notify(init, number_of_subscribers):
    """ Testing .notify(v) method """
    p = Publisher(init)
    m = mock.Mock()

    # subscribing Sinks to the publisher and test .notify on subscribe
    subscribers = [Sink(m, i) for i in range(number_of_subscribers)]

    m.assert_not_called()

    for s in subscribers:
        p.subscribe(s)

    if init is not NONE:
        m.assert_has_calls([mock.call(i, init) for i in range(number_of_subscribers)])
    else:
        m.assert_not_called()

    m.reset_mock()

    # test .notify() for listening subscribers
    p.notify(1)

    m.assert_has_calls([mock.call(i, 1) for i in range(number_of_subscribers)])

    m.reset_mock()

    # re- .notify() with the same value
    p.notify(1)

    m.assert_has_calls([mock.call(i, 1) for i in range(number_of_subscribers)])
예제 #8
0
async def test_throttle_reset(event_loop):
    p = Publisher()
    mock_sink = mock.Mock()

    throttle = p | op.Throttle(0.1)
    disposable = throttle.subscribe(Sink(mock_sink))

    p.notify(1)
    await asyncio.sleep(0.05, loop=event_loop)
    throttle.reset()
    p.notify(3)

    await asyncio.sleep(0.05, loop=event_loop)

    # reset is called after "1" was emitted
    mock_sink.assert_has_calls((mock.call(1), mock.call(3)))

    ## wait until initial state is set and reset mock
    await asyncio.sleep(0.1, loop=event_loop)
    mock_sink.reset_mock()

    p.notify(1)
    await asyncio.sleep(0.05, loop=event_loop)
    p.notify(2)
    throttle.reset()
    p.notify(3)

    await asyncio.sleep(0.05, loop=event_loop)

    # reset is called after "1" was emitted, and while "2" was hold back,
    #   therefore "1" and "3" are emitted, but "2" is ignored
    mock_sink.assert_has_calls((mock.call(1), mock.call(3)))

    disposable.dispose()
예제 #9
0
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()
예제 #10
0
async def test_throttle_unsubscribe(event_loop):
    p = Publisher()
    mock_sink = mock.Mock()

    throttle = p | op.Throttle(0.1)
    disposable = throttle.subscribe(Sink(mock_sink))

    # test subscription and unsubscribe
    p.notify(2)
    mock_sink.assert_called_once_with(2)

    await asyncio.sleep(0.05, loop=event_loop)
    mock_sink.reset_mock()

    disposable.dispose()
    await asyncio.sleep(0.1, loop=event_loop)

    # dispose must not emit anything
    mock_sink.assert_not_called()

    p.notify(3)

    await asyncio.sleep(0.1, loop=event_loop)

    # after dispose was called, p.notify must not emit to mock_sink
    mock_sink.assert_not_called()
def test_operator_with_publishers():
    v1 = Value(0)
    v2 = Value(0)

    o = v1 + v2

    assert isinstance(o, Publisher)
    assert isinstance(o, Subscriber)
    assert o.get() == 0

    v1.emit(1)
    assert o.get() == 1

    assert len(o.subscriptions) == 0

    mock_sink = mock.Mock()

    o.subscribe(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(0, who=Publisher())

    with pytest.raises(ValueError):
        Value(1).subscribe(o)
예제 #12
0
def test_build(build_kwargs, init_args, init_kwargs, ref_args, ref_kwargs,
               exception):
    mock_cb = mock.Mock()
    ref_mock_cb = mock.Mock()

    reference = Sink(ref_mock_cb, *ref_args, **ref_kwargs)

    try:
        if build_kwargs is None:
            dut = build_sink_factory(mock_cb)(*init_args, **init_kwargs)
        else:
            dut = build_sink_factory(**build_kwargs)(mock_cb)(*init_args,
                                                              **init_kwargs)
    except Exception as e:
        assert isinstance(e, exception)
        return
    else:
        assert exception is None

    assert dut._unpack == reference._unpack

    v = Publisher((1, 2))
    v.subscribe(dut)
    v.subscribe(reference)

    assert mock_cb.mock_calls == ref_mock_cb.mock_calls
    assert len(mock_cb.mock_calls) == 1
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.subscribe(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(TypeError):
        Value(1) | o

    with pytest.raises(ValueError):
        o.emit(0, who=Publisher())
def test_getattr_attribute():
    class Foo:
        a = None

        def __init__(self, a=5):
            self.a = a

    p = Publisher(Foo(3))
    p.inherit_type(Foo)

    dut = p.a
    m = mock.Mock()
    dut.subscribe(Sink(m))

    m.assert_called_once_with(3)
    assert dut.get() == 3
    m.reset_mock()

    p.notify(Foo(4))

    assert dut.get() == 4

    m.assert_called_once_with(4)

    with pytest.raises(ValueError):
        dut.emit(0, who=Publisher())

    with pytest.raises(AttributeError):
        dut.assnign(5)
예제 #15
0
def check_get_method(operator, input_vector, output_vector):
    input_value, output_value = input_vector[0], output_vector[0]

    p = Publisher()
    p.get = mock.MagicMock(return_value=input_value)
    o = p | operator

    with pytest.raises(ValueError):
        o.emit(input_value, who=None)

    assert o.get() == output_value

    disposable = o.subscribe(Sink())

    if input_value is not NONE:
        o.emit(input_value, who=p)  # simulate emit on subscribe

    p.get = None  # .get should not be called when operator has a subscription

    assert o.get() == output_value  # this should retrieve the internal state

    # after unsubscription it should remove the internal state and retrieve it
    # directly from orignator publisher via get
    disposable.dispose()

    p.get = mock.MagicMock(return_value=input_value)

    assert o.get() == output_value

    p.get.assert_called_once_with()
예제 #16
0
def check_subscription(operator, input_vector, output_vector):
    assert len(input_vector) == len(output_vector)

    m = mock.Mock()

    p = Publisher(input_vector[0])
    o = p | operator

    o2 = Publisher() | operator

    # subscribe operator to publisher
    disposable = o.subscribe(Sink(m))

    assert p.subscriptions == (o,)  # now it should be subscribed
    assert o.dependencies == (p,)

    # test emit on subscription
    if output_vector[0] is not NONE:
        m.assert_called_once_with(output_vector[0])

    m.reset_mock()

    # test input_vector
    for input_value, output_value in zip(input_vector[1:], output_vector[1:]):
        if input_value is not NONE:
            p.notify(input_value)

        if output_value is NONE:
            m.assert_not_called()
        else:
            m.assert_called_with(output_value)
        m.reset_mock()

    # test input_vector with unsubscriptions between
    disposable.dispose()
    assert o.dependencies == (p,)
    disposable = o.subscribe(Sink(m))

    for input_value, output_value in zip(input_vector, output_vector):
        if input_value is not NONE:
            m.reset_mock()
            p.notify(input_value)
            if output_value is NONE:
                m.assert_not_called()
            else:
                m.assert_called_once_with(output_value)
예제 #17
0
def test_prepend():
    """ Testing the prepend argument in .subscribe() """
    m = mock.Mock()
    p = Publisher()

    s1 = Sink(m, 1)
    s2 = Sink(m, 2)
    s3 = Sink(m, 3)
    s4 = Sink(m, 4)

    p.subscribe(s1)
    p.subscribe(s2, prepend=True)  # will be inserted before s1
    p.subscribe(s3)  # will be appended after s1
    p.subscribe(s4, prepend=True)  # will be inserted even before s2

    p.notify('test')

    # notification order should now be: s4, s2, s1, s3
    m.assert_has_calls([mock.call(4, 'test'), mock.call(2, 'test'), mock.call(1, 'test'), mock.call(3, 'test')])
def test_inherit_with_operators():
    p = Publisher('')
    p.inherit_type(str)

    dut = op.Len(('abc' + p + 'ghi').upper())
    m = mock.Mock()
    dut.subscribe(Sink(m))
    m.assert_called_once_with(6)
    m.reset_mock()

    p.notify('def')
    m.assert_called_once_with(9)
def test_inherit_getattr():
    p = Publisher('')
    p.inherit_type(str)

    dut = p.lower().split(' ')
    m = mock.Mock()
    dut.subscribe(Sink(m))
    m.assert_called_once_with([''])
    m.reset_mock()

    p.notify('This is a TEST')
    m.assert_called_once_with(['this', 'is', 'a', 'test'])
예제 #20
0
def check_dependencies(operator, *_):
    p = Publisher(NONE)

    assert len(p.subscriptions) == 0

    o = p | operator

    assert p.subscriptions == ()  # operator should not be subscribed yet
    assert o.dependencies == (p,)
    assert o.subscriptions == ()

    # subscribe to operator
    disposable1 = o.subscribe(Sink())

    assert p.subscriptions == (o,)  # operator should now be subscriped
    assert o.dependencies == (p,)
    assert o.subscriptions == (disposable1.subscriber,)

    # second subscribe to operator
    disposable2 = o.subscribe(Sink(), prepend=True)

    assert p.subscriptions == (o,)
    assert o.dependencies == (p,)
    assert o.subscriptions == (disposable2.subscriber, disposable1.subscriber)

    # remove first subscriber
    disposable1.dispose()

    assert p.subscriptions == (o,)
    assert o.dependencies == (p,)
    assert o.subscriptions == (disposable2.subscriber,)

    # remove second subscriber
    disposable2.dispose()

    assert p.subscriptions == ()  # operator should now be subscriped
    assert o.dependencies == (p,)
    assert o.subscriptions == ()
def test_getattr_method():
    p = Publisher('')
    p.inherit_type(str)

    dut1 = p.split()
    dut2 = p.split(',')
    dut3 = p.split(sep='!')

    mock1 = mock.Mock()
    mock2 = mock.Mock()
    mock3 = mock.Mock()

    dut1.subscribe(Sink(mock1))
    dut2.subscribe(Sink(mock2))
    dut3.subscribe(Sink(mock3))

    assert dut1.get() == []
    assert dut2.get() == ['']
    assert dut3.get() == ['']

    mock1.assert_called_once_with([])
    mock2.assert_called_once_with([''])
    mock3.assert_called_once_with([''])

    mock1.reset_mock()
    mock2.reset_mock()
    mock3.reset_mock()

    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', ''])
예제 #22
0
def test_subscription_callback():
    """ testing .register_on_subscription_callback() """
    m = mock.Mock()

    p = Publisher()
    p.register_on_subscription_callback(m)

    # callback should be called on first subscription (with True as argument)
    d1 = p.subscribe(Sink())
    m.assert_called_once_with(True)
    m.reset_mock()

    # it should not be called until the last subscriber is unsubscribing
    d2 = p.subscribe(Sink())
    d1.dispose()

    m.assert_not_called()

    # callback should be called with False as argument on last unsubscription
    d2.dispose()
    m.assert_called_once_with(False)
    m.reset_mock()

    # callback should again be called with True as argument on first subscription
    d3 = p.subscribe(Sink())
    m.assert_called_once_with(True)
    m.reset_mock()

    # after reseting callback it should no be called again
    p.register_on_subscription_callback(None)
    d3.dispose()
    p.subscribe(Sink())
    m.assert_not_called()

    # check if callback is called when subscriber is already available
    p.register_on_subscription_callback(m)
    m.assert_called_once_with(True)
예제 #23
0
async def test_throttle(event_loop, emit_sequence, expected_emits):
    p = Publisher()
    mock_sink = mock.Mock()

    throttle = p | op.Throttle(0.5)
    disposable = throttle.subscribe(Sink(mock_sink))

    mock_sink.assert_not_called()

    for item in emit_sequence:
        await asyncio.sleep(item[0], loop=event_loop)
        p.notify(item[1])

    await asyncio.sleep(0.5, loop=event_loop)

    mock_sink.assert_has_calls(expected_emits)
예제 #24
0
async def test_subscribe(event_loop):
    poll_mock = mock.Mock(return_value=3)
    sink_mock = mock.Mock()

    p = PollPublisher(poll_mock, 1)

    await asyncio.sleep(1, loop=event_loop)
    assert p.get() is NONE

    p.subscribe(Sink(sink_mock))
    sink_mock.assert_called_once_with(3)
    poll_mock.assert_called_once()

    await asyncio.sleep(2.5, loop=event_loop)
    sink_mock.assert_called_with(3)
    assert sink_mock.call_count == 3
def test_unsubscibe(subscribe):
    m = mock.Mock()

    p1, p2 = Publisher(NONE), Publisher(NONE)

    operator = op.CombineLatest(p1, p2)

    if subscribe:
        operator.subscribe(Sink())

    assert operator.get() == NONE

    p1.notify(1)
    assert operator.get() == NONE

    p2.notify(2)
    assert operator.get() == (1, 2)
def test_unary_operators(operator, value, result):
    v = Publisher(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).subscribe(Sink(cb))
    except Exception as e:
        assert isinstance(e, result)
    else:
        assert cb.mock_called_once_with(result)

    with pytest.raises(TypeError):
        Value(1) | operator(v)

    with pytest.raises(ValueError):
        operator(v).emit(0, who=Publisher())
예제 #27
0
def check_get_method(operator, input_vector, output_vector):
    input_value, output_value = input_vector[0], output_vector[0]

    publishers = operator.dependencies

    for p, v in zip(publishers, input_value):
        p.get = mock.MagicMock(return_value=v)

    with pytest.raises(ValueError):
        operator.emit(input_value[0], who=None)

    assert operator.get() == output_value

    disposable = operator.subscribe(Sink())

    for p, v in zip(publishers, input_value):
        if v is not NONE:
            operator.emit(v, who=p)  # simulate emit on subscribe

    for p, v in zip(publishers, input_value):
        p.get = None  # .get should not be called when operator has a subscription

    assert operator.get(
    ) == output_value  # this should retrieve the internal state

    # after unsubscription it should remove the internal state and retrieve it
    # directly from orignator publisher via get
    disposable.dispose()

    for p, v in zip(publishers, input_value):
        p.get = mock.MagicMock(return_value=v)

    assert operator.get() == output_value

    for p in publishers:
        p.get.assert_called_once_with()
예제 #28
0
def test_bitwise_uninitialized_publishers():
    m = Mock()
    p = Publisher()
    b = BitwiseCombineLatest({p: 0})
    b.subscribe(Sink(m))
    m.assert_called_once_with(0)