1" Functions shared by several tests. 2 3" Only load this script once. 4if exists('*WaitFor') 5 finish 6endif 7 8" 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 96 call assert_false(1, 'Caught exception: "' . v:exception . '" in ' . v:throwpoint) 97 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 116" 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" 119" 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. 121func WaitFor(expr, ...) 122 let timeout = get(a:000, 0, 1000) 123 " 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 129 if type(a:expr) == v:t_func 130 let Test = a:expr 131 else 132 let Test = {-> eval(a:expr) } 133 endif 134 for i in range(timeout / 10) 135 if Test() 136 if has('reltime') 137 return float2nr(reltimefloat(reltime(start)) * 1000) 138 endif 139 return slept 140 endif 141 if !has('reltime') 142 let slept += 10 143 endif 144 sleep 10m 145 endfor 146 throw 'WaitFor() timed out after ' . timeout . ' msec' 147endfunc 148 149" 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 177" 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 186" Get the command to run Vim, with -u NONE and --not-a-term arguments. 187" If there is an argument use it instead of "NONE". 188" Returns an empty string on error. 189func GetVimCommand(...) 190 if !filereadable('vimcmd') 191 return '' 192 endif 193 if a:0 == 0 194 let name = 'NONE' 195 else 196 let name = a:1 197 endif 198 " 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]) 204 let cmd = substitute(cmd, '-u \f\+', '-u ' . name, '') 205 if cmd !~ '-u '. name 206 let cmd = cmd . ' -u ' . name 207 endif 208 let cmd .= ' --not-a-term' 209 let cmd = substitute(cmd, 'VIMRUNTIME=.*VIMRUNTIME;', '', '') 210 return cmd 211endfunc 212 213" Run Vim, using the "vimcmd" file and "-u NORC". 214" "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. 216" Plugins are not loaded, unless 'loadplugins' is set in "before". 217" Return 1 if Vim could be executed. 218func RunVim(before, after, arguments) 219 return RunVimPiped(a:before, a:after, a:arguments, '') 220endfunc 221 222func RunVimPiped(before, after, arguments, pipecmd) 223 let cmd = GetVimCommand() 224 if cmd == '' 225 return 0 226 endif 227 let args = '' 228 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 236 237 exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments 238 239 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 245 return 1 246endfunc 247 248func CanRunGui() 249 return has('gui') && ($DISPLAY != "" || has('gui_running')) 250endfunc 251