blob: 3cf2a506c975e470305101a7222f3e836ebf1c87 [file] [log] [blame]
Bram Moolenaar43345542015-11-29 17:35:35 +01001" 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"
Bram Moolenaarbefb3662016-02-20 14:41:40 +01005" To execute only specific test functions, add a second argument. It will be
Bram Moolenaare219f732019-11-30 15:34:08 +01006" matched against the names of the Test_ function. E.g.:
Bram Moolenaarbefb3662016-02-20 14:41:40 +01007" ../vim -u NONE -S runtest.vim test_channel.vim open_delay
8" The output can be found in the "messages" file.
9"
Bram Moolenaarce436de2020-03-21 15:17:20 +010010" If the environment variable $TEST_FILTER is set then only test functions
11" matching this pattern are executed. E.g. for sh/bash:
12" export TEST_FILTER=Test_channel
13" For csh:
14" setenv TEST_FILTER Test_channel
15"
16" To ignore failure for tests that are known to fail in a certain environment,
17" set $TEST_MAY_FAIL to a comma separated list of function names. E.g. for
18" sh/bash:
19" export TEST_MAY_FAIL=Test_channel_one,Test_channel_other
20" The failure report will then not be included in the test.log file and
21" "make test" will not fail.
22"
Bram Moolenaar43345542015-11-29 17:35:35 +010023" The test script may contain anything, only functions that start with
24" "Test_" are special. These will be invoked and should contain assert
25" functions. See test_assert.vim for an example.
26"
27" It is possible to source other files that contain "Test_" functions. This
28" can speed up testing, since Vim does not need to restart. But be careful
29" that the tests do not interfere with each other.
30"
31" If an error cannot be detected properly with an assert function add the
32" error to the v:errors list:
33" call add(v:errors, 'test foo failed: Cannot find xyz')
34"
35" If preparation for each Test_ function is needed, define a SetUp function.
36" It will be called before each Test_ function.
37"
38" If cleanup after each Test_ function is needed, define a TearDown function.
39" It will be called after each Test_ function.
Bram Moolenaar00af60b2016-02-13 14:06:14 +010040"
41" When debugging a test it can be useful to add messages to v:errors:
Bram Moolenaar8ad16da2019-01-06 15:29:57 +010042" call add(v:errors, "this happened")
Bram Moolenaar00af60b2016-02-13 14:06:14 +010043
Bram Moolenaar43345542015-11-29 17:35:35 +010044
45" Without the +eval feature we can't run these tests, bail out.
Bram Moolenaar4686b322015-12-28 14:44:10 +010046so small.vim
Bram Moolenaar43345542015-11-29 17:35:35 +010047
Bram Moolenaar18aa13d2020-07-11 13:09:36 +020048" In the GUI we can always change the screen size.
49if has('gui_running')
50 set columns=80 lines=25
51endif
52
Bram Moolenaar43345542015-11-29 17:35:35 +010053" Check that the screen size is at least 24 x 80 characters.
54if &lines < 24 || &columns < 80
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020055 let error = 'Screen size too small! Tests require at least 24 lines with 80 characters, got ' .. &lines .. ' lines with ' .. &columns .. ' characters'
Bram Moolenaar43345542015-11-29 17:35:35 +010056 echoerr error
57 split test.log
58 $put =error
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020059 write
60 split messages
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020061 call append(line('$'), '')
62 call append(line('$'), 'From ' . expand('%') . ':')
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020063 call append(line('$'), error)
64 write
65 qa!
Bram Moolenaar43345542015-11-29 17:35:35 +010066endif
67
Bram Moolenaar75ee5442019-06-06 18:05:25 +020068if has('reltime')
69 let s:start_time = reltime()
70endif
71
Bram Moolenaar89b10422016-07-12 22:51:22 +020072" Common with all tests on all systems.
73source setup.vim
74
Bram Moolenaarc0662462015-12-30 15:49:05 +010075" For consistency run all tests with 'nocompatible' set.
76" This also enables use of line continuation.
77set nocp viminfo+=nviminfo
78
Bram Moolenaar30276f22019-01-24 17:59:39 +010079" Use utf-8 by default, instead of whatever the system default happens to be.
Bram Moolenaared79d1e2019-02-22 14:38:58 +010080" Individual tests can overrule this at the top of the file and use
81" g:orig_encoding if needed.
82let g:orig_encoding = &encoding
Bram Moolenaar30276f22019-01-24 17:59:39 +010083set encoding=utf-8
Bram Moolenaarac105ed2016-07-21 20:33:32 +020084
Bram Moolenaard8f27b32018-10-07 15:42:07 +020085" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for
86" the test_name.vim file itself. Replace it here with a more restrictive one,
87" so we still catch mistakes.
88let s:test_script_fname = expand('%')
89au! SwapExists * call HandleSwapExists()
90func HandleSwapExists()
Bram Moolenaarb073da82019-07-13 14:47:26 +020091 " Ignore finding a swap file for the test script (the user might be
Bram Moolenaard8f27b32018-10-07 15:42:07 +020092 " editing it and do ":make test_name") and the output file.
Bram Moolenaarb073da82019-07-13 14:47:26 +020093 " Report finding another swap file and chose 'q' to avoid getting stuck.
Bram Moolenaard8f27b32018-10-07 15:42:07 +020094 if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname
95 let v:swapchoice = 'e'
Bram Moolenaarb073da82019-07-13 14:47:26 +020096 else
97 call assert_report('Unexpected swap file: ' .. v:swapname)
98 let v:swapchoice = 'q'
Bram Moolenaard8f27b32018-10-07 15:42:07 +020099 endif
100endfunc
101
Bram Moolenaar7a073542017-02-01 23:17:36 +0100102" Avoid stopping at the "hit enter" prompt
103set nomore
104
Bram Moolenaarc0662462015-12-30 15:49:05 +0100105" Output all messages in English.
106lang mess C
107
Bram Moolenaar10e1d012020-07-18 22:03:11 +0200108" suppress menu translation
109if has('gui_running') && exists('did_install_default_menus')
110 source $VIMRUNTIME/delmenu.vim
111 set langmenu=none
112 source $VIMRUNTIME/menu.vim
113endif
114
Bram Moolenaarf60b7962016-01-16 22:47:23 +0100115" Always use forward slashes.
116set shellslash
117
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100118let s:srcdir = expand('%:p:h:h')
119
Bram Moolenaar2690b5a2020-07-22 18:14:58 +0200120if has('win32')
121 " avoid prompt that is long or contains a line break
122 let $PROMPT = '$P$G'
123endif
124
Bram Moolenaar8e8df252016-05-25 21:23:21 +0200125" Prepare for calling test_garbagecollect_now().
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200126let v:testing = 1
127
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100128" Support function: get the alloc ID by name.
129function GetAllocId(name)
130 exe 'split ' . s:srcdir . '/alloc.h'
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100131 let top = search('typedef enum')
132 if top == 0
133 call add(v:errors, 'typedef not found in alloc.h')
134 endif
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100135 let lnum = search('aid_' . a:name . ',')
136 if lnum == 0
137 call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
138 endif
139 close
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100140 return lnum - top - 1
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100141endfunc
142
Bram Moolenaar42205552017-03-18 19:42:22 +0100143func RunTheTest(test)
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100144 echo 'Executing ' . a:test
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200145 if has('reltime')
146 let func_start = reltime()
147 endif
Bram Moolenaare5f2a072017-02-01 22:31:49 +0100148
149 " Avoid stopping at the "hit enter" prompt
150 set nomore
151
152 " Avoid a three second wait when a message is about to be overwritten by the
153 " mode message.
154 set noshowmode
155
Bram Moolenaareb992cb2017-03-09 18:20:16 +0100156 " Clear any overrides.
157 call test_override('ALL', 0)
158
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200159 " Some tests wipe out buffers. To be consistent, always wipe out all
160 " buffers.
161 %bwipe!
162
Bram Moolenaar209d3872017-11-16 21:52:51 +0100163 " The test may change the current directory. Save and restore the
164 " directory after executing the test.
165 let save_cwd = getcwd()
166
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100167 if exists("*SetUp")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100168 try
169 call SetUp()
170 catch
171 call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
172 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100173 endif
174
Bram Moolenaarf204e052017-10-26 17:14:01 +0200175 if a:test =~ 'Test_nocatch_'
176 " Function handles errors itself. This avoids skipping commands after the
177 " error.
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100178 exe 'call ' . a:test
Bram Moolenaarf204e052017-10-26 17:14:01 +0200179 else
180 try
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200181 au VimLeavePre * call EarlyExit(g:testfunc)
Bram Moolenaarf204e052017-10-26 17:14:01 +0200182 exe 'call ' . a:test
Bram Moolenaar89036762018-06-12 14:58:39 +0200183 au! VimLeavePre
Bram Moolenaarf204e052017-10-26 17:14:01 +0200184 catch /^\cskipped/
185 call add(s:messages, ' Skipped')
186 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
187 catch
188 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
189 endtry
190 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100191
Bram Moolenaar8ad16da2019-01-06 15:29:57 +0100192 " In case 'insertmode' was set and something went wrong, make sure it is
193 " reset to avoid trouble with anything else.
194 set noinsertmode
195
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100196 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100197 try
198 call TearDown()
199 catch
200 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
201 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100202 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200203
Bram Moolenaar0b5dc642019-08-11 22:56:15 +0200204 " Clear any autocommands and put back the catch-all for SwapExists.
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200205 au!
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200206 au SwapExists * call HandleSwapExists()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200207
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200208 " Check for and close any stray popup windows.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100209 if has('popupwin')
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200210 call assert_equal([], popup_list())
Bram Moolenaar03a9f842020-05-13 13:40:16 +0200211 call popup_clear(1)
Bram Moolenaarae943152019-06-16 22:54:14 +0200212 endif
213
Bram Moolenaarce11de82017-10-26 22:00:00 +0200214 " Close any extra tab pages and windows and make the current one not modified.
215 while tabpagenr('$') > 1
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200216 quit!
Bram Moolenaarce11de82017-10-26 22:00:00 +0200217 endwhile
218
Bram Moolenaar358308d2016-08-24 21:21:26 +0200219 while 1
220 let wincount = winnr('$')
221 if wincount == 1
222 break
223 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200224 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200225 if wincount == winnr('$')
226 " Did not manage to close a window.
227 only!
228 break
229 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200230 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100231
232 exe 'cd ' . save_cwd
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200233
234 let message = 'Executed ' . a:test
235 if has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200236 let message ..= repeat(' ', 50 - len(message))
237 let time = reltime(func_start)
238 if has('float') && reltimefloat(time) > 0.1
239 let message = &t_md .. message
240 endif
241 let message ..= ' in ' .. reltimestr(time) .. ' seconds'
242 if has('float') && reltimefloat(time) > 0.1
243 let message ..= &t_me
244 endif
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200245 endif
246 call add(s:messages, message)
247 let s:done += 1
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100248endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100249
Bram Moolenaarce436de2020-03-21 15:17:20 +0100250func AfterTheTest(func_name)
Bram Moolenaar42205552017-03-18 19:42:22 +0100251 if len(v:errors) > 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100252 if match(s:may_fail_list, '^' .. a:func_name) >= 0
253 let s:fail_expected += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200254 call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100255 call extend(s:errors_expected, v:errors)
256 else
257 let s:fail += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200258 call add(s:errors, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100259 call extend(s:errors, v:errors)
260 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100261 let v:errors = []
262 endif
263endfunc
264
Bram Moolenaar89036762018-06-12 14:58:39 +0200265func EarlyExit(test)
266 " It's OK for the test we use to test the quit detection.
267 if a:test != 'Test_zz_quit_detected()'
268 call add(v:errors, 'Test caused Vim to exit: ' . a:test)
269 endif
270
271 call FinishTesting()
272endfunc
273
Bram Moolenaar42205552017-03-18 19:42:22 +0100274" This function can be called by a test if it wants to abort testing.
275func FinishTesting()
Bram Moolenaarce436de2020-03-21 15:17:20 +0100276 call AfterTheTest('')
Bram Moolenaar42205552017-03-18 19:42:22 +0100277
278 " Don't write viminfo on exit.
279 set viminfo=
280
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200281 " Clean up files created by setup.vim
282 call delete('XfakeHOME', 'rf')
283
Bram Moolenaarce436de2020-03-21 15:17:20 +0100284 if s:fail == 0 && s:fail_expected == 0
Bram Moolenaar42205552017-03-18 19:42:22 +0100285 " Success, create the .res file so that make knows it's done.
286 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
287 write
288 endif
289
290 if len(s:errors) > 0
291 " Append errors to test.log
292 split test.log
293 call append(line('$'), '')
294 call append(line('$'), 'From ' . g:testname . ':')
295 call append(line('$'), s:errors)
296 write
297 endif
298
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200299 if s:done == 0
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200300 if s:filtered > 0
301 let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
302 else
303 let message = 'NO tests executed'
304 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200305 else
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200306 if s:filtered > 0
307 call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER")
308 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200309 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
310 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200311 if s:done > 0 && has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200312 let message = &t_md .. message .. repeat(' ', 40 - len(message))
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200313 let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
Bram Moolenaar8d943792020-06-21 20:39:37 +0200314 let message ..= &t_me
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200315 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100316 echo message
317 call add(s:messages, message)
318 if s:fail > 0
319 let message = s:fail . ' FAILED:'
320 echo message
321 call add(s:messages, message)
322 call extend(s:messages, s:errors)
323 endif
Bram Moolenaarce436de2020-03-21 15:17:20 +0100324 if s:fail_expected > 0
325 let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
326 echo message
327 call add(s:messages, message)
328 call extend(s:messages, s:errors_expected)
329 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100330
331 " Add SKIPPED messages
332 call extend(s:messages, s:skipped)
333
334 " Append messages to the file "messages"
335 split messages
336 call append(line('$'), '')
337 call append(line('$'), 'From ' . g:testname . ':')
338 call append(line('$'), s:messages)
339 write
340
341 qall!
342endfunc
343
Bram Moolenaar43345542015-11-29 17:35:35 +0100344" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100345" navigates away. g:testname can be used by the tests.
346let g:testname = expand('%')
347let s:done = 0
348let s:fail = 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100349let s:fail_expected = 0
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100350let s:errors = []
Bram Moolenaarce436de2020-03-21 15:17:20 +0100351let s:errors_expected = []
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100352let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200353let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100354if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaarce436de2020-03-21 15:17:20 +0100355 " this test has intentional errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100356 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100357else
358 try
359 source %
Bram Moolenaar9c0cec62019-06-06 13:38:15 +0200360 catch /^\cskipped/
361 call add(s:messages, ' Skipped')
362 call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
Bram Moolenaara2cce862016-01-02 19:50:04 +0100363 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100364 let s:fail += 1
365 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100366 endtry
367endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100368
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100369" Names of flaky tests.
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100370let s:flaky_tests = [
Bram Moolenaar0d0c3ca2019-09-25 21:16:15 +0200371 \ 'Test_autocmd_SafeState()',
Bram Moolenaar42205552017-03-18 19:42:22 +0100372 \ 'Test_client_server()',
Bram Moolenaar6fe2eb42017-01-29 21:49:51 +0100373 \ 'Test_close_and_exit_cb()',
Bram Moolenaard80232b2018-12-15 17:46:23 +0100374 \ 'Test_close_output_buffer()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100375 \ 'Test_collapse_buffers()',
Bram Moolenaar65873842018-03-25 17:12:58 +0200376 \ 'Test_cwd()',
Bram Moolenaar218959b2018-11-11 18:51:42 +0100377 \ 'Test_diff_screen()',
Bram Moolenaar0529b3e2017-03-16 22:30:37 +0100378 \ 'Test_exit_callback_interval()',
Bram Moolenaarea94c852019-08-16 21:47:27 +0200379 \ 'Test_map_timeout_with_timer_interrupt()',
Bram Moolenaar1eca6f12017-12-05 14:04:27 +0100380 \ 'Test_out_cb()',
Bram Moolenaarc79d6aa2016-09-25 22:27:37 +0200381 \ 'Test_pipe_through_sort_all()',
Bram Moolenaar4e032e12017-02-01 20:48:13 +0100382 \ 'Test_pipe_through_sort_some()',
Bram Moolenaar44f0bd82019-11-21 18:27:01 +0100383 \ 'Test_popup_and_window_resize()',
Bram Moolenaar0fbff642017-03-05 14:30:52 +0100384 \ 'Test_quoteplus()',
Bram Moolenaar7dd48502017-03-19 20:04:22 +0100385 \ 'Test_quotestar()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100386 \ 'Test_reltime()',
Bram Moolenaar3c8cd4a2019-10-14 22:26:20 +0200387 \ 'Test_state()',
Bram Moolenaarf204e052017-10-26 17:14:01 +0200388 \ 'Test_terminal_composing_unicode()',
Bram Moolenaar38767892019-02-21 18:17:14 +0100389 \ 'Test_terminal_does_not_truncate_last_newlines()',
Bram Moolenaar3615abb2019-02-10 23:04:12 +0100390 \ 'Test_terminal_no_cmd()',
Bram Moolenaar75a60f72017-09-07 22:24:41 +0200391 \ 'Test_terminal_noblock()',
Bram Moolenaar7dd88c52017-11-04 20:46:40 +0100392 \ 'Test_terminal_redir_file()',
Bram Moolenaare219f732019-11-30 15:34:08 +0100393 \ 'Test_termwinscroll()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200394 \ 'Test_timer_oneshot()',
395 \ 'Test_timer_paused()',
396 \ 'Test_timer_repeat_many()',
397 \ 'Test_timer_repeat_three()',
398 \ 'Test_timer_stop_all_in_callback()',
399 \ 'Test_timer_stop_in_callback()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200400 \ 'Test_timer_with_partial_callback()',
Bram Moolenaare1c8c7a2016-09-11 16:48:50 +0200401 \ ]
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100402
Bram Moolenaar43345542015-11-29 17:35:35 +0100403" Locate Test_ functions and execute them.
404redir @q
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100405silent function /^Test_
Bram Moolenaar43345542015-11-29 17:35:35 +0100406redir END
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +0100407let s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g'))
Bram Moolenaar43345542015-11-29 17:35:35 +0100408
Bram Moolenaarbefb3662016-02-20 14:41:40 +0100409" If there is an extra argument filter the function names against it.
410if argc() > 1
411 let s:tests = filter(s:tests, 'v:val =~ argv(1)')
412endif
413
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200414" If the environment variable $TEST_FILTER is set then filter the function
415" names against it.
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200416let s:filtered = 0
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200417if $TEST_FILTER != ''
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200418 let s:filtered = len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200419 let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER')
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200420 let s:filtered -= len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200421endif
422
Bram Moolenaarce436de2020-03-21 15:17:20 +0100423let s:may_fail_list = []
424if $TEST_MAY_FAIL != ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200425 " Split the list at commas and add () to make it match g:testfunc.
Bram Moolenaarce436de2020-03-21 15:17:20 +0100426 let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'})
427endif
428
Bram Moolenaarcfc0a352016-01-09 20:23:00 +0100429" Execute the tests in alphabetical order.
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200430for g:testfunc in sort(s:tests)
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200431 " Silence, please!
432 set belloff=all
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100433 let prev_error = ''
434 let total_errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100435 let g:run_nr = 1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200436
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200437 " A test can set g:test_is_flaky to retry running the test.
438 let g:test_is_flaky = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100439
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200440 call RunTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100441
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100442 " Repeat a flaky test. Give up when:
443 " - it fails again with the same message
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200444 " - it fails five times (with a different message)
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100445 if len(v:errors) > 0
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200446 \ && (index(s:flaky_tests, g:testfunc) >= 0
447 \ || g:test_is_flaky)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100448 while 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200449 call add(s:messages, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100450 call extend(s:messages, v:errors)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100451
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100452 call add(total_errors, 'Run ' . g:run_nr . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100453 call extend(total_errors, v:errors)
Bram Moolenaar55058602017-11-21 15:14:51 +0100454
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100455 if g:run_nr == 5 || prev_error == v:errors[0]
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100456 call add(total_errors, 'Flaky test failed too often, giving up')
457 let v:errors = total_errors
458 break
459 endif
460
461 call add(s:messages, 'Flaky test failed, running it again')
462
463 " Flakiness is often caused by the system being very busy. Sleep a
464 " couple of seconds to have a higher chance of succeeding the second
465 " time.
466 sleep 2
467
468 let prev_error = v:errors[0]
469 let v:errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100470 let g:run_nr += 1
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100471
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200472 call RunTheTest(g:testfunc)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100473
474 if len(v:errors) == 0
475 " Test passed on rerun.
476 break
477 endif
478 endwhile
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100479 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100480
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200481 call AfterTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100482endfor
483
Bram Moolenaar42205552017-03-18 19:42:22 +0100484call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100485
486" vim: shiftwidth=2 sts=2 expandtab