#830 Implement a socket wrapper API for use with LSP connections

This commit is contained in:
w0rp
2018-07-02 23:49:47 +01:00
parent b637b35ea8
commit 01c68fedd6
7 changed files with 340 additions and 36 deletions

33
test/dumb_tcp_client.py Normal file
View File

@@ -0,0 +1,33 @@
"""
This is just a script for testing that the dumb TCP server actually works
correctly, for verifying that problems with tests are in Vim. Pass the
same port number given to the test server to check that it's working.
"""
import socket
import sys
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex(('127.0.0.1', int(sys.argv[1])))
if result:
sock.close()
sys.exit("Couldn't connect to the socket!")
data_sent = 'x' * 1024
sock.send(data_sent)
data_received = sock.recv(1024)
if data_sent != data_received:
sock.close()
sys.exit("Data sent didn't match data received.")
sock.close()
print("Everything was just fine.")
if __name__ == "__main__":
main()

40
test/dumb_tcp_server.py Normal file
View File

@@ -0,0 +1,40 @@
"""
This Python script creates a TCP server that does nothing but send its input
back to the client that connects to it. Only one argument must be given, a port
to bind to.
"""
import os
import socket
import sys
def main():
if len(sys.argv) < 2 or not sys.argv[1].isdigit():
sys.exit('You must specify a port number')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', int(sys.argv[1])))
sock.listen(0)
pid = os.fork()
if pid:
print(pid)
sys.exit()
while True:
connection = sock.accept()[0]
connection.settimeout(5)
while True:
try:
connection.send(connection.recv(1024))
except socket.timeout:
break
connection.close()
if __name__ == "__main__":
main()

View File

@@ -18,67 +18,67 @@ After:
delfunction RawCallback
Execute (ALE should handle empty Lists for the lines):
let g:last_line = ale#job#JoinNeovimOutput(1, '', [], 'nl', function('LineCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, '', [], 'nl', function('LineCallback'))
AssertEqual [], g:lines
AssertEqual '', g:last_line
Execute (ALE should pass on full lines for NeoVim):
let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', 'y', ''], 'nl', function('LineCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x', 'y', ''], 'nl', function('LineCallback'))
AssertEqual ['x', 'y'], g:lines
AssertEqual '', g:last_line
Execute (ALE should pass on a single long line):
let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x'], 'nl', function('LineCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x'], 'nl', function('LineCallback'))
AssertEqual [], g:lines
AssertEqual 'x', g:last_line
Execute (ALE should handle just a single line of output):
let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', ''], 'nl', function('LineCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x', ''], 'nl', function('LineCallback'))
AssertEqual ['x'], g:lines
AssertEqual '', g:last_line
Execute (ALE should join two incomplete pieces of large lines together):
let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y'], 'nl', function('LineCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, 'x', ['y'], 'nl', function('LineCallback'))
AssertEqual [], g:lines
AssertEqual 'xy', g:last_line
Execute (ALE join incomplete lines, and set new ones):
let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y', 'z', 'a'], 'nl', function('LineCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, 'x', ['y', 'z', 'a'], 'nl', function('LineCallback'))
AssertEqual ['xy', 'z'], g:lines
AssertEqual 'a', g:last_line
Execute (ALE join incomplete lines, and set new ones, with two elements):
let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y', 'z'], 'nl', function('LineCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, 'x', ['y', 'z'], 'nl', function('LineCallback'))
AssertEqual ['xy'], g:lines
AssertEqual 'z', g:last_line
Execute (ALE should pass on full lines for NeoVim for raw data):
let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', 'y', ''], 'raw', function('RawCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x', 'y', ''], 'raw', function('RawCallback'))
AssertEqual "x\ny\n", g:data
AssertEqual '', g:last_line
Execute (ALE should pass on a single long line):
let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x'], 'raw', function('RawCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x'], 'raw', function('RawCallback'))
AssertEqual 'x', g:data
AssertEqual '', g:last_line
Execute (ALE should handle just a single line of output):
let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', ''], 'raw', function('RawCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x', ''], 'raw', function('RawCallback'))
AssertEqual "x\n", g:data
AssertEqual '', g:last_line
Execute (ALE should pass on two lines and one incomplete one):
let g:last_line = ale#job#JoinNeovimOutput(1, '', ['y', 'z', 'a'], 'raw', function('RawCallback'))
let g:last_line = ale#util#JoinNeovimOutput(1, '', ['y', 'z', 'a'], 'raw', function('RawCallback'))
AssertEqual "y\nz\na", g:data
AssertEqual '', g:last_line

View File

@@ -0,0 +1,90 @@
Before:
let g:can_run_socket_tests = !has('win32')
\ && (exists('*ch_close') || exists('*chanclose'))
if g:can_run_socket_tests
call ale#test#SetDirectory('/testplugin/test')
let g:channel_id_received = 0
let g:data_received = ''
function! WaitForData(expected_data, timeout) abort
let l:ticks = 0
while l:ticks < a:timeout
" Sleep first, so we can switch to the callback.
let l:ticks += 10
sleep 10ms
if g:data_received is# a:expected_data
break
endif
endwhile
endfunction
function! TestCallback(channel_id, data) abort
let g:channel_id_received = a:channel_id
let g:data_received .= a:data
endfunction
let g:port = 10347
let g:pid = str2nr(system(
\ 'python'
\ . ' ' . ale#Escape(g:dir . '/dumb_tcp_server.py')
\ . ' ' . g:port
\))
endif
After:
if g:can_run_socket_tests
call ale#test#RestoreDirectory()
unlet! g:channel_id_received
unlet! g:data_received
unlet! g:channel_id
delfunction WaitForData
delfunction TestCallback
if has_key(g:, 'pid')
call system('kill ' . g:pid)
endif
unlet! g:pid
unlet! g:port
endif
unlet! g:can_run_socket_tests
Execute(Sending and receiving connections to sockets should work):
if g:can_run_socket_tests
let g:channel_id = ale#socket#Open(
\ '127.0.0.1:' . g:port,
\ {'callback': function('TestCallback')}
\)
Assert g:channel_id >= 0, 'The socket was not opened!'
call ale#socket#Send(g:channel_id, 'hello')
call ale#socket#Send(g:channel_id, ' world')
AssertEqual 1, ale#socket#IsOpen(g:channel_id)
" Wait up to 1 second for the expected data to arrive.
call WaitForData('hello world', 1000)
AssertEqual g:channel_id, g:channel_id_received
AssertEqual 'hello world', g:data_received
call ale#socket#Close(g:channel_id)
AssertEqual 0, ale#socket#IsOpen(g:channel_id)
endif
" NeoVim versions which can't connect to sockets should just fail.
if has('nvim') && !exists('*chanclose')
AssertEqual -1, ale#socket#Open(
\ '127.0.0.1:1111',
\ {'callback': function('function')}
\)
endif