xref: /vim-8.2.3635/src/testdir/runtest.vim (revision e16b00a1)
1" This script is sourced while editing the .vim file with the tests.
2" When the script is successful the .res file will be created.
3" Errors are appended to the test.log file.
4"
5" To execute only specific test functions, add a second argument.  It will be
6" matched against the names of the Test_ funtion.  E.g.:
7"	../vim -u NONE -S runtest.vim test_channel.vim open_delay
8" The output can be found in the "messages" file.
9"
10" The test script may contain anything, only functions that start with
11" "Test_" are special.  These will be invoked and should contain assert
12" functions.  See test_assert.vim for an example.
13"
14" It is possible to source other files that contain "Test_" functions.  This
15" can speed up testing, since Vim does not need to restart.  But be careful
16" that the tests do not interfere with each other.
17"
18" If an error cannot be detected properly with an assert function add the
19" error to the v:errors list:
20"   call add(v:errors, 'test foo failed: Cannot find xyz')
21"
22" If preparation for each Test_ function is needed, define a SetUp function.
23" It will be called before each Test_ function.
24"
25" If cleanup after each Test_ function is needed, define a TearDown function.
26" It will be called after each Test_ function.
27"
28" When debugging a test it can be useful to add messages to v:errors:
29" 	call add(v:errors, "this happened")
30
31
32" Without the +eval feature we can't run these tests, bail out.
33so small.vim
34
35" Check that the screen size is at least 24 x 80 characters.
36if &lines < 24 || &columns < 80
37  let error = 'Screen size too small! Tests require at least 24 lines with 80 characters'
38  echoerr error
39  split test.log
40  $put =error
41  w
42  cquit
43endif
44
45" Common with all tests on all systems.
46source setup.vim
47
48" For consistency run all tests with 'nocompatible' set.
49" This also enables use of line continuation.
50set nocp viminfo+=nviminfo
51
52" Use utf-8 or latin1 by default, instead of whatever the system default
53" happens to be.  Individual tests can overrule this at the top of the file.
54if has('multi_byte')
55  set encoding=utf-8
56else
57  set encoding=latin1
58endif
59
60" Avoid stopping at the "hit enter" prompt
61set nomore
62
63" Output all messages in English.
64lang mess C
65
66" Always use forward slashes.
67set shellslash
68
69let s:srcdir = expand('%:p:h:h')
70
71" Prepare for calling test_garbagecollect_now().
72let v:testing = 1
73
74" Support function: get the alloc ID by name.
75function GetAllocId(name)
76  exe 'split ' . s:srcdir . '/alloc.h'
77  let top = search('typedef enum')
78  if top == 0
79    call add(v:errors, 'typedef not found in alloc.h')
80  endif
81  let lnum = search('aid_' . a:name . ',')
82  if lnum == 0
83    call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
84  endif
85  close
86  return lnum - top - 1
87endfunc
88
89func RunTheTest(test)
90  echo 'Executing ' . a:test
91
92  " Avoid stopping at the "hit enter" prompt
93  set nomore
94
95  " Avoid a three second wait when a message is about to be overwritten by the
96  " mode message.
97  set noshowmode
98
99  " Clear any overrides.
100  call test_override('ALL', 0)
101
102  if exists("*SetUp")
103    try
104      call SetUp()
105    catch
106      call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
107    endtry
108  endif
109
110  call add(s:messages, 'Executing ' . a:test)
111  let s:done += 1
112  try
113    exe 'call ' . a:test
114  catch /^\cskipped/
115    call add(s:messages, '    Skipped')
116    call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '',  ''))
117  catch
118    call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
119  endtry
120
121  if exists("*TearDown")
122    try
123      call TearDown()
124    catch
125      call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
126    endtry
127  endif
128
129  " Close any extra windows and make the current one not modified.
130  while 1
131    let wincount = winnr('$')
132    if wincount == 1
133      break
134    endif
135    bwipe!
136    if wincount == winnr('$')
137      " Did not manage to close a window.
138      only!
139      break
140    endif
141  endwhile
142  set nomodified
143endfunc
144
145func AfterTheTest()
146  if len(v:errors) > 0
147    let s:fail += 1
148    call add(s:errors, 'Found errors in ' . s:test . ':')
149    call extend(s:errors, v:errors)
150    let v:errors = []
151  endif
152endfunc
153
154" This function can be called by a test if it wants to abort testing.
155func FinishTesting()
156  call AfterTheTest()
157
158  " Don't write viminfo on exit.
159  set viminfo=
160
161  " Clean up files created by setup.vim
162  call delete('XfakeHOME', 'rf')
163
164  if s:fail == 0
165    " Success, create the .res file so that make knows it's done.
166    exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
167    write
168  endif
169
170  if len(s:errors) > 0
171    " Append errors to test.log
172    split test.log
173    call append(line('$'), '')
174    call append(line('$'), 'From ' . g:testname . ':')
175    call append(line('$'), s:errors)
176    write
177  endif
178
179  let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
180  echo message
181  call add(s:messages, message)
182  if s:fail > 0
183    let message = s:fail . ' FAILED:'
184    echo message
185    call add(s:messages, message)
186    call extend(s:messages, s:errors)
187  endif
188
189  " Add SKIPPED messages
190  call extend(s:messages, s:skipped)
191
192  " Append messages to the file "messages"
193  split messages
194  call append(line('$'), '')
195  call append(line('$'), 'From ' . g:testname . ':')
196  call append(line('$'), s:messages)
197  write
198
199  qall!
200endfunc
201
202" Source the test script.  First grab the file name, in case the script
203" navigates away.  g:testname can be used by the tests.
204let g:testname = expand('%')
205let s:done = 0
206let s:fail = 0
207let s:errors = []
208let s:messages = []
209let s:skipped = []
210if expand('%') =~ 'test_vimscript.vim'
211  " this test has intentional s:errors, don't use try/catch.
212  source %
213else
214  try
215    source %
216  catch
217    let s:fail += 1
218    call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
219  endtry
220endif
221
222" Names of flaky tests.
223let s:flaky = [
224      \ 'Test_client_server()',
225      \ 'Test_close_and_exit_cb()',
226      \ 'Test_collapse_buffers()',
227      \ 'Test_communicate()',
228      \ 'Test_exit_callback_interval()',
229      \ 'Test_nb_basic()',
230      \ 'Test_oneshot()',
231      \ 'Test_pipe_through_sort_all()',
232      \ 'Test_pipe_through_sort_some()',
233      \ 'Test_quoteplus()',
234      \ 'Test_quotestar()',
235      \ 'Test_reltime()',
236      \ 'Test_with_partial_callback()',
237      \ ]
238
239" Locate Test_ functions and execute them.
240redir @q
241silent function /^Test_
242redir END
243let s:tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g'))
244
245" If there is an extra argument filter the function names against it.
246if argc() > 1
247  let s:tests = filter(s:tests, 'v:val =~ argv(1)')
248endif
249
250" Execute the tests in alphabetical order.
251for s:test in sort(s:tests)
252  call RunTheTest(s:test)
253
254  if len(v:errors) > 0 && index(s:flaky, s:test) >= 0
255    call add(s:messages, 'Found errors in ' . s:test . ':')
256    call extend(s:messages, v:errors)
257    call add(s:messages, 'Flaky test failed, running it again')
258    let first_run = v:errors
259
260    let v:errors = []
261    call RunTheTest(s:test)
262    if len(v:errors) > 0
263      let second_run = v:errors
264      let v:errors = ['First run:']
265      call extend(v:errors, first_run)
266      call add(v:errors, 'Second run:')
267      call extend(v:errors, second_run)
268    endif
269  endif
270
271  call AfterTheTest()
272endfor
273
274call FinishTesting()
275
276" vim: shiftwidth=2 sts=2 expandtab
277