blob: e894c09cc100b9eeaf3063dc23c0cd42201a3e7a [file] [log] [blame]
Bram Moolenaard7ece102016-02-02 23:23:02 +01001" Test for channel functions.
2scriptencoding utf-8
3
Bram Moolenaare2469252016-02-04 10:54:34 +01004if !has('channel')
5 finish
6endif
7
8" This test requires the Python command to run the test server.
Bram Moolenaara8343c12016-02-04 22:09:48 +01009" This most likely only works on Unix and Windows.
Bram Moolenaara0f9cd12016-02-03 20:13:24 +010010if has('unix')
Bram Moolenaar835dc632016-02-07 14:27:38 +010011 " We also need the job feature or the pkill command to make sure the server
12 " can be stopped.
13 if !(executable('python') && (has('job') || executable('pkill')))
Bram Moolenaara0f9cd12016-02-03 20:13:24 +010014 finish
15 endif
Bram Moolenaara8343c12016-02-04 22:09:48 +010016elseif has('win32')
Bram Moolenaara0f9cd12016-02-03 20:13:24 +010017 " Use Python Launcher for Windows (py.exe).
18 if !executable('py')
19 finish
20 endif
21else
Bram Moolenaard6a8d482016-02-10 20:32:20 +010022 " Can't run this test.
Bram Moolenaard7ece102016-02-02 23:23:02 +010023 finish
24endif
25
Bram Moolenaara4833262016-02-09 23:33:25 +010026let s:chopt = has('macunix') ? {'waittime' : 1} : {}
Bram Moolenaar3b05b132016-02-03 23:25:07 +010027
Bram Moolenaard6a8d482016-02-10 20:32:20 +010028" Run "testfunc" after sarting the server and stop the server afterwards.
29func s:run_server(testfunc)
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010030 " The Python program writes the port number in Xportnr.
31 call delete("Xportnr")
32
Bram Moolenaard6a8d482016-02-10 20:32:20 +010033 try
34 if has('job')
35 let s:job = job_start("python test_channel.py")
36 elseif has('win32')
37 silent !start cmd /c start "test_channel" py test_channel.py
38 else
39 silent !python test_channel.py&
Bram Moolenaard7ece102016-02-02 23:23:02 +010040 endif
Bram Moolenaard7ece102016-02-02 23:23:02 +010041
Bram Moolenaard6a8d482016-02-10 20:32:20 +010042 " Wait for up to 2 seconds for the port number to be there.
43 let cnt = 20
44 let l = []
45 while cnt > 0
46 try
47 let l = readfile("Xportnr")
48 catch
49 endtry
50 if len(l) >= 1
51 break
52 endif
53 sleep 100m
54 let cnt -= 1
55 endwhile
56 call delete("Xportnr")
57
58 if len(l) == 0
59 " Can't make the connection, give up.
60 call assert_false(1, "Can't start test_channel.py")
61 return -1
62 endif
63 let port = l[0]
64
65 call call(function(a:testfunc), [port])
66 catch
67 call assert_false(1, "Caught exception: " . v:exception)
68 finally
Bram Moolenaara0f9cd12016-02-03 20:13:24 +010069 call s:kill_server()
Bram Moolenaard6a8d482016-02-10 20:32:20 +010070 endtry
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010071endfunc
72
73func s:kill_server()
Bram Moolenaar835dc632016-02-07 14:27:38 +010074 if has('job')
Bram Moolenaard6a8d482016-02-10 20:32:20 +010075 if exists('s:job')
76 call job_stop(s:job)
77 unlet s:job
78 endif
Bram Moolenaar835dc632016-02-07 14:27:38 +010079 elseif has('win32')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010080 call system('taskkill /IM py.exe /T /F /FI "WINDOWTITLE eq test_channel"')
81 else
Bram Moolenaar608a8912016-02-03 22:39:51 +010082 call system("pkill -f test_channel.py")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010083 endif
84endfunc
85
Bram Moolenaara07fec92016-02-05 21:04:08 +010086let s:responseMsg = ''
87func s:RequestHandler(handle, msg)
88 let s:responseHandle = a:handle
89 let s:responseMsg = a:msg
90endfunc
91
Bram Moolenaard6a8d482016-02-10 20:32:20 +010092func s:communicate(port)
93 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +010094 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +010095 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010096 return
97 endif
Bram Moolenaard7ece102016-02-02 23:23:02 +010098
99 " Simple string request and reply.
100 call assert_equal('got it', ch_sendexpr(handle, 'hello!'))
101
102 " Request that triggers sending two ex commands. These will usually be
103 " handled before getting the response, but it's not guaranteed, thus wait a
104 " tiny bit for the commands to get executed.
105 call assert_equal('ok', ch_sendexpr(handle, 'make change'))
106 sleep 10m
107 call assert_equal('added1', getline(line('$') - 1))
108 call assert_equal('added2', getline('$'))
109
Bram Moolenaarf4160862016-02-05 23:09:12 +0100110 call assert_equal('ok', ch_sendexpr(handle, 'do normal'))
111 sleep 10m
112 call assert_equal('added more', getline('$'))
113
Bram Moolenaara07fec92016-02-05 21:04:08 +0100114 " Send a request with a specific handler.
115 call ch_sendexpr(handle, 'hello!', 's:RequestHandler')
116 sleep 10m
Bram Moolenaar77073442016-02-13 23:23:53 +0100117 if !exists('s:responseHandle')
118 call assert_false(1, 's:responseHandle was not set')
119 else
120 call assert_equal(handle, s:responseHandle)
121 endif
Bram Moolenaara07fec92016-02-05 21:04:08 +0100122 call assert_equal('got it', s:responseMsg)
123
Bram Moolenaar77073442016-02-13 23:23:53 +0100124 unlet s:responseHandle
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100125 let s:responseMsg = ''
126 call ch_sendexpr(handle, 'hello!', function('s:RequestHandler'))
127 sleep 10m
Bram Moolenaar77073442016-02-13 23:23:53 +0100128 if !exists('s:responseHandle')
129 call assert_false(1, 's:responseHandle was not set')
130 else
131 call assert_equal(handle, s:responseHandle)
132 endif
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100133 call assert_equal('got it', s:responseMsg)
134
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100135 " Send an eval request that works.
136 call assert_equal('ok', ch_sendexpr(handle, 'eval-works'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100137 sleep 10m
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100138 call assert_equal([-1, 'foo123'], ch_sendexpr(handle, 'eval-result'))
139
140 " Send an eval request that fails.
141 call assert_equal('ok', ch_sendexpr(handle, 'eval-fails'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100142 sleep 10m
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100143 call assert_equal([-2, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
144
Bram Moolenaar55fab432016-02-07 16:53:13 +0100145 " Send an eval request that works but can't be encoded.
146 call assert_equal('ok', ch_sendexpr(handle, 'eval-error'))
147 sleep 10m
148 call assert_equal([-3, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
149
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100150 " Send a bad eval request. There will be no response.
151 call assert_equal('ok', ch_sendexpr(handle, 'eval-bad'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100152 sleep 10m
Bram Moolenaar55fab432016-02-07 16:53:13 +0100153 call assert_equal([-3, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100154
Bram Moolenaarf4160862016-02-05 23:09:12 +0100155 " Send an expr request
156 call assert_equal('ok', ch_sendexpr(handle, 'an expr'))
157 sleep 10m
158 call assert_equal('one', getline(line('$') - 2))
159 call assert_equal('two', getline(line('$') - 1))
160 call assert_equal('three', getline('$'))
161
162 " Request a redraw, we don't check for the effect.
163 call assert_equal('ok', ch_sendexpr(handle, 'redraw'))
164 call assert_equal('ok', ch_sendexpr(handle, 'redraw!'))
165
166 call assert_equal('ok', ch_sendexpr(handle, 'empty-request'))
167
Bram Moolenaard7ece102016-02-02 23:23:02 +0100168 " make the server quit, can't check if this works, should not hang.
169 call ch_sendexpr(handle, '!quit!', 0)
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100170endfunc
Bram Moolenaard7ece102016-02-02 23:23:02 +0100171
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100172func Test_communicate()
173 call s:run_server('s:communicate')
Bram Moolenaard7ece102016-02-02 23:23:02 +0100174endfunc
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100175
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100176" Test that we can open two channels.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100177func s:two_channels(port)
Bram Moolenaar39b21272016-02-10 23:28:21 +0100178 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100179 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100180 call assert_false(1, "Can't open channel")
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100181 return
182 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100183
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100184 call assert_equal('got it', ch_sendexpr(handle, 'hello!'))
185
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100186 let newhandle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100187 if ch_status(newhandle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100188 call assert_false(1, "Can't open second channel")
189 return
190 endif
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100191 call assert_equal('got it', ch_sendexpr(newhandle, 'hello!'))
192 call assert_equal('got it', ch_sendexpr(handle, 'hello!'))
193
194 call ch_close(handle)
195 call assert_equal('got it', ch_sendexpr(newhandle, 'hello!'))
196
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100197 call ch_close(newhandle)
198endfunc
199
200func Test_two_channels()
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100201 call s:run_server('s:two_channels')
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100202endfunc
203
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100204" Test that a server crash is handled gracefully.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100205func s:server_crash(port)
206 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100207 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100208 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100209 return
210 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100211
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100212 call ch_sendexpr(handle, '!crash!')
213
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100214 sleep 10m
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100215endfunc
216
217func Test_server_crash()
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100218 call s:run_server('s:server_crash')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100219endfunc
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100220
Bram Moolenaarf6157282016-02-10 21:07:14 +0100221let s:reply = ""
222func s:Handler(chan, msg)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100223 unlet s:reply
Bram Moolenaarf6157282016-02-10 21:07:14 +0100224 let s:reply = a:msg
225endfunc
226
227func s:channel_handler(port)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100228 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100229 if ch_status(handle) == "fail"
Bram Moolenaarf6157282016-02-10 21:07:14 +0100230 call assert_false(1, "Can't open channel")
231 return
232 endif
233
234 " Test that it works while waiting on a numbered message.
235 call assert_equal('ok', ch_sendexpr(handle, 'call me'))
236 sleep 10m
237 call assert_equal('we called you', s:reply)
238
239 " Test that it works while not waiting on a numbered message.
240 call ch_sendexpr(handle, 'call me again', 0)
241 sleep 10m
242 call assert_equal('we did call you', s:reply)
243endfunc
244
245func Test_channel_handler()
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100246 let s:chopt.callback = 's:Handler'
Bram Moolenaarf6157282016-02-10 21:07:14 +0100247 call s:run_server('s:channel_handler')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100248 let s:chopt.callback = function('s:Handler')
249 call s:run_server('s:channel_handler')
250 unlet s:chopt.callback
Bram Moolenaarf6157282016-02-10 21:07:14 +0100251endfunc
252
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100253" Test that trying to connect to a non-existing port fails quickly.
254func Test_connect_waittime()
255 let start = reltime()
Bram Moolenaara4833262016-02-09 23:33:25 +0100256 let handle = ch_open('localhost:9876', s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100257 if ch_status(handle) == "fail"
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100258 " Oops, port does exists.
259 call ch_close(handle)
260 else
261 let elapsed = reltime(start)
Bram Moolenaar74f5e652016-02-07 21:44:49 +0100262 call assert_true(reltimefloat(elapsed) < 1.0)
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100263 endif
264
265 let start = reltime()
266 let handle = ch_open('localhost:9867', {'waittime': 2000})
Bram Moolenaar77073442016-02-13 23:23:53 +0100267 if ch_status(handle) != "fail"
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100268 " Oops, port does exists.
269 call ch_close(handle)
270 else
Bram Moolenaar0fa98e72016-02-07 22:21:19 +0100271 " Failed connection doesn't wait the full time on Unix.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100272 " TODO: why is MS-Windows different?
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100273 let elapsed = reltime(start)
Bram Moolenaar0fa98e72016-02-07 22:21:19 +0100274 call assert_true(reltimefloat(elapsed) < (has('unix') ? 1.0 : 3.0))
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100275 endif
276endfunc
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100277
278func Test_pipe()
279 if !has('job') || !has('unix')
280 return
281 endif
282 let job = job_start("python test_channel_pipe.py")
283 call assert_equal("run", job_status(job))
284 try
285 let handle = job_getchannel(job)
286 call ch_sendraw(handle, "echo something\n", 0)
287 call assert_equal("something\n", ch_readraw(handle))
288 let reply = ch_sendraw(handle, "quit\n")
289 call assert_equal("Goodbye!\n", reply)
290 finally
291 call job_stop(job)
292 endtry
293endfunc