xref: /vim-8.2.3635/src/testdir/shared.vim (revision 37c64c78)
1" Functions shared by several tests.
2
3" Get the name of the Python executable.
4" Also keeps it in s:python.
5func PythonProg()
6  " This test requires the Python command to run the test server.
7  " This most likely only works on Unix and Windows.
8  if has('unix')
9    " We also need the job feature or the pkill command to make sure the server
10    " can be stopped.
11    if !(executable('python') && (has('job') || executable('pkill')))
12      return ''
13    endif
14    let s:python = 'python'
15  elseif has('win32')
16    " Use Python Launcher for Windows (py.exe) if available.
17    if executable('py.exe')
18      let s:python = 'py.exe'
19    elseif executable('python.exe')
20      let s:python = 'python.exe'
21    else
22      return ''
23    endif
24  else
25    return ''
26  endif
27  return s:python
28endfunc
29
30" Run "cmd".  Returns the job if using a job.
31func RunCommand(cmd)
32  let job = 0
33  if has('job')
34    let job = job_start(a:cmd, {"stoponexit": "hup"})
35    call job_setoptions(job, {"stoponexit": "kill"})
36  elseif has('win32')
37    exe 'silent !start cmd /c start "test_channel" ' . a:cmd
38  else
39    exe 'silent !' . a:cmd . '&'
40  endif
41  return job
42endfunc
43
44" Read the port number from the Xportnr file.
45func GetPort()
46  let l = []
47  for i in range(200)
48    try
49      let l = readfile("Xportnr")
50    catch
51    endtry
52    if len(l) >= 1
53      break
54    endif
55    sleep 10m
56  endfor
57  call delete("Xportnr")
58
59  if len(l) == 0
60    " Can't make the connection, give up.
61    return 0
62  endif
63  return l[0]
64endfunc
65
66" Run a Python server for "cmd" and call "testfunc".
67" Always kills the server before returning.
68func RunServer(cmd, testfunc, args)
69  " The Python program writes the port number in Xportnr.
70  call delete("Xportnr")
71
72  if len(a:args) == 1
73    let arg = ' ' . a:args[0]
74  else
75    let arg = ''
76  endif
77  let pycmd = s:python . " " . a:cmd . arg
78
79  try
80    let g:currentJob = RunCommand(pycmd)
81
82    " Wait for up to 2 seconds for the port number to be there.
83    let port = GetPort()
84    if port == 0
85      call assert_false(1, "Can't start " . a:cmd)
86      return
87    endif
88
89    call call(function(a:testfunc), [port])
90  catch
91    call assert_false(1, 'Caught exception: "' . v:exception . '" in ' . v:throwpoint)
92  finally
93    call s:kill_server(a:cmd)
94  endtry
95endfunc
96
97func s:kill_server(cmd)
98  if has('job')
99    if exists('g:currentJob')
100      call job_stop(g:currentJob)
101      unlet g:currentJob
102    endif
103  elseif has('win32')
104    let cmd = substitute(a:cmd, ".py", '', '')
105    call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq ' . cmd . '"')
106  else
107    call system("pkill -f " . a:cmd)
108  endif
109endfunc
110
111" Wait for up to a second for "expr" to become true.
112" Return time slept in milliseconds.  With the +reltime feature this can be
113" more than the actual waiting time.  Without +reltime it can also be less.
114func WaitFor(expr, ...)
115  let timeout = get(a:000, 0, 1000)
116  " using reltime() is more accurate, but not always available
117  if has('reltime')
118    let start = reltime()
119  else
120    let slept = 0
121  endif
122  for i in range(timeout / 10)
123    try
124      if eval(a:expr)
125	if has('reltime')
126	  return float2nr(reltimefloat(reltime(start)) * 1000)
127	endif
128	return slept
129      endif
130    catch
131    endtry
132    if !has('reltime')
133      let slept += 10
134    endif
135    sleep 10m
136  endfor
137  return timeout
138endfunc
139
140" Wait for up to a given milliseconds.
141" With the +timers feature this waits for key-input by getchar(), Resume()
142" feeds key-input and resumes process. Return time waited in milliseconds.
143" Without +timers it uses simply :sleep.
144func Standby(msec)
145  if has('timers')
146    let start = reltime()
147    let g:_standby_timer = timer_start(a:msec, function('s:feedkeys'))
148    call getchar()
149    return float2nr(reltimefloat(reltime(start)) * 1000)
150  else
151    execute 'sleep ' a:msec . 'm'
152    return a:msec
153  endif
154endfunc
155
156func Resume()
157  if exists('g:_standby_timer')
158    call timer_stop(g:_standby_timer)
159    call s:feedkeys(0)
160    unlet g:_standby_timer
161  endif
162endfunc
163
164func s:feedkeys(timer)
165  call feedkeys('x', 'nt')
166endfunc
167
168" Get the command to run Vim, with -u NONE and --not-a-term arguments.
169" If there is an argument use it instead of "NONE".
170" Returns an empty string on error.
171func GetVimCommand(...)
172  if !filereadable('vimcmd')
173    return ''
174  endif
175  if a:0 == 0
176    let name = 'NONE'
177  else
178    let name = a:1
179  endif
180  let cmd = readfile('vimcmd')[0]
181  let cmd = substitute(cmd, '-u \f\+', '-u ' . name, '')
182  if cmd !~ '-u '. name
183    let cmd = cmd . ' -u ' . name
184  endif
185  let cmd .= ' --not-a-term'
186  let cmd = substitute(cmd, 'VIMRUNTIME=.*VIMRUNTIME;', '', '')
187  return cmd
188endfunc
189
190" Run Vim, using the "vimcmd" file and "-u NORC".
191" "before" is a list of Vim commands to be executed before loading plugins.
192" "after" is a list of Vim commands to be executed after loading plugins.
193" Plugins are not loaded, unless 'loadplugins' is set in "before".
194" Return 1 if Vim could be executed.
195func RunVim(before, after, arguments)
196  return RunVimPiped(a:before, a:after, a:arguments, '')
197endfunc
198
199func RunVimPiped(before, after, arguments, pipecmd)
200  let cmd = GetVimCommand()
201  if cmd == ''
202    return 0
203  endif
204  let args = ''
205  if len(a:before) > 0
206    call writefile(a:before, 'Xbefore.vim')
207    let args .= ' --cmd "so Xbefore.vim"'
208  endif
209  if len(a:after) > 0
210    call writefile(a:after, 'Xafter.vim')
211    let args .= ' -S Xafter.vim'
212  endif
213
214  exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments
215
216  if len(a:before) > 0
217    call delete('Xbefore.vim')
218  endif
219  if len(a:after) > 0
220    call delete('Xafter.vim')
221  endif
222  return 1
223endfunc
224
225func CanRunGui()
226  return has('gui') && ($DISPLAY != "" || has('gui_running'))
227endfunc
228