Ejemplo n.º 1
0
 def test_update_squashing(self):
     # set some data
     self.block["attr"] = Dummy()
     self.block.attr["value"] = 32
     self.block["attr2"] = Dummy()
     self.block.attr2["value"] = "st"
     # subscribe once and check initial response
     r1 = Subscribe(path=["b"], delta=True)
     r1.set_callback(Mock())
     r2 = Subscribe(path=["b"])
     r2.set_callback(Mock())
     self.handle_subscribe(r1)
     self.handle_subscribe(r2)
     expected = OrderedDict()
     expected["attr"] = dict(value=32)
     expected["attr2"] = dict(value="st")
     self.assert_called_with(r1.callback, Delta(changes=[[[], expected]]))
     self.assert_called_with(r2.callback, Update(value=expected))
     r1.callback.reset_mock()
     r2.callback.reset_mock()
     # squash two changes together
     with self.o.changes_squashed:
         self.block.attr["value"] = 33
         self.o.add_squashed_change(["b", "attr", "value"], 33)
         assert self.block.attr.value == 33
         self.block.attr2["value"] = "tr"
         self.o.add_squashed_change(["b", "attr2", "value"], "tr")
         assert self.block.attr2.value == "tr"
     self.assert_called_with(
         r1.callback,
         Delta(
             changes=[[["attr", "value"], 33], [["attr2", "value"], "tr"]]))
     expected["attr"]["value"] = 33
     expected["attr2"]["value"] = "tr"
     self.assert_called_with(r2.callback, Update(value=expected))
Ejemplo n.º 2
0
 def test_subscribe_no_data_then_set_data(self):
     # subscribe
     request = Subscribe(path=["b", "attr", "value"], delta=False)
     request.set_callback(Mock())
     self.handle_subscribe(request)
     assert (self.o._tree.children["attr"].children["value"].update_requests
             ) == ([request])
     self.assert_called_with(request.callback, Update(value=None))
     request.callback.reset_mock()
     # set data and check response
     self.block["attr"] = Dummy()
     with self.o.changes_squashed:
         self.block.attr["value"] = 32
         self.o.add_squashed_change(["b", "attr", "value"], 32)
     assert self.block.attr.value == 32
     self.assert_called_with(request.callback, Update(value=32))
     request.callback.reset_mock()
     # unsubscribe
     unsub = Unsubscribe()
     unsub.set_callback(request.callback)
     self.handle_unsubscribe(unsub)
     self.assert_called_with(request.callback, Return(value=None))
     request.callback.reset_mock()
     # notify and check no longer responding
     with self.o.changes_squashed:
         self.block.attr["value"] = 33
         self.o.add_squashed_change(["b", "attr", "value"], 33)
     assert self.block.attr.value == 33
     request.callback.assert_not_called()
Ejemplo n.º 3
0
    def test_subscribe_cb_failure(self):
        def cb(value):
            raise MyWarning()

        f = self.o.subscribe(["block", "attr", "value"], cb)
        self.o._q.put(Update(1, "value1"))
        with self.assertRaises(MyWarning):
            self.o.wait_all_futures(f, 0.01)
        assert not f.done()
        self.o._q.put(Update(1, "value1"))
        with self.assertRaises(MyWarning):
            self.o.wait_all_futures(f, 0.01)
        assert not f.done()
        self.o._q.put(Return(1))
        self.o.wait_all_futures(f, 0.01)
        assert f.done()
Ejemplo n.º 4
0
 def test_when_matches(self):
     self.o._q.put(Update(1, "value1"))
     self.o._q.put(Return(1))
     self.o.when_matches(["block", "attr", "value"], "value1", timeout=0.01)
     assert self.controller.handle_request.call_args_list == [
         call(Subscribe(1, ["block", "attr", "value"])),
         call(Unsubscribe(1))
     ]
