Exemple #1
0
def test_value_dict_persistent():
    a = Value("a")
    b = Value("b")
    c = Value("c")

    dct = value_dict({"a": a, "b": b, "c": c})

    # Initial value should have passed through
    assert dct.value == {"a": "a", "b": "b", "c": "c"}

    m = Mock()
    dct.on_value_changed(m)

    # Changes should propagate through
    a.value = "A"
    assert dct.value == {"a": "A", "b": "b", "c": "c"}
    m.assert_called_once_with({"a": "A", "b": "b", "c": "c"})

    m.reset_mock()
    b.value = "B"
    assert dct.value == {"a": "A", "b": "B", "c": "c"}
    m.assert_called_once_with({"a": "A", "b": "B", "c": "c"})

    m.reset_mock()
    c.value = "C"
    assert dct.value == {"a": "A", "b": "B", "c": "C"}
    m.assert_called_once_with({"a": "A", "b": "B", "c": "C"})
Exemple #2
0
def test_positional_kwargs():
    m = Mock()
    
    @fn
    def example(a, b):
        return a - b
    
    a_value = Value(10)
    b_value = Value(5)
    
    # Initial value should pass through
    result = example(a=a_value, b=b_value)
    result.on_value_changed(m)
    assert result.value == 5
    
    # Changes should propagate, callbacks should fire
    m.reset_mock()
    a_value.value = 20
    m.assert_called_once_with(15)
    assert result.value == 15
    
    m.reset_mock()
    b_value.value = -5
    m.assert_called_once_with(25)
    assert result.value == 25
Exemple #3
0
def test_value_tuple_persistent():
    a = Value("a")
    b = Value("b")
    c = Value("c")

    tup = value_tuple((a, b, c))

    # Initial value should have passed through
    assert tup.value == ("a", "b", "c")

    m = Mock()
    tup.on_value_changed(m)

    # Changes should propagate through
    a.value = "A"
    assert tup.value == ("A", "b", "c")
    m.assert_called_once_with(("A", "b", "c"))

    m.reset_mock()
    b.value = "B"
    assert tup.value == ("A", "B", "c")
    m.assert_called_once_with(("A", "B", "c"))

    m.reset_mock()
    c.value = "C"
    assert tup.value == ("A", "B", "C")
    m.assert_called_once_with(("A", "B", "C"))
Exemple #4
0
def test_value_list_persistent():
    a = Value("a")
    b = Value("b")
    c = Value("c")

    lst = value_list([a, b, c])

    # Initial value should have passed through
    assert lst.value == ["a", "b", "c"]

    m = Mock()
    lst.on_value_changed(m)

    # Changes should propagate through
    a.value = "A"
    assert lst.value == ["A", "b", "c"]
    m.assert_called_once_with(["A", "b", "c"])

    m.reset_mock()
    b.value = "B"
    assert lst.value == ["A", "B", "c"]
    m.assert_called_once_with(["A", "B", "c"])

    m.reset_mock()
    c.value = "C"
    assert lst.value == ["A", "B", "C"]
    m.assert_called_once_with(["A", "B", "C"])
Exemple #5
0
async def test_set_property_register(qth_client, event_loop):
    a = Value(123)
    qth_yarp.set_property("foo/bar",
                          a,
                          register=True,
                          description="Something",
                          qth_client=qth_client)

    # Allow asyncio functions to run...
    await asyncio.sleep(0.1)

    # Initial should have been sent to Qth
    qth_client.set_property.assert_called_once_with("foo/bar", 123)

    # Registration should have been sent
    qth_client.register.assert_called_once_with(
        "foo/bar",
        qth.PROPERTY_ONE_TO_MANY,
        "Something",
        delete_on_unregister=True,
    )

    # Setting the qth value should update Qth
    a.value = 321
    await asyncio.sleep(0.1)
    qth_client.set_property.assert_called_with("foo/bar", 321)

    # And again...
    a.value = 1234
    await asyncio.sleep(0.1)
    qth_client.set_property.assert_called_with("foo/bar", 1234)
Exemple #6
0
def test_window():
    v = Value(1)
    ws = Value(3)

    win = window(v, ws)

    # Should start with the current value
    assert win.value == [1]

    # Values should accumulate
    v.value = 2
    assert win.value == [1, 2]

    v.value = 3
    assert win.value == [1, 2, 3]

    # Should truncate to only most recent values
    v.value = 4
    assert win.value == [2, 3, 4]

    # Increasing the window size should be possible
    ws.value = 4
    v.value = 5
    assert win.value == [2, 3, 4, 5]
    v.value = 6
    assert win.value == [3, 4, 5, 6]

    # Decreasing it should be too
    ws.value = 2
    assert win.value == [5, 6]
    v.value = 7
    assert win.value == [6, 7]
