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. 117" Return time slept in milliseconds. With the +reltime feature this can be 118" more than the actual waiting time. Without +reltime it can also be less. 119func WaitFor(expr, ...) 120 let timeout = get(a:000, 0, 1000) 121 " using reltime() is more accurate, but not always available 122 if has('reltime') 123 let start = reltime() 124 else 125 let slept = 0 126 endif 127 for i in range(timeout / 10) 128 try 129 if eval(a:expr) 130 if has('reltime') 131 return float2nr(reltimefloat(reltime(start)) * 1000) 132 endif 133 return slept 134 endif 135 catch 136 endtry 137 if !has('reltime') 138 let slept += 10 139 endif 140 sleep 10m 141 endfor 142 return timeout 143endfunc 144 145" Wait for up to a given milliseconds. 146" With the +timers feature this waits for key-input by getchar(), Resume() 147" feeds key-input and resumes process. Return time waited in milliseconds. 148" Without +timers it uses simply :sleep. 149func Standby(msec) 150 if has('timers') 151 let start = reltime() 152 let g:_standby_timer = timer_start(a:msec, function('s:feedkeys')) 153 call getchar() 154 return float2nr(reltimefloat(reltime(start)) * 1000) 155 else 156 execute 'sleep ' a:msec . 'm' 157 return a:msec 158 endif 159endfunc 160 161func Resume() 162 if exists('g:_standby_timer') 163 call timer_stop(g:_standby_timer) 164 call s:feedkeys(0) 165 unlet g:_standby_timer 166 endif 167endfunc 168 169func s:feedkeys(timer) 170 call feedkeys('x', 'nt') 171endfunc 172 173" Get $VIMPROG to run Vim executable. 174" The Makefile writes it as the first line in the "vimcmd" file. 175func GetVimProg() 176 if !filereadable('vimcmd') 177 return '' 178 endif 179 return readfile('vimcmd')[0] 180endfunc 181 182" Get the command to run Vim, with -u NONE and --not-a-term arguments. 183" If there is an argument use it instead of "NONE". 184" Returns an empty string on error. 185func GetVimCommand(...) 186 if !filereadable('vimcmd') 187 return '' 188 endif 189 if a:0 == 0 190 let name = 'NONE' 191 else 192 let name = a:1 193 endif 194 " For Unix Makefile writes the command to use in the second line of the 195 " "vimcmd" file, including environment options. 196 " Other Makefiles just write the executable in the first line, so fall back 197 " to that if there is no second line. 198 let lines = readfile('vimcmd') 199 let cmd = get(lines, 1, lines[0]) 200 let cmd = substitute(cmd, '-u \f\+', '-u ' . name, '') 201 if cmd !~ '-u '. name 202 let cmd = cmd . ' -u ' . name 203 endif 204 let cmd .= ' --not-a-term' 205 let cmd = substitute(cmd, 'VIMRUNTIME=.*VIMRUNTIME;', '', '') 206 return cmd 207endfunc 208 209" Run Vim, using the "vimcmd" file and "-u NORC". 210" "before" is a list of Vim commands to be executed before loading plugins. 211" "after" is a list of Vim commands to be executed after loading plugins. 212" Plugins are not loaded, unless 'loadplugins' is set in "before". 213" Return 1 if Vim could be executed. 214func RunVim(before, after, arguments) 215 return RunVimPiped(a:before, a:after, a:arguments, '') 216endfunc 217 218func RunVimPiped(before, after, arguments, pipecmd) 219 let cmd = GetVimCommand() 220 if cmd == '' 221 return 0 222 endif 223 let args = '' 224 if len(a:before) > 0 225 call writefile(a:before, 'Xbefore.vim') 226 let args .= ' --cmd "so Xbefore.vim"' 227 endif 228 if len(a:after) > 0 229 call writefile(a:after, 'Xafter.vim') 230 let args .= ' -S Xafter.vim' 231 endif 232 233 exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments 234 235 if len(a:before) > 0 236 call delete('Xbefore.vim') 237 endif 238 if len(a:after) > 0 239 call delete('Xafter.vim') 240 endif 241 return 1 242endfunc 243 244func CanRunGui() 245 return has('gui') && ($DISPLAY != "" || has('gui_running')) 246endfunc 247