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()
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)
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')
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(RuntimeWarning, t.wait_all, f1, 0) self.assertEquals(self.bad_called_back, True)
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(RuntimeWarning, f[0].result)
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(RuntimeWarning, t.wait_all, f1, 0) self.assertEqual(self.callback_value, 'changedVal') self.assertEqual(self.callback_result, 8) t.unsubscribe(new_id)
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)
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] = []
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)
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()
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()
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_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()