Exemple #7
0
async def test_rate_limit_persistent(event_loop):
    v = Value(1)
    
    # Initial value should be passed through
    rlv = rate_limit(v, 0.1, event_loop)
    assert rlv.value == 1
    
    log = []
    sem = asyncio.Semaphore(0, loop=event_loop)
    def on_change(new_value):
        log.append(new_value)
        sem.release()
    rlv.on_value_changed(on_change)
    
    # Change should not make it through yet
    v.value = 2
    assert rlv.value == 1
    assert len(log) == 0
    
    # Change should come through after a delay
    before = time.time()
    await sem.acquire()
    assert time.time() - before >= 0.1
    assert rlv.value == 2
    assert len(log) == 1
    assert log[-1] == 2
    
    # After a suitable delay, the next change should come through immediately
    await asyncio.sleep(0.15, loop=event_loop)
    v.value = 3
    assert rlv.value == 3
    assert len(log) == 2
    assert log[-1] == 3
    await sem.acquire()
    
    # A rapid succession of calls should result in only the last value
    # comming out, and then only after a delay
    v.value = 4
    v.value = 5
    v.value = 6
    assert rlv.value == 3
    assert len(log) == 2
    before = time.time()
    await sem.acquire()
    assert time.time() - before >= 0.1
    assert rlv.value == 6
    assert len(log) == 3
    assert log[-1] == 6
Exemple #8
0
def test_value_list_instantaneous():
    # A mix of instantaneous and continuous
    a = Value("a")
    b = Value()
    c = Value()

    lst = value_list([a, b, c])

    # Initial value should have passed through
    assert lst.value == ["a", NoValue, NoValue]

    m = Mock()
    lst.on_value_changed(m)

    # Changes should propagate through
    a.value = "A"
    assert lst.value == ["A", NoValue, NoValue]
    m.assert_called_once_with(["A", NoValue, NoValue])

    # Instantaneous values should propagate only into the callback
    m.reset_mock()
    b.set_instantaneous_value("b")
    assert lst.value == ["A", NoValue, NoValue]
    m.assert_called_once_with(["A", "b", NoValue])

    m.reset_mock()
    c.set_instantaneous_value("c")
    assert lst.value == ["A", NoValue, NoValue]
    m.assert_called_once_with(["A", NoValue, "c"])
Exemple #9
0
def test_value_tuple_instantaneous():
    # A mix of instantaneous and continuous
    a = Value("a")
    b = Value()
    c = Value()

    tup = value_tuple([a, b, c])

    # Initial value should have passed through
    assert tup.value == ("a", NoValue, NoValue)

    m = Mock()
    tup.on_value_changed(m)

    # Changes should propagate through
    a.value = "A"
    assert tup.value == ("A", NoValue, NoValue)
    m.assert_called_once_with(("A", NoValue, NoValue))

    # Instantaneous values should propagate only into the callback
    m.reset_mock()
    b.set_instantaneous_value("b")
    assert tup.value == ("A", NoValue, NoValue)
    m.assert_called_once_with(("A", "b", NoValue))

    m.reset_mock()
    c.set_instantaneous_value("c")
    assert tup.value == ("A", NoValue, NoValue)
    m.assert_called_once_with(("A", NoValue, "c"))
Exemple #10
0
def test_value_dict_instantaneous():
    # A mix of instantaneous and continuous
    a = Value("a")
    b = Value()
    c = Value()

    dct = value_dict({"a": a, "b": b, "c": c})

    # Initial value should have passed through
    assert dct.value == {"a": "a", "b": NoValue, "c": NoValue}

    m = Mock()
    dct.on_value_changed(m)

    # Changes should propagate through
    a.value = "A"
    assert dct.value == {"a": "A", "b": NoValue, "c": NoValue}
    m.assert_called_once_with({"a": "A", "b": NoValue, "c": NoValue})

    # Instantaneous values should propagate only into the callback
    m.reset_mock()
    b.set_instantaneous_value("b")
    assert dct.value == {"a": "A", "b": NoValue, "c": NoValue}
    m.assert_called_once_with({"a": "A", "b": "b", "c": NoValue})

    m.reset_mock()
    c.set_instantaneous_value("c")
    assert dct.value == {"a": "A", "b": NoValue, "c": NoValue}
    m.assert_called_once_with({"a": "A", "b": NoValue, "c": "c"})
Exemple #11
0
def test_change_callback():
    m = Mock()

    v = Value()
    v.on_value_changed(m)

    v.value = 123
    m.assert_called_once_with(123)
