示例#1
0
 def test_hello_good_input(self):
     q = Queue()
     request = Post(id=44,
                    path=["hello_block", "greet"],
                    parameters=dict(name="thing"))
     request.set_callback(q.put)
     self.controller.handle_request(request)
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Return)
     assert response.id == 44
     assert response.value == "Hello thing"
示例#2
0
    def rpc(self, pv, op):
        # type: (SharedPV, ServerOperation) -> None
        value = op.value()
        if value.getID() == "epics:nt/NTURI:1.0":
            # We got an NTURI, get path from path and parameters from query
            assert value.scheme == "pva", \
                "Can only handle NTURI with scheme=pva"
            prefix = self.controller.mri + "."
            assert value.path.startswith(prefix), \
                "NTURI path '%s' doesn't start with '%s'" % (value.path, prefix)
            method = value.path[len(prefix):]
            parameters = convert_value_to_dict(value.query)
        else:
            # We got something else, take path from pvRequest method and our mri
            # and parameters from the full value
            if self.field is not None:
                # We already know the method name
                method = self.field
            else:
                # Get the path and string "value" from the put value
                method = op.pvRequest().get("method")
                assert method, "No 'method' in pvRequest:\n%s" % op.pvRequest()
            parameters = convert_value_to_dict(value)
        path = [self.controller.mri, method]
        view = self.controller.block_view()[method]
        assert isinstance(view, Method), \
            "%s.%s is not a Method so cannot do RPC" % tuple(path)
        add_wrapper = method_return_unpacked() in view.tags

        post = Post(path=path, parameters=parameters)

        def handle_post_response(response):
            # type: (Response) -> None
            if isinstance(response, Return):
                if add_wrapper:
                    # Method gave us return unpacked (bare string or other type)
                    # so we must wrap it in a structure to send it
                    ret = {"return": response.value}
                else:
                    ret = response.value
                serialized = serialize_object(ret)
                v = convert_dict_to_value(serialized)
                op.done(v)
            else:
                if isinstance(response, Error):
                    message = stringify_error(response.message)
                else:
                    message = "BadResponse: %s" % response.to_dict()
                op.done(error=message)

        post.set_callback(handle_post_response)
        self.controller.handle_request(post).get()
 def test_concurrency(self):
     msg1 = Post(id=0,
                 path=["hello", "greet"],
                 parameters=dict(name="me", sleep=2)).to_dict()
     msg2 = Post(id=1, path=["hello", "error"]).to_dict()
     IOLoopHelper.call(self.send_messages, [msg1, msg2])
     resp = self.result.get(timeout=1)
     assert resp == dict(typeid="malcolm:core/Error:1.0",
                         id=1,
                         message="RuntimeError: You called method error()")
     resp = self.result.get(timeout=3)
     assert resp == dict(typeid="malcolm:core/Return:1.0",
                         id=0,
                         value="Hello me")
示例#4
0
 def set_value(self, value):
     args = {}
     for item in self.children:
         args[item.endpoint[-1]] = item.get_value()
         item.reset_value()
     self._state = self.RUNNING
     request = Post(self, None, self.endpoint, args)
     return request
示例#5
0
 def post(self, endpoint_str):
     # called from tornado thread
     path = endpoint_str.split("/")
     parameters = json_decode(self.get_body_argument("parameters"))
     request = Post(path=path,
                    parameters=parameters,
                    callback=self.on_response)
     self._server_part.on_request(request)
示例#6
0
 def test_concurrent(self):
     q = Queue()
     request = Subscribe(id=40, path=["hello_block", "greet"], delta=True)
     request.set_callback(q.put)
     self.controller.handle_request(request)
     # Get the initial subscribe value
     inital = q.get(timeout=0.1)
     self.assertIsInstance(inital, Delta)
     assert inital.changes[0][1]["took"]["value"] == dict(sleep=0, name="")
     assert inital.changes[0][1]["returned"]["value"] == {"return": ""}
     # Do a greet
     request = Post(id=44,
                    path=["hello_block", "greet"],
                    parameters=dict(name="me", sleep=1))
     request.set_callback(q.put)
     self.controller.handle_request(request)
     # Then an error
     request = Post(id=45, path=["hello_block", "error"])
     request.set_callback(q.put)
     self.controller.handle_request(request)
     # We should quickly get the error response first
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Error)
     assert response.id == 45
     # Then the long running greet delta
     response = q.get(timeout=3.0)
     self.assertIsInstance(response, Delta)
     assert len(response.changes) == 2
     assert response.changes[0][0] == ["took"]
     took = response.changes[0][1]
     assert took.value == dict(sleep=1, name="me")
     assert took.present == ["name", "sleep"]
     assert took.alarm == Alarm.ok
     assert response.changes[1][0] == ["returned"]
     returned = response.changes[1][1]
     assert returned.value == {"return": "Hello me"}
     assert returned.present == ["return"]
     assert returned.alarm == Alarm.ok
     # Check it took about 1s to run
     assert abs(1 - (returned.timeStamp.to_time() -
                     took.timeStamp.to_time())) < 0.4
     # And it's response
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Return)
     assert response.id == 44
     assert response.value == "Hello me"
