summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2022-04-19 10:25:13 +0100
committerBram Moolenaar <Bram@vim.org>2022-04-19 10:25:13 +0100
commitbac9a9e5c233dcf9cf734c61e4e4311fe57eccd1 (patch)
tree6f39b0b5f9405ca4791d568b5c83ee08c5fb7564
parent9bd3ce22e36b5760a5e22e7d34d1bd6a3411258e (diff)
patch 8.2.4788: large payload for LSP message not testedv8.2.4788
Problem: Large payload for LSP message not tested. Solution: Add a test with a large LSP payload. (Yegappan Lakshmanan, closes #10223)
-rw-r--r--src/channel.c2
-rw-r--r--src/testdir/test_channel.vim12
-rw-r--r--src/testdir/test_channel_lsp.py49
-rw-r--r--src/version.c2
4 files changed, 46 insertions, 19 deletions
diff --git a/src/channel.c b/src/channel.c
index b981af4006..87dc00cd0c 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -2031,6 +2031,8 @@ channel_consume(channel_T *channel, ch_part_T part, int len)
* Collapses the first and second buffer for "channel"/"part".
* Returns FAIL if that is not possible.
* When "want_nl" is TRUE collapse more buffers until a NL is found.
+ * When the channel part mode is "lsp", collapse all the buffers as the http
+ * header and the JSON content can be present in multiple buffers.
*/
int
channel_collapse(channel_T *channel, ch_part_T part, int want_nl)
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index 6fef421e56..e156fa6870 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -2466,7 +2466,7 @@ func LspOtCb(chan, msg)
endfunc
func LspTests(port)
- " call ch_logfile('Xlsprpc.log', 'w')
+ " call ch_logfile('Xlspclient.log', 'w')
let ch = ch_open(s:localhost .. a:port, #{mode: 'lsp', callback: 'LspCb'})
if ch_status(ch) == "fail"
call assert_report("Can't open the lsp channel")
@@ -2620,6 +2620,16 @@ func LspTests(port)
" send a ping to make sure communication still works
call assert_equal('alive', ch_evalexpr(ch, #{method: 'ping'}).result)
+ " Test for a large payload
+ let content = repeat('abcdef', 11000)
+ let resp = ch_evalexpr(ch, #{method: 'large-payload',
+ \ params: #{text: content}})
+ call assert_equal(#{jsonrpc: '2.0', id: 26, result:
+ \ #{method: 'large-payload', jsonrpc: '2.0', id: 26,
+ \ params: #{text: content}}}, resp)
+ " send a ping to make sure communication still works
+ call assert_equal('alive', ch_evalexpr(ch, #{method: 'ping'}).result)
+
" 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 fb8ed2243f..ea0fd1034a 100644
--- a/src/testdir/test_channel_lsp.py
+++ b/src/testdir/test_channel_lsp.py
@@ -24,6 +24,11 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def setup(self):
self.request.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+ def debuglog(self, msg):
+ if self.debug:
+ with open("Xlspserver.log", "a") as myfile:
+ myfile.write(msg)
+
def send_lsp_msg(self, msgid, resp_dict):
v = {'jsonrpc': '2.0', 'result': resp_dict}
if msgid != -1:
@@ -34,8 +39,7 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
resp += "\r\n"
resp += s
if self.debug:
- with open("Xlspdebug.log", "a") as myfile:
- myfile.write("\n=> send\n" + resp)
+ self.debuglog("SEND: ({0} bytes) '{1}'\n".format(len(resp), resp))
self.request.sendall(resp.encode('utf-8'))
def send_wrong_payload(self):
@@ -136,6 +140,10 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
time.sleep(0.2)
self.send_lsp_msg(-1, 'wrong-payload')
+ def do_large_payload(self, payload):
+ # test for sending a large (> 64K) payload
+ self.send_lsp_msg(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')
@@ -185,8 +193,6 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def process_msg(self, msg):
try:
decoded = json.loads(msg)
- print("Decoded:")
- print(str(decoded))
if 'method' in decoded:
test_map = {
'ping': self.do_ping,
@@ -194,6 +200,7 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
'simple-rpc': self.do_simple_rpc,
'rpc-with-notif': self.do_rpc_with_notif,
'wrong-payload': self.do_wrong_payload,
+ 'large-payload': self.do_large_payload,
'rpc-resp-incorrect-id': self.do_rpc_resp_incorrect_id,
'simple-notif': self.do_simple_notif,
'multi-notif': self.do_multi_notif,
@@ -211,28 +218,40 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
if decoded['method'] in test_map:
test_map[decoded['method']](decoded)
else:
- print("Error: Unsupported method: " + decoded['method'])
+ self.debuglog("Error: Unsupported method - " + decoded['method'] + "\n")
else:
- print("Error: 'method' field is not found")
+ self.debuglog("Error: 'method' field is not found\n")
except ValueError:
- print("json decoding failed")
+ self.debuglog("Error: json decoding failed\n")
def process_msgs(self, msgbuf):
while True:
sidx = msgbuf.find('Content-Length: ')
if sidx == -1:
+ # partial message received
return msgbuf
sidx += 16
eidx = msgbuf.find('\r\n')
if eidx == -1:
+ # partial message received
return msgbuf
msglen = int(msgbuf[sidx:eidx])
hdrend = msgbuf.find('\r\n\r\n')
if hdrend == -1:
+ # partial message received
+ return msgbuf
+
+ if msglen > len(msgbuf[hdrend + 4:]):
+ if self.debug:
+ self.debuglog("Partial message ({0} bytes)\n".format(len(msgbuf)))
+ # partial message received
return msgbuf
+ if self.debug:
+ self.debuglog("Complete message ({0} bytes) received\n".format(msglen))
+
# Remove the header
msgbuf = msgbuf[hdrend + 4:]
payload = msgbuf[:msglen]
@@ -243,27 +262,25 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
msgbuf = msgbuf[msglen:]
def handle(self):
- print("=== socket opened ===")
self.debug = False
+ self.debuglog("=== socket opened ===\n")
msgbuf = ''
while True:
try:
received = self.request.recv(4096).decode('utf-8')
except socket.error:
- print("=== socket error ===")
+ self.debuglog("=== socket error ===\n")
break
except IOError:
- print("=== socket closed ===")
+ self.debuglog("=== socket closed ===\n")
break
if received == '':
- print("=== socket closed ===")
+ self.debuglog("=== socket closed ===\n")
break
- print("\nReceived:\n{0}".format(received))
# Write the received lines into the file for debugging
if self.debug:
- with open("Xlspdebug.log", "a") as myfile:
- myfile.write("\n<= recv\n" + received)
+ self.debuglog("RECV: ({0} bytes) '{1}'\n".format(len(received), received))
# Can receive more than one line in a response or a partial line.
# Accumulate all the received characters and process one line at
@@ -287,8 +304,6 @@ def main(host, port, server_class=ThreadedTCPServer):
if len(sys.argv) >= 2 and sys.argv[1] == 'delay':
port = 13684
writePortInFile(port)
-
- print("Wait for it...")
time.sleep(0.5)
server = server_class((host, port), ThreadedTCPRequestHandler)
@@ -301,8 +316,6 @@ def main(host, port, server_class=ThreadedTCPServer):
writePortInFile(port)
- print("Listening on port {0}".format(port))
-
# Main thread terminates, but the server continues running
# until server.shutdown() is called.
try:
diff --git a/src/version.c b/src/version.c
index c221c28ad8..411ea1ad8d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4788,
+/**/
4787,
/**/
4786,