Ejemplo n.º 5
0
 def test_2_subscribes(self):
     # set some data
     self.block["attr"] = Dummy()
     self.block.attr["value"] = 32
     # subscribe once and check initial response
     r1 = Subscribe(path=["b", "attr", "value"], delta=False)
     r1.set_callback(Mock())
     self.handle_subscribe(r1)
     self.assert_called_with(r1.callback, Update(value=32))
     r1.callback.reset_mock()
     # subscribe again and check initial response
     r2 = Subscribe(path=["b"], delta=True)
     r2.set_callback(Mock())
     self.handle_subscribe(r2)
     self.assert_called_with(
         r2.callback, Delta(changes=[[[], dict(attr=dict(value=32))]])
     )
     r2.callback.reset_mock()
     # set some data and check only second got called
     self.block["attr2"] = Dummy()
     with self.o.changes_squashed:
         self.block.attr2["value"] = "st"
         self.o.add_squashed_change(["b", "attr2"], self.block.attr2)
     r1.callback.assert_not_called()
     self.assert_called_with(
         r2.callback, Delta(changes=[[["attr2"], dict(value="st")]])
     )
     r2.callback.reset_mock()
     # delete the first and check calls
     with self.o.changes_squashed:
         self.block.data.pop("attr")
         self.o.add_squashed_delete(["b", "attr"])
     self.assert_called_with(r1.callback, Update(value=None))
     r1.callback.reset_mock()
     self.assert_called_with(r2.callback, Delta(changes=[[["attr"]]]))
     r2.callback.reset_mock()
     # add it again and check updates
     self.block["attr"] = Dummy()
     with self.o.changes_squashed:
         self.block.attr["value"] = 22
         self.o.add_squashed_change(["b", "attr"], self.block.attr)
     self.assert_called_with(r1.callback, Update(value=22))
     self.assert_called_with(
         r2.callback, Delta(changes=[[["attr"], dict(value=22)]])
     )
Ejemplo n.º 6
0
    def test_when_matches(self):
        t = Task("testTask", self.proc)

        f = t.when_matches_async(self.attr, "matchTest")
        resp = Update(1, None, None)
        resp.set_value('matchTest')
        t.q.put(resp)
        self.assertEqual(f[0].result(0), 'matchTest')
        t.stop()
Ejemplo n.º 7
0
    def respond_with_update(self, value):
        """
        Create an Update Response object to handle the request

        Args:
            value (dict): Dictionary describing the new structure
        """
        response = Update(self.id, self.context, value=value)
        self.response_queue.put(response)
Ejemplo n.º 8
0
 def test_when_not_matches(self):
     self.o._q.put(Update(1, "value2"))
     with self.assertRaises(BadValueError):
         self.o.when_matches(["block", "attr", "value"],
                             "value1", ["value2"],
                             timeout=0.01)
     assert self.controller.handle_request.call_args_list == [
         call(Subscribe(1, ["block", "attr", "value"])),
         call(Unsubscribe(1))
     ]
Ejemplo n.º 9
0
    def test_Update(self):
        context = Mock()
        value = {"attribute": "value"}
        r = Update(123, context, value)
        self.assertEquals(123, r.id_)
        self.assertEquals(context, r.context)
        self.assertEquals({"attribute": "value"}, r.value)

        r.set_value({"key": "value2"})
        self.assertEquals({"key": "value2"}, r.value)
Ejemplo n.º 10
0
    def test_when_not_matches(self):
        self.o._q.put(Update(1, "value2"))
        with self.assertRaises(BadValueError) as cm:
            self.o.when_matches(["block", "attr", "value"],
                                "value1", ["value2"],
                                timeout=0.01)
        assert str(cm.exception) == "Waiting for 'value1', got 'value2'"

        self.assert_handle_request_called_with(
            Subscribe(1, ["block", "attr", "value"]), Unsubscribe(1))
Ejemplo n.º 11
0
 def test_subscribe(self):
     cb = MagicMock()
     f = self.o.subscribe(["block", "attr", "value"], cb, self.o, "arg2")
     self.assert_handle_request_called_with(
         Subscribe(1, ["block", "attr", "value"]))
     self.o._q.put(Update(1, "value1"))
     with self.assertRaises(TimeoutError):
         self.o.wait_all_futures(f, 0.01)
     cb.assert_called_once_with("value1", ANY, "arg2")
     # since args = self.o it should be a weak proxy in second argument
     cb.call_args[0][1]
     # TODO: giles cant work out how to check weakproxy equivalence??
     # self.assertEquals(param1, self.o)
     cb.reset_mock()
     self.o._q.put(Update(1, "value2"))
     self.o._q.put(Return(1))
     self.o.wait_all_futures(f, 0.01)
     cb.assert_called_once_with("value2", ANY, "arg2")
     assert f.result(0.01) is None
Ejemplo n.º 12
0
    def test_respond_with_update(self):
        value = MagicMock()

        self.subscribe.respond_with_update(value)

        call_arg = self.response_queue.put.call_args_list[0][0][0].to_dict()

        expected_response = Update(self.subscribe.id_, self.subscribe.context, value=value).to_dict()

        self.assertEqual(call_arg, expected_response)
Ejemplo n.º 13
0
    def test_when_matches_func(self):
        self.o._q.put(Update(1, "value1"))
        self.o._q.put(Return(1))

        def f(value):
            return value.startswith("v")

        self.o.when_matches(["block", "attr", "value"], f, timeout=0.01)
        self.assert_handle_request_called_with(
            Subscribe(1, ["block", "attr", "value"]), Unsubscribe(1))