示例#7
0
 def post(self, endpoint_str):
     # called from tornado thread
     path = endpoint_str.split("/")
     parameters = json_decode(self.request.body.decode())
     request = Post(path=path, parameters=parameters)
     self.report_request(request)
     response = yield self._queue.get()
     self.handle_response(response)
示例#8
0
 def set_value(self, value):
     args = {}
     for item in self.children:
         args[item.endpoint[-1]] = item.get_value()
         item.reset_value()
     self._state = self.RUNNING
     request = Post(path=self.endpoint, parameters=args,
                    callback=self.handle_response)
     return request
示例#9
0
 def test_counter_subscribe(self):
     q = Queue()
     # Subscribe to the value
     sub = Subscribe(id=20, path=["counting", "counter"], delta=False)
     sub.set_callback(q.put)
     self.controller.handle_request(sub)
     # Check initial return
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["typeid"] == "epics:nt/NTScalar:1.0"
     assert response.value["value"] == 0
     # Post increment()
     post = Post(id=21, path=["counting", "increment"])
     post.set_callback(q.put)
     self.controller.handle_request(post)
     # Check the value updates...
     response = q.get(timeout=1)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["value"] == 1
     # ... then we get the return
     response = q.get(timeout=1)
     self.assertIsInstance(response, Return)
     assert response.id == 21
     assert response.value is None
     # Check we can put too
     put = Put(id=22, path=["counting", "counter", "value"], value=31)
     put.set_callback(q.put)
     self.controller.handle_request(put)
     # Check the value updates...
     response = q.get(timeout=1)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["value"] == 31
     # ... then we get the return
     response = q.get(timeout=1)
     self.assertIsInstance(response, Return)
     assert response.id == 22
     assert response.value is None
     # And that there isn't anything else
     with self.assertRaises(TimeoutError):
         q.get(timeout=0.05)
示例#10
0
    def send_post(self, mri, method_name, **params):
        """Abstract method to dispatch a Post to the server

        Args:
            mri (str): The mri of the Block
            method_name (str): The name of the Method within the Block
            params: The parameters to send

        Returns:
            The return results from the server
        """
        q = Queue()
        request = Post(path=[mri, method_name], parameters=params)
        request.set_callback(q.put)
        IOLoopHelper.call(self._send_request, request)
        response = q.get()
        if isinstance(response, Error):
            raise response.message
        else:
            return response.value
示例#11
0
 def test_concurrent(self):
     q = Queue()
     request = Post(id=44,
                    path=["hello_block", "greet"],
                    parameters=dict(name="me", sleep=1))
     request.set_callback(q.put)
     self.controller.handle_request(request)
     request = Post(id=45, path=["hello_block", "error"])
     request.set_callback(q.put)
     self.controller.handle_request(request)
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Error)
     assert response.id == 45
     response = q.get(timeout=3.0)
     self.assertIsInstance(response, Return)
     assert response.id == 44
     assert response.value == "Hello me"
示例#12
0
    def call_server_method(self, method_name, parameters, returns):
        """Call method_name on the server

        Args:
            method_name (str): Name of the method
            parameters (Map): Map of arguments to be called with
            returns (Map): Returns map to fill and return
        """
        self.log_debug(dict(parameters))
        q = self.process.create_queue()
        request = Post(None, q, [self.block.name, method_name], parameters)
        self.client_comms.q.put(request)
        response = q.get()
        assert isinstance(response, Return), \
            "Expected Return, got %s" % response.typeid
        if "typeid" in response.value:
            response.value.pop("typeid")
        returns.update(response.value)
        return returns
示例#13
0
 def test_counter_subscribe(self):
     q = Queue()
     sub = Subscribe(id=20,
                     path=["counting", "counter"],
                     delta=False,
                     callback=q.put)
     self.controller.handle_request(sub)
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["typeid"] == "epics:nt/NTScalar:1.0"
     assert response.value["value"] == 0
     post = Post(id=21, path=["counting", "increment"], callback=q.put)
     self.controller.handle_request(post)
     response = q.get(timeout=1)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["value"] == 1
     response = q.get(timeout=1)
     self.assertIsInstance(response, Return)
     assert response.id == 21
     assert response.value == None
     with self.assertRaises(TimeoutError):
         q.get(timeout=0.05)
