blob: 7cc3f146f699bcc67a0375d88218838fc45fb8f2 [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 Moolenaarb6a77372016-02-15 22:55:28 +010016 let s:python = 'python'
Bram Moolenaara8343c12016-02-04 22:09:48 +010017elseif has('win32')
Bram Moolenaarb6a77372016-02-15 22:55:28 +010018 " Use Python Launcher for Windows (py.exe) if available.
19 if executable('py.exe')
20 let s:python = 'py.exe'
21 elseif executable('python.exe')
22 let s:python = 'python.exe'
23 else
Bram Moolenaara0f9cd12016-02-03 20:13:24 +010024 finish
25 endif
26else
Bram Moolenaard6a8d482016-02-10 20:32:20 +010027 " Can't run this test.
Bram Moolenaard7ece102016-02-02 23:23:02 +010028 finish
29endif
30
Bram Moolenaara4833262016-02-09 23:33:25 +010031let s:chopt = has('macunix') ? {'waittime' : 1} : {}
Bram Moolenaar3b05b132016-02-03 23:25:07 +010032
Bram Moolenaard6a8d482016-02-10 20:32:20 +010033" Run "testfunc" after sarting the server and stop the server afterwards.
34func s:run_server(testfunc)
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010035 " The Python program writes the port number in Xportnr.
36 call delete("Xportnr")
37
Bram Moolenaard6a8d482016-02-10 20:32:20 +010038 try
39 if has('job')
Bram Moolenaarb6a77372016-02-15 22:55:28 +010040 let s:job = job_start(s:python . " test_channel.py")
Bram Moolenaard6a8d482016-02-10 20:32:20 +010041 elseif has('win32')
Bram Moolenaarb6a77372016-02-15 22:55:28 +010042 exe 'silent !start cmd /c start "test_channel" ' . s:python . ' test_channel.py'
Bram Moolenaard6a8d482016-02-10 20:32:20 +010043 else
Bram Moolenaarb6a77372016-02-15 22:55:28 +010044 exe 'silent !' . s:python . ' test_channel.py&'
Bram Moolenaard7ece102016-02-02 23:23:02 +010045 endif
Bram Moolenaard7ece102016-02-02 23:23:02 +010046
Bram Moolenaard6a8d482016-02-10 20:32:20 +010047 " Wait for up to 2 seconds for the port number to be there.
48 let cnt = 20
49 let l = []
50 while cnt > 0
51 try
52 let l = readfile("Xportnr")
53 catch
54 endtry
55 if len(l) >= 1
56 break
57 endif
58 sleep 100m
59 let cnt -= 1
60 endwhile
61 call delete("Xportnr")
62
63 if len(l) == 0
64 " Can't make the connection, give up.
65 call assert_false(1, "Can't start test_channel.py")
66 return -1
67 endif
68 let port = l[0]
69
70 call call(function(a:testfunc), [port])
71 catch
72 call assert_false(1, "Caught exception: " . v:exception)
73 finally
Bram Moolenaara0f9cd12016-02-03 20:13:24 +010074 call s:kill_server()
Bram Moolenaard6a8d482016-02-10 20:32:20 +010075 endtry
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010076endfunc
77
78func s:kill_server()
Bram Moolenaar835dc632016-02-07 14:27:38 +010079 if has('job')
Bram Moolenaard6a8d482016-02-10 20:32:20 +010080 if exists('s:job')
81 call job_stop(s:job)
82 unlet s:job
83 endif
Bram Moolenaar835dc632016-02-07 14:27:38 +010084 elseif has('win32')
Bram Moolenaarb6a77372016-02-15 22:55:28 +010085 call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq test_channel"')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010086 else
Bram Moolenaar608a8912016-02-03 22:39:51 +010087 call system("pkill -f test_channel.py")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010088 endif
89endfunc
90
Bram Moolenaara07fec92016-02-05 21:04:08 +010091let s:responseMsg = ''
92func s:RequestHandler(handle, msg)
93 let s:responseHandle = a:handle
94 let s:responseMsg = a:msg
95endfunc
96
Bram Moolenaard6a8d482016-02-10 20:32:20 +010097func s:communicate(port)
98 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +010099 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100100 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100101 return
102 endif
Bram Moolenaard7ece102016-02-02 23:23:02 +0100103
104 " Simple string request and reply.
105 call assert_equal('got it', ch_sendexpr(handle, 'hello!'))
106
107 " Request that triggers sending two ex commands. These will usually be
108 " handled before getting the response, but it's not guaranteed, thus wait a
109 " tiny bit for the commands to get executed.
110 call assert_equal('ok', ch_sendexpr(handle, 'make change'))
111 sleep 10m
112 call assert_equal('added1', getline(line('$') - 1))
113 call assert_equal('added2', getline('$'))
114
Bram Moolenaarf4160862016-02-05 23:09:12 +0100115 call assert_equal('ok', ch_sendexpr(handle, 'do normal'))
116 sleep 10m
117 call assert_equal('added more', getline('$'))
118
Bram Moolenaara07fec92016-02-05 21:04:08 +0100119 " Send a request with a specific handler.
120 call ch_sendexpr(handle, 'hello!', 's:RequestHandler')
121 sleep 10m
Bram Moolenaar77073442016-02-13 23:23:53 +0100122 if !exists('s:responseHandle')
123 call assert_false(1, 's:responseHandle was not set')
124 else
125 call assert_equal(handle, s:responseHandle)
126 endif
Bram Moolenaara07fec92016-02-05 21:04:08 +0100127 call assert_equal('got it', s:responseMsg)
128
Bram Moolenaar77073442016-02-13 23:23:53 +0100129 unlet s:responseHandle
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100130 let s:responseMsg = ''
131 call ch_sendexpr(handle, 'hello!', function('s:RequestHandler'))
132 sleep 10m
Bram Moolenaar77073442016-02-13 23:23:53 +0100133 if !exists('s:responseHandle')
134 call assert_false(1, 's:responseHandle was not set')
135 else
136 call assert_equal(handle, s:responseHandle)
137 endif
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100138 call assert_equal('got it', s:responseMsg)
139
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100140 " Send an eval request that works.
141 call assert_equal('ok', ch_sendexpr(handle, 'eval-works'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100142 sleep 10m
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100143 call assert_equal([-1, 'foo123'], ch_sendexpr(handle, 'eval-result'))
144
145 " Send an eval request that fails.
146 call assert_equal('ok', ch_sendexpr(handle, 'eval-fails'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100147 sleep 10m
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100148 call assert_equal([-2, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
149
Bram Moolenaar55fab432016-02-07 16:53:13 +0100150 " Send an eval request that works but can't be encoded.
151 call assert_equal('ok', ch_sendexpr(handle, 'eval-error'))
152 sleep 10m
153 call assert_equal([-3, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
154
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100155 " Send a bad eval request. There will be no response.
156 call assert_equal('ok', ch_sendexpr(handle, 'eval-bad'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100157 sleep 10m
Bram Moolenaar55fab432016-02-07 16:53:13 +0100158 call assert_equal([-3, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100159
Bram Moolenaarf4160862016-02-05 23:09:12 +0100160 " Send an expr request
161 call assert_equal('ok', ch_sendexpr(handle, 'an expr'))
162 sleep 10m
163 call assert_equal('one', getline(line('$') - 2))
164 call assert_equal('two', getline(line('$') - 1))
165 call assert_equal('three', getline('$'))
166
167 " Request a redraw, we don't check for the effect.
168 call assert_equal('ok', ch_sendexpr(handle, 'redraw'))
169 call assert_equal('ok', ch_sendexpr(handle, 'redraw!'))
170
171 call assert_equal('ok', ch_sendexpr(handle, 'empty-request'))
172
Bram Moolenaard7ece102016-02-02 23:23:02 +0100173 " make the server quit, can't check if this works, should not hang.
174 call ch_sendexpr(handle, '!quit!', 0)
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100175endfunc
Bram Moolenaard7ece102016-02-02 23:23:02 +0100176
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100177func Test_communicate()
178 call s:run_server('s:communicate')
Bram Moolenaard7ece102016-02-02 23:23:02 +0100179endfunc
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100180
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100181" Test that we can open two channels.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100182func s:two_channels(port)
Bram Moolenaar39b21272016-02-10 23:28:21 +0100183 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100184 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100185 call assert_false(1, "Can't open channel")
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100186 return
187 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100188
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100189 call assert_equal('got it', ch_sendexpr(handle, 'hello!'))
190
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100191 let newhandle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100192 if ch_status(newhandle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100193 call assert_false(1, "Can't open second channel")
194 return
195 endif
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100196 call assert_equal('got it', ch_sendexpr(newhandle, 'hello!'))
197 call assert_equal('got it', ch_sendexpr(handle, 'hello!'))
198
199 call ch_close(handle)
200 call assert_equal('got it', ch_sendexpr(newhandle, 'hello!'))
201
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100202 call ch_close(newhandle)
203endfunc
204
205func Test_two_channels()
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100206 call s:run_server('s:two_channels')
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100207endfunc
208
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100209" Test that a server crash is handled gracefully.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100210func s:server_crash(port)
211 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100212 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100213 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100214 return
215 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100216
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100217 call ch_sendexpr(handle, '!crash!')
218
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100219 sleep 10m
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100220endfunc
221
222func Test_server_crash()
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100223 call s:run_server('s:server_crash')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100224endfunc
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100225
Bram Moolenaarf6157282016-02-10 21:07:14 +0100226let s:reply = ""
227func s:Handler(chan, msg)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100228 unlet s:reply
Bram Moolenaarf6157282016-02-10 21:07:14 +0100229 let s:reply = a:msg
230endfunc
231
232func s:channel_handler(port)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100233 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100234 if ch_status(handle) == "fail"
Bram Moolenaarf6157282016-02-10 21:07:14 +0100235 call assert_false(1, "Can't open channel")
236 return
237 endif
238
239 " Test that it works while waiting on a numbered message.
240 call assert_equal('ok', ch_sendexpr(handle, 'call me'))
241 sleep 10m
242 call assert_equal('we called you', s:reply)
243
244 " Test that it works while not waiting on a numbered message.
245 call ch_sendexpr(handle, 'call me again', 0)
246 sleep 10m
247 call assert_equal('we did call you', s:reply)
248endfunc
249
250func Test_channel_handler()
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100251 let s:chopt.callback = 's:Handler'
Bram Moolenaarf6157282016-02-10 21:07:14 +0100252 call s:run_server('s:channel_handler')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100253 let s:chopt.callback = function('s:Handler')
254 call s:run_server('s:channel_handler')
255 unlet s:chopt.callback
Bram Moolenaarf6157282016-02-10 21:07:14 +0100256endfunc
257
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100258" Test that trying to connect to a non-existing port fails quickly.
259func Test_connect_waittime()
Bram Moolenaar0727d362016-02-14 00:19:59 +0100260 if !has('unix')
261 " TODO: Make this work again for MS-Windows.
262 return
263 endif
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100264 let start = reltime()
Bram Moolenaara4833262016-02-09 23:33:25 +0100265 let handle = ch_open('localhost:9876', s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100266 if ch_status(handle) == "fail"
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100267 " Oops, port does exists.
268 call ch_close(handle)
269 else
270 let elapsed = reltime(start)
Bram Moolenaar74f5e652016-02-07 21:44:49 +0100271 call assert_true(reltimefloat(elapsed) < 1.0)
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100272 endif
273
274 let start = reltime()
275 let handle = ch_open('localhost:9867', {'waittime': 2000})
Bram Moolenaar77073442016-02-13 23:23:53 +0100276 if ch_status(handle) != "fail"
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100277 " Oops, port does exists.
278 call ch_close(handle)
279 else
Bram Moolenaar0fa98e72016-02-07 22:21:19 +0100280 " Failed connection doesn't wait the full time on Unix.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100281 " TODO: why is MS-Windows different?
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100282 let elapsed = reltime(start)
Bram Moolenaar0fa98e72016-02-07 22:21:19 +0100283 call assert_true(reltimefloat(elapsed) < (has('unix') ? 1.0 : 3.0))
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100284 endif
285endfunc
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100286
287func Test_pipe()
Bram Moolenaard8070362016-02-15 21:56:54 +0100288 if !has('job')
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100289 return
290 endif
Bram Moolenaarb6a77372016-02-15 22:55:28 +0100291 let job = job_start(s:python . " test_channel_pipe.py")
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100292 call assert_equal("run", job_status(job))
293 try
294 let handle = job_getchannel(job)
295 call ch_sendraw(handle, "echo something\n", 0)
296 call assert_equal("something\n", ch_readraw(handle))
297 let reply = ch_sendraw(handle, "quit\n")
298 call assert_equal("Goodbye!\n", reply)
299 finally
300 call job_stop(job)
301 endtry
302endfunc
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100303
304let s:unletResponse = ''
305func s:UnletHandler(handle, msg)
306 let s:unletResponse = a:msg
307 unlet s:channelfd
308endfunc
309
310" Test that "unlet handle" in a handler doesn't crash Vim.
311func s:unlet_handle(port)
312 let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
313 call ch_sendexpr(s:channelfd, "test", function('s:UnletHandler'))
314 sleep 10m
315 call assert_equal('what?', s:unletResponse)
316endfunc
317
318func Test_unlet_handle()
319 call s:run_server('s:unlet_handle')
320endfunc
Bram Moolenaar5cefd402016-02-16 12:44:26 +0100321
322func Test_open_fail()
323 silent! let ch = ch_open("noserver")
324 echo ch
325 let d = ch
326endfunc