Ejemplo n.º 14
0
    def test_when_matches(self):
        t = Task("testTask", self.proc)
        f = t.when_matches(self.attr, "matchTest")

        # match (response goes to the subscription at id 1,
        # not the future at id 0)
        resp = Update(1, None, None)
        resp.set_value('matchTest')
        t.q.put(resp)
        t.stop()
        self.assertEqual(f[0].result(0), 'matchTest')
Ejemplo n.º 15
0
 def monitor_update(self, response):
     self.log_debug("Monitor Update called: %s", response)
     # Create the Update object and populate it with the response
     value = response.toDict(True)
     if 'typeid' in value:
         if value['typeid'] == 'malcolm:core/Error:1.0':
             return_object = Error(id_=self._id, message=value['message'])
         else:
             return_object = Update(id_=self._id, value=value)
     else:
         return_object = Error(id_=self._id, message="No valid return typeid")
     self._client.send_to_caller(return_object)
Ejemplo n.º 16
0
    def test_callback_crash(self):
        t = Task("testTask", self.proc)
        resp = Update(0, None, None)
        resp.set_value('changedVal')
        t.q.put(resp)
        t.stop()

        t.subscribe(self.attr, self._bad_callback)
        f1 = Future(t)
        t._futures = {1: f1}
        self.assertRaises(StopIteration, t.wait_all, f1, 0)
        self.assertEquals(self.bad_called_back, True)
Ejemplo n.º 17
0
    def test_not_when_matches(self):
        t = Task("testTask", self.proc)
        f = t.when_matches(self.attr, "matchTest")

        # match (response goes to the subscription at id 1,
        # not the future at id 0)
        resp = Update(1, None, None)
        resp.set_value('NOTmatchTest')
        t.q.put(resp)
        t.stop()

        # this will abort the task because f[0] never gets filled
        self.assertRaises(StopIteration, f[0].result)
Ejemplo n.º 18
0
    def test_subscribe(self):
        t = Task("testTask", self.proc)
        resp = Update(0, None, None)
        resp.set_value('changedVal')
        t.q.put(resp)
        t.stop()

        new_id = t.subscribe(self.attr, self._callback, 3, 5)
        f1 = Future(t)
        t._futures = {1: f1}

        self.assertRaises(StopIteration, t.wait_all, f1, 0)
        self.assertEqual(self.callback_value, 'changedVal')
        self.assertEqual(self.callback_result, 8)
        t.unsubscribe(new_id)
Ejemplo n.º 19
0
    def test_subscription_with_callback_calling_unsubscribe(self):
        # This test was designed to trigger a bug. Concluding a future inside a
        # callback, as is done here by unsubscribe() followed by sleep(0), would
        # not be recognised by the call to wait_all_futures(...). This would
        # result in an indefinite hang.

        def cb(value):
            self.o.unsubscribe_all()
            self.o._q.put(Return(1))  # Return from subscribe
            self.o.sleep(0)  # Service futures

        self.o.subscribe(["block", "attr", "value"], cb)  # id=1
        self.o._q.put(Update(1, "original_value"))  # Update from initial value

        future = self.o.put_async(["block", "attr2", "value"], "new")  # id=2
        self.o._q.put(Return(2))  # Return from put to attr2

        self.o.wait_all_futures(future)
Ejemplo n.º 20
0
    def _handle_block_notify(self, request):
        """Update subscribers with changes and applies stored changes to the
        cached structure"""
        # update cached dict
        for delta in self._last_changes.setdefault(request.name, []):
            self._block_state_cache.delta_update(delta)

        for subscription in self._subscriptions.setdefault(request.name, []):
            endpoint = subscription.endpoint
            # find stuff that's changed that is relevant to this subscriber
            changes = []
            for change in self._last_changes[request.name]:
                change_path = change[0]
                # look for a change_path where the beginning matches the
                # endpoint path, then strip away the matching part and add
                # to the change set
                i = 0
                for (cp_element, ep_element) in zip(change_path, endpoint):
                    if cp_element != ep_element:
                        break
                    i += 1
                else:
                    # change has matching path, so keep it
                    # but strip off the end point path
                    filtered_change = [change_path[i:]] + change[1:]
                    changes.append(filtered_change)
            if len(changes) > 0:
                if subscription.delta:
                    # respond with the filtered changes
                    response = Delta(subscription.id_, subscription.context,
                                     changes)
                else:
                    # respond with the structure of everything
                    # below the endpoint
                    d = self._block_state_cache.walk_path(endpoint)
                    response = Update(subscription.id_, subscription.context,
                                      d)
                self.log_debug("Responding to subscription %s", response)
                subscription.response_queue.put(response)
        self._last_changes[request.name] = []