示例#14
0
    def rpc(self, pv: SharedPV, op: ServerOperation) -> None:
        value = op.value()
        if value.getID() == "epics:nt/NTURI:1.0":
            # We got an NTURI, get path from path and parameters from query
            assert value.scheme == "pva", "Can only handle NTURI with scheme=pva"
            prefix = self.controller.mri + "."
            assert value.path.startswith(
                prefix
            ), f"NTURI path '{value.path}' doesn't start with '{prefix}'"
            method = value.path[len(prefix):]
            parameters = convert_value_to_dict(value.query)
        else:
            # We got something else, take path from pvRequest method and our mri
            # and parameters from the full value
            if self.field is not None:
                # We already know the method name
                method = self.field
            else:
                # Get the path and string "value" from the put value
                method = op.pvRequest().get("method")
                assert method, f"No 'method' in pvRequest:\n{op.pvRequest()}"
            parameters = convert_value_to_dict(value)
        path = [self.controller.mri, method]
        view = self.controller.block_view()[method]
        assert isinstance(
            view,
            Method), "%s.%s is not a Method so cannot do RPC" % tuple(path)
        add_wrapper = method_return_unpacked() in view.meta.tags

        self.controller.log.debug(
            f"{self.controller.mri}: RPC method {method} called with "
            f"params {parameters}")
        post = Post(path=path, parameters=parameters)

        def handle_post_response(response: Response) -> None:
            if isinstance(response, Return):
                ret: Any
                if add_wrapper:
                    # Method gave us return unpacked (bare string or other type)
                    # so we must wrap it in a structure to send it
                    ret = {"return": response.value}
                else:
                    ret = response.value
                v = convert_dict_to_value(ret)
                if ret:
                    self.controller.log.debug(
                        f"{self.controller.mri}: RPC method {method} returned with "
                        f"value {ret}")
                else:
                    self.controller.log.debug(
                        f"{self.controller.mri}: RPC method {method} returned")
                op.done(v)
            else:
                if isinstance(response, Error):
                    message = stringify_error(response.message)
                    self.controller.log.debug(
                        f"{self.controller.mri}: RPC method {method} resulted in "
                        f"error ({message})")
                else:
                    message = f"BadResponse: {response.to_dict()}"
                    self.controller.log.debug(
                        f"{self.controller.mri}: RPC method {method} got a bad "
                        f"response ({message})")
                op.done(error=message)

        post.set_callback(handle_post_response)
        self.controller.handle_request(post).get()
示例#15
0
 def post(self, endpoint_str):
     # called from tornado thread
     path = endpoint_str.split("/")
     parameters = json_decode(self.get_body_argument("parameters"))
     request = Post(path=path, parameters=parameters)
     self.report_request(request)
 def post(self, endpoint_str):
     endpoint = endpoint_str.split("/")
     parameters = json.loads(self.get_body_argument("parameters"))
     request = Post(self, None, endpoint, parameters)
     self.servercomms.on_request(request)
示例#17
0
    def test_handle_request(self):
        q = Queue()

        request = Get(id=41, path=["mri", "myAttribute"])
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Return)
        assert response.id == 41
        assert response.value["value"] == "hello_block"
        self.part.my_attribute.meta.writeable = False
        request = Put(
            id=42, path=["mri", "myAttribute"], value="hello_block2", get=True
        )
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Error)  # not writeable
        assert response.id == 42

        self.part.my_attribute.meta.writeable = True
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Return)
        assert response.id == 42
        assert response.value == "hello_block2"

        request = Post(id=43, path=["mri", "method"])
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Return)
        assert response.id == 43
        assert response.value == "world"

        # cover the controller._handle_post path for parameters
        request = Post(id=43, path=["mri", "method"], parameters={"dummy": 1})
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Error)
        assert response.id == 43
        assert (
            str(response.message)
            == "Given keys ['dummy'], some of which aren't in allowed keys []"
        )

        request = Subscribe(id=44, path=["mri", "myAttribute"], delta=False)
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Update)
        assert response.id == 44
        assert response.value["typeid"] == "epics:nt/NTScalar:1.0"
        assert response.value["value"] == "hello_block2"

        request = Unsubscribe(id=44)
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Return)
        assert response.id == 44