blob: c4e23c97fa3b58d84484fd617bcc684649817b49 [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.
Bram Moolenaard6a8d482016-02-10 20:32:20 +010056 let l = []
Bram Moolenaar9fe885e2016-03-08 16:06:55 +010057 for i in range(200)
Bram Moolenaard6a8d482016-02-10 20:32:20 +010058 try
59 let l = readfile("Xportnr")
60 catch
61 endtry
62 if len(l) >= 1
63 break
64 endif
Bram Moolenaar9fe885e2016-03-08 16:06:55 +010065 sleep 10m
66 endfor
Bram Moolenaard6a8d482016-02-10 20:32:20 +010067 call delete("Xportnr")
68
69 if len(l) == 0
70 " Can't make the connection, give up.
71 call assert_false(1, "Can't start test_channel.py")
72 return -1
73 endif
74 let port = l[0]
75
76 call call(function(a:testfunc), [port])
77 catch
78 call assert_false(1, "Caught exception: " . v:exception)
79 finally
Bram Moolenaara0f9cd12016-02-03 20:13:24 +010080 call s:kill_server()
Bram Moolenaard6a8d482016-02-10 20:32:20 +010081 endtry
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010082endfunc
83
84func s:kill_server()
Bram Moolenaar835dc632016-02-07 14:27:38 +010085 if has('job')
Bram Moolenaard6a8d482016-02-10 20:32:20 +010086 if exists('s:job')
87 call job_stop(s:job)
88 unlet s:job
89 endif
Bram Moolenaar835dc632016-02-07 14:27:38 +010090 elseif has('win32')
Bram Moolenaarb6a77372016-02-15 22:55:28 +010091 call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq test_channel"')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010092 else
Bram Moolenaar608a8912016-02-03 22:39:51 +010093 call system("pkill -f test_channel.py")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +010094 endif
95endfunc
96
Bram Moolenaara07fec92016-02-05 21:04:08 +010097let s:responseMsg = ''
98func s:RequestHandler(handle, msg)
99 let s:responseHandle = a:handle
100 let s:responseMsg = a:msg
101endfunc
102
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100103" Wait for up to a second for "expr" to become true.
104func s:waitFor(expr)
105 for i in range(100)
Bram Moolenaard9d473e2016-03-08 19:07:22 +0100106 try
107 if eval(a:expr)
108 return
109 endif
110 catch
111 endtry
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100112 sleep 10m
113 endfor
114endfunc
115
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100116func s:communicate(port)
117 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100118 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100119 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100120 return
121 endif
Bram Moolenaar839fd112016-03-06 21:34:03 +0100122 if has('job')
123 " check that no job is handled correctly
124 call assert_equal('no process', string(ch_getjob(handle)))
125 endif
Bram Moolenaard7ece102016-02-02 23:23:02 +0100126 " Simple string request and reply.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100127 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaard7ece102016-02-02 23:23:02 +0100128
Bram Moolenaarac74d5e2016-03-20 14:31:00 +0100129 " Malformed command should be ignored.
Bram Moolenaarba61ac02016-03-20 16:40:37 +0100130 call assert_equal('ok', ch_evalexpr(handle, 'malformed1'))
131 call assert_equal('ok', ch_evalexpr(handle, 'malformed2'))
132 call assert_equal('ok', ch_evalexpr(handle, 'malformed3'))
133
134 " split command should work
135 call assert_equal('ok', ch_evalexpr(handle, 'split'))
136 call s:waitFor('exists("g:split")')
137 call assert_equal(123, g:split)
Bram Moolenaarac74d5e2016-03-20 14:31:00 +0100138
Bram Moolenaard7ece102016-02-02 23:23:02 +0100139 " Request that triggers sending two ex commands. These will usually be
140 " handled before getting the response, but it's not guaranteed, thus wait a
141 " tiny bit for the commands to get executed.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100142 call assert_equal('ok', ch_evalexpr(handle, 'make change'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100143 call s:waitFor('"added2" == getline("$")')
Bram Moolenaard7ece102016-02-02 23:23:02 +0100144 call assert_equal('added1', getline(line('$') - 1))
145 call assert_equal('added2', getline('$'))
146
Bram Moolenaarda94fdf2016-03-03 18:09:10 +0100147 call assert_equal('ok', ch_evalexpr(handle, 'do normal', {'timeout': 100}))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100148 call s:waitFor('"added more" == getline("$")')
Bram Moolenaarf4160862016-02-05 23:09:12 +0100149 call assert_equal('added more', getline('$'))
150
Bram Moolenaara07fec92016-02-05 21:04:08 +0100151 " Send a request with a specific handler.
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100152 call ch_sendexpr(handle, 'hello!', {'callback': 's:RequestHandler'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100153 call s:waitFor('exists("s:responseHandle")')
Bram Moolenaar77073442016-02-13 23:23:53 +0100154 if !exists('s:responseHandle')
155 call assert_false(1, 's:responseHandle was not set')
156 else
157 call assert_equal(handle, s:responseHandle)
Bram Moolenaar9186a272016-02-23 19:34:01 +0100158 unlet s:responseHandle
Bram Moolenaar77073442016-02-13 23:23:53 +0100159 endif
Bram Moolenaara07fec92016-02-05 21:04:08 +0100160 call assert_equal('got it', s:responseMsg)
161
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100162 let s:responseMsg = ''
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100163 call ch_sendexpr(handle, 'hello!', {'callback': function('s:RequestHandler')})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100164 call s:waitFor('exists("s:responseHandle")')
Bram Moolenaar77073442016-02-13 23:23:53 +0100165 if !exists('s:responseHandle')
166 call assert_false(1, 's:responseHandle was not set')
167 else
168 call assert_equal(handle, s:responseHandle)
Bram Moolenaar9186a272016-02-23 19:34:01 +0100169 unlet s:responseHandle
Bram Moolenaar77073442016-02-13 23:23:53 +0100170 endif
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100171 call assert_equal('got it', s:responseMsg)
172
Bram Moolenaar38fd4bb2016-03-06 16:38:28 +0100173 " Collect garbage, tests that our handle isn't collected.
174 call garbagecollect()
175
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100176 " check setting options (without testing the effect)
177 call ch_setoptions(handle, {'callback': 's:NotUsed'})
Bram Moolenaar1f6ef662016-02-19 22:59:44 +0100178 call ch_setoptions(handle, {'timeout': 1111})
Bram Moolenaarb6b52522016-02-20 23:30:07 +0100179 call ch_setoptions(handle, {'mode': 'json'})
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100180 call assert_fails("call ch_setoptions(handle, {'waittime': 111})", "E475")
Bram Moolenaar0ba75a92016-02-19 23:21:26 +0100181 call ch_setoptions(handle, {'callback': ''})
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100182
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100183 " Send an eval request that works.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100184 call assert_equal('ok', ch_evalexpr(handle, 'eval-works'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100185 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100186 call assert_equal([-1, 'foo123'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100187
188 " Send an eval request that fails.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100189 call assert_equal('ok', ch_evalexpr(handle, 'eval-fails'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100190 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100191 call assert_equal([-2, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100192
Bram Moolenaar55fab432016-02-07 16:53:13 +0100193 " Send an eval request that works but can't be encoded.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100194 call assert_equal('ok', ch_evalexpr(handle, 'eval-error'))
Bram Moolenaar55fab432016-02-07 16:53:13 +0100195 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100196 call assert_equal([-3, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaar55fab432016-02-07 16:53:13 +0100197
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100198 " Send a bad eval request. There will be no response.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100199 call assert_equal('ok', ch_evalexpr(handle, 'eval-bad'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100200 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100201 call assert_equal([-3, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100202
Bram Moolenaarf4160862016-02-05 23:09:12 +0100203 " Send an expr request
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100204 call assert_equal('ok', ch_evalexpr(handle, 'an expr'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100205 call s:waitFor('"three" == getline("$")')
Bram Moolenaarf4160862016-02-05 23:09:12 +0100206 call assert_equal('one', getline(line('$') - 2))
207 call assert_equal('two', getline(line('$') - 1))
208 call assert_equal('three', getline('$'))
209
210 " Request a redraw, we don't check for the effect.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100211 call assert_equal('ok', ch_evalexpr(handle, 'redraw'))
212 call assert_equal('ok', ch_evalexpr(handle, 'redraw!'))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100213
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100214 call assert_equal('ok', ch_evalexpr(handle, 'empty-request'))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100215
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100216 " Reading while there is nothing available.
Bram Moolenaar9186a272016-02-23 19:34:01 +0100217 call assert_equal(v:none, ch_read(handle, {'timeout': 0}))
218 let start = reltime()
219 call assert_equal(v:none, ch_read(handle, {'timeout': 333}))
220 let elapsed = reltime(start)
221 call assert_true(reltimefloat(elapsed) > 0.3)
222 call assert_true(reltimefloat(elapsed) < 0.6)
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100223
224 " Send without waiting for a response, then wait for a response.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100225 call ch_sendexpr(handle, 'wait a bit')
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100226 let resp = ch_read(handle)
227 call assert_equal(type([]), type(resp))
228 call assert_equal(type(11), type(resp[0]))
229 call assert_equal('waited', resp[1])
230
Bram Moolenaard7ece102016-02-02 23:23:02 +0100231 " make the server quit, can't check if this works, should not hang.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100232 call ch_sendexpr(handle, '!quit!')
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100233endfunc
Bram Moolenaard7ece102016-02-02 23:23:02 +0100234
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100235func Test_communicate()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100236 call ch_log('Test_communicate()')
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100237 call s:run_server('s:communicate')
Bram Moolenaard7ece102016-02-02 23:23:02 +0100238endfunc
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100239
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100240" Test that we can open two channels.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100241func s:two_channels(port)
Bram Moolenaar39b21272016-02-10 23:28:21 +0100242 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100243 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100244 call assert_false(1, "Can't open channel")
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100245 return
246 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100247
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100248 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100249
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100250 let newhandle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100251 if ch_status(newhandle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100252 call assert_false(1, "Can't open second channel")
253 return
254 endif
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100255 call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
256 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100257
258 call ch_close(handle)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100259 call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100260
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100261 call ch_close(newhandle)
262endfunc
263
264func Test_two_channels()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100265 call ch_log('Test_two_channels()')
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100266 call s:run_server('s:two_channels')
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100267endfunc
268
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100269" Test that a server crash is handled gracefully.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100270func s:server_crash(port)
271 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100272 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100273 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100274 return
275 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100276
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100277 call ch_evalexpr(handle, '!crash!')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100278
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100279 sleep 10m
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100280endfunc
281
282func Test_server_crash()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100283 call ch_log('Test_server_crash()')
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100284 call s:run_server('s:server_crash')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100285endfunc
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100286
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100287"""""""""
288
Bram Moolenaarf6157282016-02-10 21:07:14 +0100289let s:reply = ""
290func s:Handler(chan, msg)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100291 unlet s:reply
Bram Moolenaarf6157282016-02-10 21:07:14 +0100292 let s:reply = a:msg
293endfunc
294
295func s:channel_handler(port)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100296 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100297 if ch_status(handle) == "fail"
Bram Moolenaarf6157282016-02-10 21:07:14 +0100298 call assert_false(1, "Can't open channel")
299 return
300 endif
301
302 " Test that it works while waiting on a numbered message.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100303 call assert_equal('ok', ch_evalexpr(handle, 'call me'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100304 call s:waitFor('"we called you" == s:reply')
Bram Moolenaarf6157282016-02-10 21:07:14 +0100305 call assert_equal('we called you', s:reply)
306
307 " Test that it works while not waiting on a numbered message.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100308 call ch_sendexpr(handle, 'call me again')
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100309 call s:waitFor('"we did call you" == s:reply')
Bram Moolenaarf6157282016-02-10 21:07:14 +0100310 call assert_equal('we did call you', s:reply)
311endfunc
312
313func Test_channel_handler()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100314 call ch_log('Test_channel_handler()')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100315 let s:chopt.callback = 's:Handler'
Bram Moolenaarf6157282016-02-10 21:07:14 +0100316 call s:run_server('s:channel_handler')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100317 let s:chopt.callback = function('s:Handler')
318 call s:run_server('s:channel_handler')
319 unlet s:chopt.callback
Bram Moolenaarf6157282016-02-10 21:07:14 +0100320endfunc
321
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100322"""""""""
323
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100324let s:ch_reply = ''
325func s:ChHandler(chan, msg)
326 unlet s:ch_reply
327 let s:ch_reply = a:msg
328endfunc
329
330let s:zero_reply = ''
331func s:OneHandler(chan, msg)
332 unlet s:zero_reply
333 let s:zero_reply = a:msg
334endfunc
335
336func s:channel_zero(port)
337 let handle = ch_open('localhost:' . a:port, s:chopt)
338 if ch_status(handle) == "fail"
339 call assert_false(1, "Can't open channel")
340 return
341 endif
342
343 " Check that eval works.
344 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
345
346 " Check that eval works if a zero id message is sent back.
347 let s:ch_reply = ''
348 call assert_equal('sent zero', ch_evalexpr(handle, 'send zero'))
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100349 if s:has_handler
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100350 call s:waitFor('"zero index" == s:ch_reply')
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100351 call assert_equal('zero index', s:ch_reply)
352 else
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100353 sleep 20m
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100354 call assert_equal('', s:ch_reply)
355 endif
356
357 " Check that handler works if a zero id message is sent back.
358 let s:ch_reply = ''
359 let s:zero_reply = ''
360 call ch_sendexpr(handle, 'send zero', {'callback': 's:OneHandler'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100361 call s:waitFor('"sent zero" == s:zero_reply')
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100362 if s:has_handler
363 call assert_equal('zero index', s:ch_reply)
364 else
365 call assert_equal('', s:ch_reply)
366 endif
367 call assert_equal('sent zero', s:zero_reply)
368endfunc
369
370func Test_zero_reply()
371 call ch_log('Test_zero_reply()')
372 " Run with channel handler
373 let s:has_handler = 1
374 let s:chopt.callback = 's:ChHandler'
375 call s:run_server('s:channel_zero')
376 unlet s:chopt.callback
377
378 " Run without channel handler
379 let s:has_handler = 0
380 call s:run_server('s:channel_zero')
381endfunc
382
383"""""""""
384
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100385let s:reply1 = ""
386func s:HandleRaw1(chan, msg)
387 unlet s:reply1
388 let s:reply1 = a:msg
389endfunc
390
391let s:reply2 = ""
392func s:HandleRaw2(chan, msg)
393 unlet s:reply2
394 let s:reply2 = a:msg
395endfunc
396
397let s:reply3 = ""
398func s:HandleRaw3(chan, msg)
399 unlet s:reply3
400 let s:reply3 = a:msg
401endfunc
402
403func s:raw_one_time_callback(port)
404 let handle = ch_open('localhost:' . a:port, s:chopt)
405 if ch_status(handle) == "fail"
406 call assert_false(1, "Can't open channel")
407 return
408 endif
409 call ch_setoptions(handle, {'mode': 'raw'})
410
411 " The message are sent raw, we do our own JSON strings here.
412 call ch_sendraw(handle, "[1, \"hello!\"]", {'callback': 's:HandleRaw1'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100413 call s:waitFor('s:reply1 != ""')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100414 call assert_equal("[1, \"got it\"]", s:reply1)
415 call ch_sendraw(handle, "[2, \"echo something\"]", {'callback': 's:HandleRaw2'})
416 call ch_sendraw(handle, "[3, \"wait a bit\"]", {'callback': 's:HandleRaw3'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100417 call s:waitFor('s:reply2 != ""')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100418 call assert_equal("[2, \"something\"]", s:reply2)
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100419 " wait for the 200 msec delayed reply
420 call s:waitFor('s:reply3 != ""')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100421 call assert_equal("[3, \"waited\"]", s:reply3)
422endfunc
423
424func Test_raw_one_time_callback()
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100425 call ch_log('Test_raw_one_time_callback()')
426 call s:run_server('s:raw_one_time_callback')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100427endfunc
428
429"""""""""
430
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100431" Test that trying to connect to a non-existing port fails quickly.
432func Test_connect_waittime()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100433 call ch_log('Test_connect_waittime()')
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100434 let start = reltime()
Bram Moolenaara4833262016-02-09 23:33:25 +0100435 let handle = ch_open('localhost:9876', s:chopt)
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100436 if ch_status(handle) != "fail"
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100437 " Oops, port does exists.
438 call ch_close(handle)
439 else
440 let elapsed = reltime(start)
Bram Moolenaar74f5e652016-02-07 21:44:49 +0100441 call assert_true(reltimefloat(elapsed) < 1.0)
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100442 endif
443
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100444 " We intend to use a socket that doesn't exist and wait for half a second
445 " before giving up. If the socket does exist it can fail in various ways.
446 " Check for "Connection reset by peer" to avoid flakyness.
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100447 let start = reltime()
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100448 try
449 let handle = ch_open('localhost:9867', {'waittime': 500})
450 if ch_status(handle) != "fail"
451 " Oops, port does exists.
452 call ch_close(handle)
453 else
Bram Moolenaarac42afd2016-03-12 13:48:49 +0100454 " Failed connection should wait about 500 msec. Can be longer if the
455 " computer is busy with other things.
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100456 let elapsed = reltime(start)
457 call assert_true(reltimefloat(elapsed) > 0.3)
Bram Moolenaarac42afd2016-03-12 13:48:49 +0100458 call assert_true(reltimefloat(elapsed) < 1.5)
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100459 endif
460 catch
461 if v:exception !~ 'Connection reset by peer'
462 call assert_false(1, "Caught exception: " . v:exception)
463 endif
464 endtry
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100465endfunc
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100466
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100467"""""""""
468
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100469func Test_raw_pipe()
470 if !has('job')
471 return
472 endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100473 call ch_log('Test_raw_pipe()')
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100474 let job = job_start(s:python . " test_channel_pipe.py", {'mode': 'raw'})
475 call assert_equal("run", job_status(job))
476 try
Bram Moolenaar151f6562016-03-07 21:19:38 +0100477 " For a change use the job where a channel is expected.
478 call ch_sendraw(job, "echo something\n")
479 let msg = ch_readraw(job)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100480 call assert_equal("something\n", substitute(msg, "\r", "", 'g'))
481
Bram Moolenaar151f6562016-03-07 21:19:38 +0100482 call ch_sendraw(job, "double this\n")
483 let msg = ch_readraw(job)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100484 call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g'))
485
Bram Moolenaar151f6562016-03-07 21:19:38 +0100486 let reply = ch_evalraw(job, "quit\n", {'timeout': 100})
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100487 call assert_equal("Goodbye!\n", substitute(reply, "\r", "", 'g'))
488 finally
489 call job_stop(job)
490 endtry
Bram Moolenaar8950a562016-03-12 15:22:55 +0100491
492 let s:job = job
493 call s:waitFor('"dead" == job_status(s:job)')
494 let info = job_info(job)
495 call assert_equal("dead", info.status)
496 call assert_equal("term", info.stoponexit)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100497endfunc
498
499func Test_nl_pipe()
Bram Moolenaard8070362016-02-15 21:56:54 +0100500 if !has('job')
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100501 return
502 endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100503 call ch_log('Test_nl_pipe()')
Bram Moolenaar1adda342016-03-12 15:39:40 +0100504 let job = job_start([s:python, "test_channel_pipe.py"])
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100505 call assert_equal("run", job_status(job))
506 try
507 let handle = job_getchannel(job)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100508 call ch_sendraw(handle, "echo something\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100509 call assert_equal("something", ch_readraw(handle))
510
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100511 call ch_sendraw(handle, "echoerr wrong\n")
512 call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
513
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100514 call ch_sendraw(handle, "double this\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100515 call assert_equal("this", ch_readraw(handle))
516 call assert_equal("AND this", ch_readraw(handle))
517
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100518 let reply = ch_evalraw(handle, "quit\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100519 call assert_equal("Goodbye!", reply)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100520 finally
521 call job_stop(job)
522 endtry
523endfunc
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100524
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100525func Test_nl_err_to_out_pipe()
526 if !has('job')
527 return
528 endif
Bram Moolenaar5a6ec522016-03-12 15:51:44 +0100529 call ch_logfile('Xlog')
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100530 call ch_log('Test_nl_err_to_out_pipe()')
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100531 let job = job_start(s:python . " test_channel_pipe.py", {'err_io': 'out'})
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100532 call assert_equal("run", job_status(job))
533 try
534 let handle = job_getchannel(job)
535 call ch_sendraw(handle, "echo something\n")
536 call assert_equal("something", ch_readraw(handle))
537
538 call ch_sendraw(handle, "echoerr wrong\n")
539 call assert_equal("wrong", ch_readraw(handle))
540 finally
541 call job_stop(job)
Bram Moolenaar5a6ec522016-03-12 15:51:44 +0100542 call ch_logfile('')
543 let loglines = readfile('Xlog')
544 call assert_true(len(loglines) > 10)
545 let found_test = 0
546 let found_send = 0
547 let found_recv = 0
548 let found_stop = 0
549 for l in loglines
550 if l =~ 'Test_nl_err_to_out_pipe'
551 let found_test = 1
552 endif
553 if l =~ 'SEND on.*echo something'
554 let found_send = 1
555 endif
556 if l =~ 'RECV on.*something'
557 let found_recv = 1
558 endif
559 if l =~ 'Stopping job with'
560 let found_stop = 1
561 endif
562 endfor
563 call assert_equal(1, found_test)
564 call assert_equal(1, found_send)
565 call assert_equal(1, found_recv)
566 call assert_equal(1, found_stop)
567 call delete('Xlog')
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100568 endtry
569endfunc
570
Bram Moolenaarb69fccf2016-03-06 23:06:25 +0100571func Test_nl_read_file()
572 if !has('job')
573 return
574 endif
Bram Moolenaarb69fccf2016-03-06 23:06:25 +0100575 call ch_log('Test_nl_read_file()')
576 call writefile(['echo something', 'echoerr wrong', 'double this'], 'Xinput')
577 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100578 \ {'in_io': 'file', 'in_name': 'Xinput'})
Bram Moolenaarb69fccf2016-03-06 23:06:25 +0100579 call assert_equal("run", job_status(job))
580 try
581 let handle = job_getchannel(job)
582 call assert_equal("something", ch_readraw(handle))
583 call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
584 call assert_equal("this", ch_readraw(handle))
585 call assert_equal("AND this", ch_readraw(handle))
586 finally
587 call job_stop(job)
588 call delete('Xinput')
589 endtry
590endfunc
591
Bram Moolenaare98d1212016-03-08 15:37:41 +0100592func Test_nl_write_out_file()
593 if !has('job')
594 return
595 endif
Bram Moolenaare98d1212016-03-08 15:37:41 +0100596 call ch_log('Test_nl_write_out_file()')
597 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100598 \ {'out_io': 'file', 'out_name': 'Xoutput'})
Bram Moolenaare98d1212016-03-08 15:37:41 +0100599 call assert_equal("run", job_status(job))
600 try
601 let handle = job_getchannel(job)
602 call ch_sendraw(handle, "echo line one\n")
603 call ch_sendraw(handle, "echo line two\n")
604 call ch_sendraw(handle, "double this\n")
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100605 call s:waitFor('len(readfile("Xoutput")) > 2')
Bram Moolenaare98d1212016-03-08 15:37:41 +0100606 call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput'))
607 finally
608 call job_stop(job)
609 call delete('Xoutput')
610 endtry
611endfunc
612
613func Test_nl_write_err_file()
614 if !has('job')
615 return
616 endif
Bram Moolenaare98d1212016-03-08 15:37:41 +0100617 call ch_log('Test_nl_write_err_file()')
618 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100619 \ {'err_io': 'file', 'err_name': 'Xoutput'})
Bram Moolenaare98d1212016-03-08 15:37:41 +0100620 call assert_equal("run", job_status(job))
621 try
622 let handle = job_getchannel(job)
623 call ch_sendraw(handle, "echoerr line one\n")
624 call ch_sendraw(handle, "echoerr line two\n")
625 call ch_sendraw(handle, "doubleerr this\n")
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100626 call s:waitFor('len(readfile("Xoutput")) > 2')
Bram Moolenaare98d1212016-03-08 15:37:41 +0100627 call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput'))
628 finally
629 call job_stop(job)
630 call delete('Xoutput')
631 endtry
632endfunc
633
634func Test_nl_write_both_file()
635 if !has('job')
636 return
637 endif
Bram Moolenaare98d1212016-03-08 15:37:41 +0100638 call ch_log('Test_nl_write_both_file()')
639 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100640 \ {'out_io': 'file', 'out_name': 'Xoutput', 'err_io': 'out'})
Bram Moolenaare98d1212016-03-08 15:37:41 +0100641 call assert_equal("run", job_status(job))
642 try
643 let handle = job_getchannel(job)
644 call ch_sendraw(handle, "echoerr line one\n")
645 call ch_sendraw(handle, "echo line two\n")
646 call ch_sendraw(handle, "double this\n")
647 call ch_sendraw(handle, "doubleerr that\n")
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100648 call s:waitFor('len(readfile("Xoutput")) > 5')
Bram Moolenaare98d1212016-03-08 15:37:41 +0100649 call assert_equal(['line one', 'line two', 'this', 'AND this', 'that', 'AND that'], readfile('Xoutput'))
650 finally
651 call job_stop(job)
652 call delete('Xoutput')
653 endtry
654endfunc
655
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100656func Run_test_pipe_to_buffer(use_name)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100657 if !has('job')
658 return
659 endif
660 call ch_log('Test_pipe_to_buffer()')
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100661 let options = {'out_io': 'buffer'}
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100662 if a:use_name
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100663 let options['out_name'] = 'pipe-output'
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100664 let firstline = 'Reading from channel output...'
665 else
666 sp pipe-output
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100667 let options['out_buf'] = bufnr('%')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100668 quit
669 let firstline = ''
670 endif
671 let job = job_start(s:python . " test_channel_pipe.py", options)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100672 call assert_equal("run", job_status(job))
673 try
674 let handle = job_getchannel(job)
675 call ch_sendraw(handle, "echo line one\n")
676 call ch_sendraw(handle, "echo line two\n")
677 call ch_sendraw(handle, "double this\n")
678 call ch_sendraw(handle, "quit\n")
679 sp pipe-output
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100680 call s:waitFor('line("$") >= 6')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100681 call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this', 'Goodbye!'], getline(1, '$'))
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100682 bwipe!
683 finally
684 call job_stop(job)
685 endtry
686endfunc
687
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100688func Test_pipe_to_buffer_name()
689 call Run_test_pipe_to_buffer(1)
690endfunc
691
692func Test_pipe_to_buffer_nr()
693 call Run_test_pipe_to_buffer(0)
694endfunc
695
696func Run_test_pipe_err_to_buffer(use_name)
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100697 if !has('job')
698 return
699 endif
700 call ch_log('Test_pipe_err_to_buffer()')
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100701 let options = {'err_io': 'buffer'}
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100702 if a:use_name
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100703 let options['err_name'] = 'pipe-err'
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100704 let firstline = 'Reading from channel error...'
705 else
706 sp pipe-err
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100707 let options['err_buf'] = bufnr('%')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100708 quit
709 let firstline = ''
710 endif
711 let job = job_start(s:python . " test_channel_pipe.py", options)
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100712 call assert_equal("run", job_status(job))
713 try
714 let handle = job_getchannel(job)
715 call ch_sendraw(handle, "echoerr line one\n")
716 call ch_sendraw(handle, "echoerr line two\n")
717 call ch_sendraw(handle, "doubleerr this\n")
718 call ch_sendraw(handle, "quit\n")
719 sp pipe-err
720 call s:waitFor('line("$") >= 5')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100721 call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this'], getline(1, '$'))
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100722 bwipe!
723 finally
724 call job_stop(job)
725 endtry
726endfunc
727
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100728func Test_pipe_err_to_buffer_name()
729 call Run_test_pipe_err_to_buffer(1)
730endfunc
731
732func Test_pipe_err_to_buffer_nr()
733 call Run_test_pipe_err_to_buffer(0)
734endfunc
735
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100736func Test_pipe_both_to_buffer()
737 if !has('job')
738 return
739 endif
740 call ch_log('Test_pipe_both_to_buffer()')
741 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100742 \ {'out_io': 'buffer', 'out_name': 'pipe-err', 'err_io': 'out'})
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100743 call assert_equal("run", job_status(job))
744 try
745 let handle = job_getchannel(job)
746 call ch_sendraw(handle, "echo line one\n")
747 call ch_sendraw(handle, "echoerr line two\n")
748 call ch_sendraw(handle, "double this\n")
749 call ch_sendraw(handle, "doubleerr that\n")
750 call ch_sendraw(handle, "quit\n")
751 sp pipe-err
752 call s:waitFor('line("$") >= 7')
753 call assert_equal(['Reading from channel output...', 'line one', 'line two', 'this', 'AND this', 'that', 'AND that', 'Goodbye!'], getline(1, '$'))
754 bwipe!
755 finally
756 call job_stop(job)
757 endtry
758endfunc
759
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100760func Run_test_pipe_from_buffer(use_name)
Bram Moolenaar014069a2016-03-03 22:51:40 +0100761 if !has('job')
762 return
763 endif
Bram Moolenaar014069a2016-03-03 22:51:40 +0100764 call ch_log('Test_pipe_from_buffer()')
765
766 sp pipe-input
767 call setline(1, ['echo one', 'echo two', 'echo three'])
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100768 let options = {'in_io': 'buffer'}
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100769 if a:use_name
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100770 let options['in_name'] = 'pipe-input'
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100771 else
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100772 let options['in_buf'] = bufnr('%')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100773 endif
Bram Moolenaar014069a2016-03-03 22:51:40 +0100774
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100775 let job = job_start(s:python . " test_channel_pipe.py", options)
Bram Moolenaar014069a2016-03-03 22:51:40 +0100776 call assert_equal("run", job_status(job))
777 try
778 let handle = job_getchannel(job)
779 call assert_equal('one', ch_read(handle))
780 call assert_equal('two', ch_read(handle))
781 call assert_equal('three', ch_read(handle))
782 bwipe!
783 finally
784 call job_stop(job)
785 endtry
Bram Moolenaar014069a2016-03-03 22:51:40 +0100786endfunc
787
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100788func Test_pipe_from_buffer_name()
789 call Run_test_pipe_from_buffer(1)
790endfunc
791
792func Test_pipe_from_buffer_nr()
793 call Run_test_pipe_from_buffer(0)
794endfunc
795
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100796func Test_pipe_to_nameless_buffer()
797 if !has('job')
798 return
799 endif
800 call ch_log('Test_pipe_to_nameless_buffer()')
801 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100802 \ {'out_io': 'buffer'})
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100803 call assert_equal("run", job_status(job))
804 try
805 let handle = job_getchannel(job)
806 call ch_sendraw(handle, "echo line one\n")
807 call ch_sendraw(handle, "echo line two\n")
808 exe ch_getbufnr(handle, "out") . 'sbuf'
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100809 call s:waitFor('line("$") >= 3')
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100810 call assert_equal(['Reading from channel output...', 'line one', 'line two'], getline(1, '$'))
811 bwipe!
812 finally
813 call job_stop(job)
814 endtry
815endfunc
816
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +0100817func Test_pipe_to_buffer_json()
818 if !has('job')
819 return
820 endif
821 call ch_log('Test_pipe_to_buffer_json()')
822 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100823 \ {'out_io': 'buffer', 'out_mode': 'json'})
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +0100824 call assert_equal("run", job_status(job))
825 try
826 let handle = job_getchannel(job)
827 call ch_sendraw(handle, "echo [0, \"hello\"]\n")
828 call ch_sendraw(handle, "echo [-2, 12.34]\n")
829 exe ch_getbufnr(handle, "out") . 'sbuf'
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100830 call s:waitFor('line("$") >= 3')
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +0100831 call assert_equal(['Reading from channel output...', '[0,"hello"]', '[-2,12.34]'], getline(1, '$'))
832 bwipe!
833 finally
834 call job_stop(job)
835 endtry
836endfunc
837
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100838" Wait a little while for the last line, minus "offset", to equal "line".
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100839func s:wait_for_last_line(line, offset)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100840 for i in range(100)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100841 if getline(line('$') - a:offset) == a:line
842 break
843 endif
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100844 sleep 10m
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100845 endfor
846endfunc
847
848func Test_pipe_io_two_buffers()
849 if !has('job')
850 return
851 endif
852 call ch_log('Test_pipe_io_two_buffers()')
853
854 " Create two buffers, one to read from and one to write to.
855 split pipe-output
856 set buftype=nofile
857 split pipe-input
858 set buftype=nofile
859
860 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100861 \ {'in_io': 'buffer', 'in_name': 'pipe-input', 'in_top': 0,
862 \ 'out_io': 'buffer', 'out_name': 'pipe-output'})
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100863 call assert_equal("run", job_status(job))
864 try
865 exe "normal Gaecho hello\<CR>"
866 exe bufwinnr('pipe-output') . "wincmd w"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100867 call s:wait_for_last_line('hello', 0)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100868 call assert_equal('hello', getline('$'))
869
870 exe bufwinnr('pipe-input') . "wincmd w"
871 exe "normal Gadouble this\<CR>"
872 exe bufwinnr('pipe-output') . "wincmd w"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100873 call s:wait_for_last_line('AND this', 0)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100874 call assert_equal('this', getline(line('$') - 1))
875 call assert_equal('AND this', getline('$'))
876
877 bwipe!
878 exe bufwinnr('pipe-input') . "wincmd w"
879 bwipe!
880 finally
881 call job_stop(job)
882 endtry
883endfunc
884
885func Test_pipe_io_one_buffer()
886 if !has('job')
887 return
888 endif
889 call ch_log('Test_pipe_io_one_buffer()')
890
891 " Create one buffer to read from and to write to.
892 split pipe-io
893 set buftype=nofile
894
895 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100896 \ {'in_io': 'buffer', 'in_name': 'pipe-io', 'in_top': 0,
897 \ 'out_io': 'buffer', 'out_name': 'pipe-io'})
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100898 call assert_equal("run", job_status(job))
899 try
900 exe "normal Goecho hello\<CR>"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100901 call s:wait_for_last_line('hello', 1)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100902 call assert_equal('hello', getline(line('$') - 1))
903
904 exe "normal Gadouble this\<CR>"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100905 call s:wait_for_last_line('AND this', 1)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100906 call assert_equal('this', getline(line('$') - 2))
907 call assert_equal('AND this', getline(line('$') - 1))
908
909 bwipe!
910 finally
911 call job_stop(job)
912 endtry
913endfunc
914
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100915func Test_pipe_null()
916 if !has('job')
917 return
918 endif
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100919 call ch_log('Test_pipe_null()')
920
921 " We cannot check that no I/O works, we only check that the job starts
922 " properly.
923 let job = job_start(s:python . " test_channel_pipe.py something",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100924 \ {'in_io': 'null'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100925 call assert_equal("run", job_status(job))
926 try
927 call assert_equal('something', ch_read(job))
928 finally
929 call job_stop(job)
930 endtry
931
932 let job = job_start(s:python . " test_channel_pipe.py err-out",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100933 \ {'out_io': 'null'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100934 call assert_equal("run", job_status(job))
935 try
936 call assert_equal('err-out', ch_read(job, {"part": "err"}))
937 finally
938 call job_stop(job)
939 endtry
940
941 let job = job_start(s:python . " test_channel_pipe.py something",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100942 \ {'err_io': 'null'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100943 call assert_equal("run", job_status(job))
944 try
945 call assert_equal('something', ch_read(job))
946 finally
947 call job_stop(job)
948 endtry
949
950 let job = job_start(s:python . " test_channel_pipe.py something",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100951 \ {'out_io': 'null', 'err_io': 'out'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100952 call assert_equal("run", job_status(job))
953 call job_stop(job)
954
955 let job = job_start(s:python . " test_channel_pipe.py something",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100956 \ {'in_io': 'null', 'out_io': 'null', 'err_io': 'null'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100957 call assert_equal("run", job_status(job))
958 call assert_equal('channel fail', string(job_getchannel(job)))
959 call assert_equal('fail', ch_status(job))
960 call job_stop(job)
961endfunc
962
Bram Moolenaarde279892016-03-11 22:19:44 +0100963func Test_reuse_channel()
964 if !has('job')
965 return
966 endif
967 call ch_log('Test_reuse_channel()')
968
969 let job = job_start(s:python . " test_channel_pipe.py")
970 call assert_equal("run", job_status(job))
971 let handle = job_getchannel(job)
972 try
973 call ch_sendraw(handle, "echo something\n")
974 call assert_equal("something", ch_readraw(handle))
975 finally
976 call job_stop(job)
977 endtry
978
979 let job = job_start(s:python . " test_channel_pipe.py", {'channel': handle})
980 call assert_equal("run", job_status(job))
981 let handle = job_getchannel(job)
982 try
983 call ch_sendraw(handle, "echo again\n")
984 call assert_equal("again", ch_readraw(handle))
985 finally
986 call job_stop(job)
987 endtry
988endfunc
989
Bram Moolenaard46ae142016-02-16 13:33:52 +0100990""""""""""
991
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100992let s:unletResponse = ''
993func s:UnletHandler(handle, msg)
994 let s:unletResponse = a:msg
995 unlet s:channelfd
996endfunc
997
998" Test that "unlet handle" in a handler doesn't crash Vim.
999func s:unlet_handle(port)
1000 let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar910b8aa2016-02-16 21:03:07 +01001001 call ch_sendexpr(s:channelfd, "test", {'callback': function('s:UnletHandler')})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001002 call s:waitFor('"what?" == s:unletResponse')
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01001003 call assert_equal('what?', s:unletResponse)
1004endfunc
1005
1006func Test_unlet_handle()
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001007 call ch_log('Test_unlet_handle()')
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01001008 call s:run_server('s:unlet_handle')
1009endfunc
Bram Moolenaar5cefd402016-02-16 12:44:26 +01001010
Bram Moolenaard46ae142016-02-16 13:33:52 +01001011""""""""""
1012
1013let s:unletResponse = ''
1014func s:CloseHandler(handle, msg)
1015 let s:unletResponse = a:msg
1016 call ch_close(s:channelfd)
1017endfunc
1018
1019" Test that "unlet handle" in a handler doesn't crash Vim.
1020func s:close_handle(port)
1021 let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar910b8aa2016-02-16 21:03:07 +01001022 call ch_sendexpr(s:channelfd, "test", {'callback': function('s:CloseHandler')})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001023 call s:waitFor('"what?" == s:unletResponse')
Bram Moolenaard46ae142016-02-16 13:33:52 +01001024 call assert_equal('what?', s:unletResponse)
1025endfunc
1026
1027func Test_close_handle()
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001028 call ch_log('Test_close_handle()')
Bram Moolenaard46ae142016-02-16 13:33:52 +01001029 call s:run_server('s:close_handle')
1030endfunc
1031
1032""""""""""
1033
Bram Moolenaar5cefd402016-02-16 12:44:26 +01001034func Test_open_fail()
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001035 call ch_log('Test_open_fail()')
Bram Moolenaar5cefd402016-02-16 12:44:26 +01001036 silent! let ch = ch_open("noserver")
1037 echo ch
1038 let d = ch
1039endfunc
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001040
1041""""""""""
1042
1043func s:open_delay(port)
1044 " Wait up to a second for the port to open.
1045 let s:chopt.waittime = 1000
1046 let channel = ch_open('localhost:' . a:port, s:chopt)
1047 unlet s:chopt.waittime
1048 if ch_status(channel) == "fail"
1049 call assert_false(1, "Can't open channel")
1050 return
1051 endif
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01001052 call assert_equal('got it', ch_evalexpr(channel, 'hello!'))
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001053 call ch_close(channel)
1054endfunc
1055
1056func Test_open_delay()
1057 call ch_log('Test_open_delay()')
1058 " The server will wait half a second before creating the port.
1059 call s:run_server('s:open_delay', 'delay')
1060endfunc
Bram Moolenaarece61b02016-02-20 21:39:05 +01001061
1062"""""""""
1063
1064function MyFunction(a,b,c)
1065 let s:call_ret = [a:a, a:b, a:c]
1066endfunc
1067
1068function s:test_call(port)
1069 let handle = ch_open('localhost:' . a:port, s:chopt)
1070 if ch_status(handle) == "fail"
1071 call assert_false(1, "Can't open channel")
1072 return
1073 endif
1074
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001075 let s:call_ret = []
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01001076 call assert_equal('ok', ch_evalexpr(handle, 'call-func'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001077 call s:waitFor('len(s:call_ret) > 0')
Bram Moolenaarece61b02016-02-20 21:39:05 +01001078 call assert_equal([1, 2, 3], s:call_ret)
1079endfunc
1080
1081func Test_call()
1082 call ch_log('Test_call()')
1083 call s:run_server('s:test_call')
1084endfunc
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001085
1086"""""""""
1087
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001088let s:job_exit_ret = 'not yet'
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001089function MyExitCb(job, status)
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001090 let s:job_exit_ret = 'done'
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001091endfunc
1092
1093function s:test_exit_callback(port)
Bram Moolenaard6c2f052016-03-14 23:22:59 +01001094 call job_setoptions(s:job, {'exit_cb': 'MyExitCb'})
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001095 let s:exit_job = s:job
Bram Moolenaard6c2f052016-03-14 23:22:59 +01001096 call assert_equal('MyExitCb', job_info(s:job)['exit_cb'])
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001097endfunc
1098
1099func Test_exit_callback()
1100 if has('job')
Bram Moolenaar9730f742016-02-28 19:50:51 +01001101 call ch_log('Test_exit_callback()')
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001102 call s:run_server('s:test_exit_callback')
1103
Bram Moolenaar9730f742016-02-28 19:50:51 +01001104 " wait up to a second for the job to exit
1105 for i in range(100)
1106 if s:job_exit_ret == 'done'
1107 break
1108 endif
1109 sleep 10m
1110 " calling job_status() triggers the callback
1111 call job_status(s:exit_job)
1112 endfor
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001113
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001114 call assert_equal('done', s:job_exit_ret)
Bram Moolenaar8950a562016-03-12 15:22:55 +01001115 call assert_equal('dead', job_info(s:exit_job).status)
Bram Moolenaar9730f742016-02-28 19:50:51 +01001116 unlet s:exit_job
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001117 endif
1118endfunc
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001119
1120"""""""""
1121
1122let s:ch_close_ret = 'alive'
1123function MyCloseCb(ch)
1124 let s:ch_close_ret = 'closed'
1125endfunc
1126
1127function s:test_close_callback(port)
1128 let handle = ch_open('localhost:' . a:port, s:chopt)
1129 if ch_status(handle) == "fail"
1130 call assert_false(1, "Can't open channel")
1131 return
1132 endif
Bram Moolenaard6c2f052016-03-14 23:22:59 +01001133 call ch_setoptions(handle, {'close_cb': 'MyCloseCb'})
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001134
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01001135 call assert_equal('', ch_evalexpr(handle, 'close me'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001136 call s:waitFor('"closed" == s:ch_close_ret')
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001137 call assert_equal('closed', s:ch_close_ret)
1138endfunc
1139
1140func Test_close_callback()
1141 call ch_log('Test_close_callback()')
1142 call s:run_server('s:test_close_callback')
1143endfunc
1144
Bram Moolenaar9730f742016-02-28 19:50:51 +01001145" Uncomment this to see what happens, output is in src/testdir/channellog.
1146" call ch_logfile('channellog', 'w')