Ejemplo n.º 21
0
 def test_Update(self):
     r = Update(19, "Running")
     assert r.typeid == "malcolm:core/Update:1.0"
     assert r.id == 19
     assert r.value == "Running"
     assert get_doc_json("update_state_value") == r.to_dict()
Ejemplo n.º 22
0
 def test_respond_with_update(self):
     cb, response = self.o.update_response(value=5)
     assert cb == self.callback
     assert response.to_dict() == Update(id=11, value=5).to_dict()
Ejemplo n.º 23
0
 def test_when_matches(self):
     self.o._q.put(Update(1, "value1"))
     self.o._q.put(Return(1))
     self.o.when_matches(["block", "attr", "value"], "value1", timeout=0.01)
     self.assert_handle_request_called_with(
         Subscribe(1, ["block", "attr", "value"]), Unsubscribe(1))
 def test_send_to_caller_with_block_update(self):
     c = ClientComms(Mock())
     response = Update(id_=0)
     c.send_to_caller(response)
     c.process.update_block_list.assert_called_once_with(c, response.value)
Ejemplo n.º 25
0
 def test_send_to_client(self):
     self.PVA = PvaServerComms(self.p)
     self.PVA._update_cache = MagicMock()
     rpc_mock1 = MagicMock()
     rpc_mock2 = MagicMock()
     self.PVA._rpcs[1] = rpc_mock1
     self.PVA._rpcs[2] = rpc_mock2
     response1 = Return(id_=1)
     self.PVA.send_to_client(response1)
     rpc_mock1.notify_reply.assert_has_calls([call(response1)])
     response2 = Error(id_=2)
     self.PVA.send_to_client(response2)
     rpc_mock2.notify_reply.assert_has_calls([call(response2)])
     response3 = Return(id_=3)
     self.PVA.send_to_client(response3)
     rpc_mock1.notify_reply.assert_has_calls([call(response1)])
     rpc_mock2.notify_reply.assert_has_calls([call(response2)])
     # Gets
     get_mock1 = MagicMock()
     get_mock2 = MagicMock()
     self.PVA._gets[3] = get_mock1
     self.PVA._gets[4] = get_mock2
     response1 = Return(id_=3)
     self.PVA.send_to_client(response1)
     get_mock1.notify_reply.assert_has_calls([call(response1)])
     response2 = Error(id_=4)
     self.PVA.send_to_client(response2)
     get_mock2.notify_reply.assert_has_calls([call(response2)])
     response3 = Return(id_=5)
     self.PVA.send_to_client(response3)
     get_mock1.notify_reply.assert_has_calls([call(response1)])
     get_mock2.notify_reply.assert_has_calls([call(response2)])
     # Puts
     put_mock1 = MagicMock()
     put_mock2 = MagicMock()
     self.PVA._puts[5] = put_mock1
     self.PVA._puts[6] = put_mock2
     response1 = Return(id_=5)
     self.PVA.send_to_client(response1)
     put_mock1.notify_reply.assert_has_calls([call(response1)])
     response2 = Error(id_=6)
     self.PVA.send_to_client(response2)
     put_mock2.notify_reply.assert_has_calls([call(response2)])
     response3 = Return(id_=7)
     self.PVA.send_to_client(response3)
     put_mock1.notify_reply.assert_has_calls([call(response1)])
     put_mock2.notify_reply.assert_has_calls([call(response2)])
     # Monitors
     mon_mock1 = MagicMock()
     mon_mock2 = MagicMock()
     self.PVA._monitors[7] = mon_mock1
     self.PVA._monitors[8] = mon_mock2
     response1 = Return(id_=7)
     self.PVA.send_to_client(response1)
     mon_mock1.notify_reply.assert_has_calls([call(response1)])
     response2 = Error(id_=8)
     self.PVA.send_to_client(response2)
     mon_mock2.notify_reply.assert_has_calls([call(response2)])
     response3 = Return(id_=9)
     self.PVA.send_to_client(response3)
     mon_mock1.notify_reply.assert_has_calls([call(response1)])
     mon_mock2.notify_reply.assert_has_calls([call(response2)])
     # Delta
     mon_mock3 = MagicMock()
     self.PVA._monitors[9] = mon_mock3
     response3 = Delta(id_=9)
     self.PVA.send_to_client(response3)
     mon_mock3.update.assert_has_calls([call(response3["changes"])])
     # Updates
     self.PVA._update_local_block_list = MagicMock()
     self.PVA._update_remote_block_list = MagicMock()
     response4 = Update(id_=self.PVA._local_block_id)
     response5 = Update(id_=self.PVA._remote_block_id)
     self.PVA.send_to_client(response4)
     self.PVA._update_local_block_list.assert_called_once()
     self.PVA.send_to_client(response5)
     self.PVA._update_remote_block_list.assert_called_once()