コード例 #1
0
ファイル: plugin.py プロジェクト: splone/splonebox-client
    def __init__(self, name: str, desc: str, author: str, licence: str, core:
                 Core):
        """
        :param name: Name of the plugin
        :param desc: Description of the plugin
        :param author: Author of the plugin
        :param licence: License of the plugin
        :param core: Core instance
        """
        # [<name>, <description>, <author>, <license>]
        self._metadata = [name, desc, author, licence]
        self.function_meta = {}

        # active threads
        self._active_threads = {int: Thread()}

        core.set_run_handler(self._handle_run)
        self.core = core

        # A dict containing all functions this plugin wants to register
        self.functions = {}

        for f in RemoteFunction.remote_functions:
            self.functions[f.__name__] = f
            self.function_meta[f.__name__] = [f.__doc__, f.args]
コード例 #2
0
    def test_connect_functional(self):
        core = Core()

        mock_sock = mocks.connection_socket(core._rpc._connection)
        core._rpc._connection.listen = Mock()
        core._rpc._connection._init_crypto = Mock()

        core.connect("localhost", 1234)
        ip = mock_sock.connect.call_args[0][0][0]
        port = mock_sock.connect.call_args[0][0][1]

        self.assertEqual(ip, socket.gethostbyname("localhost"))
        self.assertEqual(port, 1234)
コード例 #3
0
    def test_run_incoming(self):
        mock_foo = Mock()

        def foo(a: ctypes.c_bool, b: ctypes.c_byte, c: ctypes.c_uint64,
                d: ctypes.c_int64, e: ctypes.c_double, f: ctypes.c_char_p,
                g: ctypes.c_long):
            mock_foo(a, b, c, d, e, f, g)

        RemoteFunction(foo)

        core = Core()
        plug = Plugin("foo", "bar", "bob", "alice", core)
        mock_send = mocks.core_rpc_send(core)

        # pretend that we received a message
        call = ApiRun("id", "foo", [True, b'hi', 5, -82, 7.23, "hi", 64])
        call.msg.arguments[0][0] = None  # remove plugin_id
        call.msg.arguments[0][1] = 123  # set some call id
        core._rpc._message_callback(call.msg.pack())

        # wait for execution to finish
        plug._active_threads[123].join()
        mock_foo.assert_called_with(True, b'hi', 5, -82, 7.23, "hi", 64)

        # check response
        msg = mock_send.call_args_list[0][0][0]
        self.assertEqual(msg.get_type(), 1)
        self.assertEqual(msg.get_msgid(), call.msg.get_msgid())
        self.assertEqual(msg.error, None)
        self.assertEqual(msg.response[0], 123)
コード例 #4
0
    def test_run_functional(self):
        core = Core()
        rplug = RemotePlugin("plugin_id", "foo", "bar", "bob", "alice", core)
        mock_send = mocks.rpc_connection_send(core._rpc)

        rplug.run("function", [1, "hi", 42.317, b'hi'])
        outgoing = msgpack.unpackb(mock_send.call_args[0][0])

        self.assertEqual(0, outgoing[0])
        self.assertEqual(b'run', outgoing[2])
        self.assertEqual([b'plugin_id', None], outgoing[3][0])
        self.assertEqual(b"function", outgoing[3][1])
        self.assertEqual([1, b'hi', 42.317, b'hi'], outgoing[3][2])
コード例 #5
0
    def test_10_handle_run(self):
        core = Core()
        plug = Plugin("foo", "bar", "bob", "alice", core)
        send = mocks.core_rpc_send(core)  # catch results/responses

        mock = Mock()
        mock.__name__ = "foo"
        mock.return_value = "return"
        plug.functions["foo"] = mock
        plug.function_meta["foo"] = (["", []])

        msg = MRequest()
        msg.function = "run"
        msg.arguments = [[None, 123], b'foo', [1, 1.1, "hi"]]

        error, response = plug._handle_run(msg)
        self.assertIsNotNone(plug._active_threads.get(123))

        plug._active_threads.pop(123).join()
        mock.assert_called_with([1, 1.1, "hi"])
        # request was valid  + 1x result
        self.assertEqual(send.call_count, 1)
        self.assertEqual(send.call_args_list[0][0][0].arguments[0][0], 123)
        self.assertEqual(send.call_args_list[0][0][0].arguments[1][0],
                         "return")

        # (response is sent by msgpack-rpc handler)
        self.assertEqual(response, [123])
        self.assertIsNone(error)

        send.reset_mock()  # reset call count
        msg.arguments = [[None, 123], b'mock', [1, 1.1, "hi"]]
        error, response = plug._handle_run(msg)
        # request was invalid -> error response
        self.assertEqual(error, [404, "Function does not exist!"])
        self.assertIsNone(response)
        with self.assertRaises(KeyError):
            plug._active_threads[123]

        send.reset_mock()  # reset call count
        msg.arguments = [None, b'mock', [1, 1.1, "hi"]]
        error, response = plug._handle_run(msg)
        # request was invalid -> error response
        self.assertEqual(error, [400, "Message is not a valid run call"])
        self.assertIsNone(response)

        with self.assertRaises(KeyError):
            plug._active_threads[123]