Exemple #12
0
def test_str_format_operator():
    # Special attention due for str_format as its an almost custom function(!)
    a = Value(0xAB)
    b = Value("hi")
    fmt = Value("{}, {}")

    stringified = str_format(fmt, a, b)
    assert stringified.value == "171, hi"

    a.value = 0xBC
    assert stringified.value == "188, hi"

    b.value = "foo"
    assert stringified.value == "188, foo"

    fmt.value = "0x{:04X}: {!r}"
    assert stringified.value == "0x00BC: 'foo'"
Exemple #13
0
def test_change_persistent():
    rule = lambda x: x < 10

    m = Mock()
    v = Value(1)
    fl = filter(v, rule)
    fl.on_value_changed(m)
    assert fl.value == 1

    v.value = 2
    assert fl.value == 2
    m.assert_called_once_with(2)

    # Above ten, shouldn't get through
    v.value = 100
    assert fl.value == 2
    m.assert_called_once_with(2)
Exemple #14
0
def test_replace_novalue():
    a = Value()
    replacement = Value(123)
    ar = replace_novalue(a, replacement)

    assert ar.value == 123

    a.value = "hi"
    assert ar.value == "hi"

    a.value = NoValue
    assert ar.value == 123

    replacement.value = 321
    assert ar.value == 321

    a.value = "bye"
    assert ar.value == "bye"
Exemple #15
0
def test_no_repeat_persistent():
    v = Value(1)

    # Initial value should come through
    nrv = no_repeat(v)
    assert nrv.value == 1

    m = Mock()
    nrv.on_value_changed(m)

    # Same value doesn't pass through
    v.value = 1
    assert not m.called

    # New values do
    v.value = 2
    assert nrv.value == 2
    m.assert_called_once_with(2)
Exemple #16
0
def test_operator_wrapper_continous():
    # Only test addition since others are defined in exactly the same way
    a = Value(1)
    b = Value(2)

    a_add_b = add(a, b)
    assert a_add_b.value == 3

    a.value = 10
    assert a_add_b.value == 12
Exemple #17
0
def test_ensure_value_list():
    a = 123
    b = Value(456)

    v = ensure_value([a, b])
    assert isinstance(v, Value)
    assert v.value == [123, 456]

    b.value = 789
    assert v.value == [123, 789]
Exemple #18
0
def test_ensure_value_tuple():
    a = 123
    b = Value(456)

    v = ensure_value((a, b))
    assert isinstance(v, Value)
    assert v.value == (123, 456)

    b.value = 789
    assert v.value == (123, 789)
Exemple #19
0
def test_ensure_value_dict():
    a = 123
    b = Value(456)

    v = ensure_value({"a": a, "b": b})
    assert isinstance(v, Value)
    assert v.value == {"a": 123, "b": 456}

    b.value = 789
    assert v.value == {"a": 123, "b": 789}
Exemple #20
0
def test_ensure_value_nested():
    a = Value(123)
    b = Value(456)
    c = Value(789)

    v = ensure_value({"a": a, "bc": [b, c]})
    assert isinstance(v, Value)
    assert v.value == {"a": 123, "bc": [456, 789]}

    b.value = 654
    assert v.value == {"a": 123, "bc": [654, 789]}
Exemple #21
0
def test_make_instantaneous():
    v = Value(1)

    iv = make_instantaneous(v)
    m = Mock()
    iv.on_value_changed(m)

    assert iv.value is NoValue

    v.value = 2
    assert iv.value is NoValue
    m.assert_called_once_with(2)
Exemple #22
0
async def test_set_property(qth_client, event_loop):
    a = Value(123)
    qth_yarp.set_property("foo/bar", a, qth_client=qth_client)

    # Allow asyncio functions to run...
    await asyncio.sleep(0.1)

    # Initial should have been sent to Qth
    qth_client.set_property.assert_called_once_with("foo/bar", 123)

    # No registration should be made
    assert len(qth_client.register.mock_calls) == 0

    # Setting the qth value should update Qth
    a.value = 321
    await asyncio.sleep(0.1)
    qth_client.set_property.assert_called_with("foo/bar", 321)

    # And again...
    a.value = 1234
    await asyncio.sleep(0.1)
    qth_client.set_property.assert_called_with("foo/bar", 1234)
Exemple #23
0
def test_getattr_value_name():
    # Special attention since this is important
    m = Mock()
    m.foo = "FOO!"
    m.bar = "BAR!"
    v = Value(m)

    name_v = Value("foo")
    attr_v = getattr(v, name_v)

    assert attr_v.value == "FOO!"

    log = []
    attr_v.on_value_changed(log.append)

    name_v.value = "bar"

    assert attr_v.value == "BAR!"
    assert log == ["BAR!"]
