diff options
author | Yegappan Lakshmanan <yegappan@yahoo.com> | 2023-09-21 16:36:28 +0200 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2023-09-21 16:36:28 +0200 |
commit | 1926ae41845c3b6e2045b29225365c8a2e4eb1da (patch) | |
tree | 4244ed2884cc22c4cbc7383c91f4d3fc3283ee46 /src/testdir | |
parent | db54e989b5cff3cc6442dfc500e3962cc1c0b6d0 (diff) |
patch 9.0.1924: LSP server message still wrongly handled (after 9.0.1922)v9.0.1924
Problem: LSP server message still wrongly handled (after 9.0.1922)
Solution: Handle 'method' messages properly, don't discard them, add
tests.
closes: #13141
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Diffstat (limited to 'src/testdir')
-rw-r--r-- | src/testdir/test_channel.vim | 21 | ||||
-rw-r--r-- | src/testdir/test_channel_lsp.py | 66 |
2 files changed, 68 insertions, 19 deletions
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index 5a35083248..edfd56e0ba 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -2481,6 +2481,14 @@ endfunc " Test for the 'lsp' channel mode func LspCb(chan, msg) call add(g:lspNotif, a:msg) + if a:msg->has_key('method') + " Requests received from the LSP server + if a:msg['method'] == 'server-req-in-middle' + \ && a:msg['params']['text'] == 'server-req' + call ch_sendexpr(a:chan, #{method: 'server-req-in-middle-resp', + \ id: a:msg['id'], params: #{text: 'client-resp'}}) + endif + endif endfunc func LspOtCb(chan, msg) @@ -2652,6 +2660,19 @@ func LspTests(port) " send a ping to make sure communication still works call assert_equal('alive', ch_evalexpr(ch, #{method: 'ping'}).result) + " Test for processing a request message from the server while the client + " is waiting for a response with the same identifier. + let g:lspNotif = [] + let resp = ch_evalexpr(ch, #{method: 'server-req-in-middle', + \ params: #{text: 'client-req'}}) + call assert_equal(#{jsonrpc: '2.0', id: 28, + \ result: #{text: 'server-resp'}}, resp) + call assert_equal([ + \ #{id: -1, jsonrpc: '2.0', method: 'server-req-in-middle', + \ params: #{text: 'server-notif'}}, + \ #{id: 28, jsonrpc: '2.0', method: 'server-req-in-middle', + \ params: #{text: 'server-req'}}], g:lspNotif) + " Test for invoking an unsupported method let resp = ch_evalexpr(ch, #{method: 'xyz', params: {}}, #{timeout: 200}) call assert_equal({}, resp) diff --git a/src/testdir/test_channel_lsp.py b/src/testdir/test_channel_lsp.py index eccb8937f0..887f6974e1 100644 --- a/src/testdir/test_channel_lsp.py +++ b/src/testdir/test_channel_lsp.py @@ -29,7 +29,20 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): with open("Xlspserver.log", "a") as myfile: myfile.write(msg) - def send_lsp_msg(self, msgid, resp_dict): + def send_lsp_req(self, msgid, method, params): + v = {'jsonrpc': '2.0', 'id': msgid, 'method': method} + if len(params) != 0: + v['params'] = params + s = json.dumps(v) + req = "Content-Length: " + str(len(s)) + "\r\n" + req += "Content-Type: application/vscode-jsonrpc; charset=utf-8\r\n" + req += "\r\n" + req += s + if self.debug: + self.debuglog("SEND: ({0} bytes) '{1}'\n".format(len(req), req)) + self.request.sendall(req.encode('utf-8')) + + def send_lsp_resp(self, msgid, resp_dict): v = {'jsonrpc': '2.0', 'result': resp_dict} if msgid != -1: v['id'] = msgid @@ -118,56 +131,56 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): def do_ping(self, payload): time.sleep(0.2) - self.send_lsp_msg(payload['id'], 'alive') + self.send_lsp_resp(payload['id'], 'alive') def do_echo(self, payload): - self.send_lsp_msg(-1, payload) + self.send_lsp_resp(-1, payload) def do_simple_rpc(self, payload): # test for a simple RPC request - self.send_lsp_msg(payload['id'], 'simple-rpc') + self.send_lsp_resp(payload['id'], 'simple-rpc') def do_rpc_with_notif(self, payload): # test for sending a notification before replying to a request message - self.send_lsp_msg(-1, 'rpc-with-notif-notif') + self.send_lsp_resp(-1, 'rpc-with-notif-notif') # sleep for some time to make sure the notification is delivered time.sleep(0.2) - self.send_lsp_msg(payload['id'], 'rpc-with-notif-resp') + self.send_lsp_resp(payload['id'], 'rpc-with-notif-resp') def do_wrong_payload(self, payload): # test for sending a non dict payload self.send_wrong_payload() time.sleep(0.2) - self.send_lsp_msg(-1, 'wrong-payload') + self.send_lsp_resp(-1, 'wrong-payload') def do_large_payload(self, payload): # test for sending a large (> 64K) payload - self.send_lsp_msg(payload['id'], payload) + self.send_lsp_resp(payload['id'], payload) def do_rpc_resp_incorrect_id(self, payload): - self.send_lsp_msg(-1, 'rpc-resp-incorrect-id-1') - self.send_lsp_msg(-1, 'rpc-resp-incorrect-id-2') - self.send_lsp_msg(1, 'rpc-resp-incorrect-id-3') + self.send_lsp_resp(-1, 'rpc-resp-incorrect-id-1') + self.send_lsp_resp(-1, 'rpc-resp-incorrect-id-2') + self.send_lsp_resp(1, 'rpc-resp-incorrect-id-3') time.sleep(0.2) - self.send_lsp_msg(payload['id'], 'rpc-resp-incorrect-id-4') + self.send_lsp_resp(payload['id'], 'rpc-resp-incorrect-id-4') def do_simple_notif(self, payload): # notification message test - self.send_lsp_msg(-1, 'simple-notif') + self.send_lsp_resp(-1, 'simple-notif') def do_multi_notif(self, payload): # send multiple notifications - self.send_lsp_msg(-1, 'multi-notif1') - self.send_lsp_msg(-1, 'multi-notif2') + self.send_lsp_resp(-1, 'multi-notif1') + self.send_lsp_resp(-1, 'multi-notif2') def do_msg_with_id(self, payload): - self.send_lsp_msg(payload['id'], 'msg-with-id') + self.send_lsp_resp(payload['id'], 'msg-with-id') def do_msg_specific_cb(self, payload): - self.send_lsp_msg(payload['id'], 'msg-specific-cb') + self.send_lsp_resp(payload['id'], 'msg-specific-cb') def do_server_req(self, payload): - self.send_lsp_msg(201, {'method': 'checkhealth', 'params': {'a': 20}}) + self.send_lsp_resp(201, {'method': 'checkhealth', 'params': {'a': 20}}) def do_extra_hdr_fields(self, payload): self.send_extra_hdr_fields(payload['id'], 'extra-hdr-fields') @@ -190,6 +203,19 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): def do_empty_payload(self, payload): self.send_empty_payload() + def do_server_req_in_middle(self, payload): + # Send a notification message to the client in the middle of processing + # a request message from the client + self.send_lsp_req(-1, 'server-req-in-middle', {'text': 'server-notif'}) + # Send a request message to the client in the middle of processing a + # request message from the client. + self.send_lsp_req(payload['id'], 'server-req-in-middle', {'text': 'server-req'}) + + def do_server_req_in_middle_resp(self, payload): + # After receiving a response from the client send the response to the + # client request. + self.send_lsp_resp(payload['id'], {'text': 'server-resp'}) + def process_msg(self, msg): try: decoded = json.loads(msg) @@ -213,7 +239,9 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): 'hdr-with-wrong-len': self.do_hdr_with_wrong_len, 'hdr-with-negative-len': self.do_hdr_with_negative_len, 'empty-header': self.do_empty_header, - 'empty-payload': self.do_empty_payload + 'empty-payload': self.do_empty_payload, + 'server-req-in-middle': self.do_server_req_in_middle, + 'server-req-in-middle-resp': self.do_server_req_in_middle_resp, } if decoded['method'] in test_map: test_map[decoded['method']](decoded) |