def test_Error(self): context = Mock() r = Error(123, context, "Test Error") self.assertEquals(123, r.id_) self.assertEquals("malcolm:core/Error:1.0", r.typeid) self.assertEquals(context, r.context) r.set_message("Test Error 2") self.assertEquals("Test Error 2", r.message)
def test_callback_error(self): t = Task("testTask", self.proc) resp = Error(0, None, None) resp.set_message('error') t.q.put(resp) t.stop() t.subscribe(self.attr, self._callback, 3, 5) f1 = Future(t) t._futures = {1: f1} self.assertRaises(RuntimeError, t.wait_all, f1, 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)
def test_result(self): # timeout due to no response arriving f0 = Future(self.task) f1 = Future(self.task) self.task._futures = {0: f0, 1: f1} self.assertRaises(queue.Empty, f0.result, 0) # return after waiting for response object resp0 = Return(0, None, None) resp0.set_value('testVal') resp1 = Error(1, None, "test Error") resp1.set_message('test Error') self.task.q.put(resp0) self.task.q.put(resp1) self.assertEqual(f0.result(), 'testVal')
def test_exception(self): # timeout due to no response arriving f0 = Future(self.task) f1 = Future(self.task) self.task._futures = {0: f0, 1: f1} self.assertRaises(queue.Empty, f0.exception, 0) # return after waiting for response object resp0 = Return(0, None, None) resp0.set_value('testVal') resp1 = Error(1, None, None) resp1.set_message('test Error') self.task.q.put(resp0) self.task.q.put(resp1) self.assertEqual(f1.exception(), 'test Error')
def send_to_server(self, request): """Dispatch a request to the server Args: request(Request): The message to pass to the server """ try: if isinstance(request, Get): self.log_debug("Get message with endpoint: %s", request["endpoint"]) return_object = self.execute_get(request) elif isinstance(request, Put): self.log_debug("Put message with endpoint: %s", request["endpoint"]) self.log_debug("Put message with value: %s", request["value"]) return_object = self.execute_put(request) elif isinstance(request, Post): self.log_debug("Post message with endpoint: %s", request["endpoint"]) self.log_debug("Parameters: %s", request["parameters"]) return_object = self.execute_rpc(request) elif isinstance(request, Subscribe): self.log_debug("Subscribe message with endpoint: %s", request["endpoint"]) return_object = self.execute_monitor(request) # TODO: Implement unsubscribe # TODO: Currently monitors always return updates, deltas are not available except: # PvAccess error, create the Error message self.log_exception("Error processing request %s", request) return_object = Error(id_=request["id"], message="PvAccess error") if return_object: self.send_to_caller(return_object)
def test_send_to_client_error(self, _, _2): ws = WebsocketServerComms(self.p, dict(port=1)) response = Error(11, MagicMock(), "bad") ws._send_to_client(response) response.context.set_status.assert_called_once_with(500, "bad") response.context.write_error.assert_called_once_with(500)
def get_response(self, request): """Call exposed function using request parameters and respond with the result Args: request (Request): The request to handle """ self.log_debug("Received request %s", request) try: try: parameters = request.parameters if parameters is None: parameters = {} except AttributeError: parameters = {} if "typeid" in parameters: parameters.pop("typeid") result = self.call_function(parameters) except Exception as error: err_message = str(error) self.log_exception("Error raised %s", err_message) message = "Method %s raised an error: %s" % (self.name, err_message) return Error(request.id_, request.context, message) else: self.log_debug("Returning result %s", result) return Return(request.id_, request.context, value=result)
def test_respond_with_error(self): cb, response = self.o.error_response( exception=ValueError("Test Error")) assert cb == self.callback assert response.to_dict() == \ Error(id=32, message=ANY).to_dict() assert str(response.message) == "Test Error"
def test_exception(self): # timeout due to no response arriving f0 = Future(self.task) f1 = Future(self.task) self.task._futures = {0: f0, 1: f1} self.assertRaises(queue.Empty, f0.exception, 0) # return after waiting for response object resp0 = Return(0, None, None) resp0.set_value('testVal') resp1 = Error(1, None, None) resp1.set_message('test Error') self.task.q.put(resp0) self.task.q.put(resp1) with self.assertRaises(ValueError) as cm: f1.exception() self.assertEqual(str(cm.exception), 'test Error')
def test_respond_with_error(self): self.request.respond_with_error(message="Test Error") call_arg = self.response_queue.put.call_args_list[0][0][0].to_dict() expected_response = Error(self.request.id_, self.request.context, message="Test Error").to_dict() self.assertEqual(call_arg, expected_response)
def execute_get(self, request): # Connect to the channel c = pvaccess.Channel(request["endpoint"][0]) # Create the path request from the endpoints (not including the block name endpoint) path = ".".join(request["endpoint"][1:]) self.log_debug("path: %s", path) # Perform a get and record the response response = c.get(path) self.log_debug("Response: %s", response) # Now create the Return 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_=request["id"], message=value['message']) else: return_object = Return(id_=request["id"], value=value) else: return_object = Error(id_=request["id"], message="No valid return typeid") return return_object
def respond_with_error(self, message): """ Create an Error Response object to handle the request Args: message(str): Message explaining error """ response = Error(self.id, self.context, message=message) self.response_queue.put(response)
def execute_rpc(self, request): method = pvaccess.PvObject({'method': pvaccess.STRING}) method.set({'method': request["endpoint"][1]}) # Connect to the channel and create the RPC client rpc = pvaccess.RpcClient(request["endpoint"][0], method) # Construct the pv object from the parameters params = self.dict_to_pv_object(request["parameters"]) self.log_debug("PvObject parameters: %s", params) # Call the method on the RPC object response = rpc.invoke(params) self.log_debug("Response: %s", response) # Now create the Return 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_=request["id"], message=value['message']) else: return_object = Return(id_=request["id"], value=value) else: return_object = Error(id_=request["id"], message="No valid return typeid") return return_object
def test_post(self): t = Task("testTask", self.proc) resp1 = Return(0, None, None) resp1.set_value('testVal') resp2 = Error(1, None, None) # cheat and add the responses before the blocking call to put t.q.put(resp1) t.q.put(resp2) t.stop() t.post(self.method, {"a": "testParm"}) self.assertRaises(ValueError, t.post, self.method, {"a": "testParm2"}) self.assertEqual(len(t._futures), 0) self.assertEqual(self.proc.q.qsize(), 2)
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 = Delta(id_=3) self.PVA.send_to_client(response3) self.PVA._update_cache.assert_has_calls([call(response3)])
def handle_request(self, request): """ Process the request depending on the type Args: request(Request): Request object specifying action """ self.log_debug("Received request %s", request) try: assert isinstance(request, Post) or isinstance(request, Put), \ "Expected Post or Put request, received %s" % request.typeid child_name = request.endpoint[1] child = self[child_name] writeable_function = self._writeable_functions[child_name] result = child.handle_request(request, writeable_function) response = Return(request.id, request.context, result) except Exception as e: # pylint:disable=broad-except self.log_exception("Exception while handling %s" % request) response = Error(request.id, request.context, str(e)) self._parent.block_respond(response, request.response_queue)
def test_wait_all(self): t = Task("testTask", self.proc) f1 = Future(t) f2 = Future(t) f3 = Future(t) f0 = Future(t) t._futures = {0: f0, 1: f1, 2: f2, 3: f3} f_wait1 = [f2, f0] self.assertRaises(queue.Empty, t.wait_all, f_wait1, 0) resp0 = Return(0, None, None) resp0.set_value('testVal') resp2 = Error(2, None, None) t.q.put(resp0) t.q.put(resp2) self.assertRaises(ValueError, t.wait_all, f_wait1, 0) self.assertEqual(t._futures, {1: f1, 3: f3}) self.assertEqual(f0.done(), True) self.assertEqual(f1.done(), False) self.assertEqual(f2.done(), True) self.assertEqual(f3.done(), False) self.assertEqual(self.proc.q.qsize(), 0) resp3 = Delta(3, None, None) t.q.put(resp3) f_wait1 = [f3] self.assertRaises(ValueError, t.wait_all, f_wait1, 0.01) t.stop() self.assertRaises(StopIteration, t.wait_all, f_wait1, 0.01) resp1 = Return(1, None, None) resp1.set_value('testVal') t.q.put(resp1) self.assertRaises(queue.Empty, t.wait_all, f_wait1, 0.01) self.assertEqual(t._futures, {}) t._futures = {0: f0, 1: f1, 2: f2} t.q.put(resp1) t.q.put(Spawnable.STOP) self.assertEqual(f1.result(), 'testVal')
def test_Error(self): r = Error(2, "Non-existant block 'foo'") assert r.typeid == "malcolm:core/Error:1.0" assert r.id == 2 assert r.message == "Non-existant block 'foo'" assert get_doc_json("error") == r.to_dict()
def test_handle_response_error(self): response = Error(None, None, "bad") self.item.handle_response(response) self.assertEqual(self.item.get_state(), self.item.ERROR)
def test_post_failure(self): self.o._q.put(Error(1, ValueError("Test Exception"))) with self.assertRaises(ValueError) as cm: self.o.post(["block", "method"], dict(b=32)) assert str(cm.exception) == "Test Exception"
def test_put_failure(self): self.o._q.put(Error(1, ResponseError("Test Exception"))) with self.assertRaises(ResponseError) as cm: self.o.put(["block", "attr", "value"], 32) assert str(cm.exception) == "Test Exception"
def test_respond_with_error(self): cb, response = self.o.error_response( exception=ValueError("Test Error")) assert cb == self.callback assert response == Error(id=32, message="ValueError: Test Error")
def test_handle_response_error(self): response = Error(message="bad") self.item.handle_response(response) assert self.item.get_state() == self.item.ERROR
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()