Exemple #24
0
def test_getattr_string_name():
    # Special attention since this is important
    m = Mock()
    m.foo = "bar"
    v = Value(m)

    foo_v = getattr(v, "foo")

    assert isinstance(foo_v, Value)
    assert foo_v.value == "bar"

    log = []
    foo_v.on_value_changed(log.append)

    m2 = Mock()
    m2.foo = "baz"
    v.value = m2

    assert foo_v.value == "baz"
    assert log == ["baz"]
Exemple #25
0
def test_native_value_operators():
    """Not exhaustive but just checks the most valuable ones."""
    a = Value(1)
    b = Value(2)
    c = value_list([a, b])
    d = value_dict({"ay": a, "be": b})

    a_add_b = a + b
    assert a_add_b.value == 3

    a.value = 0
    assert a_add_b.value == 2

    minus_b = -b
    assert minus_b.value == -2

    # Comparison
    a_lt_b = a < b
    a_eq_b = a == b
    assert a_lt_b.value
    assert not a_eq_b.value
    a.value = 2
    assert not a_lt_b.value
    assert a_eq_b.value

    # Non-Value things should get converted
    b_add_3 = b + 3
    assert b_add_3.value == 5

    four_sub_b = 4 - b
    assert four_sub_b.value == 2

    # Indexing
    c_0 = c[0]
    assert c_0.value == 2
    a.value = -1
    assert c_0.value == -1

    # Slicing
    c_backwards = c[::-1]
    assert c_backwards.value == [2, -1]
    b.value = 20
    assert c_backwards.value == [20, -1]
    a.value = -10
    assert c_backwards.value == [20, -10]

    # Dictionaries
    d_ay = d["ay"]
    assert d_ay.value == -10
    a.value = 10
    assert d_ay.value == 10

    # Calling and getattring
    class Cls(object):
        def __init__(self, n):
            self.n = n

        def __call__(self, n2):
            return self.n + n2

        def get(self):
            return self.n

        @property
        def n_plus_one(self):
            return self.n + 1

    c1 = Cls(1)
    c2 = Cls(2)
    av = Value(c1)

    # Getattr for variable
    nv = av.n
    assert nv.value == 1
    av.value = c2
    assert nv.value == 2
    av.value = c1

    # Getattr for property
    n_plus_one_v = av.n_plus_one
    assert n_plus_one_v.value == 2
    av.value = c2
    assert n_plus_one_v.value == 3
    av.value = c1

    # Calling callable classes
    ret_v = av(10)
    assert ret_v.value == 11
    av.value = c2
    assert ret_v.value == 12
    av.value = c1

    # Calling callable attributes
    get_v = av.get()
    assert get_v.value == 1
    av.value = c2
    assert get_v.value == 2
    av.value = c1
Exemple #26
0
async def test_rate_limit_min_interval_change(event_loop):
    v = Value(123)
    mi = Value(0.1)
    
    start = time.time()
    rlv = rate_limit(v, mi, event_loop)
    
    log = []
    sem = asyncio.Semaphore(0, loop=event_loop)
    def on_change(new_value):
        log.append(new_value)
        sem.release()
    rlv.on_value_changed(on_change)
    
    # The initial value will have blocked changes for 0.1 seconds, increase
    # this to 0.15 seconds and ensure it takes place
    v.value = 321
    mi.value = 0.15
    assert rlv.value == 123
    await sem.acquire()
    assert time.time() - start >= 0.15
    assert rlv.value == 321
    assert len(log) == 1
    assert log[-1] == 321
    
    # Should be able to shorten the blocking period, too
    start = time.time()
    v.value = 1234
    mi.value = 0.1
    assert rlv.value == 321
    await sem.acquire()
    assert 0.1 <= time.time() - start < 0.125
    assert rlv.value == 1234
    assert len(log) == 2
    assert log[-1] == 1234
    
    # Also, should be able to shorten the blocking period to shorter than has
    # already ellapsed and the value should emmerge immediately
    v.value = 4321
    assert rlv.value == 1234
    await asyncio.sleep(0.05, loop=event_loop)
    assert rlv.value == 1234
    mi.value = 0.025
    assert rlv.value == 4321
    assert len(log) == 3
    assert log[-1] == 4321
    await sem.acquire()
    
    # If we ensure blocking is not occurring, changing the time shouldn't cause
    # problems
    await asyncio.sleep(0.05, loop=event_loop)
    mi.value = 0.1
    v.value = 12345
    assert rlv.value == 12345
    await sem.acquire()
    v.value = 54321
    start = time.time()
    assert rlv.value == 12345
    await sem.acquire()
    assert rlv.value == 54321
    assert time.time() - start >= 0.1