blob: b356c88fe48fbfb68d97389a1924fcb30d3a9b3e [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')
Bram Moolenaar03602ec2016-03-20 20:57:45 +0100123 " check that getjob without a job is handled correctly
Bram Moolenaar839fd112016-03-06 21:34:03 +0100124 call assert_equal('no process', string(ch_getjob(handle)))
125 endif
Bram Moolenaar03602ec2016-03-20 20:57:45 +0100126 let dict = ch_info(handle)
127 call assert_true(dict.id != 0)
128 call assert_equal('open', dict.status)
129 call assert_equal(a:port, string(dict.port))
130 call assert_equal('open', dict.sock_status)
131 call assert_equal('socket', dict.sock_io)
132
Bram Moolenaard7ece102016-02-02 23:23:02 +0100133 " Simple string request and reply.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100134 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaard7ece102016-02-02 23:23:02 +0100135
Bram Moolenaarac74d5e2016-03-20 14:31:00 +0100136 " Malformed command should be ignored.
Bram Moolenaarba61ac02016-03-20 16:40:37 +0100137 call assert_equal('ok', ch_evalexpr(handle, 'malformed1'))
138 call assert_equal('ok', ch_evalexpr(handle, 'malformed2'))
139 call assert_equal('ok', ch_evalexpr(handle, 'malformed3'))
140
141 " split command should work
142 call assert_equal('ok', ch_evalexpr(handle, 'split'))
143 call s:waitFor('exists("g:split")')
144 call assert_equal(123, g:split)
Bram Moolenaarac74d5e2016-03-20 14:31:00 +0100145
Bram Moolenaard7ece102016-02-02 23:23:02 +0100146 " Request that triggers sending two ex commands. These will usually be
147 " handled before getting the response, but it's not guaranteed, thus wait a
148 " tiny bit for the commands to get executed.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100149 call assert_equal('ok', ch_evalexpr(handle, 'make change'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100150 call s:waitFor('"added2" == getline("$")')
Bram Moolenaard7ece102016-02-02 23:23:02 +0100151 call assert_equal('added1', getline(line('$') - 1))
152 call assert_equal('added2', getline('$'))
153
Bram Moolenaarda94fdf2016-03-03 18:09:10 +0100154 call assert_equal('ok', ch_evalexpr(handle, 'do normal', {'timeout': 100}))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100155 call s:waitFor('"added more" == getline("$")')
Bram Moolenaarf4160862016-02-05 23:09:12 +0100156 call assert_equal('added more', getline('$'))
157
Bram Moolenaara07fec92016-02-05 21:04:08 +0100158 " Send a request with a specific handler.
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100159 call ch_sendexpr(handle, 'hello!', {'callback': 's:RequestHandler'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100160 call s:waitFor('exists("s:responseHandle")')
Bram Moolenaar77073442016-02-13 23:23:53 +0100161 if !exists('s:responseHandle')
162 call assert_false(1, 's:responseHandle was not set')
163 else
164 call assert_equal(handle, s:responseHandle)
Bram Moolenaar9186a272016-02-23 19:34:01 +0100165 unlet s:responseHandle
Bram Moolenaar77073442016-02-13 23:23:53 +0100166 endif
Bram Moolenaara07fec92016-02-05 21:04:08 +0100167 call assert_equal('got it', s:responseMsg)
168
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100169 let s:responseMsg = ''
Bram Moolenaar910b8aa2016-02-16 21:03:07 +0100170 call ch_sendexpr(handle, 'hello!', {'callback': function('s:RequestHandler')})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100171 call s:waitFor('exists("s:responseHandle")')
Bram Moolenaar77073442016-02-13 23:23:53 +0100172 if !exists('s:responseHandle')
173 call assert_false(1, 's:responseHandle was not set')
174 else
175 call assert_equal(handle, s:responseHandle)
Bram Moolenaar9186a272016-02-23 19:34:01 +0100176 unlet s:responseHandle
Bram Moolenaar77073442016-02-13 23:23:53 +0100177 endif
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100178 call assert_equal('got it', s:responseMsg)
179
Bram Moolenaar38fd4bb2016-03-06 16:38:28 +0100180 " Collect garbage, tests that our handle isn't collected.
181 call garbagecollect()
182
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100183 " check setting options (without testing the effect)
184 call ch_setoptions(handle, {'callback': 's:NotUsed'})
Bram Moolenaar1f6ef662016-02-19 22:59:44 +0100185 call ch_setoptions(handle, {'timeout': 1111})
Bram Moolenaarb6b52522016-02-20 23:30:07 +0100186 call ch_setoptions(handle, {'mode': 'json'})
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100187 call assert_fails("call ch_setoptions(handle, {'waittime': 111})", "E475")
Bram Moolenaar0ba75a92016-02-19 23:21:26 +0100188 call ch_setoptions(handle, {'callback': ''})
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100189
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100190 " Send an eval request that works.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100191 call assert_equal('ok', ch_evalexpr(handle, 'eval-works'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100192 sleep 10m
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100193 call assert_equal([-1, 'foo123'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100194
Bram Moolenaarfa8b2e12016-03-26 22:19:27 +0100195 " Send an eval request with special characters.
196 call assert_equal('ok', ch_evalexpr(handle, 'eval-special'))
197 sleep 10m
198 call assert_equal([-2, "foo\x7f\x10\x01bar"], ch_evalexpr(handle, 'eval-result'))
199
200 " Send an eval request to get a line with special characters.
201 call setline(3, "a\nb\<CR>c\x01d\x7fe")
202 call assert_equal('ok', ch_evalexpr(handle, 'eval-getline'))
203 sleep 10m
204 call assert_equal([-3, "a\nb\<CR>c\x01d\x7fe"], ch_evalexpr(handle, 'eval-result'))
205
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100206 " Send an eval request that fails.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100207 call assert_equal('ok', ch_evalexpr(handle, 'eval-fails'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100208 sleep 10m
Bram Moolenaarfa8b2e12016-03-26 22:19:27 +0100209 call assert_equal([-4, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100210
Bram Moolenaar55fab432016-02-07 16:53:13 +0100211 " Send an eval request that works but can't be encoded.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100212 call assert_equal('ok', ch_evalexpr(handle, 'eval-error'))
Bram Moolenaar55fab432016-02-07 16:53:13 +0100213 sleep 10m
Bram Moolenaarfa8b2e12016-03-26 22:19:27 +0100214 call assert_equal([-5, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaar55fab432016-02-07 16:53:13 +0100215
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100216 " Send a bad eval request. There will be no response.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100217 call assert_equal('ok', ch_evalexpr(handle, 'eval-bad'))
Bram Moolenaara02b3212016-02-04 21:03:33 +0100218 sleep 10m
Bram Moolenaarfa8b2e12016-03-26 22:19:27 +0100219 call assert_equal([-5, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100220
Bram Moolenaarf4160862016-02-05 23:09:12 +0100221 " Send an expr request
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100222 call assert_equal('ok', ch_evalexpr(handle, 'an expr'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100223 call s:waitFor('"three" == getline("$")')
Bram Moolenaarf4160862016-02-05 23:09:12 +0100224 call assert_equal('one', getline(line('$') - 2))
225 call assert_equal('two', getline(line('$') - 1))
226 call assert_equal('three', getline('$'))
227
228 " Request a redraw, we don't check for the effect.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100229 call assert_equal('ok', ch_evalexpr(handle, 'redraw'))
230 call assert_equal('ok', ch_evalexpr(handle, 'redraw!'))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100231
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100232 call assert_equal('ok', ch_evalexpr(handle, 'empty-request'))
Bram Moolenaarf4160862016-02-05 23:09:12 +0100233
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100234 " Reading while there is nothing available.
Bram Moolenaar9186a272016-02-23 19:34:01 +0100235 call assert_equal(v:none, ch_read(handle, {'timeout': 0}))
236 let start = reltime()
237 call assert_equal(v:none, ch_read(handle, {'timeout': 333}))
238 let elapsed = reltime(start)
239 call assert_true(reltimefloat(elapsed) > 0.3)
240 call assert_true(reltimefloat(elapsed) < 0.6)
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100241
242 " Send without waiting for a response, then wait for a response.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100243 call ch_sendexpr(handle, 'wait a bit')
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100244 let resp = ch_read(handle)
245 call assert_equal(type([]), type(resp))
246 call assert_equal(type(11), type(resp[0]))
247 call assert_equal('waited', resp[1])
248
Bram Moolenaard7ece102016-02-02 23:23:02 +0100249 " make the server quit, can't check if this works, should not hang.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100250 call ch_sendexpr(handle, '!quit!')
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100251endfunc
Bram Moolenaard7ece102016-02-02 23:23:02 +0100252
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100253func Test_communicate()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100254 call ch_log('Test_communicate()')
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100255 call s:run_server('s:communicate')
Bram Moolenaard7ece102016-02-02 23:23:02 +0100256endfunc
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100257
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100258" Test that we can open two channels.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100259func s:two_channels(port)
Bram Moolenaar39b21272016-02-10 23:28:21 +0100260 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100261 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100262 call assert_false(1, "Can't open channel")
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100263 return
264 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100265
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100266 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100267
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100268 let newhandle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100269 if ch_status(newhandle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100270 call assert_false(1, "Can't open second channel")
271 return
272 endif
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100273 call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
274 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100275
276 call ch_close(handle)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100277 call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100278
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100279 call ch_close(newhandle)
280endfunc
281
282func Test_two_channels()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100283 call ch_log('Test_two_channels()')
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100284 call s:run_server('s:two_channels')
Bram Moolenaar3b05b132016-02-03 23:25:07 +0100285endfunc
286
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100287" Test that a server crash is handled gracefully.
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100288func s:server_crash(port)
289 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100290 if ch_status(handle) == "fail"
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100291 call assert_false(1, "Can't open channel")
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100292 return
293 endif
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100294
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100295 call ch_evalexpr(handle, '!crash!')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100296
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100297 sleep 10m
Bram Moolenaard6a8d482016-02-10 20:32:20 +0100298endfunc
299
300func Test_server_crash()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100301 call ch_log('Test_server_crash()')
Bram Moolenaarbfa1ffc2016-02-13 18:40:30 +0100302 call s:run_server('s:server_crash')
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100303endfunc
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100304
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100305"""""""""
306
Bram Moolenaarf6157282016-02-10 21:07:14 +0100307let s:reply = ""
308func s:Handler(chan, msg)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100309 unlet s:reply
Bram Moolenaarf6157282016-02-10 21:07:14 +0100310 let s:reply = a:msg
311endfunc
312
313func s:channel_handler(port)
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100314 let handle = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar77073442016-02-13 23:23:53 +0100315 if ch_status(handle) == "fail"
Bram Moolenaarf6157282016-02-10 21:07:14 +0100316 call assert_false(1, "Can't open channel")
317 return
318 endif
319
320 " Test that it works while waiting on a numbered message.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100321 call assert_equal('ok', ch_evalexpr(handle, 'call me'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100322 call s:waitFor('"we called you" == s:reply')
Bram Moolenaarf6157282016-02-10 21:07:14 +0100323 call assert_equal('we called you', s:reply)
324
325 " Test that it works while not waiting on a numbered message.
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100326 call ch_sendexpr(handle, 'call me again')
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100327 call s:waitFor('"we did call you" == s:reply')
Bram Moolenaarf6157282016-02-10 21:07:14 +0100328 call assert_equal('we did call you', s:reply)
329endfunc
330
331func Test_channel_handler()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100332 call ch_log('Test_channel_handler()')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100333 let s:chopt.callback = 's:Handler'
Bram Moolenaarf6157282016-02-10 21:07:14 +0100334 call s:run_server('s:channel_handler')
Bram Moolenaarb6a4fee2016-02-11 20:48:34 +0100335 let s:chopt.callback = function('s:Handler')
336 call s:run_server('s:channel_handler')
337 unlet s:chopt.callback
Bram Moolenaarf6157282016-02-10 21:07:14 +0100338endfunc
339
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100340"""""""""
341
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100342let s:ch_reply = ''
343func s:ChHandler(chan, msg)
344 unlet s:ch_reply
345 let s:ch_reply = a:msg
346endfunc
347
348let s:zero_reply = ''
349func s:OneHandler(chan, msg)
350 unlet s:zero_reply
351 let s:zero_reply = a:msg
352endfunc
353
354func s:channel_zero(port)
355 let handle = ch_open('localhost:' . a:port, s:chopt)
356 if ch_status(handle) == "fail"
357 call assert_false(1, "Can't open channel")
358 return
359 endif
360
361 " Check that eval works.
362 call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
363
364 " Check that eval works if a zero id message is sent back.
365 let s:ch_reply = ''
366 call assert_equal('sent zero', ch_evalexpr(handle, 'send zero'))
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100367 if s:has_handler
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100368 call s:waitFor('"zero index" == s:ch_reply')
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100369 call assert_equal('zero index', s:ch_reply)
370 else
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100371 sleep 20m
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100372 call assert_equal('', s:ch_reply)
373 endif
374
375 " Check that handler works if a zero id message is sent back.
376 let s:ch_reply = ''
377 let s:zero_reply = ''
378 call ch_sendexpr(handle, 'send zero', {'callback': 's:OneHandler'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100379 call s:waitFor('"sent zero" == s:zero_reply')
Bram Moolenaar5983ad02016-03-05 20:54:36 +0100380 if s:has_handler
381 call assert_equal('zero index', s:ch_reply)
382 else
383 call assert_equal('', s:ch_reply)
384 endif
385 call assert_equal('sent zero', s:zero_reply)
386endfunc
387
388func Test_zero_reply()
389 call ch_log('Test_zero_reply()')
390 " Run with channel handler
391 let s:has_handler = 1
392 let s:chopt.callback = 's:ChHandler'
393 call s:run_server('s:channel_zero')
394 unlet s:chopt.callback
395
396 " Run without channel handler
397 let s:has_handler = 0
398 call s:run_server('s:channel_zero')
399endfunc
400
401"""""""""
402
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100403let s:reply1 = ""
404func s:HandleRaw1(chan, msg)
405 unlet s:reply1
406 let s:reply1 = a:msg
407endfunc
408
409let s:reply2 = ""
410func s:HandleRaw2(chan, msg)
411 unlet s:reply2
412 let s:reply2 = a:msg
413endfunc
414
415let s:reply3 = ""
416func s:HandleRaw3(chan, msg)
417 unlet s:reply3
418 let s:reply3 = a:msg
419endfunc
420
421func s:raw_one_time_callback(port)
422 let handle = ch_open('localhost:' . a:port, s:chopt)
423 if ch_status(handle) == "fail"
424 call assert_false(1, "Can't open channel")
425 return
426 endif
427 call ch_setoptions(handle, {'mode': 'raw'})
428
429 " The message are sent raw, we do our own JSON strings here.
430 call ch_sendraw(handle, "[1, \"hello!\"]", {'callback': 's:HandleRaw1'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100431 call s:waitFor('s:reply1 != ""')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100432 call assert_equal("[1, \"got it\"]", s:reply1)
433 call ch_sendraw(handle, "[2, \"echo something\"]", {'callback': 's:HandleRaw2'})
434 call ch_sendraw(handle, "[3, \"wait a bit\"]", {'callback': 's:HandleRaw3'})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100435 call s:waitFor('s:reply2 != ""')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100436 call assert_equal("[2, \"something\"]", s:reply2)
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100437 " wait for the 200 msec delayed reply
438 call s:waitFor('s:reply3 != ""')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100439 call assert_equal("[3, \"waited\"]", s:reply3)
440endfunc
441
442func Test_raw_one_time_callback()
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100443 call ch_log('Test_raw_one_time_callback()')
444 call s:run_server('s:raw_one_time_callback')
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100445endfunc
446
447"""""""""
448
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100449" Test that trying to connect to a non-existing port fails quickly.
450func Test_connect_waittime()
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100451 call ch_log('Test_connect_waittime()')
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100452 let start = reltime()
Bram Moolenaara4833262016-02-09 23:33:25 +0100453 let handle = ch_open('localhost:9876', s:chopt)
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100454 if ch_status(handle) != "fail"
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100455 " Oops, port does exists.
456 call ch_close(handle)
457 else
458 let elapsed = reltime(start)
Bram Moolenaar74f5e652016-02-07 21:44:49 +0100459 call assert_true(reltimefloat(elapsed) < 1.0)
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100460 endif
461
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100462 " We intend to use a socket that doesn't exist and wait for half a second
463 " before giving up. If the socket does exist it can fail in various ways.
464 " Check for "Connection reset by peer" to avoid flakyness.
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100465 let start = reltime()
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100466 try
467 let handle = ch_open('localhost:9867', {'waittime': 500})
468 if ch_status(handle) != "fail"
469 " Oops, port does exists.
470 call ch_close(handle)
471 else
Bram Moolenaarac42afd2016-03-12 13:48:49 +0100472 " Failed connection should wait about 500 msec. Can be longer if the
473 " computer is busy with other things.
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100474 let elapsed = reltime(start)
475 call assert_true(reltimefloat(elapsed) > 0.3)
Bram Moolenaarac42afd2016-03-12 13:48:49 +0100476 call assert_true(reltimefloat(elapsed) < 1.5)
Bram Moolenaar08298fa2016-02-21 13:01:53 +0100477 endif
478 catch
479 if v:exception !~ 'Connection reset by peer'
480 call assert_false(1, "Caught exception: " . v:exception)
481 endif
482 endtry
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100483endfunc
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100484
Bram Moolenaard6547fc2016-03-03 19:35:02 +0100485"""""""""
486
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100487func Test_raw_pipe()
488 if !has('job')
489 return
490 endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100491 call ch_log('Test_raw_pipe()')
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100492 let job = job_start(s:python . " test_channel_pipe.py", {'mode': 'raw'})
493 call assert_equal("run", job_status(job))
494 try
Bram Moolenaar151f6562016-03-07 21:19:38 +0100495 " For a change use the job where a channel is expected.
496 call ch_sendraw(job, "echo something\n")
497 let msg = ch_readraw(job)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100498 call assert_equal("something\n", substitute(msg, "\r", "", 'g'))
499
Bram Moolenaar151f6562016-03-07 21:19:38 +0100500 call ch_sendraw(job, "double this\n")
501 let msg = ch_readraw(job)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100502 call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g'))
503
Bram Moolenaar151f6562016-03-07 21:19:38 +0100504 let reply = ch_evalraw(job, "quit\n", {'timeout': 100})
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100505 call assert_equal("Goodbye!\n", substitute(reply, "\r", "", 'g'))
506 finally
507 call job_stop(job)
508 endtry
Bram Moolenaar8950a562016-03-12 15:22:55 +0100509
510 let s:job = job
511 call s:waitFor('"dead" == job_status(s:job)')
512 let info = job_info(job)
513 call assert_equal("dead", info.status)
514 call assert_equal("term", info.stoponexit)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100515endfunc
516
517func Test_nl_pipe()
Bram Moolenaard8070362016-02-15 21:56:54 +0100518 if !has('job')
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100519 return
520 endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100521 call ch_log('Test_nl_pipe()')
Bram Moolenaar1adda342016-03-12 15:39:40 +0100522 let job = job_start([s:python, "test_channel_pipe.py"])
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100523 call assert_equal("run", job_status(job))
524 try
525 let handle = job_getchannel(job)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100526 call ch_sendraw(handle, "echo something\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100527 call assert_equal("something", ch_readraw(handle))
528
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100529 call ch_sendraw(handle, "echoerr wrong\n")
530 call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
531
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100532 call ch_sendraw(handle, "double this\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100533 call assert_equal("this", ch_readraw(handle))
534 call assert_equal("AND this", ch_readraw(handle))
535
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100536 let reply = ch_evalraw(handle, "quit\n")
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +0100537 call assert_equal("Goodbye!", reply)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100538 finally
539 call job_stop(job)
540 endtry
541endfunc
Bram Moolenaar3bece9f2016-02-15 20:39:46 +0100542
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100543func Test_nl_err_to_out_pipe()
544 if !has('job')
545 return
546 endif
Bram Moolenaar5a6ec522016-03-12 15:51:44 +0100547 call ch_logfile('Xlog')
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100548 call ch_log('Test_nl_err_to_out_pipe()')
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100549 let job = job_start(s:python . " test_channel_pipe.py", {'err_io': 'out'})
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100550 call assert_equal("run", job_status(job))
551 try
552 let handle = job_getchannel(job)
553 call ch_sendraw(handle, "echo something\n")
554 call assert_equal("something", ch_readraw(handle))
555
556 call ch_sendraw(handle, "echoerr wrong\n")
557 call assert_equal("wrong", ch_readraw(handle))
558 finally
559 call job_stop(job)
Bram Moolenaar5a6ec522016-03-12 15:51:44 +0100560 call ch_logfile('')
561 let loglines = readfile('Xlog')
562 call assert_true(len(loglines) > 10)
563 let found_test = 0
564 let found_send = 0
565 let found_recv = 0
566 let found_stop = 0
567 for l in loglines
568 if l =~ 'Test_nl_err_to_out_pipe'
569 let found_test = 1
570 endif
571 if l =~ 'SEND on.*echo something'
572 let found_send = 1
573 endif
574 if l =~ 'RECV on.*something'
575 let found_recv = 1
576 endif
577 if l =~ 'Stopping job with'
578 let found_stop = 1
579 endif
580 endfor
581 call assert_equal(1, found_test)
582 call assert_equal(1, found_send)
583 call assert_equal(1, found_recv)
584 call assert_equal(1, found_stop)
585 call delete('Xlog')
Bram Moolenaarc25558b2016-03-03 21:02:23 +0100586 endtry
587endfunc
588
Bram Moolenaarb69fccf2016-03-06 23:06:25 +0100589func Test_nl_read_file()
590 if !has('job')
591 return
592 endif
Bram Moolenaarb69fccf2016-03-06 23:06:25 +0100593 call ch_log('Test_nl_read_file()')
594 call writefile(['echo something', 'echoerr wrong', 'double this'], 'Xinput')
595 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100596 \ {'in_io': 'file', 'in_name': 'Xinput'})
Bram Moolenaarb69fccf2016-03-06 23:06:25 +0100597 call assert_equal("run", job_status(job))
598 try
599 let handle = job_getchannel(job)
600 call assert_equal("something", ch_readraw(handle))
601 call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
602 call assert_equal("this", ch_readraw(handle))
603 call assert_equal("AND this", ch_readraw(handle))
604 finally
605 call job_stop(job)
606 call delete('Xinput')
607 endtry
608endfunc
609
Bram Moolenaare98d1212016-03-08 15:37:41 +0100610func Test_nl_write_out_file()
611 if !has('job')
612 return
613 endif
Bram Moolenaare98d1212016-03-08 15:37:41 +0100614 call ch_log('Test_nl_write_out_file()')
615 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100616 \ {'out_io': 'file', 'out_name': 'Xoutput'})
Bram Moolenaare98d1212016-03-08 15:37:41 +0100617 call assert_equal("run", job_status(job))
618 try
619 let handle = job_getchannel(job)
620 call ch_sendraw(handle, "echo line one\n")
621 call ch_sendraw(handle, "echo line two\n")
622 call ch_sendraw(handle, "double this\n")
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100623 call s:waitFor('len(readfile("Xoutput")) > 2')
Bram Moolenaare98d1212016-03-08 15:37:41 +0100624 call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput'))
625 finally
626 call job_stop(job)
627 call delete('Xoutput')
628 endtry
629endfunc
630
631func Test_nl_write_err_file()
632 if !has('job')
633 return
634 endif
Bram Moolenaare98d1212016-03-08 15:37:41 +0100635 call ch_log('Test_nl_write_err_file()')
636 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100637 \ {'err_io': 'file', 'err_name': 'Xoutput'})
Bram Moolenaare98d1212016-03-08 15:37:41 +0100638 call assert_equal("run", job_status(job))
639 try
640 let handle = job_getchannel(job)
641 call ch_sendraw(handle, "echoerr line one\n")
642 call ch_sendraw(handle, "echoerr line two\n")
643 call ch_sendraw(handle, "doubleerr this\n")
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100644 call s:waitFor('len(readfile("Xoutput")) > 2')
Bram Moolenaare98d1212016-03-08 15:37:41 +0100645 call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput'))
646 finally
647 call job_stop(job)
648 call delete('Xoutput')
649 endtry
650endfunc
651
652func Test_nl_write_both_file()
653 if !has('job')
654 return
655 endif
Bram Moolenaare98d1212016-03-08 15:37:41 +0100656 call ch_log('Test_nl_write_both_file()')
657 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100658 \ {'out_io': 'file', 'out_name': 'Xoutput', 'err_io': 'out'})
Bram Moolenaare98d1212016-03-08 15:37:41 +0100659 call assert_equal("run", job_status(job))
660 try
661 let handle = job_getchannel(job)
662 call ch_sendraw(handle, "echoerr line one\n")
663 call ch_sendraw(handle, "echo line two\n")
664 call ch_sendraw(handle, "double this\n")
665 call ch_sendraw(handle, "doubleerr that\n")
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100666 call s:waitFor('len(readfile("Xoutput")) > 5')
Bram Moolenaare98d1212016-03-08 15:37:41 +0100667 call assert_equal(['line one', 'line two', 'this', 'AND this', 'that', 'AND that'], readfile('Xoutput'))
668 finally
669 call job_stop(job)
670 call delete('Xoutput')
671 endtry
672endfunc
673
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100674func Run_test_pipe_to_buffer(use_name)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100675 if !has('job')
676 return
677 endif
678 call ch_log('Test_pipe_to_buffer()')
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100679 let options = {'out_io': 'buffer'}
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100680 if a:use_name
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100681 let options['out_name'] = 'pipe-output'
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100682 let firstline = 'Reading from channel output...'
683 else
684 sp pipe-output
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100685 let options['out_buf'] = bufnr('%')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100686 quit
687 let firstline = ''
688 endif
689 let job = job_start(s:python . " test_channel_pipe.py", options)
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100690 call assert_equal("run", job_status(job))
691 try
692 let handle = job_getchannel(job)
693 call ch_sendraw(handle, "echo line one\n")
694 call ch_sendraw(handle, "echo line two\n")
695 call ch_sendraw(handle, "double this\n")
696 call ch_sendraw(handle, "quit\n")
697 sp pipe-output
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100698 call s:waitFor('line("$") >= 6')
Bram Moolenaar6a063632016-03-21 23:18:54 +0100699 if getline('$') == 'DETACH'
700 $del
701 endif
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100702 call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this', 'Goodbye!'], getline(1, '$'))
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100703 bwipe!
704 finally
705 call job_stop(job)
706 endtry
707endfunc
708
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100709func Test_pipe_to_buffer_name()
710 call Run_test_pipe_to_buffer(1)
711endfunc
712
713func Test_pipe_to_buffer_nr()
714 call Run_test_pipe_to_buffer(0)
715endfunc
716
717func Run_test_pipe_err_to_buffer(use_name)
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100718 if !has('job')
719 return
720 endif
721 call ch_log('Test_pipe_err_to_buffer()')
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100722 let options = {'err_io': 'buffer'}
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100723 if a:use_name
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100724 let options['err_name'] = 'pipe-err'
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100725 let firstline = 'Reading from channel error...'
726 else
727 sp pipe-err
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100728 let options['err_buf'] = bufnr('%')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100729 quit
730 let firstline = ''
731 endif
732 let job = job_start(s:python . " test_channel_pipe.py", options)
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100733 call assert_equal("run", job_status(job))
734 try
735 let handle = job_getchannel(job)
736 call ch_sendraw(handle, "echoerr line one\n")
737 call ch_sendraw(handle, "echoerr line two\n")
738 call ch_sendraw(handle, "doubleerr this\n")
739 call ch_sendraw(handle, "quit\n")
740 sp pipe-err
741 call s:waitFor('line("$") >= 5')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100742 call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this'], getline(1, '$'))
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100743 bwipe!
744 finally
745 call job_stop(job)
746 endtry
747endfunc
748
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100749func Test_pipe_err_to_buffer_name()
750 call Run_test_pipe_err_to_buffer(1)
751endfunc
752
753func Test_pipe_err_to_buffer_nr()
754 call Run_test_pipe_err_to_buffer(0)
755endfunc
756
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100757func Test_pipe_both_to_buffer()
758 if !has('job')
759 return
760 endif
761 call ch_log('Test_pipe_both_to_buffer()')
762 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100763 \ {'out_io': 'buffer', 'out_name': 'pipe-err', 'err_io': 'out'})
Bram Moolenaar6ff02c92016-03-08 20:12:44 +0100764 call assert_equal("run", job_status(job))
765 try
766 let handle = job_getchannel(job)
767 call ch_sendraw(handle, "echo line one\n")
768 call ch_sendraw(handle, "echoerr line two\n")
769 call ch_sendraw(handle, "double this\n")
770 call ch_sendraw(handle, "doubleerr that\n")
771 call ch_sendraw(handle, "quit\n")
772 sp pipe-err
773 call s:waitFor('line("$") >= 7')
774 call assert_equal(['Reading from channel output...', 'line one', 'line two', 'this', 'AND this', 'that', 'AND that', 'Goodbye!'], getline(1, '$'))
775 bwipe!
776 finally
777 call job_stop(job)
778 endtry
779endfunc
780
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100781func Run_test_pipe_from_buffer(use_name)
Bram Moolenaar014069a2016-03-03 22:51:40 +0100782 if !has('job')
783 return
784 endif
Bram Moolenaar014069a2016-03-03 22:51:40 +0100785 call ch_log('Test_pipe_from_buffer()')
786
787 sp pipe-input
788 call setline(1, ['echo one', 'echo two', 'echo three'])
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100789 let options = {'in_io': 'buffer'}
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100790 if a:use_name
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100791 let options['in_name'] = 'pipe-input'
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100792 else
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100793 let options['in_buf'] = bufnr('%')
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100794 endif
Bram Moolenaar014069a2016-03-03 22:51:40 +0100795
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100796 let job = job_start(s:python . " test_channel_pipe.py", options)
Bram Moolenaar014069a2016-03-03 22:51:40 +0100797 call assert_equal("run", job_status(job))
798 try
799 let handle = job_getchannel(job)
800 call assert_equal('one', ch_read(handle))
801 call assert_equal('two', ch_read(handle))
802 call assert_equal('three', ch_read(handle))
803 bwipe!
804 finally
805 call job_stop(job)
806 endtry
Bram Moolenaar014069a2016-03-03 22:51:40 +0100807endfunc
808
Bram Moolenaar29fd0382016-03-09 23:14:07 +0100809func Test_pipe_from_buffer_name()
810 call Run_test_pipe_from_buffer(1)
811endfunc
812
813func Test_pipe_from_buffer_nr()
814 call Run_test_pipe_from_buffer(0)
815endfunc
816
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100817func Test_pipe_to_nameless_buffer()
818 if !has('job')
819 return
820 endif
821 call ch_log('Test_pipe_to_nameless_buffer()')
822 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100823 \ {'out_io': 'buffer'})
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100824 call assert_equal("run", job_status(job))
825 try
826 let handle = job_getchannel(job)
827 call ch_sendraw(handle, "echo line one\n")
828 call ch_sendraw(handle, "echo line two\n")
829 exe ch_getbufnr(handle, "out") . 'sbuf'
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100830 call s:waitFor('line("$") >= 3')
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100831 call assert_equal(['Reading from channel output...', 'line one', 'line two'], getline(1, '$'))
832 bwipe!
833 finally
834 call job_stop(job)
835 endtry
836endfunc
837
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +0100838func Test_pipe_to_buffer_json()
839 if !has('job')
840 return
841 endif
842 call ch_log('Test_pipe_to_buffer_json()')
843 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100844 \ {'out_io': 'buffer', 'out_mode': 'json'})
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +0100845 call assert_equal("run", job_status(job))
846 try
847 let handle = job_getchannel(job)
848 call ch_sendraw(handle, "echo [0, \"hello\"]\n")
849 call ch_sendraw(handle, "echo [-2, 12.34]\n")
850 exe ch_getbufnr(handle, "out") . 'sbuf'
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100851 call s:waitFor('line("$") >= 3')
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +0100852 call assert_equal(['Reading from channel output...', '[0,"hello"]', '[-2,12.34]'], getline(1, '$'))
853 bwipe!
854 finally
855 call job_stop(job)
856 endtry
857endfunc
858
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100859" Wait a little while for the last line, minus "offset", to equal "line".
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100860func s:wait_for_last_line(line, offset)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100861 for i in range(100)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100862 if getline(line('$') - a:offset) == a:line
863 break
864 endif
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100865 sleep 10m
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100866 endfor
867endfunc
868
869func Test_pipe_io_two_buffers()
870 if !has('job')
871 return
872 endif
873 call ch_log('Test_pipe_io_two_buffers()')
874
875 " Create two buffers, one to read from and one to write to.
876 split pipe-output
877 set buftype=nofile
878 split pipe-input
879 set buftype=nofile
880
881 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100882 \ {'in_io': 'buffer', 'in_name': 'pipe-input', 'in_top': 0,
883 \ 'out_io': 'buffer', 'out_name': 'pipe-output'})
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100884 call assert_equal("run", job_status(job))
885 try
886 exe "normal Gaecho hello\<CR>"
887 exe bufwinnr('pipe-output') . "wincmd w"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100888 call s:wait_for_last_line('hello', 0)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100889 call assert_equal('hello', getline('$'))
890
891 exe bufwinnr('pipe-input') . "wincmd w"
892 exe "normal Gadouble this\<CR>"
893 exe bufwinnr('pipe-output') . "wincmd w"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100894 call s:wait_for_last_line('AND this', 0)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100895 call assert_equal('this', getline(line('$') - 1))
896 call assert_equal('AND this', getline('$'))
897
898 bwipe!
899 exe bufwinnr('pipe-input') . "wincmd w"
900 bwipe!
901 finally
902 call job_stop(job)
903 endtry
904endfunc
905
906func Test_pipe_io_one_buffer()
907 if !has('job')
908 return
909 endif
910 call ch_log('Test_pipe_io_one_buffer()')
911
912 " Create one buffer to read from and to write to.
913 split pipe-io
914 set buftype=nofile
915
916 let job = job_start(s:python . " test_channel_pipe.py",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100917 \ {'in_io': 'buffer', 'in_name': 'pipe-io', 'in_top': 0,
918 \ 'out_io': 'buffer', 'out_name': 'pipe-io'})
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100919 call assert_equal("run", job_status(job))
920 try
921 exe "normal Goecho hello\<CR>"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100922 call s:wait_for_last_line('hello', 1)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100923 call assert_equal('hello', getline(line('$') - 1))
924
925 exe "normal Gadouble this\<CR>"
Bram Moolenaar9fe885e2016-03-08 16:06:55 +0100926 call s:wait_for_last_line('AND this', 1)
Bram Moolenaar3f39f642016-03-06 21:35:57 +0100927 call assert_equal('this', getline(line('$') - 2))
928 call assert_equal('AND this', getline(line('$') - 1))
929
930 bwipe!
931 finally
932 call job_stop(job)
933 endtry
934endfunc
935
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100936func Test_pipe_null()
937 if !has('job')
938 return
939 endif
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100940 call ch_log('Test_pipe_null()')
941
942 " We cannot check that no I/O works, we only check that the job starts
943 " properly.
944 let job = job_start(s:python . " test_channel_pipe.py something",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100945 \ {'in_io': 'null'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100946 call assert_equal("run", job_status(job))
947 try
948 call assert_equal('something', ch_read(job))
949 finally
950 call job_stop(job)
951 endtry
952
953 let job = job_start(s:python . " test_channel_pipe.py err-out",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100954 \ {'out_io': 'null'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100955 call assert_equal("run", job_status(job))
956 try
957 call assert_equal('err-out', ch_read(job, {"part": "err"}))
958 finally
959 call job_stop(job)
960 endtry
961
962 let job = job_start(s:python . " test_channel_pipe.py something",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100963 \ {'err_io': 'null'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100964 call assert_equal("run", job_status(job))
965 try
966 call assert_equal('something', ch_read(job))
967 finally
968 call job_stop(job)
969 endtry
970
971 let job = job_start(s:python . " test_channel_pipe.py something",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100972 \ {'out_io': 'null', 'err_io': 'out'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100973 call assert_equal("run", job_status(job))
974 call job_stop(job)
975
976 let job = job_start(s:python . " test_channel_pipe.py something",
Bram Moolenaard6c2f052016-03-14 23:22:59 +0100977 \ {'in_io': 'null', 'out_io': 'null', 'err_io': 'null'})
Bram Moolenaarf65333c2016-03-08 18:27:21 +0100978 call assert_equal("run", job_status(job))
979 call assert_equal('channel fail', string(job_getchannel(job)))
980 call assert_equal('fail', ch_status(job))
981 call job_stop(job)
982endfunc
983
Bram Moolenaarde279892016-03-11 22:19:44 +0100984func Test_reuse_channel()
985 if !has('job')
986 return
987 endif
988 call ch_log('Test_reuse_channel()')
989
990 let job = job_start(s:python . " test_channel_pipe.py")
991 call assert_equal("run", job_status(job))
992 let handle = job_getchannel(job)
993 try
994 call ch_sendraw(handle, "echo something\n")
995 call assert_equal("something", ch_readraw(handle))
996 finally
997 call job_stop(job)
998 endtry
999
1000 let job = job_start(s:python . " test_channel_pipe.py", {'channel': handle})
1001 call assert_equal("run", job_status(job))
1002 let handle = job_getchannel(job)
1003 try
1004 call ch_sendraw(handle, "echo again\n")
1005 call assert_equal("again", ch_readraw(handle))
1006 finally
1007 call job_stop(job)
1008 endtry
1009endfunc
1010
Bram Moolenaar75f72652016-03-20 22:16:56 +01001011func Test_out_cb()
1012 if !has('job')
1013 return
1014 endif
1015 call ch_log('Test_out_cb()')
1016
1017 let dict = {'thisis': 'dict: '}
1018 func dict.outHandler(chan, msg) dict
1019 let s:outmsg = self.thisis . a:msg
1020 endfunc
1021 func dict.errHandler(chan, msg) dict
1022 let s:errmsg = self.thisis . a:msg
1023 endfunc
1024 let job = job_start(s:python . " test_channel_pipe.py",
1025 \ {'out_cb': dict.outHandler,
1026 \ 'out_mode': 'json',
1027 \ 'err_cb': dict.errHandler,
1028 \ 'err_mode': 'json'})
1029 call assert_equal("run", job_status(job))
1030 try
1031 let s:outmsg = ''
1032 let s:errmsg = ''
1033 call ch_sendraw(job, "echo [0, \"hello\"]\n")
1034 call ch_sendraw(job, "echoerr [0, \"there\"]\n")
1035 call s:waitFor('s:outmsg != ""')
1036 call assert_equal("dict: hello", s:outmsg)
1037 call s:waitFor('s:errmsg != ""')
1038 call assert_equal("dict: there", s:errmsg)
1039 finally
1040 call job_stop(job)
1041 endtry
1042endfunc
1043
Bram Moolenaard46ae142016-02-16 13:33:52 +01001044""""""""""
1045
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01001046let s:unletResponse = ''
1047func s:UnletHandler(handle, msg)
1048 let s:unletResponse = a:msg
1049 unlet s:channelfd
1050endfunc
1051
1052" Test that "unlet handle" in a handler doesn't crash Vim.
1053func s:unlet_handle(port)
1054 let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar910b8aa2016-02-16 21:03:07 +01001055 call ch_sendexpr(s:channelfd, "test", {'callback': function('s:UnletHandler')})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001056 call s:waitFor('"what?" == s:unletResponse')
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01001057 call assert_equal('what?', s:unletResponse)
1058endfunc
1059
1060func Test_unlet_handle()
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001061 call ch_log('Test_unlet_handle()')
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01001062 call s:run_server('s:unlet_handle')
1063endfunc
Bram Moolenaar5cefd402016-02-16 12:44:26 +01001064
Bram Moolenaard46ae142016-02-16 13:33:52 +01001065""""""""""
1066
1067let s:unletResponse = ''
1068func s:CloseHandler(handle, msg)
1069 let s:unletResponse = a:msg
1070 call ch_close(s:channelfd)
1071endfunc
1072
1073" Test that "unlet handle" in a handler doesn't crash Vim.
1074func s:close_handle(port)
1075 let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
Bram Moolenaar910b8aa2016-02-16 21:03:07 +01001076 call ch_sendexpr(s:channelfd, "test", {'callback': function('s:CloseHandler')})
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001077 call s:waitFor('"what?" == s:unletResponse')
Bram Moolenaard46ae142016-02-16 13:33:52 +01001078 call assert_equal('what?', s:unletResponse)
1079endfunc
1080
1081func Test_close_handle()
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001082 call ch_log('Test_close_handle()')
Bram Moolenaard46ae142016-02-16 13:33:52 +01001083 call s:run_server('s:close_handle')
1084endfunc
1085
1086""""""""""
1087
Bram Moolenaar5cefd402016-02-16 12:44:26 +01001088func Test_open_fail()
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001089 call ch_log('Test_open_fail()')
Bram Moolenaar5cefd402016-02-16 12:44:26 +01001090 silent! let ch = ch_open("noserver")
1091 echo ch
1092 let d = ch
1093endfunc
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001094
1095""""""""""
1096
1097func s:open_delay(port)
1098 " Wait up to a second for the port to open.
1099 let s:chopt.waittime = 1000
1100 let channel = ch_open('localhost:' . a:port, s:chopt)
1101 unlet s:chopt.waittime
1102 if ch_status(channel) == "fail"
1103 call assert_false(1, "Can't open channel")
1104 return
1105 endif
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01001106 call assert_equal('got it', ch_evalexpr(channel, 'hello!'))
Bram Moolenaar81661fb2016-02-18 22:23:34 +01001107 call ch_close(channel)
1108endfunc
1109
1110func Test_open_delay()
1111 call ch_log('Test_open_delay()')
1112 " The server will wait half a second before creating the port.
1113 call s:run_server('s:open_delay', 'delay')
1114endfunc
Bram Moolenaarece61b02016-02-20 21:39:05 +01001115
1116"""""""""
1117
1118function MyFunction(a,b,c)
1119 let s:call_ret = [a:a, a:b, a:c]
1120endfunc
1121
1122function s:test_call(port)
1123 let handle = ch_open('localhost:' . a:port, s:chopt)
1124 if ch_status(handle) == "fail"
1125 call assert_false(1, "Can't open channel")
1126 return
1127 endif
1128
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001129 let s:call_ret = []
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01001130 call assert_equal('ok', ch_evalexpr(handle, 'call-func'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001131 call s:waitFor('len(s:call_ret) > 0')
Bram Moolenaarece61b02016-02-20 21:39:05 +01001132 call assert_equal([1, 2, 3], s:call_ret)
1133endfunc
1134
1135func Test_call()
1136 call ch_log('Test_call()')
1137 call s:run_server('s:test_call')
1138endfunc
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001139
1140"""""""""
1141
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001142let s:job_exit_ret = 'not yet'
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001143function MyExitCb(job, status)
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001144 let s:job_exit_ret = 'done'
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001145endfunc
1146
1147function s:test_exit_callback(port)
Bram Moolenaard6c2f052016-03-14 23:22:59 +01001148 call job_setoptions(s:job, {'exit_cb': 'MyExitCb'})
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001149 let s:exit_job = s:job
Bram Moolenaard6c2f052016-03-14 23:22:59 +01001150 call assert_equal('MyExitCb', job_info(s:job)['exit_cb'])
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001151endfunc
1152
1153func Test_exit_callback()
1154 if has('job')
Bram Moolenaar9730f742016-02-28 19:50:51 +01001155 call ch_log('Test_exit_callback()')
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001156 call s:run_server('s:test_exit_callback')
1157
Bram Moolenaar9730f742016-02-28 19:50:51 +01001158 " wait up to a second for the job to exit
1159 for i in range(100)
1160 if s:job_exit_ret == 'done'
1161 break
1162 endif
1163 sleep 10m
1164 " calling job_status() triggers the callback
1165 call job_status(s:exit_job)
1166 endfor
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001167
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001168 call assert_equal('done', s:job_exit_ret)
Bram Moolenaar8950a562016-03-12 15:22:55 +01001169 call assert_equal('dead', job_info(s:exit_job).status)
Bram Moolenaar9730f742016-02-28 19:50:51 +01001170 unlet s:exit_job
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001171 endif
1172endfunc
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001173
1174"""""""""
1175
1176let s:ch_close_ret = 'alive'
1177function MyCloseCb(ch)
1178 let s:ch_close_ret = 'closed'
1179endfunc
1180
1181function s:test_close_callback(port)
1182 let handle = ch_open('localhost:' . a:port, s:chopt)
1183 if ch_status(handle) == "fail"
1184 call assert_false(1, "Can't open channel")
1185 return
1186 endif
Bram Moolenaard6c2f052016-03-14 23:22:59 +01001187 call ch_setoptions(handle, {'close_cb': 'MyCloseCb'})
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001188
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01001189 call assert_equal('', ch_evalexpr(handle, 'close me'))
Bram Moolenaar9fe885e2016-03-08 16:06:55 +01001190 call s:waitFor('"closed" == s:ch_close_ret')
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001191 call assert_equal('closed', s:ch_close_ret)
1192endfunc
1193
1194func Test_close_callback()
1195 call ch_log('Test_close_callback()')
1196 call s:run_server('s:test_close_callback')
1197endfunc
1198
Bram Moolenaar9730f742016-02-28 19:50:51 +01001199" Uncomment this to see what happens, output is in src/testdir/channellog.
1200" call ch_logfile('channellog', 'w')