def test_read_multiple_messages(self):
        # Setup:
        # ... Create an input stream with two messages
        test_bytes = b'Content-Length: 30\r\n\r\n{"method":"test", "params":{}}'
        input_stream = io.BytesIO(test_bytes + test_bytes)
        output_stream = io.BytesIO()

        # ... Create a server that uses the input and output streams
        server = JSONRPCServer(input_stream, output_stream, logger=utils.get_mock_logger())

        # ... Patch the server to not dispatch a message
        dispatch_mock = mock.MagicMock()
        server._dispatch_message = dispatch_mock

        # If: I start the server, run it for a bit, and stop it
        server.start()
        time.sleep(1)
        server.stop()
        server.wait_for_exit()

        # Then: The dispatch method should have been called twice
        expected_output = JSONRPCMessage.from_dictionary({"method": "test", "params": {}})
        self.assertEqual(len(dispatch_mock.mock_calls), 2)
        self.assertDictEqual(dispatch_mock.mock_calls[0][1][0].dictionary, expected_output.dictionary)
        self.assertDictEqual(dispatch_mock.mock_calls[1][1][0].dictionary, expected_output.dictionary)

        # Teardown: All background threads should be shut down.
        self.assertFalse(server._input_consumer.isAlive())
        self.assertFalse(server._output_consumer.isAlive())
    def test_server_init(self):
        # Setup: Create objects to init the server with
        input_stream = io.BytesIO()
        output_stream = io.BytesIO()
        logger = utils.get_mock_logger()

        # If: I create a server
        server = JSONRPCServer(input_stream, output_stream, logger=logger)

        # Then: The state should be initialized as defined
        self.assertIsInstance(server.writer, JSONRPCWriter)
        self.assertIsInstance(server.reader, JSONRPCReader)
        self.assertIs(server._logger, logger)
        self.assertEqual(server._version, '0')
        self.assertFalse(server._stop_requested)

        # ... The output queue should be empty
        self.assertIsInstance(server._output_queue, Queue)
        self.assertTrue(server._output_queue.all_tasks_done)
        self.assertDictEqual(server._notification_handlers, {})
        self.assertListEqual(server._shutdown_handlers, [])

        # ... The threads shouldn't be assigned yet
        self.assertIsNone(server._output_consumer)
        self.assertIsNone(server._input_consumer)

        # ... The built-in handlers should be assigned
        self.assertTrue('echo' in server._request_handlers)
        self.assertIsNotNone(server._request_handlers['echo'])
        self.assertTrue('version' in server._request_handlers)
        self.assertIsNotNone(server._request_handlers['version'].handler)
        self.assertTrue('shutdown' in server._request_handlers)
        self.assertIsNotNone(server._request_handlers['shutdown'].handler)
        self.assertTrue('exit' in server._request_handlers)
        self.assertIsNotNone(server._request_handlers['exit'].handler)
    def test_add_shutdown_handler(self):
        # If: I add a shutdown handler
        handler = mock.MagicMock()
        server = JSONRPCServer(None, None)
        server.add_shutdown_handler(handler)

        # Then: The shutdown handlers should contain the handler
        self.assertTrue(handler in server._shutdown_handlers)
    def test_version_request():
        # If: I send a request for the version
        rc = utils.MockRequestContext()
        server = JSONRPCServer(None, None)
        server._handle_version_request(rc, None)

        # Then: I should get a response
        rc.send_response.assert_called_once_with(server._version)
        rc.send_error.assert_not_called()
        rc.send_notification.assert_not_called()
