blob: 3bdfd4cbf8cdc8a298b55db7c617788fa1cc5eb9 [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 Moolenaare74e8e72016-02-16 22:01:30 +010031let s:chopt = {}
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.
Bram Moolenaar81661fb2016-02-18 22:23:34 +010034func 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 Moolenaar81661fb2016-02-18 22:23:34 +010038 if a:0 == 1
39 let arg = ' ' . a:1
40 else
41 let arg = ''
42 endif
43 let cmd = s:python . " test_channel.py" . arg
44
Bram Moolenaard6a8d482016-02-10 20:32:20 +010045 try
46 if has('job')
Bram Moolenaar65edff82016-02-21 16:40:11 +010047 let s:job = job_start(cmd, {"stoponexit": "hup"})
48 call job_setoptions(s:job, {"stoponexit": "kill"})
Bram Moolenaard6a8d482016-02-10 20:32:20 +010049 elseif has('win32')
Bram Moolenaar81661fb2016-02-18 22:23:34 +010050 exe 'silent !start cmd /c start "test_channel" ' . cmd
Bram Moolenaard6a8d482016-02-10 20:32:20 +010051 else
Bram Moolenaar81661fb2016-02-18 22:23:34 +010052 exe 'silent !' . cmd . '&'
Bram Moolenaard7ece102016-02-02 23:23:02 +010053 endif
Bram Moolenaard7ece102016-02-02 23:23:02 +010054
Bram Moolenaard6a8d482016-02-10 20:32:20 +010055 " Wait for up to 2 seconds for the port number to be there.
56 let cnt = 20
57 let l = []
58 while cnt > 0
59 try
60 let l = readfile("Xportnr")
61 catch
62 endtry
63 if len(l) >= 1
64 break
65 endif
66 sleep 100m
67 let cnt -= 1
68 endwhile
69 call delete("Xportnr")
70
71 if len(l) == 0
72 " Can't make the connection, give up.
73 call assert_false(1, "Can't start test_channel.py")
74 return -1
75 endif
76 let port = l[0]
77
78 call call(function(a:testfunc), [port])
79 catch
80 call assert_false(1, "Caught exception: " . v:exception)
81 finally
Bram Moolenaara0f9cd12016-02-03 20:13:24 +010082 call s:kill_server()
Bram Moolenaard6a8d482016-02-10 20:32:20 +010083 endtry
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010084endfunc
85
86func s:kill_server()
Bram Moolenaar835dc632016-02-07 14:27:38 +010087 if has('job')
Bram Moolenaard6a8d482016-02-10 20:32:20 +010088 if exists('s:job')
89 call job_stop(s:job)
90 unlet s:job
91 endif
Bram Moolenaar835dc632016-02-07 14:27:38 +010092 elseif has('win32')
Bram Moolenaarb6a77372016-02-15 22:55:28 +010093 call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq test_channel"')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010094 else
Bram Moolenaar608a8912016-02-03 22:39:51 +010095 call system("pkill -f test_channel.py")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010096 endif
97endfunc
98
Bram Moolenaara07fec92016-02-05 21:04:08 +010099let s:responseMsg = ''
100func s:RequestHandler(handle, msg)
101 let s:responseHandle = a:handle
102 let s:responseMsg = a:msg
103endfunc
104
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100105func s:communicate(port)
106 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100107 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100108 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100109 return
110 endif
Bram Moolenaard7ece102016-02-02 23:23:02 +0100111
112 " Simple string request and reply.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100113 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaard7ece102016-02-02 23:23:02 +0100114
115 " Request that triggers sending two ex commands. These will usually be
116 " handled before getting the response, but it's not guaranteed, thus wait a
117 " tiny bit for the commands to get executed.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100118 call assert_equal('ok', ch_evalexpr(handle, 'make change'))
Bram Moolenaard7ece102016-02-02 23:23:02 +0100119 sleep 10m
120 call assert_equal('added1', getline(line('$') - 1))
121 call assert_equal('added2', getline('$'))
122
Bram Moolenaarda94fdf2016-03-03 18:09:10 +0100123 call assert_equal('ok', ch_evalexpr(handle, 'do normal', {'timeout': 100}))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100124 sleep 10m
125 call assert_equal('added more', getline('$'))
126
Bram Moolenaara07fec92016-02-05 21:04:08 +0100127 " Send a request with a specific handler.
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100128 call ch_sendexpr(handle, 'hello!', {'callback': 's:RequestHandler'})
Bram Moolenaara07fec92016-02-05 21:04:08 +0100129 sleep 10m
Bram Moolenaar77073442016-02-13 23:23:53 +0100130 if !exists('s:responseHandle')
131 call assert_false(1, 's:responseHandle was not set')
132 else
133 call assert_equal(handle, s:responseHandle)
Bram Moolenaar9186a272016-02-23 19:34:01 +0100134 unlet s:responseHandle
Bram Moolenaar77073442016-02-13 23:23:53 +0100135 endif
Bram Moolenaara07fec92016-02-05 21:04:08 +0100136 call assert_equal('got it', s:responseMsg)
137
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100138 let s:responseMsg = ''
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100139 call ch_sendexpr(handle, 'hello!', {'callback': function('s:RequestHandler')})
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100140 sleep 10m
Bram Moolenaar77073442016-02-13 23:23:53 +0100141 if !exists('s:responseHandle')
142 call assert_false(1, 's:responseHandle was not set')
143 else
144 call assert_equal(handle, s:responseHandle)
Bram Moolenaar9186a272016-02-23 19:34:01 +0100145 unlet s:responseHandle
Bram Moolenaar77073442016-02-13 23:23:53 +0100146 endif
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100147 call assert_equal('got it', s:responseMsg)
148
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100149 " check setting options (without testing the effect)
150 call ch_setoptions(handle, {'callback': 's:NotUsed'})
Bram Moolenaar1f6ef662016-02-19 22:59:44 +0100151 call ch_setoptions(handle, {'timeout': 1111})
Bram Moolenaarb6b52522016-02-20 23:30:07 +0100152 call ch_setoptions(handle, {'mode': 'json'})
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100153 call assert_fails("call ch_setoptions(handle, {'waittime': 111})", "E475")
Bram Moolenaar0ba75a92016-02-19 23:21:26 +0100154 call ch_setoptions(handle, {'callback': ''})
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100155
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100156 " Send an eval request that works.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100157 call assert_equal('ok', ch_evalexpr(handle, 'eval-works'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100158 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100159 call assert_equal([-1, 'foo123'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100160
161 " Send an eval request that fails.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100162 call assert_equal('ok', ch_evalexpr(handle, 'eval-fails'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100163 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100164 call assert_equal([-2, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100165
Bram Moolenaar55fab432016-02-07 16:53:13 +0100166 " Send an eval request that works but can't be encoded.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100167 call assert_equal('ok', ch_evalexpr(handle, 'eval-error'))
Bram Moolenaar55fab432016-02-07 16:53:13 +0100168 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100169 call assert_equal([-3, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaar55fab432016-02-07 16:53:13 +0100170
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100171 " Send a bad eval request. There will be no response.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100172 call assert_equal('ok', ch_evalexpr(handle, 'eval-bad'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100173 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100174 call assert_equal([-3, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100175
Bram Moolenaarf4160862016-02-05 23:09:12 +0100176 " Send an expr request
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100177 call assert_equal('ok', ch_evalexpr(handle, 'an expr'))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100178 sleep 10m
179 call assert_equal('one', getline(line('$') - 2))
180 call assert_equal('two', getline(line('$') - 1))
181 call assert_equal('three', getline('$'))
182
183 " Request a redraw, we don't check for the effect.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100184 call assert_equal('ok', ch_evalexpr(handle, 'redraw'))
185 call assert_equal('ok', ch_evalexpr(handle, 'redraw!'))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100186
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100187 call assert_equal('ok', ch_evalexpr(handle, 'empty-request'))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100188
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100189 " Reading while there is nothing available.
Bram Moolenaar9186a272016-02-23 19:34:01 +0100190 call assert_equal(v:none, ch_read(handle, {'timeout': 0}))
191 let start = reltime()
192 call assert_equal(v:none, ch_read(handle, {'timeout': 333}))
193 let elapsed = reltime(start)
194 call assert_true(reltimefloat(elapsed) > 0.3)
195 call assert_true(reltimefloat(elapsed) < 0.6)
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100196
197 " Send without waiting for a response, then wait for a response.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100198 call ch_sendexpr(handle, 'wait a bit')
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100199 let resp = ch_read(handle)
200 call assert_equal(type([]), type(resp))
201 call assert_equal(type(11), type(resp[0]))
202 call assert_equal('waited', resp[1])
203
Bram Moolenaard7ece102016-02-02 23:23:02 +0100204 " make the server quit, can't check if this works, should not hang.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100205 call ch_sendexpr(handle, '!quit!')
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100206endfunc
Bram Moolenaard7ece102016-02-02 23:23:02 +0100207
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100208func Test_communicate()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100209 call ch_log('Test_communicate()')
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100210 call s:run_server('s:communicate')
Bram Moolenaard7ece102016-02-02 23:23:02 +0100211endfunc
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100212
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100213" Test that we can open two channels.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100214func s:two_channels(port)
Bram Moolenaar39b21272016-02-10 23:28:21 +0100215 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100216 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100217 call assert_false(1, "Can't open channel")
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100218 return
219 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100220
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100221 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100222
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100223 let newhandle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100224 if ch_status(newhandle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100225 call assert_false(1, "Can't open second channel")
226 return
227 endif
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100228 call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
229 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100230
231 call ch_close(handle)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100232 call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100233
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100234 call ch_close(newhandle)
235endfunc
236
237func Test_two_channels()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100238 call ch_log('Test_two_channels()')
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100239 call s:run_server('s:two_channels')
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100240endfunc
241
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100242" Test that a server crash is handled gracefully.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100243func s:server_crash(port)
244 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100245 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100246 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100247 return
248 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100249
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100250 call ch_evalexpr(handle, '!crash!')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100251
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100252 sleep 10m
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100253endfunc
254
255func Test_server_crash()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100256 call ch_log('Test_server_crash()')
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100257 call s:run_server('s:server_crash')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100258endfunc
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100259
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100260"""""""""
261
Bram Moolenaarf6157282016-02-10 21:07:14 +0100262let s:reply = ""
263func s:Handler(chan, msg)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100264 unlet s:reply
Bram Moolenaarf6157282016-02-10 21:07:14 +0100265 let s:reply = a:msg
266endfunc
267
268func s:channel_handler(port)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100269 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100270 if ch_status(handle) == "fail"
Bram Moolenaarf6157282016-02-10 21:07:14 +0100271 call assert_false(1, "Can't open channel")
272 return
273 endif
274
275 " Test that it works while waiting on a numbered message.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100276 call assert_equal('ok', ch_evalexpr(handle, 'call me'))
Bram Moolenaarf6157282016-02-10 21:07:14 +0100277 sleep 10m
278 call assert_equal('we called you', s:reply)
279
280 " Test that it works while not waiting on a numbered message.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100281 call ch_sendexpr(handle, 'call me again')
Bram Moolenaarf6157282016-02-10 21:07:14 +0100282 sleep 10m
283 call assert_equal('we did call you', s:reply)
284endfunc
285
286func Test_channel_handler()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100287 call ch_log('Test_channel_handler()')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100288 let s:chopt.callback = 's:Handler'
Bram Moolenaarf6157282016-02-10 21:07:14 +0100289 call s:run_server('s:channel_handler')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100290 let s:chopt.callback = function('s:Handler')
291 call s:run_server('s:channel_handler')
292 unlet s:chopt.callback
Bram Moolenaarf6157282016-02-10 21:07:14 +0100293endfunc
294
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100295"""""""""
296
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100297let s:ch_reply = ''
298func s:ChHandler(chan, msg)
299 unlet s:ch_reply
300 let s:ch_reply = a:msg
301endfunc
302
303let s:zero_reply = ''
304func s:OneHandler(chan, msg)
305 unlet s:zero_reply
306 let s:zero_reply = a:msg
307endfunc
308
309func s:channel_zero(port)
310 let handle = ch_open('localhost:' . a:port, s:chopt)
311 if ch_status(handle) == "fail"
312 call assert_false(1, "Can't open channel")
313 return
314 endif
315
316 " Check that eval works.
317 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
318
319 " Check that eval works if a zero id message is sent back.
320 let s:ch_reply = ''
321 call assert_equal('sent zero', ch_evalexpr(handle, 'send zero'))
322 sleep 10m
323 if s:has_handler
324 call assert_equal('zero index', s:ch_reply)
325 else
326 call assert_equal('', s:ch_reply)
327 endif
328
329 " Check that handler works if a zero id message is sent back.
330 let s:ch_reply = ''
331 let s:zero_reply = ''
332 call ch_sendexpr(handle, 'send zero', {'callback': 's:OneHandler'})
333 " Somehow the second message takes a bit of time.
334 for i in range(50)
335 if s:zero_reply == 'sent zero'
336 break
337 endif
338 sleep 10m
339 endfor
340 if s:has_handler
341 call assert_equal('zero index', s:ch_reply)
342 else
343 call assert_equal('', s:ch_reply)
344 endif
345 call assert_equal('sent zero', s:zero_reply)
346endfunc
347
348func Test_zero_reply()
349 call ch_log('Test_zero_reply()')
350 " Run with channel handler
351 let s:has_handler = 1
352 let s:chopt.callback = 's:ChHandler'
353 call s:run_server('s:channel_zero')
354 unlet s:chopt.callback
355
356 " Run without channel handler
357 let s:has_handler = 0
358 call s:run_server('s:channel_zero')
359endfunc
360
361"""""""""
362
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100363let s:reply1 = ""
364func s:HandleRaw1(chan, msg)
365 unlet s:reply1
366 let s:reply1 = a:msg
367endfunc
368
369let s:reply2 = ""
370func s:HandleRaw2(chan, msg)
371 unlet s:reply2
372 let s:reply2 = a:msg
373endfunc
374
375let s:reply3 = ""
376func s:HandleRaw3(chan, msg)
377 unlet s:reply3
378 let s:reply3 = a:msg
379endfunc
380
381func s:raw_one_time_callback(port)
382 let handle = ch_open('localhost:' . a:port, s:chopt)
383 if ch_status(handle) == "fail"
384 call assert_false(1, "Can't open channel")
385 return
386 endif
387 call ch_setoptions(handle, {'mode': 'raw'})
388
389 " The message are sent raw, we do our own JSON strings here.
390 call ch_sendraw(handle, "[1, \"hello!\"]", {'callback': 's:HandleRaw1'})
391 sleep 10m
392 call assert_equal("[1, \"got it\"]", s:reply1)
393 call ch_sendraw(handle, "[2, \"echo something\"]", {'callback': 's:HandleRaw2'})
394 call ch_sendraw(handle, "[3, \"wait a bit\"]", {'callback': 's:HandleRaw3'})
395 sleep 10m
396 call assert_equal("[2, \"something\"]", s:reply2)
397 " wait for up to 500 msec for the 200 msec delayed reply
398 for i in range(50)
399 sleep 10m
400 if s:reply3 != ''
401 break
402 endif
403 endfor
404 call assert_equal("[3, \"waited\"]", s:reply3)
405endfunc
406
407func Test_raw_one_time_callback()
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100408 call ch_log('Test_raw_one_time_callback()')
409 call s:run_server('s:raw_one_time_callback')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100410endfunc
411
412"""""""""
413
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100414" Test that trying to connect to a non-existing port fails quickly.
415func Test_connect_waittime()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100416 call ch_log('Test_connect_waittime()')
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100417 let start = reltime()
Bram Moolenaara4833262016-02-09 23:33:25 +0100418 let handle = ch_open('localhost:9876', s:chopt)
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100419 if ch_status(handle) != "fail"
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100420 " Oops, port does exists.
421 call ch_close(handle)
422 else
423 let elapsed = reltime(start)
Bram Moolenaar74f5e652016-02-07 21:44:49 +0100424 call assert_true(reltimefloat(elapsed) < 1.0)
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100425 endif
426
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100427 " We intend to use a socket that doesn't exist and wait for half a second
428 " before giving up. If the socket does exist it can fail in various ways.
429 " Check for "Connection reset by peer" to avoid flakyness.
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100430 let start = reltime()
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100431 try
432 let handle = ch_open('localhost:9867', {'waittime': 500})
433 if ch_status(handle) != "fail"
434 " Oops, port does exists.
435 call ch_close(handle)
436 else
437 " Failed connection should wait about 500 msec.
438 let elapsed = reltime(start)
439 call assert_true(reltimefloat(elapsed) > 0.3)
440 call assert_true(reltimefloat(elapsed) < 1.0)
441 endif
442 catch
443 if v:exception !~ 'Connection reset by peer'
444 call assert_false(1, "Caught exception: " . v:exception)
445 endif
446 endtry
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100447endfunc
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100448
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100449"""""""""
450
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100451func Test_raw_pipe()
452 if !has('job')
453 return
454 endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100455 call ch_log('Test_raw_pipe()')
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100456 let job = job_start(s:python . " test_channel_pipe.py", {'mode': 'raw'})
457 call assert_equal("run", job_status(job))
458 try
459 let handle = job_getchannel(job)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100460 call ch_sendraw(handle, "echo something\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100461 let msg = ch_readraw(handle)
462 call assert_equal("something\n", substitute(msg, "\r", "", 'g'))
463
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100464 call ch_sendraw(handle, "double this\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100465 let msg = ch_readraw(handle)
466 call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g'))
467
Bram Moolenaarda94fdf2016-03-03 18:09:10 +0100468 let reply = ch_evalraw(handle, "quit\n", {'timeout': 100})
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100469 call assert_equal("Goodbye!\n", substitute(reply, "\r", "", 'g'))
470 finally
471 call job_stop(job)
472 endtry
473endfunc
474
475func Test_nl_pipe()
Bram Moolenaard8070362016-02-15 21:56:54 +0100476 if !has('job')
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100477 return
478 endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100479 call ch_log('Test_nl_pipe()')
Bram Moolenaarb6a77372016-02-15 22:55:28 +0100480 let job = job_start(s:python . " test_channel_pipe.py")
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100481 call assert_equal("run", job_status(job))
482 try
483 let handle = job_getchannel(job)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100484 call ch_sendraw(handle, "echo something\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100485 call assert_equal("something", ch_readraw(handle))
486
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100487 call ch_sendraw(handle, "echoerr wrong\n")
488 call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
489
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100490 call ch_sendraw(handle, "double this\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100491 call assert_equal("this", ch_readraw(handle))
492 call assert_equal("AND this", ch_readraw(handle))
493
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100494 let reply = ch_evalraw(handle, "quit\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100495 call assert_equal("Goodbye!", reply)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100496 finally
497 call job_stop(job)
498 endtry
499endfunc
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100500
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100501func Test_nl_err_to_out_pipe()
502 if !has('job')
503 return
504 endif
505 call ch_log('Test_nl_err_to_out_pipe()')
506 let job = job_start(s:python . " test_channel_pipe.py", {'err-io': 'out'})
507 call assert_equal("run", job_status(job))
508 try
509 let handle = job_getchannel(job)
510 call ch_sendraw(handle, "echo something\n")
511 call assert_equal("something", ch_readraw(handle))
512
513 call ch_sendraw(handle, "echoerr wrong\n")
514 call assert_equal("wrong", ch_readraw(handle))
515 finally
516 call job_stop(job)
517 endtry
518endfunc
519
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100520func Test_pipe_to_buffer()
521 if !has('job')
522 return
523 endif
524 call ch_log('Test_pipe_to_buffer()')
525 let job = job_start(s:python . " test_channel_pipe.py",
526 \ {'out-io': 'buffer', 'out-name': 'pipe-output'})
527 call assert_equal("run", job_status(job))
528 try
529 let handle = job_getchannel(job)
530 call ch_sendraw(handle, "echo line one\n")
531 call ch_sendraw(handle, "echo line two\n")
532 call ch_sendraw(handle, "double this\n")
533 call ch_sendraw(handle, "quit\n")
534 sp pipe-output
535 for i in range(100)
536 sleep 10m
537 if line('$') >= 6
538 break
539 endif
540 endfor
541 call assert_equal(['Reading from channel output...', 'line one', 'line two', 'this', 'AND this', 'Goodbye!'], getline(1, '$'))
542 bwipe!
543 finally
544 call job_stop(job)
545 endtry
546endfunc
547
Bram Moolenaar014069a2016-03-03 22:51:40 +0100548func Test_pipe_from_buffer()
549 if !has('job')
550 return
551 endif
552call ch_logfile('channellog', 'w')
553 call ch_log('Test_pipe_from_buffer()')
554
555 sp pipe-input
556 call setline(1, ['echo one', 'echo two', 'echo three'])
557
558 let job = job_start(s:python . " test_channel_pipe.py",
559 \ {'in-io': 'buffer', 'in-name': 'pipe-input'})
560 call assert_equal("run", job_status(job))
561 try
562 let handle = job_getchannel(job)
563 call assert_equal('one', ch_read(handle))
564 call assert_equal('two', ch_read(handle))
565 call assert_equal('three', ch_read(handle))
566 bwipe!
567 finally
568 call job_stop(job)
569 endtry
570call ch_logfile('')
571endfunc
572
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100573func Test_pipe_to_nameless_buffer()
574 if !has('job')
575 return
576 endif
577 call ch_log('Test_pipe_to_nameless_buffer()')
578 let job = job_start(s:python . " test_channel_pipe.py",
579 \ {'out-io': 'buffer'})
580 call assert_equal("run", job_status(job))
581 try
582 let handle = job_getchannel(job)
583 call ch_sendraw(handle, "echo line one\n")
584 call ch_sendraw(handle, "echo line two\n")
585 exe ch_getbufnr(handle, "out") . 'sbuf'
586 for i in range(100)
587 sleep 10m
588 if line('$') >= 3
589 break
590 endif
591 endfor
592 call assert_equal(['Reading from channel output...', 'line one', 'line two'], getline(1, '$'))
593 bwipe!
594 finally
595 call job_stop(job)
596 endtry
597endfunc
598
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +0100599func Test_pipe_to_buffer_json()
600 if !has('job')
601 return
602 endif
603 call ch_log('Test_pipe_to_buffer_json()')
604 let job = job_start(s:python . " test_channel_pipe.py",
605 \ {'out-io': 'buffer', 'out-mode': 'json'})
606 call assert_equal("run", job_status(job))
607 try
608 let handle = job_getchannel(job)
609 call ch_sendraw(handle, "echo [0, \"hello\"]\n")
610 call ch_sendraw(handle, "echo [-2, 12.34]\n")
611 exe ch_getbufnr(handle, "out") . 'sbuf'
612 for i in range(100)
613 sleep 10m
614 if line('$') >= 3
615 break
616 endif
617 endfor
618 call assert_equal(['Reading from channel output...', '[0,"hello"]', '[-2,12.34]'], getline(1, '$'))
619 bwipe!
620 finally
621 call job_stop(job)
622 endtry
623endfunc
624
Bram Moolenaard46ae142016-02-16 13:33:52 +0100625""""""""""
626
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100627let s:unletResponse = ''
628func s:UnletHandler(handle, msg)
629 let s:unletResponse = a:msg
630 unlet s:channelfd
631endfunc
632
633" Test that "unlet handle" in a handler doesn't crash Vim.
634func s:unlet_handle(port)
635 let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100636 call ch_sendexpr(s:channelfd, "test", {'callback': function('s:UnletHandler')})
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100637 sleep 10m
638 call assert_equal('what?', s:unletResponse)
639endfunc
640
641func Test_unlet_handle()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100642 call ch_log('Test_unlet_handle()')
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100643 call s:run_server('s:unlet_handle')
644endfunc
Bram Moolenaar5cefd402016-02-16 12:44:26 +0100645
Bram Moolenaard46ae142016-02-16 13:33:52 +0100646""""""""""
647
648let s:unletResponse = ''
649func s:CloseHandler(handle, msg)
650 let s:unletResponse = a:msg
651 call ch_close(s:channelfd)
652endfunc
653
654" Test that "unlet handle" in a handler doesn't crash Vim.
655func s:close_handle(port)
656 let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100657 call ch_sendexpr(s:channelfd, "test", {'callback': function('s:CloseHandler')})
Bram Moolenaard46ae142016-02-16 13:33:52 +0100658 sleep 10m
659 call assert_equal('what?', s:unletResponse)
660endfunc
661
662func Test_close_handle()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100663 call ch_log('Test_close_handle()')
Bram Moolenaard46ae142016-02-16 13:33:52 +0100664 call s:run_server('s:close_handle')
665endfunc
666
667""""""""""
668
Bram Moolenaar5cefd402016-02-16 12:44:26 +0100669func Test_open_fail()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100670 call ch_log('Test_open_fail()')
Bram Moolenaar5cefd402016-02-16 12:44:26 +0100671 silent! let ch = ch_open("noserver")
672 echo ch
673 let d = ch
674endfunc
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100675
676""""""""""
677
678func s:open_delay(port)
679 " Wait up to a second for the port to open.
680 let s:chopt.waittime = 1000
681 let channel = ch_open('localhost:' . a:port, s:chopt)
682 unlet s:chopt.waittime
683 if ch_status(channel) == "fail"
684 call assert_false(1, "Can't open channel")
685 return
686 endif
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100687 call assert_equal('got it', ch_evalexpr(channel, 'hello!'))
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100688 call ch_close(channel)
689endfunc
690
691func Test_open_delay()
692 call ch_log('Test_open_delay()')
693 " The server will wait half a second before creating the port.
694 call s:run_server('s:open_delay', 'delay')
695endfunc
Bram Moolenaarece61b02016-02-20 21:39:05 +0100696
697"""""""""
698
699function MyFunction(a,b,c)
700 let s:call_ret = [a:a, a:b, a:c]
701endfunc
702
703function s:test_call(port)
704 let handle = ch_open('localhost:' . a:port, s:chopt)
705 if ch_status(handle) == "fail"
706 call assert_false(1, "Can't open channel")
707 return
708 endif
709
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100710 call assert_equal('ok', ch_evalexpr(handle, 'call-func'))
Bram Moolenaarece61b02016-02-20 21:39:05 +0100711 sleep 20m
712 call assert_equal([1, 2, 3], s:call_ret)
713endfunc
714
715func Test_call()
716 call ch_log('Test_call()')
717 call s:run_server('s:test_call')
718endfunc
Bram Moolenaaree1cffc2016-02-21 19:14:41 +0100719
720"""""""""
721
Bram Moolenaar4e221c92016-02-23 13:20:22 +0100722let s:job_exit_ret = 'not yet'
Bram Moolenaaree1cffc2016-02-21 19:14:41 +0100723function MyExitCb(job, status)
Bram Moolenaar4e221c92016-02-23 13:20:22 +0100724 let s:job_exit_ret = 'done'
Bram Moolenaaree1cffc2016-02-21 19:14:41 +0100725endfunc
726
727function s:test_exit_callback(port)
728 call job_setoptions(s:job, {'exit-cb': 'MyExitCb'})
729 let s:exit_job = s:job
730endfunc
731
732func Test_exit_callback()
733 if has('job')
Bram Moolenaar9730f742016-02-28 19:50:51 +0100734 call ch_log('Test_exit_callback()')
Bram Moolenaaree1cffc2016-02-21 19:14:41 +0100735 call s:run_server('s:test_exit_callback')
736
Bram Moolenaar9730f742016-02-28 19:50:51 +0100737 " wait up to a second for the job to exit
738 for i in range(100)
739 if s:job_exit_ret == 'done'
740 break
741 endif
742 sleep 10m
743 " calling job_status() triggers the callback
744 call job_status(s:exit_job)
745 endfor
Bram Moolenaaree1cffc2016-02-21 19:14:41 +0100746
Bram Moolenaar4e221c92016-02-23 13:20:22 +0100747 call assert_equal('done', s:job_exit_ret)
Bram Moolenaar9730f742016-02-28 19:50:51 +0100748 unlet s:exit_job
Bram Moolenaaree1cffc2016-02-21 19:14:41 +0100749 endif
750endfunc
Bram Moolenaar4e221c92016-02-23 13:20:22 +0100751
752"""""""""
753
754let s:ch_close_ret = 'alive'
755function MyCloseCb(ch)
756 let s:ch_close_ret = 'closed'
757endfunc
758
759function s:test_close_callback(port)
760 let handle = ch_open('localhost:' . a:port, s:chopt)
761 if ch_status(handle) == "fail"
762 call assert_false(1, "Can't open channel")
763 return
764 endif
765 call ch_setoptions(handle, {'close-cb': 'MyCloseCb'})
766
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100767 call assert_equal('', ch_evalexpr(handle, 'close me'))
Bram Moolenaar4e221c92016-02-23 13:20:22 +0100768 sleep 20m
769 call assert_equal('closed', s:ch_close_ret)
770endfunc
771
772func Test_close_callback()
773 call ch_log('Test_close_callback()')
774 call s:run_server('s:test_close_callback')
775endfunc
776
Bram Moolenaar9730f742016-02-28 19:50:51 +0100777" Uncomment this to see what happens, output is in src/testdir/channellog.
778" call ch_logfile('channellog', 'w')