blob: 8042428cf4c3260907ad017cc2f4445c7e3291d5 [file] [log] [blame]
Bram Moolenaar321efdd2016-07-15 17:09:11 +02001" Functions shared by several tests.
2
Bram Moolenaara5e66212017-09-29 22:42:33 +02003" Only load this script once.
4if exists('*WaitFor')
5 finish
6endif
7
Bram Moolenaar321efdd2016-07-15 17:09:11 +02008" Get the name of the Python executable.
9" Also keeps it in s:python.
10func PythonProg()
11 " This test requires the Python command to run the test server.
12 " This most likely only works on Unix and Windows.
13 if has('unix')
14 " We also need the job feature or the pkill command to make sure the server
15 " can be stopped.
16 if !(executable('python') && (has('job') || executable('pkill')))
17 return ''
18 endif
19 let s:python = 'python'
20 elseif has('win32')
21 " Use Python Launcher for Windows (py.exe) if available.
22 if executable('py.exe')
23 let s:python = 'py.exe'
24 elseif executable('python.exe')
25 let s:python = 'python.exe'
26 else
27 return ''
28 endif
29 else
30 return ''
31 endif
32 return s:python
33endfunc
34
35" Run "cmd". Returns the job if using a job.
36func RunCommand(cmd)
37 let job = 0
38 if has('job')
39 let job = job_start(a:cmd, {"stoponexit": "hup"})
40 call job_setoptions(job, {"stoponexit": "kill"})
41 elseif has('win32')
42 exe 'silent !start cmd /c start "test_channel" ' . a:cmd
43 else
44 exe 'silent !' . a:cmd . '&'
45 endif
46 return job
47endfunc
48
49" Read the port number from the Xportnr file.
50func GetPort()
51 let l = []
52 for i in range(200)
53 try
54 let l = readfile("Xportnr")
55 catch
56 endtry
57 if len(l) >= 1
58 break
59 endif
60 sleep 10m
61 endfor
62 call delete("Xportnr")
63
64 if len(l) == 0
65 " Can't make the connection, give up.
66 return 0
67 endif
68 return l[0]
69endfunc
70
71" Run a Python server for "cmd" and call "testfunc".
72" Always kills the server before returning.
73func RunServer(cmd, testfunc, args)
74 " The Python program writes the port number in Xportnr.
75 call delete("Xportnr")
76
77 if len(a:args) == 1
78 let arg = ' ' . a:args[0]
79 else
80 let arg = ''
81 endif
82 let pycmd = s:python . " " . a:cmd . arg
83
84 try
85 let g:currentJob = RunCommand(pycmd)
86
87 " Wait for up to 2 seconds for the port number to be there.
88 let port = GetPort()
89 if port == 0
90 call assert_false(1, "Can't start " . a:cmd)
91 return
92 endif
93
94 call call(function(a:testfunc), [port])
95 catch
Bram Moolenaar4b785f62016-11-29 21:54:44 +010096 call assert_false(1, 'Caught exception: "' . v:exception . '" in ' . v:throwpoint)
Bram Moolenaar321efdd2016-07-15 17:09:11 +020097 finally
98 call s:kill_server(a:cmd)
99 endtry
100endfunc
101
102func s:kill_server(cmd)
103 if has('job')
104 if exists('g:currentJob')
105 call job_stop(g:currentJob)
106 unlet g:currentJob
107 endif
108 elseif has('win32')
109 let cmd = substitute(a:cmd, ".py", '', '')
110 call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq ' . cmd . '"')
111 else
112 call system("pkill -f " . a:cmd)
113 endif
114endfunc
115
Bram Moolenaar13deab82017-11-04 18:48:43 +0100116" Wait for up to a second for "expr" to become true. "expr" can be a
117" stringified expression to evaluate, or a funcref without arguments.
118"
Bram Moolenaarf267f8b2016-08-22 21:40:29 +0200119" Return time slept in milliseconds. With the +reltime feature this can be
120" more than the actual waiting time. Without +reltime it can also be less.
Bram Moolenaarcdb7e1b2017-07-19 19:55:58 +0200121func WaitFor(expr, ...)
122 let timeout = get(a:000, 0, 1000)
Bram Moolenaarf267f8b2016-08-22 21:40:29 +0200123 " using reltime() is more accurate, but not always available
124 if has('reltime')
125 let start = reltime()
126 else
127 let slept = 0
128 endif
Bram Moolenaar13deab82017-11-04 18:48:43 +0100129 if type(a:expr) == v:t_func
130 let Test = a:expr
131 else
132 let Test = {-> eval(a:expr) }
133 endif
Bram Moolenaarcdb7e1b2017-07-19 19:55:58 +0200134 for i in range(timeout / 10)
Bram Moolenaar13deab82017-11-04 18:48:43 +0100135 if Test()
Bram Moolenaarc20e0d52017-11-02 18:19:19 +0100136 if has('reltime')
137 return float2nr(reltimefloat(reltime(start)) * 1000)
Bram Moolenaar321efdd2016-07-15 17:09:11 +0200138 endif
Bram Moolenaarc20e0d52017-11-02 18:19:19 +0100139 return slept
140 endif
Bram Moolenaarf267f8b2016-08-22 21:40:29 +0200141 if !has('reltime')
142 let slept += 10
143 endif
Bram Moolenaar321efdd2016-07-15 17:09:11 +0200144 sleep 10m
145 endfor
Bram Moolenaar3e1c6172017-11-02 16:58:00 +0100146 throw 'WaitFor() timed out after ' . timeout . ' msec'
Bram Moolenaar321efdd2016-07-15 17:09:11 +0200147endfunc
Bram Moolenaar66459b72016-08-06 19:01:55 +0200148
Bram Moolenaar01688ad2016-10-27 20:00:07 +0200149" Wait for up to a given milliseconds.
150" With the +timers feature this waits for key-input by getchar(), Resume()
151" feeds key-input and resumes process. Return time waited in milliseconds.
152" Without +timers it uses simply :sleep.
153func Standby(msec)
154 if has('timers')
155 let start = reltime()
156 let g:_standby_timer = timer_start(a:msec, function('s:feedkeys'))
157 call getchar()
158 return float2nr(reltimefloat(reltime(start)) * 1000)
159 else
160 execute 'sleep ' a:msec . 'm'
161 return a:msec
162 endif
163endfunc
164
165func Resume()
166 if exists('g:_standby_timer')
167 call timer_stop(g:_standby_timer)
168 call s:feedkeys(0)
169 unlet g:_standby_timer
170 endif
171endfunc
172
173func s:feedkeys(timer)
174 call feedkeys('x', 'nt')
175endfunc
176
Bram Moolenaar63182052017-10-07 20:03:23 +0200177" Get $VIMPROG to run Vim executable.
178" The Makefile writes it as the first line in the "vimcmd" file.
179func GetVimProg()
180 if !filereadable('vimcmd')
181 return ''
182 endif
183 return readfile('vimcmd')[0]
184endfunc
185
Bram Moolenaar15bf76d2017-03-18 16:18:37 +0100186" Get the command to run Vim, with -u NONE and --not-a-term arguments.
Bram Moolenaar9d954202017-09-04 20:34:19 +0200187" If there is an argument use it instead of "NONE".
Bram Moolenaar15bf76d2017-03-18 16:18:37 +0100188" Returns an empty string on error.
Bram Moolenaar9d954202017-09-04 20:34:19 +0200189func GetVimCommand(...)
Bram Moolenaar15bf76d2017-03-18 16:18:37 +0100190 if !filereadable('vimcmd')
191 return ''
192 endif
Bram Moolenaar9d954202017-09-04 20:34:19 +0200193 if a:0 == 0
194 let name = 'NONE'
195 else
196 let name = a:1
197 endif
Bram Moolenaar63182052017-10-07 20:03:23 +0200198 " For Unix Makefile writes the command to use in the second line of the
199 " "vimcmd" file, including environment options.
200 " Other Makefiles just write the executable in the first line, so fall back
201 " to that if there is no second line.
202 let lines = readfile('vimcmd')
203 let cmd = get(lines, 1, lines[0])
Bram Moolenaar9d954202017-09-04 20:34:19 +0200204 let cmd = substitute(cmd, '-u \f\+', '-u ' . name, '')
205 if cmd !~ '-u '. name
206 let cmd = cmd . ' -u ' . name
Bram Moolenaar15bf76d2017-03-18 16:18:37 +0100207 endif
208 let cmd .= ' --not-a-term'
209 let cmd = substitute(cmd, 'VIMRUNTIME=.*VIMRUNTIME;', '', '')
210 return cmd
211endfunc
212
Bram Moolenaar66459b72016-08-06 19:01:55 +0200213" Run Vim, using the "vimcmd" file and "-u NORC".
Bram Moolenaar3a938382016-08-07 16:36:40 +0200214" "before" is a list of Vim commands to be executed before loading plugins.
215" "after" is a list of Vim commands to be executed after loading plugins.
Bram Moolenaar66459b72016-08-06 19:01:55 +0200216" Plugins are not loaded, unless 'loadplugins' is set in "before".
217" Return 1 if Vim could be executed.
Bram Moolenaar472a0a82016-08-06 22:31:42 +0200218func RunVim(before, after, arguments)
Bram Moolenaar7a9a5f42016-08-08 22:34:14 +0200219 return RunVimPiped(a:before, a:after, a:arguments, '')
Bram Moolenaar3a938382016-08-07 16:36:40 +0200220endfunc
221
222func RunVimPiped(before, after, arguments, pipecmd)
Bram Moolenaar15bf76d2017-03-18 16:18:37 +0100223 let cmd = GetVimCommand()
224 if cmd == ''
Bram Moolenaar66459b72016-08-06 19:01:55 +0200225 return 0
226 endif
Bram Moolenaarba98bef2016-08-07 15:51:39 +0200227 let args = ''
Bram Moolenaar472a0a82016-08-06 22:31:42 +0200228 if len(a:before) > 0
229 call writefile(a:before, 'Xbefore.vim')
230 let args .= ' --cmd "so Xbefore.vim"'
231 endif
232 if len(a:after) > 0
233 call writefile(a:after, 'Xafter.vim')
234 let args .= ' -S Xafter.vim'
235 endif
Bram Moolenaar66459b72016-08-06 19:01:55 +0200236
Bram Moolenaar3a938382016-08-07 16:36:40 +0200237 exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments
Bram Moolenaar66459b72016-08-06 19:01:55 +0200238
Bram Moolenaar472a0a82016-08-06 22:31:42 +0200239 if len(a:before) > 0
240 call delete('Xbefore.vim')
241 endif
242 if len(a:after) > 0
243 call delete('Xafter.vim')
244 endif
Bram Moolenaar66459b72016-08-06 19:01:55 +0200245 return 1
246endfunc
Bram Moolenaar9f0139a2017-08-13 20:26:20 +0200247
248func CanRunGui()
249 return has('gui') && ($DISPLAY != "" || has('gui_running'))
250endfunc