xref: /vim-8.2.3635/src/testdir/runtest.vim (revision bc2eada5)
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 be 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
89function RunTheTest(test)
90  echo 'Executing ' . a:test
91  if exists("*SetUp")
92    try
93      call SetUp()
94    catch
95      call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
96    endtry
97  endif
98
99  call add(s:messages, 'Executing ' . a:test)
100  let s:done += 1
101  try
102    exe 'call ' . a:test
103  catch /^\cskipped/
104    call add(s:messages, '    Skipped')
105    call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '',  ''))
106  catch
107    call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
108  endtry
109
110  if exists("*TearDown")
111    try
112      call TearDown()
113    catch
114      call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
115    endtry
116  endif
117
118  " Close any extra windows and make the current one not modified.
119  while 1
120    let wincount = winnr('$')
121    if wincount == 1
122      break
123    endif
124    bwipe!
125    if wincount == winnr('$')
126      " Did not manage to close a window.
127      only!
128      break
129    endif
130  endwhile
131  set nomodified
132endfunc
133
134" Source the test script.  First grab the file name, in case the script
135" navigates away.  g:testname can be used by the tests.
136let g:testname = expand('%')
137let s:done = 0
138let s:fail = 0
139let s:errors = []
140let s:messages = []
141let s:skipped = []
142if expand('%') =~ 'test_viml.vim'
143  " this test has intentional s:errors, don't use try/catch.
144  source %
145else
146  try
147    source %
148  catch
149    let s:fail += 1
150    call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
151  endtry
152endif
153
154" Names of flaky tests.
155let s:flaky = [
156      \ 'Test_reltime()',
157      \ 'Test_nb_basic()',
158      \ 'Test_communicate()',
159      \ 'Test_pipe_through_sort_all()',
160      \ 'Test_pipe_through_sort_some()'
161      \ ]
162
163" Locate Test_ functions and execute them.
164set nomore
165redir @q
166silent function /^Test_
167redir END
168let s:tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g'))
169
170" If there is an extra argument filter the function names against it.
171if argc() > 1
172  let s:tests = filter(s:tests, 'v:val =~ argv(1)')
173endif
174
175" Execute the tests in alphabetical order.
176for s:test in sort(s:tests)
177  call RunTheTest(s:test)
178
179  if len(v:errors) > 0 && index(s:flaky, s:test) >= 0
180    call add(s:messages, 'Flaky test failed, running it again')
181    let v:errors = []
182    call RunTheTest(s:test)
183  endif
184
185  if len(v:errors) > 0
186    let s:fail += 1
187    call add(s:errors, 'Found errors in ' . s:test . ':')
188    call extend(s:errors, v:errors)
189    let v:errors = []
190  endif
191endfor
192
193" Don't write viminfo on exit.
194set viminfo=
195
196if s:fail == 0
197  " Success, create the .res file so that make knows it's done.
198  exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
199  write
200endif
201
202if len(s:errors) > 0
203  " Append errors to test.log
204  split test.log
205  call append(line('$'), '')
206  call append(line('$'), 'From ' . g:testname . ':')
207  call append(line('$'), s:errors)
208  write
209endif
210
211let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
212echo message
213call add(s:messages, message)
214if s:fail > 0
215  let message = s:fail . ' FAILED:'
216  echo message
217  call add(s:messages, message)
218  call extend(s:messages, s:errors)
219endif
220
221" Add SKIPPED messages
222call extend(s:messages, s:skipped)
223
224" Append messages to the file "messages"
225split messages
226call append(line('$'), '')
227call append(line('$'), 'From ' . g:testname . ':')
228call append(line('$'), s:messages)
229write
230
231qall!
232
233" vim: shiftwidth=2 sts=2 expandtab
234