Exemple #5
0
    def _get_service_provider(services: int = 1) -> ServiceProvider:
        # If: I create a new service provider
        server = JSONRPCServer(None, None)
        logger = utils.get_mock_logger()
        services = {
            'service_name' + str(x): TestServiceProvider._TestService
            for x in range(0, services)
        }
        sp = ServiceProvider(server, services, PG_PROVIDER_NAME, logger)

        return sp
    def test_set_notification_handler(self):
        # If: I add a notification handler
        params = IncomingMessageConfiguration('test/test', int)
        handler = mock.MagicMock()
        server = JSONRPCServer(None, None)
        server.set_notification_handler(params, handler)

        # Then: The request handler should contain the handler
        self.assertTrue(params.method in server._notification_handlers)
        self.assertIsNotNone(server._notification_handlers[params.method])
        self.assertIs(server._notification_handlers[params.method].class_, int)
        self.assertIs(server._notification_handlers[params.method].handler, handler)
    def test_dispatch_notification_no_handler():
        # If: I dispatch a message that has no handler
        logger = utils.get_mock_logger()
        message = JSONRPCMessage.create_notification('non_existent', {})
        server = JSONRPCServer(None, None, logger=logger)
        server._dispatch_message(message)

        # Then:
        # ... Nothing should have happened
        # TODO: Capture that an error was sent
        # ... A warning should have been logged
        logger.warn.assert_called_once()
    def test_shutdown_request(self):
        # If: I send a request for the service to shutdown
        rc = utils.MockRequestContext()
        handler = mock.MagicMock()
        server = JSONRPCServer(None, None, logger=utils.get_mock_logger())
        server.add_shutdown_handler(handler)
        server._handle_shutdown_request(rc, None)

        # Then:
        # ... The server should be shutting down
        self.assertTrue(server._stop_requested)

        # ... The shutdown handler should be called
        handler.assert_called_once()
    def test_notification_enqueued(self):
        # Setup: Create empty io streams
        input_stream = io.BytesIO()
        output_stream = io.BytesIO()

        # If: I submit an outbound request
        test_client = JSONRPCServer(input_stream, output_stream)
        test_client.send_notification('test/test', {'test': 'test'})

        # Then:
        # ... There should be one request in the outbound queue
        request = test_client._output_queue.get()

        # ... The queued message should match the request we sent
        self.assertEqual(request.message_method, 'test/test')
        self.assertDictEqual(request.message_params, {'test': 'test'})
    def test_dispatch_notification_normal(self):
        # Setup: Create a server with a single handler that has none for the deserialization class
        config = IncomingMessageConfiguration('test/test', _TestParams)
        handler = mock.MagicMock()
        server = JSONRPCServer(None, None, logger=utils.get_mock_logger())
        server.set_notification_handler(config, handler)

        # If: I dispatch a message that has none set for the deserialization class
        params = {}
        message = JSONRPCMessage.create_notification('test/test', params)
        server._dispatch_message(message)

        # Then:
        # ... The handler should have been called
        handler.assert_called_once()

        # ... The parameters to the handler should have been a request context and params
        self.assertIsInstance(handler.mock_calls[0][1][0], NotificationContext)
        self.assertIs(handler.mock_calls[0][1][0]._queue, server._output_queue)
        self.assertIsInstance(handler.mock_calls[0][1][1], _TestParams)
Exemple #11
0
    def test_init(self):
        # If: I create a new service provider
        server = JSONRPCServer(None, None)
        logger = utils.get_mock_logger()
        mock_service = mock.MagicMock(return_value={})
        services = {'service_name': mock_service}
        sp = ServiceProvider(server, services, PG_PROVIDER_NAME, logger)

        # Then:
        # ... The properties should return the values I set (server/logger)
        self.assertFalse(sp._is_initialized)
        self.assertIs(sp._server, server)
        self.assertIs(sp.server, server)
        self.assertIs(sp._logger, logger)
        self.assertIs(sp.logger, logger)

        # ... The services should be transformed and called
        self.assertIsInstance(sp._services, dict)
        self.assertTrue('service_name' in sp._services)
        mock_service.assert_called_once()
 def test_dispatch_invalid():
     # If: I dispatch an invalid message
     message = JSONRPCMessage('invalidType')
     server = JSONRPCServer(None, None, logger=utils.get_mock_logger())
     server._dispatch_message(message)
 def test_dispatch_response_error():
     # TODO: Replace with robust logic once error routing is implemented
     # If: I dispatch an error message
     message = JSONRPCMessage.create_error('123', 0, message='', data={})
     server = JSONRPCServer(None, None, logger=utils.get_mock_logger())
     server._dispatch_message(message)
 def test_dispatch_response_success():
     # TODO: Replace with robust logic once response routing is implemented
     # If: I dispatch a response message
     message = JSONRPCMessage.create_response('123', {})
     server = JSONRPCServer(None, None, logger=utils.get_mock_logger())
     server._dispatch_message(message)