forked from aniani/vim
patch 8.2.4788: large payload for LSP message not tested
Problem: Large payload for LSP message not tested. Solution: Add a test with a large LSP payload. (Yegappan Lakshmanan, closes #10223)
This commit is contained in:
committed by
Bram Moolenaar
parent
9bd3ce22e3
commit
bac9a9e5c2
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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:
|
||||
|
@@ -746,6 +746,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
4788,
|
||||
/**/
|
||||
4787,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user