def test_from_dict_response_invalid(self): # If: I create an invalid response from a dictionary # Then: I should get an exception with self.assertRaises(ValueError): JSONRPCMessage.from_dictionary({ 'id': '10', 'error': {}, 'result': {} })
def test_from_dict_invalid_notification(self): # If: I create a notification message from a dictionary that is missing a method # Then: I should get an exception with self.assertRaises(ValueError): JSONRPCMessage.from_dictionary({ 'params': {} # No ID = Notification # No method = Invalid })
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_from_dict_request(self): # If: I create a request from a dictionary message = JSONRPCMessage.from_dictionary({ 'id': '10', 'method': 'test/test', 'params': {} }) # Then: # ... The message should have all the properties I defined self.assertIsNotNone(message) self.assertEqual(message.message_id, '10') self.assertEqual(message.message_method, "test/test") self.assertDictEqual(message.message_params, {}) self.assertIsNone(message.message_result) self.assertIsNone(message.message_error) self.assertEqual(message.message_type, JSONRPCMessageType.Request) # ... The dictionary should have the same values stored dictionary = message.dictionary self.assertIsNotNone(dictionary) self.assertDictEqual(dictionary, { 'jsonrpc': '2.0', 'method': 'test/test', 'params': {}, 'id': '10' })
def test_request_context_init_test(self): # If: I create a request context queue = Queue() message = JSONRPCMessage.from_dictionary({'id': '123', 'method': 'test/text/', 'params': {}}) rc = RequestContext(message, queue) # Then: The internal state should be set up correctly self.assertIs(rc._message, message) self.assertIs(rc._queue, queue)
def test_initialization(self, mockdataeditorsession): queue = Queue() message = JSONRPCMessage.from_dictionary({ 'id': '123', 'method': 'edit/initialize', 'params': {} }) request_context = RequestContext(message, queue) self._service_under_test._edit_initialize( request_context, self._initialize_edit_request) mockdataeditorsession.assert_called()
def read_message(self): """ Read JSON RPC message from buffer :raises ValueError: if the body-content cannot be serialized to a JSON object :return: JsonRpcMessage that was received """ # Using a mutable list to hold the value since an immutable string passed by reference won't # change the value content = [''] try: while not self._needs_more_data or self._read_next_chunk(): # We should have all the data we need to form a message in the buffer. If we need # more data to form the next message, this flag will be reset by an attempt to form # a header or content self._needs_more_data = False # If we can't read a header, read the next chunk if self._read_state is self.ReadState.Header and not self._try_read_headers(): self._needs_more_data = True continue # If we read the header, try the content. If that fails, read the next chunk if self._read_state is self.ReadState.Content and not self._try_read_content(content): self._needs_more_data = True continue # We have the content break # Uncomment for verbose logging # if self._logger is not None: # self._logger.debug(f'{content[0]}') return JSONRPCMessage.from_dictionary(json.loads(content[0])) except ValueError as ve: # Response has invalid json object if self._logger is not None: self._logger.warn('JSON RPC reader on read_message() encountered exception: {}'.format(ve)) raise finally: # Remove the bytes that have been read self._trim_buffer_and_resize(self._read_offset)
def test_request_context_send_response(self): # Setup: Create a request context queue = Queue() in_message = JSONRPCMessage.from_dictionary({'id': '123', 'method': 'test/text/', 'params': {}}) rc = RequestContext(in_message, queue) # If: I send a response via the response handler params = {} rc.send_response(params) # Then: # ... There should be a message in the outbound queue self.assertTrue(queue.not_empty) out_message = queue.get_nowait() self.assertIsInstance(out_message, JSONRPCMessage) # .. The message must be a response with the proper id self.assertEqual(out_message.message_type, JSONRPCMessageType.ResponseSuccess) self.assertEqual(out_message.message_id, '123') self.assertEqual(out_message.message_result, params)
def test_request_context_send_notification(self): # Setup: Create a request context queue = Queue() in_message = JSONRPCMessage.from_dictionary({'id': '123', 'method': 'test/text/', 'params': {}}) rc = RequestContext(in_message, queue) # If: I send a notification params = {} method = 'test/test' rc.send_notification(method, params) # Then: # ... There should be a message in the outbound queue self.assertTrue(queue.not_empty) out_message = queue.get_nowait() self.assertIsInstance(out_message, JSONRPCMessage) # .. The message must be a response with the proper id self.assertEqual(out_message.message_type, JSONRPCMessageType.Notification) self.assertIsNone(out_message.message_id) self.assertEqual(out_message.message_params, params)
def test_from_dict_error(self): # If: I create an error response from a dictionary message = JSONRPCMessage.from_dictionary({ 'id': '10', 'error': { 'code': 20, 'message': 'msg', 'data': {} } }) # Then: # ... The message should have all the properties I defined self.assertIsNotNone(message) self.assertEqual(message.message_id, '10') self.assertIsNone(message.message_method) self.assertIsNone(message.message_params) self.assertIsNone(message.message_result) self.assertIsNotNone(message.message_error) self.assertEqual(message.message_error['code'], 20) self.assertEqual(message.message_error['message'], 'msg') self.assertDictEqual(message.message_error['data'], {}) self.assertEqual(message.message_type, JSONRPCMessageType.ResponseError) # ... The dictionary should have the same values stored dictionary = message.dictionary self.assertIsNotNone(dictionary) self.assertDictEqual( dictionary, { 'jsonrpc': '2.0', 'error': { 'code': 20, 'message': 'msg', 'data': {} }, 'id': '10' })
def test_from_dict_response(self): # If: I create a successful response from a dictionary message = JSONRPCMessage.from_dictionary({'id': '10', 'result': {}}) # Then: # ... The message should have all the properties I defined self.assertIsNotNone(message) self.assertEqual(message.message_id, '10') self.assertIsNone(message.message_method) self.assertIsNone(message.message_params) self.assertIsNotNone(message.message_result) self.assertDictEqual(message.message_result, {}) self.assertIsNone(message.message_error) self.assertEqual(message.message_type, JSONRPCMessageType.ResponseSuccess) # ... The dictionary should have the same values stored dictionary = message.dictionary self.assertIsNotNone(dictionary) self.assertDictEqual(dictionary, { 'jsonrpc': '2.0', 'result': {}, 'id': '10' })
def test_from_dict_request_invalid(self): # If: I create an invalid request from a dictionary # Then: I should get an exception with self.assertRaises(ValueError): JSONRPCMessage.from_dictionary({'id': '10', 'params': {}})