blob: c9658802d9c539e656e6d11f16e8eb9609a93d04 [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
127 " Simple string request and reply.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100128 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaard7ece102016-02-02 23:23:02 +0100129
130 " Request that triggers sending two ex commands. These will usually be
131 " handled before getting the response, but it's not guaranteed, thus wait a
132 " tiny bit for the commands to get executed.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100133 call assert_equal('ok', ch_evalexpr(handle, 'make change'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100134 call s:waitFor('"added2" == getline("$")')
Bram Moolenaard7ece102016-02-02 23:23:02 +0100135 call assert_equal('added1', getline(line('$') - 1))
136 call assert_equal('added2', getline('$'))
137
Bram Moolenaarda94fdf2016-03-03 18:09:10 +0100138 call assert_equal('ok', ch_evalexpr(handle, 'do normal', {'timeout': 100}))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100139 call s:waitFor('"added more" == getline("$")')
Bram Moolenaarf4160862016-02-05 23:09:12 +0100140 call assert_equal('added more', getline('$'))
141
Bram Moolenaara07fec92016-02-05 21:04:08 +0100142 " Send a request with a specific handler.
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100143 call ch_sendexpr(handle, 'hello!', {'callback': 's:RequestHandler'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100144 call s:waitFor('exists("s:responseHandle")')
Bram Moolenaar77073442016-02-13 23:23:53 +0100145 if !exists('s:responseHandle')
146 call assert_false(1, 's:responseHandle was not set')
147 else
148 call assert_equal(handle, s:responseHandle)
Bram Moolenaar9186a272016-02-23 19:34:01 +0100149 unlet s:responseHandle
Bram Moolenaar77073442016-02-13 23:23:53 +0100150 endif
Bram Moolenaara07fec92016-02-05 21:04:08 +0100151 call assert_equal('got it', s:responseMsg)
152
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100153 let s:responseMsg = ''
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100154 call ch_sendexpr(handle, 'hello!', {'callback': function('s:RequestHandler')})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100155 call s:waitFor('exists("s:responseHandle")')
Bram Moolenaar77073442016-02-13 23:23:53 +0100156 if !exists('s:responseHandle')
157 call assert_false(1, 's:responseHandle was not set')
158 else
159 call assert_equal(handle, s:responseHandle)
Bram Moolenaar9186a272016-02-23 19:34:01 +0100160 unlet s:responseHandle
Bram Moolenaar77073442016-02-13 23:23:53 +0100161 endif
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100162 call assert_equal('got it', s:responseMsg)
163
Bram Moolenaar38fd4bb2016-03-06 16:38:28 +0100164 " Collect garbage, tests that our handle isn't collected.
165 call garbagecollect()
166
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100167 " check setting options (without testing the effect)
168 call ch_setoptions(handle, {'callback': 's:NotUsed'})
Bram Moolenaar1f6ef662016-02-19 22:59:44 +0100169 call ch_setoptions(handle, {'timeout': 1111})
Bram Moolenaarb6b52522016-02-20 23:30:07 +0100170 call ch_setoptions(handle, {'mode': 'json'})
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100171 call assert_fails("call ch_setoptions(handle, {'waittime': 111})", "E475")
Bram Moolenaar0ba75a92016-02-19 23:21:26 +0100172 call ch_setoptions(handle, {'callback': ''})
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100173
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100174 " Send an eval request that works.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100175 call assert_equal('ok', ch_evalexpr(handle, 'eval-works'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100176 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100177 call assert_equal([-1, 'foo123'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100178
179 " Send an eval request that fails.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100180 call assert_equal('ok', ch_evalexpr(handle, 'eval-fails'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100181 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100182 call assert_equal([-2, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100183
Bram Moolenaar55fab432016-02-07 16:53:13 +0100184 " Send an eval request that works but can't be encoded.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100185 call assert_equal('ok', ch_evalexpr(handle, 'eval-error'))
Bram Moolenaar55fab432016-02-07 16:53:13 +0100186 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100187 call assert_equal([-3, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaar55fab432016-02-07 16:53:13 +0100188
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100189 " Send a bad eval request. There will be no response.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100190 call assert_equal('ok', ch_evalexpr(handle, 'eval-bad'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100191 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100192 call assert_equal([-3, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100193
Bram Moolenaarf4160862016-02-05 23:09:12 +0100194 " Send an expr request
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100195 call assert_equal('ok', ch_evalexpr(handle, 'an expr'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100196 call s:waitFor('"three" == getline("$")')
Bram Moolenaarf4160862016-02-05 23:09:12 +0100197 call assert_equal('one', getline(line('$') - 2))
198 call assert_equal('two', getline(line('$') - 1))
199 call assert_equal('three', getline('$'))
200
201 " Request a redraw, we don't check for the effect.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100202 call assert_equal('ok', ch_evalexpr(handle, 'redraw'))
203 call assert_equal('ok', ch_evalexpr(handle, 'redraw!'))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100204
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100205 call assert_equal('ok', ch_evalexpr(handle, 'empty-request'))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100206
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100207 " Reading while there is nothing available.
Bram Moolenaar9186a272016-02-23 19:34:01 +0100208 call assert_equal(v:none, ch_read(handle, {'timeout': 0}))
209 let start = reltime()
210 call assert_equal(v:none, ch_read(handle, {'timeout': 333}))
211 let elapsed = reltime(start)
212 call assert_true(reltimefloat(elapsed) > 0.3)
213 call assert_true(reltimefloat(elapsed) < 0.6)
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100214
215 " Send without waiting for a response, then wait for a response.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100216 call ch_sendexpr(handle, 'wait a bit')
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100217 let resp = ch_read(handle)
218 call assert_equal(type([]), type(resp))
219 call assert_equal(type(11), type(resp[0]))
220 call assert_equal('waited', resp[1])
221
Bram Moolenaard7ece102016-02-02 23:23:02 +0100222 " make the server quit, can't check if this works, should not hang.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100223 call ch_sendexpr(handle, '!quit!')
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100224endfunc
Bram Moolenaard7ece102016-02-02 23:23:02 +0100225
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100226func Test_communicate()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100227 call ch_log('Test_communicate()')
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100228 call s:run_server('s:communicate')
Bram Moolenaard7ece102016-02-02 23:23:02 +0100229endfunc
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100230
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100231" Test that we can open two channels.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100232func s:two_channels(port)
Bram Moolenaar39b21272016-02-10 23:28:21 +0100233 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100234 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100235 call assert_false(1, "Can't open channel")
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100236 return
237 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100238
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100239 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100240
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100241 let newhandle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100242 if ch_status(newhandle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100243 call assert_false(1, "Can't open second channel")
244 return
245 endif
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100246 call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
247 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100248
249 call ch_close(handle)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100250 call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100251
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100252 call ch_close(newhandle)
253endfunc
254
255func Test_two_channels()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100256 call ch_log('Test_two_channels()')
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100257 call s:run_server('s:two_channels')
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100258endfunc
259
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100260" Test that a server crash is handled gracefully.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100261func s:server_crash(port)
262 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100263 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100264 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100265 return
266 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100267
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100268 call ch_evalexpr(handle, '!crash!')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100269
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100270 sleep 10m
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100271endfunc
272
273func Test_server_crash()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100274 call ch_log('Test_server_crash()')
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100275 call s:run_server('s:server_crash')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100276endfunc
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100277
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100278"""""""""
279
Bram Moolenaarf6157282016-02-10 21:07:14 +0100280let s:reply = ""
281func s:Handler(chan, msg)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100282 unlet s:reply
Bram Moolenaarf6157282016-02-10 21:07:14 +0100283 let s:reply = a:msg
284endfunc
285
286func s:channel_handler(port)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100287 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100288 if ch_status(handle) == "fail"
Bram Moolenaarf6157282016-02-10 21:07:14 +0100289 call assert_false(1, "Can't open channel")
290 return
291 endif
292
293 " Test that it works while waiting on a numbered message.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100294 call assert_equal('ok', ch_evalexpr(handle, 'call me'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100295 call s:waitFor('"we called you" == s:reply')
Bram Moolenaarf6157282016-02-10 21:07:14 +0100296 call assert_equal('we called you', s:reply)
297
298 " Test that it works while not waiting on a numbered message.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100299 call ch_sendexpr(handle, 'call me again')
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100300 call s:waitFor('"we did call you" == s:reply')
Bram Moolenaarf6157282016-02-10 21:07:14 +0100301 call assert_equal('we did call you', s:reply)
302endfunc
303
304func Test_channel_handler()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100305 call ch_log('Test_channel_handler()')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100306 let s:chopt.callback = 's:Handler'
Bram Moolenaarf6157282016-02-10 21:07:14 +0100307 call s:run_server('s:channel_handler')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100308 let s:chopt.callback = function('s:Handler')
309 call s:run_server('s:channel_handler')
310 unlet s:chopt.callback
Bram Moolenaarf6157282016-02-10 21:07:14 +0100311endfunc
312
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100313"""""""""
314
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100315let s:ch_reply = ''
316func s:ChHandler(chan, msg)
317 unlet s:ch_reply
318 let s:ch_reply = a:msg
319endfunc
320
321let s:zero_reply = ''
322func s:OneHandler(chan, msg)
323 unlet s:zero_reply
324 let s:zero_reply = a:msg
325endfunc
326
327func s:channel_zero(port)
328 let handle = ch_open('localhost:' . a:port, s:chopt)
329 if ch_status(handle) == "fail"
330 call assert_false(1, "Can't open channel")
331 return
332 endif
333
334 " Check that eval works.
335 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
336
337 " Check that eval works if a zero id message is sent back.
338 let s:ch_reply = ''
339 call assert_equal('sent zero', ch_evalexpr(handle, 'send zero'))
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100340 if s:has_handler
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100341 call s:waitFor('"zero index" == s:ch_reply')
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100342 call assert_equal('zero index', s:ch_reply)
343 else
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100344 sleep 20m
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100345 call assert_equal('', s:ch_reply)
346 endif
347
348 " Check that handler works if a zero id message is sent back.
349 let s:ch_reply = ''
350 let s:zero_reply = ''
351 call ch_sendexpr(handle, 'send zero', {'callback': 's:OneHandler'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100352 call s:waitFor('"sent zero" == s:zero_reply')
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100353 if s:has_handler
354 call assert_equal('zero index', s:ch_reply)
355 else
356 call assert_equal('', s:ch_reply)
357 endif
358 call assert_equal('sent zero', s:zero_reply)
359endfunc
360
361func Test_zero_reply()
362 call ch_log('Test_zero_reply()')
363 " Run with channel handler
364 let s:has_handler = 1
365 let s:chopt.callback = 's:ChHandler'
366 call s:run_server('s:channel_zero')
367 unlet s:chopt.callback
368
369 " Run without channel handler
370 let s:has_handler = 0
371 call s:run_server('s:channel_zero')
372endfunc
373
374"""""""""
375
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100376let s:reply1 = ""
377func s:HandleRaw1(chan, msg)
378 unlet s:reply1
379 let s:reply1 = a:msg
380endfunc
381
382let s:reply2 = ""
383func s:HandleRaw2(chan, msg)
384 unlet s:reply2
385 let s:reply2 = a:msg
386endfunc
387
388let s:reply3 = ""
389func s:HandleRaw3(chan, msg)
390 unlet s:reply3
391 let s:reply3 = a:msg
392endfunc
393
394func s:raw_one_time_callback(port)
395 let handle = ch_open('localhost:' . a:port, s:chopt)
396 if ch_status(handle) == "fail"
397 call assert_false(1, "Can't open channel")
398 return
399 endif
400 call ch_setoptions(handle, {'mode': 'raw'})
401
402 " The message are sent raw, we do our own JSON strings here.
403 call ch_sendraw(handle, "[1, \"hello!\"]", {'callback': 's:HandleRaw1'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100404 call s:waitFor('s:reply1 != ""')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100405 call assert_equal("[1, \"got it\"]", s:reply1)
406 call ch_sendraw(handle, "[2, \"echo something\"]", {'callback': 's:HandleRaw2'})
407 call ch_sendraw(handle, "[3, \"wait a bit\"]", {'callback': 's:HandleRaw3'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100408 call s:waitFor('s:reply2 != ""')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100409 call assert_equal("[2, \"something\"]", s:reply2)
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100410 " wait for the 200 msec delayed reply
411 call s:waitFor('s:reply3 != ""')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100412 call assert_equal("[3, \"waited\"]", s:reply3)
413endfunc
414
415func Test_raw_one_time_callback()
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100416 call ch_log('Test_raw_one_time_callback()')
417 call s:run_server('s:raw_one_time_callback')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100418endfunc
419
420"""""""""
421
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100422" Test that trying to connect to a non-existing port fails quickly.
423func Test_connect_waittime()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100424 call ch_log('Test_connect_waittime()')
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100425 let start = reltime()
Bram Moolenaara4833262016-02-09 23:33:25 +0100426 let handle = ch_open('localhost:9876', s:chopt)
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100427 if ch_status(handle) != "fail"
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100428 " Oops, port does exists.
429 call ch_close(handle)
430 else
431 let elapsed = reltime(start)
Bram Moolenaar74f5e652016-02-07 21:44:49 +0100432 call assert_true(reltimefloat(elapsed) < 1.0)
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100433 endif
434
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100435 " We intend to use a socket that doesn't exist and wait for half a second
436 " before giving up. If the socket does exist it can fail in various ways.
437 " Check for "Connection reset by peer" to avoid flakyness.
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100438 let start = reltime()
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100439 try
440 let handle = ch_open('localhost:9867', {'waittime': 500})
441 if ch_status(handle) != "fail"
442 " Oops, port does exists.
443 call ch_close(handle)
444 else
Bram Moolenaarac42afd2016-03-12 13:48:49 +0100445 " Failed connection should wait about 500 msec. Can be longer if the
446 " computer is busy with other things.
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100447 let elapsed = reltime(start)
448 call assert_true(reltimefloat(elapsed) > 0.3)
Bram Moolenaarac42afd2016-03-12 13:48:49 +0100449 call assert_true(reltimefloat(elapsed) < 1.5)
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100450 endif
451 catch
452 if v:exception !~ 'Connection reset by peer'
453 call assert_false(1, "Caught exception: " . v:exception)
454 endif
455 endtry
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100456endfunc
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100457
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100458"""""""""
459
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100460func Test_raw_pipe()
461 if !has('job')
462 return
463 endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100464 call ch_log('Test_raw_pipe()')
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100465 let job = job_start(s:python . " test_channel_pipe.py", {'mode': 'raw'})
466 call assert_equal("run", job_status(job))
467 try
Bram Moolenaar151f6562016-03-07 21:19:38 +0100468 " For a change use the job where a channel is expected.
469 call ch_sendraw(job, "echo something\n")
470 let msg = ch_readraw(job)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100471 call assert_equal("something\n", substitute(msg, "\r", "", 'g'))
472
Bram Moolenaar151f6562016-03-07 21:19:38 +0100473 call ch_sendraw(job, "double this\n")
474 let msg = ch_readraw(job)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100475 call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g'))
476
Bram Moolenaar151f6562016-03-07 21:19:38 +0100477 let reply = ch_evalraw(job, "quit\n", {'timeout': 100})
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100478 call assert_equal("Goodbye!\n", substitute(reply, "\r", "", 'g'))
479 finally
480 call job_stop(job)
481 endtry
Bram Moolenaar8950a562016-03-12 15:22:55 +0100482
483 let s:job = job
484 call s:waitFor('"dead" == job_status(s:job)')
485 let info = job_info(job)
486 call assert_equal("dead", info.status)
487 call assert_equal("term", info.stoponexit)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100488endfunc
489
490func Test_nl_pipe()
Bram Moolenaard8070362016-02-15 21:56:54 +0100491 if !has('job')
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100492 return
493 endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100494 call ch_log('Test_nl_pipe()')
Bram Moolenaar1adda342016-03-12 15:39:40 +0100495 let job = job_start([s:python, "test_channel_pipe.py"])
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100496 call assert_equal("run", job_status(job))
497 try
498 let handle = job_getchannel(job)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100499 call ch_sendraw(handle, "echo something\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100500 call assert_equal("something", ch_readraw(handle))
501
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100502 call ch_sendraw(handle, "echoerr wrong\n")
503 call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
504
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100505 call ch_sendraw(handle, "double this\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100506 call assert_equal("this", ch_readraw(handle))
507 call assert_equal("AND this", ch_readraw(handle))
508
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100509 let reply = ch_evalraw(handle, "quit\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100510 call assert_equal("Goodbye!", reply)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100511 finally
512 call job_stop(job)
513 endtry
514endfunc
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100515
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100516func Test_nl_err_to_out_pipe()
517 if !has('job')
518 return
519 endif
520 call ch_log('Test_nl_err_to_out_pipe()')
521 let job = job_start(s:python . " test_channel_pipe.py", {'err-io': 'out'})
522 call assert_equal("run", job_status(job))
523 try
524 let handle = job_getchannel(job)
525 call ch_sendraw(handle, "echo something\n")
526 call assert_equal("something", ch_readraw(handle))
527
528 call ch_sendraw(handle, "echoerr wrong\n")
529 call assert_equal("wrong", ch_readraw(handle))
530 finally
531 call job_stop(job)
532 endtry
533endfunc
534
Bram Moolenaarb69fccf2016-03-06 23:06:25 +0100535func Test_nl_read_file()
536 if !has('job')
537 return
538 endif
Bram Moolenaarb69fccf2016-03-06 23:06:25 +0100539 call ch_log('Test_nl_read_file()')
540 call writefile(['echo something', 'echoerr wrong', 'double this'], 'Xinput')
541 let job = job_start(s:python . " test_channel_pipe.py",
542 \ {'in-io': 'file', 'in-name': 'Xinput'})
543 call assert_equal("run", job_status(job))
544 try
545 let handle = job_getchannel(job)
546 call assert_equal("something", ch_readraw(handle))
547 call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
548 call assert_equal("this", ch_readraw(handle))
549 call assert_equal("AND this", ch_readraw(handle))
550 finally
551 call job_stop(job)
552 call delete('Xinput')
553 endtry
554endfunc
555
Bram Moolenaare98d1212016-03-08 15:37:41 +0100556func Test_nl_write_out_file()
557 if !has('job')
558 return
559 endif
Bram Moolenaare98d1212016-03-08 15:37:41 +0100560 call ch_log('Test_nl_write_out_file()')
561 let job = job_start(s:python . " test_channel_pipe.py",
562 \ {'out-io': 'file', 'out-name': 'Xoutput'})
563 call assert_equal("run", job_status(job))
564 try
565 let handle = job_getchannel(job)
566 call ch_sendraw(handle, "echo line one\n")
567 call ch_sendraw(handle, "echo line two\n")
568 call ch_sendraw(handle, "double this\n")
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100569 call s:waitFor('len(readfile("Xoutput")) > 2')
Bram Moolenaare98d1212016-03-08 15:37:41 +0100570 call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput'))
571 finally
572 call job_stop(job)
573 call delete('Xoutput')
574 endtry
575endfunc
576
577func Test_nl_write_err_file()
578 if !has('job')
579 return
580 endif
Bram Moolenaare98d1212016-03-08 15:37:41 +0100581 call ch_log('Test_nl_write_err_file()')
582 let job = job_start(s:python . " test_channel_pipe.py",
583 \ {'err-io': 'file', 'err-name': 'Xoutput'})
584 call assert_equal("run", job_status(job))
585 try
586 let handle = job_getchannel(job)
587 call ch_sendraw(handle, "echoerr line one\n")
588 call ch_sendraw(handle, "echoerr line two\n")
589 call ch_sendraw(handle, "doubleerr this\n")
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100590 call s:waitFor('len(readfile("Xoutput")) > 2')
Bram Moolenaare98d1212016-03-08 15:37:41 +0100591 call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput'))
592 finally
593 call job_stop(job)
594 call delete('Xoutput')
595 endtry
596endfunc
597
598func Test_nl_write_both_file()
599 if !has('job')
600 return
601 endif
Bram Moolenaare98d1212016-03-08 15:37:41 +0100602 call ch_log('Test_nl_write_both_file()')
603 let job = job_start(s:python . " test_channel_pipe.py",
604 \ {'out-io': 'file', 'out-name': 'Xoutput', 'err-io': 'out'})
605 call assert_equal("run", job_status(job))
606 try
607 let handle = job_getchannel(job)
608 call ch_sendraw(handle, "echoerr line one\n")
609 call ch_sendraw(handle, "echo line two\n")
610 call ch_sendraw(handle, "double this\n")
611 call ch_sendraw(handle, "doubleerr that\n")
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100612 call s:waitFor('len(readfile("Xoutput")) > 5')
Bram Moolenaare98d1212016-03-08 15:37:41 +0100613 call assert_equal(['line one', 'line two', 'this', 'AND this', 'that', 'AND that'], readfile('Xoutput'))
614 finally
615 call job_stop(job)
616 call delete('Xoutput')
617 endtry
618endfunc
619
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100620func Run_test_pipe_to_buffer(use_name)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100621 if !has('job')
622 return
623 endif
624 call ch_log('Test_pipe_to_buffer()')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100625 let options = {'out-io': 'buffer'}
626 if a:use_name
627 let options['out-name'] = 'pipe-output'
628 let firstline = 'Reading from channel output...'
629 else
630 sp pipe-output
631 let options['out-buf'] = bufnr('%')
632 quit
633 let firstline = ''
634 endif
635 let job = job_start(s:python . " test_channel_pipe.py", options)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100636 call assert_equal("run", job_status(job))
637 try
638 let handle = job_getchannel(job)
639 call ch_sendraw(handle, "echo line one\n")
640 call ch_sendraw(handle, "echo line two\n")
641 call ch_sendraw(handle, "double this\n")
642 call ch_sendraw(handle, "quit\n")
643 sp pipe-output
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100644 call s:waitFor('line("$") >= 6')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100645 call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this', 'Goodbye!'], getline(1, '$'))
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100646 bwipe!
647 finally
648 call job_stop(job)
649 endtry
650endfunc
651
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100652func Test_pipe_to_buffer_name()
653 call Run_test_pipe_to_buffer(1)
654endfunc
655
656func Test_pipe_to_buffer_nr()
657 call Run_test_pipe_to_buffer(0)
658endfunc
659
660func Run_test_pipe_err_to_buffer(use_name)
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100661 if !has('job')
662 return
663 endif
664 call ch_log('Test_pipe_err_to_buffer()')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100665 let options = {'err-io': 'buffer'}
666 if a:use_name
667 let options['err-name'] = 'pipe-err'
668 let firstline = 'Reading from channel error...'
669 else
670 sp pipe-err
671 let options['err-buf'] = bufnr('%')
672 quit
673 let firstline = ''
674 endif
675 let job = job_start(s:python . " test_channel_pipe.py", options)
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100676 call assert_equal("run", job_status(job))
677 try
678 let handle = job_getchannel(job)
679 call ch_sendraw(handle, "echoerr line one\n")
680 call ch_sendraw(handle, "echoerr line two\n")
681 call ch_sendraw(handle, "doubleerr this\n")
682 call ch_sendraw(handle, "quit\n")
683 sp pipe-err
684 call s:waitFor('line("$") >= 5')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100685 call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this'], getline(1, '$'))
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100686 bwipe!
687 finally
688 call job_stop(job)
689 endtry
690endfunc
691
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100692func Test_pipe_err_to_buffer_name()
693 call Run_test_pipe_err_to_buffer(1)
694endfunc
695
696func Test_pipe_err_to_buffer_nr()
697 call Run_test_pipe_err_to_buffer(0)
698endfunc
699
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100700func Test_pipe_both_to_buffer()
701 if !has('job')
702 return
703 endif
704 call ch_log('Test_pipe_both_to_buffer()')
705 let job = job_start(s:python . " test_channel_pipe.py",
706 \ {'out-io': 'buffer', 'out-name': 'pipe-err', 'err-io': 'out'})
707 call assert_equal("run", job_status(job))
708 try
709 let handle = job_getchannel(job)
710 call ch_sendraw(handle, "echo line one\n")
711 call ch_sendraw(handle, "echoerr line two\n")
712 call ch_sendraw(handle, "double this\n")
713 call ch_sendraw(handle, "doubleerr that\n")
714 call ch_sendraw(handle, "quit\n")
715 sp pipe-err
716 call s:waitFor('line("$") >= 7')
717 call assert_equal(['Reading from channel output...', 'line one', 'line two', 'this', 'AND this', 'that', 'AND that', 'Goodbye!'], getline(1, '$'))
718 bwipe!
719 finally
720 call job_stop(job)
721 endtry
722endfunc
723
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100724func Run_test_pipe_from_buffer(use_name)
Bram Moolenaar014069a2016-03-03 22:51:40 +0100725 if !has('job')
726 return
727 endif
Bram Moolenaar014069a2016-03-03 22:51:40 +0100728 call ch_log('Test_pipe_from_buffer()')
729
730 sp pipe-input
731 call setline(1, ['echo one', 'echo two', 'echo three'])
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100732 let options = {'in-io': 'buffer'}
733 if a:use_name
734 let options['in-name'] = 'pipe-input'
735 else
736 let options['in-buf'] = bufnr('%')
737 endif
Bram Moolenaar014069a2016-03-03 22:51:40 +0100738
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100739 let job = job_start(s:python . " test_channel_pipe.py", options)
Bram Moolenaar014069a2016-03-03 22:51:40 +0100740 call assert_equal("run", job_status(job))
741 try
742 let handle = job_getchannel(job)
743 call assert_equal('one', ch_read(handle))
744 call assert_equal('two', ch_read(handle))
745 call assert_equal('three', ch_read(handle))
746 bwipe!
747 finally
748 call job_stop(job)
749 endtry
Bram Moolenaar014069a2016-03-03 22:51:40 +0100750endfunc
751
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100752func Test_pipe_from_buffer_name()
753 call Run_test_pipe_from_buffer(1)
754endfunc
755
756func Test_pipe_from_buffer_nr()
757 call Run_test_pipe_from_buffer(0)
758endfunc
759
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100760func Test_pipe_to_nameless_buffer()
761 if !has('job')
762 return
763 endif
764 call ch_log('Test_pipe_to_nameless_buffer()')
765 let job = job_start(s:python . " test_channel_pipe.py",
766 \ {'out-io': 'buffer'})
767 call assert_equal("run", job_status(job))
768 try
769 let handle = job_getchannel(job)
770 call ch_sendraw(handle, "echo line one\n")
771 call ch_sendraw(handle, "echo line two\n")
772 exe ch_getbufnr(handle, "out") . 'sbuf'
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100773 call s:waitFor('line("$") >= 3')
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100774 call assert_equal(['Reading from channel output...', 'line one', 'line two'], getline(1, '$'))
775 bwipe!
776 finally
777 call job_stop(job)
778 endtry
779endfunc
780
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +0100781func Test_pipe_to_buffer_json()
782 if !has('job')
783 return
784 endif
785 call ch_log('Test_pipe_to_buffer_json()')
786 let job = job_start(s:python . " test_channel_pipe.py",
787 \ {'out-io': 'buffer', 'out-mode': 'json'})
788 call assert_equal("run", job_status(job))
789 try
790 let handle = job_getchannel(job)
791 call ch_sendraw(handle, "echo [0, \"hello\"]\n")
792 call ch_sendraw(handle, "echo [-2, 12.34]\n")
793 exe ch_getbufnr(handle, "out") . 'sbuf'
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100794 call s:waitFor('line("$") >= 3')
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +0100795 call assert_equal(['Reading from channel output...', '[0,"hello"]', '[-2,12.34]'], getline(1, '$'))
796 bwipe!
797 finally
798 call job_stop(job)
799 endtry
800endfunc
801
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100802" Wait a little while for the last line, minus "offset", to equal "line".
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100803func s:wait_for_last_line(line, offset)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100804 for i in range(100)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100805 if getline(line('$') - a:offset) == a:line
806 break
807 endif
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100808 sleep 10m
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100809 endfor
810endfunc
811
812func Test_pipe_io_two_buffers()
813 if !has('job')
814 return
815 endif
816 call ch_log('Test_pipe_io_two_buffers()')
817
818 " Create two buffers, one to read from and one to write to.
819 split pipe-output
820 set buftype=nofile
821 split pipe-input
822 set buftype=nofile
823
824 let job = job_start(s:python . " test_channel_pipe.py",
825 \ {'in-io': 'buffer', 'in-name': 'pipe-input', 'in-top': 0,
826 \ 'out-io': 'buffer', 'out-name': 'pipe-output'})
827 call assert_equal("run", job_status(job))
828 try
829 exe "normal Gaecho hello\<CR>"
830 exe bufwinnr('pipe-output') . "wincmd w"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100831 call s:wait_for_last_line('hello', 0)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100832 call assert_equal('hello', getline('$'))
833
834 exe bufwinnr('pipe-input') . "wincmd w"
835 exe "normal Gadouble this\<CR>"
836 exe bufwinnr('pipe-output') . "wincmd w"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100837 call s:wait_for_last_line('AND this', 0)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100838 call assert_equal('this', getline(line('$') - 1))
839 call assert_equal('AND this', getline('$'))
840
841 bwipe!
842 exe bufwinnr('pipe-input') . "wincmd w"
843 bwipe!
844 finally
845 call job_stop(job)
846 endtry
847endfunc
848
849func Test_pipe_io_one_buffer()
850 if !has('job')
851 return
852 endif
853 call ch_log('Test_pipe_io_one_buffer()')
854
855 " Create one buffer to read from and to write to.
856 split pipe-io
857 set buftype=nofile
858
859 let job = job_start(s:python . " test_channel_pipe.py",
860 \ {'in-io': 'buffer', 'in-name': 'pipe-io', 'in-top': 0,
861 \ 'out-io': 'buffer', 'out-name': 'pipe-io'})
862 call assert_equal("run", job_status(job))
863 try
864 exe "normal Goecho hello\<CR>"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100865 call s:wait_for_last_line('hello', 1)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100866 call assert_equal('hello', getline(line('$') - 1))
867
868 exe "normal Gadouble this\<CR>"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100869 call s:wait_for_last_line('AND this', 1)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100870 call assert_equal('this', getline(line('$') - 2))
871 call assert_equal('AND this', getline(line('$') - 1))
872
873 bwipe!
874 finally
875 call job_stop(job)
876 endtry
877endfunc
878
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100879func Test_pipe_null()
880 if !has('job')
881 return
882 endif
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100883 call ch_log('Test_pipe_null()')
884
885 " We cannot check that no I/O works, we only check that the job starts
886 " properly.
887 let job = job_start(s:python . " test_channel_pipe.py something",
888 \ {'in-io': 'null'})
889 call assert_equal("run", job_status(job))
890 try
891 call assert_equal('something', ch_read(job))
892 finally
893 call job_stop(job)
894 endtry
895
896 let job = job_start(s:python . " test_channel_pipe.py err-out",
897 \ {'out-io': 'null'})
898 call assert_equal("run", job_status(job))
899 try
900 call assert_equal('err-out', ch_read(job, {"part": "err"}))
901 finally
902 call job_stop(job)
903 endtry
904
905 let job = job_start(s:python . " test_channel_pipe.py something",
906 \ {'err-io': 'null'})
907 call assert_equal("run", job_status(job))
908 try
909 call assert_equal('something', ch_read(job))
910 finally
911 call job_stop(job)
912 endtry
913
914 let job = job_start(s:python . " test_channel_pipe.py something",
915 \ {'out-io': 'null', 'err-io': 'out'})
916 call assert_equal("run", job_status(job))
917 call job_stop(job)
918
919 let job = job_start(s:python . " test_channel_pipe.py something",
920 \ {'in-io': 'null', 'out-io': 'null', 'err-io': 'null'})
921 call assert_equal("run", job_status(job))
922 call assert_equal('channel fail', string(job_getchannel(job)))
923 call assert_equal('fail', ch_status(job))
924 call job_stop(job)
925endfunc
926
Bram Moolenaarde279892016-03-11 22:19:44 +0100927func Test_reuse_channel()
928 if !has('job')
929 return
930 endif
931 call ch_log('Test_reuse_channel()')
932
933 let job = job_start(s:python . " test_channel_pipe.py")
934 call assert_equal("run", job_status(job))
935 let handle = job_getchannel(job)
936 try
937 call ch_sendraw(handle, "echo something\n")
938 call assert_equal("something", ch_readraw(handle))
939 finally
940 call job_stop(job)
941 endtry
942
943 let job = job_start(s:python . " test_channel_pipe.py", {'channel': handle})
944 call assert_equal("run", job_status(job))
945 let handle = job_getchannel(job)
946 try
947 call ch_sendraw(handle, "echo again\n")
948 call assert_equal("again", ch_readraw(handle))
949 finally
950 call job_stop(job)
951 endtry
952endfunc
953
Bram Moolenaard46ae142016-02-16 13:33:52 +0100954""""""""""
955
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100956let s:unletResponse = ''
957func s:UnletHandler(handle, msg)
958 let s:unletResponse = a:msg
959 unlet s:channelfd
960endfunc
961
962" Test that "unlet handle" in a handler doesn't crash Vim.
963func s:unlet_handle(port)
964 let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100965 call ch_sendexpr(s:channelfd, "test", {'callback': function('s:UnletHandler')})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100966 call s:waitFor('"what?" == s:unletResponse')
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100967 call assert_equal('what?', s:unletResponse)
968endfunc
969
970func Test_unlet_handle()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100971 call ch_log('Test_unlet_handle()')
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100972 call s:run_server('s:unlet_handle')
973endfunc
Bram Moolenaar5cefd402016-02-16 12:44:26 +0100974
Bram Moolenaard46ae142016-02-16 13:33:52 +0100975""""""""""
976
977let s:unletResponse = ''
978func s:CloseHandler(handle, msg)
979 let s:unletResponse = a:msg
980 call ch_close(s:channelfd)
981endfunc
982
983" Test that "unlet handle" in a handler doesn't crash Vim.
984func s:close_handle(port)
985 let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100986 call ch_sendexpr(s:channelfd, "test", {'callback': function('s:CloseHandler')})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100987 call s:waitFor('"what?" == s:unletResponse')
Bram Moolenaard46ae142016-02-16 13:33:52 +0100988 call assert_equal('what?', s:unletResponse)
989endfunc
990
991func Test_close_handle()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100992 call ch_log('Test_close_handle()')
Bram Moolenaard46ae142016-02-16 13:33:52 +0100993 call s:run_server('s:close_handle')
994endfunc
995
996""""""""""
997
Bram Moolenaar5cefd402016-02-16 12:44:26 +0100998func Test_open_fail()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100999 call ch_log('Test_open_fail()')
Bram Moolenaar5cefd402016-02-16 12:44:26 +01001000 silent! let ch = ch_open("noserver")
1001 echo ch
1002 let d = ch
1003endfunc
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001004
1005""""""""""
1006
1007func s:open_delay(port)
1008 " Wait up to a second for the port to open.
1009 let s:chopt.waittime = 1000
1010 let channel = ch_open('localhost:' . a:port, s:chopt)
1011 unlet s:chopt.waittime
1012 if ch_status(channel) == "fail"
1013 call assert_false(1, "Can't open channel")
1014 return
1015 endif
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01001016 call assert_equal('got it', ch_evalexpr(channel, 'hello!'))
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001017 call ch_close(channel)
1018endfunc
1019
1020func Test_open_delay()
1021 call ch_log('Test_open_delay()')
1022 " The server will wait half a second before creating the port.
1023 call s:run_server('s:open_delay', 'delay')
1024endfunc
Bram Moolenaarece61b02016-02-20 21:39:05 +01001025
1026"""""""""
1027
1028function MyFunction(a,b,c)
1029 let s:call_ret = [a:a, a:b, a:c]
1030endfunc
1031
1032function s:test_call(port)
1033 let handle = ch_open('localhost:' . a:port, s:chopt)
1034 if ch_status(handle) == "fail"
1035 call assert_false(1, "Can't open channel")
1036 return
1037 endif
1038
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001039 let s:call_ret = []
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01001040 call assert_equal('ok', ch_evalexpr(handle, 'call-func'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001041 call s:waitFor('len(s:call_ret) > 0')
Bram Moolenaarece61b02016-02-20 21:39:05 +01001042 call assert_equal([1, 2, 3], s:call_ret)
1043endfunc
1044
1045func Test_call()
1046 call ch_log('Test_call()')
1047 call s:run_server('s:test_call')
1048endfunc
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001049
1050"""""""""
1051
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001052let s:job_exit_ret = 'not yet'
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001053function MyExitCb(job, status)
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001054 let s:job_exit_ret = 'done'
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001055endfunc
1056
1057function s:test_exit_callback(port)
1058 call job_setoptions(s:job, {'exit-cb': 'MyExitCb'})
1059 let s:exit_job = s:job
Bram Moolenaar8950a562016-03-12 15:22:55 +01001060 call assert_equal('MyExitCb', job_info(s:job)['exit-cb'])
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001061endfunc
1062
1063func Test_exit_callback()
1064 if has('job')
Bram Moolenaar9730f742016-02-28 19:50:51 +01001065 call ch_log('Test_exit_callback()')
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001066 call s:run_server('s:test_exit_callback')
1067
Bram Moolenaar9730f742016-02-28 19:50:51 +01001068 " wait up to a second for the job to exit
1069 for i in range(100)
1070 if s:job_exit_ret == 'done'
1071 break
1072 endif
1073 sleep 10m
1074 " calling job_status() triggers the callback
1075 call job_status(s:exit_job)
1076 endfor
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001077
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001078 call assert_equal('done', s:job_exit_ret)
Bram Moolenaar8950a562016-03-12 15:22:55 +01001079 call assert_equal('dead', job_info(s:exit_job).status)
Bram Moolenaar9730f742016-02-28 19:50:51 +01001080 unlet s:exit_job
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001081 endif
1082endfunc
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001083
1084"""""""""
1085
1086let s:ch_close_ret = 'alive'
1087function MyCloseCb(ch)
1088 let s:ch_close_ret = 'closed'
1089endfunc
1090
1091function s:test_close_callback(port)
1092 let handle = ch_open('localhost:' . a:port, s:chopt)
1093 if ch_status(handle) == "fail"
1094 call assert_false(1, "Can't open channel")
1095 return
1096 endif
1097 call ch_setoptions(handle, {'close-cb': 'MyCloseCb'})
1098
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01001099 call assert_equal('', ch_evalexpr(handle, 'close me'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001100 call s:waitFor('"closed" == s:ch_close_ret')
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001101 call assert_equal('closed', s:ch_close_ret)
1102endfunc
1103
1104func Test_close_callback()
1105 call ch_log('Test_close_callback()')
1106 call s:run_server('s:test_close_callback')
1107endfunc
1108
Bram Moolenaar9730f742016-02-28 19:50:51 +01001109" Uncomment this to see what happens, output is in src/testdir/channellog.
1110" call ch_logfile('channellog', 'w')