コード例 #6
0
    def test_complete_run(self):
        # In this test a plugin is created and is calling itself.
        # The called_lock is used to ensure that we receive
        # the response before the result
        called_lock = Lock()
        called_lock.acquire()

        def add(a: ctypes.c_int64, b: ctypes.c_int64):
            "add two ints"
            called_lock.acquire()
            return a + b

        RemoteFunction(add)

        core = Core()
        plug = Plugin("foo", "bar", "bob", "alice", core)
        rplug = RemotePlugin("plugin_id", "foo", "bar", "bob", "alice", core)

        mock_send = mocks.rpc_connection_send(core._rpc)
        result = rplug.run("add", [7, 8])

        # receive request
        msg = MRequest.from_unpacked(msgpack.unpackb(
            mock_send.call_args[0][0]))
        msg.arguments[0][0] = None  # remove plugin id
        msg.arguments[0][1] = 123  # set call id
        core._rpc._message_callback(msg.pack())

        # receive response
        data = mock_send.call_args_list[1][0][0]
        core._rpc._message_callback(data)

        # start execution
        called_lock.release()
        # wait for execution to finish
        plug._active_threads[123].join()
        # receive result
        data = mock_send.call_args_list[2][0][0]
        core._rpc._message_callback(data)

        self.assertEqual(result.get_result(blocking=True), 15)
        self.assertEqual(result.get_status(), 2)
        self.assertEqual(result._error, None)
        self.assertEqual(result.get_id(), 123)
コード例 #7
0
    def test_register_functional(self):
        def fun2(a: ctypes.c_bool, b: ctypes.c_byte, c: ctypes.c_uint64, d:
                 ctypes.c_int64, e: ctypes.c_double, f: ctypes.c_char_p, g:
                 ctypes.c_long):
            pass

        RemoteFunction(fun2)
        core = Core()
        plug = Plugin("foo", "bar", "bob", "alice", core)
        mock_send = mocks.rpc_connection_send(core._rpc)

        plug.register(blocking=False)
        outgoing = msgpack.unpackb(mock_send.call_args[0][0])

        self.assertEqual(0, outgoing[0])
        self.assertEqual(b'register', outgoing[2])
        self.assertEqual([b"foo", b"bar", b"bob", b"alice"], outgoing[3][0])
        self.assertIn([b'fun2', b'', [False, b'', 3, -1, 2.0, b'', -1]],
                      outgoing[3][1])
コード例 #8
0
    def test_00_register(self):
        core = Core()
        plug = Plugin("foo", "bar", "bob", "alice", core)

        rpc_send_mock = mocks.core_rpc_send(core)

        plug.register(blocking=False)
        call_args = rpc_send_mock.call_args[0][0]

        self.assertEqual(call_args._type, 0)  # 0 indicates message request

        self.assertTrue(0 <= call_args._msgid < pow(2, 32))  # valid msgid

        self.assertEqual(call_args.function, 'register')  # register request

        self.assertEqual(call_args.arguments[0],
                         ['foo', 'bar', 'bob', 'alice'])  # metadata

        self.assertEquals(
            len(call_args.arguments[1]), 0)  # no function registered
コード例 #9
0
    def test_complete_register(self):
        def fun():
            pass

        RemoteFunction(fun)
        core = Core()
        plug = Plugin("foo", "bar", "bob", "alice", core)
        mock_send = mocks.rpc_connection_send(core._rpc)

        result = plug.register(blocking=False)
        outgoing = msgpack.unpackb(mock_send.call_args_list[0][0][0])

        # validate outgoing
        self.assertEqual(0, outgoing[0])
        self.assertEqual(b'register', outgoing[2])
        self.assertEqual([b"foo", b"bar", b"bob", b"alice"], outgoing[3][0])
        self.assertIn([b'fun', b'', []], outgoing[3][1])

        # test response handling
        self.assertEqual(result.get_status(), 0)  # no response yet
        response = MResponse(outgoing[1])

        # send invalid response (Second field is set to None)
        core._rpc._handle_response(response)
        self.assertEqual(result.get_status(), -1)

        # make sure response is only handled once
        with self.assertRaises(KeyError):
            core._rpc._handle_response(response)

        # test valid response
        result = plug.register(blocking=False)
        outgoing = msgpack.unpackb(mock_send.call_args_list[1][0][0])
        response = MResponse(outgoing[1])
        response.response = []
        core._rpc._handle_response(response)
        self.assertEqual(result.get_status(), 2)

        # cleanup remote_functions
        RemoteFunction.remote_functions = {}
コード例 #10
0
def connect(addr: str, port: int):
    global __core
    __core = Core()
    __core.connect(addr, port)