blob: 28e23c0d9e0ee21d156ac69e1ebb6c8fc67f5fe6 [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"
Bram Moolenaardae453f2021-08-07 17:20:16 +020016" If the environment variable $TEST_SKIP_PAT is set then test functions
17" matching this pattern will be skipped. It's the opposite of $TEST_FILTER.
18"
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020019" While working on a test you can make $TEST_NO_RETRY non-empty to not retry:
20" export TEST_NO_RETRY=yes
21"
Bram Moolenaarce436de2020-03-21 15:17:20 +010022" To ignore failure for tests that are known to fail in a certain environment,
23" set $TEST_MAY_FAIL to a comma separated list of function names. E.g. for
24" sh/bash:
25" export TEST_MAY_FAIL=Test_channel_one,Test_channel_other
26" The failure report will then not be included in the test.log file and
27" "make test" will not fail.
28"
Bram Moolenaar43345542015-11-29 17:35:35 +010029" The test script may contain anything, only functions that start with
30" "Test_" are special. These will be invoked and should contain assert
31" functions. See test_assert.vim for an example.
32"
33" It is possible to source other files that contain "Test_" functions. This
34" can speed up testing, since Vim does not need to restart. But be careful
35" that the tests do not interfere with each other.
36"
37" If an error cannot be detected properly with an assert function add the
38" error to the v:errors list:
39" call add(v:errors, 'test foo failed: Cannot find xyz')
40"
41" If preparation for each Test_ function is needed, define a SetUp function.
42" It will be called before each Test_ function.
43"
44" If cleanup after each Test_ function is needed, define a TearDown function.
45" It will be called after each Test_ function.
Bram Moolenaar00af60b2016-02-13 14:06:14 +010046"
47" When debugging a test it can be useful to add messages to v:errors:
Bram Moolenaar8ad16da2019-01-06 15:29:57 +010048" call add(v:errors, "this happened")
Bram Moolenaar00af60b2016-02-13 14:06:14 +010049
Bram Moolenaar43345542015-11-29 17:35:35 +010050
51" Without the +eval feature we can't run these tests, bail out.
Bram Moolenaarb96a32e2020-08-13 18:59:55 +020052silent! while 0
53 qa!
54silent! endwhile
Bram Moolenaar43345542015-11-29 17:35:35 +010055
Bram Moolenaar18aa13d2020-07-11 13:09:36 +020056" In the GUI we can always change the screen size.
57if has('gui_running')
58 set columns=80 lines=25
59endif
60
Bram Moolenaar43345542015-11-29 17:35:35 +010061" Check that the screen size is at least 24 x 80 characters.
62if &lines < 24 || &columns < 80
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020063 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 +010064 echoerr error
65 split test.log
66 $put =error
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020067 write
68 split messages
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020069 call append(line('$'), '')
70 call append(line('$'), 'From ' . expand('%') . ':')
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020071 call append(line('$'), error)
72 write
73 qa!
Bram Moolenaar43345542015-11-29 17:35:35 +010074endif
75
Bram Moolenaar75ee5442019-06-06 18:05:25 +020076if has('reltime')
77 let s:start_time = reltime()
78endif
79
Bram Moolenaar89b10422016-07-12 22:51:22 +020080" Common with all tests on all systems.
81source setup.vim
82
Bram Moolenaarc0662462015-12-30 15:49:05 +010083" For consistency run all tests with 'nocompatible' set.
84" This also enables use of line continuation.
85set nocp viminfo+=nviminfo
86
Bram Moolenaar30276f22019-01-24 17:59:39 +010087" Use utf-8 by default, instead of whatever the system default happens to be.
Bram Moolenaared79d1e2019-02-22 14:38:58 +010088" Individual tests can overrule this at the top of the file and use
89" g:orig_encoding if needed.
90let g:orig_encoding = &encoding
Bram Moolenaar30276f22019-01-24 17:59:39 +010091set encoding=utf-8
Bram Moolenaarac105ed2016-07-21 20:33:32 +020092
Bram Moolenaard8f27b32018-10-07 15:42:07 +020093" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for
94" the test_name.vim file itself. Replace it here with a more restrictive one,
95" so we still catch mistakes.
Christian Brabandt4b2c8042021-11-03 22:31:44 +000096if has("win32")
97 " replace any '/' directory separators by '\\'
98 let s:test_script_fname = substitute(expand('%'), '/', '\\', 'g')
99else
100 let s:test_script_fname = expand('%')
101endif
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200102au! SwapExists * call HandleSwapExists()
103func HandleSwapExists()
Bram Moolenaar8ce4b7e2020-08-07 18:12:18 +0200104 if exists('g:ignoreSwapExists')
105 return
106 endif
Bram Moolenaarb073da82019-07-13 14:47:26 +0200107 " Ignore finding a swap file for the test script (the user might be
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200108 " editing it and do ":make test_name") and the output file.
Bram Moolenaarb073da82019-07-13 14:47:26 +0200109 " Report finding another swap file and chose 'q' to avoid getting stuck.
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200110 if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname
111 let v:swapchoice = 'e'
Bram Moolenaarb073da82019-07-13 14:47:26 +0200112 else
113 call assert_report('Unexpected swap file: ' .. v:swapname)
114 let v:swapchoice = 'q'
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200115 endif
116endfunc
117
Bram Moolenaar7a073542017-02-01 23:17:36 +0100118" Avoid stopping at the "hit enter" prompt
119set nomore
120
Bram Moolenaarc0662462015-12-30 15:49:05 +0100121" Output all messages in English.
122lang mess C
123
Bram Moolenaar10e1d012020-07-18 22:03:11 +0200124" suppress menu translation
125if has('gui_running') && exists('did_install_default_menus')
126 source $VIMRUNTIME/delmenu.vim
127 set langmenu=none
128 source $VIMRUNTIME/menu.vim
129endif
130
Bram Moolenaarf60b7962016-01-16 22:47:23 +0100131" Always use forward slashes.
132set shellslash
133
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100134let s:srcdir = expand('%:p:h:h')
135
Bram Moolenaar2690b5a2020-07-22 18:14:58 +0200136if has('win32')
137 " avoid prompt that is long or contains a line break
138 let $PROMPT = '$P$G'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200139 " On MS-Windows t_md and t_me are Vim specific escape sequences.
140 let s:t_bold = "\x1b[1m"
141 let s:t_normal = "\x1b[m"
142else
143 let s:t_bold = &t_md
144 let s:t_normal = &t_me
Bram Moolenaar2690b5a2020-07-22 18:14:58 +0200145endif
146
Bram Moolenaar4b2ce122020-11-21 21:41:41 +0100147if has('mac')
Dominique Pelle923dce22021-11-21 11:36:04 +0000148 " In macOS, when starting a shell in a terminal, a bash deprecation warning
Bram Moolenaar4b2ce122020-11-21 21:41:41 +0100149 " message is displayed. This breaks the terminal test. Disable the warning
150 " message.
151 let $BASH_SILENCE_DEPRECATION_WARNING = 1
152endif
153
Bram Moolenaar8e8df252016-05-25 21:23:21 +0200154" Prepare for calling test_garbagecollect_now().
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200155let v:testing = 1
156
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100157" Support function: get the alloc ID by name.
158function GetAllocId(name)
159 exe 'split ' . s:srcdir . '/alloc.h'
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100160 let top = search('typedef enum')
161 if top == 0
162 call add(v:errors, 'typedef not found in alloc.h')
163 endif
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100164 let lnum = search('aid_' . a:name . ',')
165 if lnum == 0
166 call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
167 endif
168 close
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100169 return lnum - top - 1
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100170endfunc
171
Bram Moolenaar42205552017-03-18 19:42:22 +0100172func RunTheTest(test)
Bram Moolenaar4c868302021-03-22 16:19:45 +0100173 echoconsole 'Executing ' . a:test
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200174 if has('reltime')
175 let func_start = reltime()
176 endif
Bram Moolenaare5f2a072017-02-01 22:31:49 +0100177
178 " Avoid stopping at the "hit enter" prompt
179 set nomore
180
181 " Avoid a three second wait when a message is about to be overwritten by the
182 " mode message.
183 set noshowmode
184
Bram Moolenaareb992cb2017-03-09 18:20:16 +0100185 " Clear any overrides.
186 call test_override('ALL', 0)
187
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200188 " Some tests wipe out buffers. To be consistent, always wipe out all
189 " buffers.
190 %bwipe!
191
Bram Moolenaar209d3872017-11-16 21:52:51 +0100192 " The test may change the current directory. Save and restore the
193 " directory after executing the test.
194 let save_cwd = getcwd()
195
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100196 if exists("*SetUp")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100197 try
198 call SetUp()
199 catch
200 call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
201 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100202 endif
203
Bram Moolenaarf204e052017-10-26 17:14:01 +0200204 if a:test =~ 'Test_nocatch_'
205 " Function handles errors itself. This avoids skipping commands after the
206 " error.
Bram Moolenaar776b9542021-03-10 22:27:48 +0100207 let g:skipped_reason = ''
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100208 exe 'call ' . a:test
Bram Moolenaar776b9542021-03-10 22:27:48 +0100209 if g:skipped_reason != ''
210 call add(s:messages, ' Skipped')
211 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . g:skipped_reason)
212 endif
Bram Moolenaarf204e052017-10-26 17:14:01 +0200213 else
214 try
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200215 au VimLeavePre * call EarlyExit(g:testfunc)
Bram Moolenaarf204e052017-10-26 17:14:01 +0200216 exe 'call ' . a:test
Bram Moolenaar89036762018-06-12 14:58:39 +0200217 au! VimLeavePre
Bram Moolenaarf204e052017-10-26 17:14:01 +0200218 catch /^\cskipped/
219 call add(s:messages, ' Skipped')
220 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
221 catch
222 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
223 endtry
224 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100225
Bram Moolenaar8ad16da2019-01-06 15:29:57 +0100226 " In case 'insertmode' was set and something went wrong, make sure it is
227 " reset to avoid trouble with anything else.
228 set noinsertmode
229
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100230 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100231 try
232 call TearDown()
233 catch
234 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
235 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100236 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200237
Bram Moolenaar0b5dc642019-08-11 22:56:15 +0200238 " Clear any autocommands and put back the catch-all for SwapExists.
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200239 au!
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200240 au SwapExists * call HandleSwapExists()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200241
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200242 " Check for and close any stray popup windows.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100243 if has('popupwin')
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200244 call assert_equal([], popup_list())
Bram Moolenaar03a9f842020-05-13 13:40:16 +0200245 call popup_clear(1)
Bram Moolenaarae943152019-06-16 22:54:14 +0200246 endif
247
Bram Moolenaarce11de82017-10-26 22:00:00 +0200248 " Close any extra tab pages and windows and make the current one not modified.
249 while tabpagenr('$') > 1
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200250 let winid = win_getid()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200251 quit!
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200252 if winid == win_getid()
253 echoerr 'Could not quit window'
254 break
255 endif
Bram Moolenaarce11de82017-10-26 22:00:00 +0200256 endwhile
257
Bram Moolenaar358308d2016-08-24 21:21:26 +0200258 while 1
259 let wincount = winnr('$')
260 if wincount == 1
261 break
262 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200263 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200264 if wincount == winnr('$')
265 " Did not manage to close a window.
266 only!
267 break
268 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200269 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100270
271 exe 'cd ' . save_cwd
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200272
273 let message = 'Executed ' . a:test
274 if has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200275 let message ..= repeat(' ', 50 - len(message))
276 let time = reltime(func_start)
277 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200278 let message = s:t_bold .. message
Bram Moolenaar8d943792020-06-21 20:39:37 +0200279 endif
280 let message ..= ' in ' .. reltimestr(time) .. ' seconds'
281 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200282 let message ..= s:t_normal
Bram Moolenaar8d943792020-06-21 20:39:37 +0200283 endif
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200284 endif
285 call add(s:messages, message)
286 let s:done += 1
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100287endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100288
Bram Moolenaarce436de2020-03-21 15:17:20 +0100289func AfterTheTest(func_name)
Bram Moolenaar42205552017-03-18 19:42:22 +0100290 if len(v:errors) > 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100291 if match(s:may_fail_list, '^' .. a:func_name) >= 0
292 let s:fail_expected += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200293 call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100294 call extend(s:errors_expected, v:errors)
295 else
296 let s:fail += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200297 call add(s:errors, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100298 call extend(s:errors, v:errors)
299 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100300 let v:errors = []
301 endif
302endfunc
303
Bram Moolenaar89036762018-06-12 14:58:39 +0200304func EarlyExit(test)
305 " It's OK for the test we use to test the quit detection.
306 if a:test != 'Test_zz_quit_detected()'
307 call add(v:errors, 'Test caused Vim to exit: ' . a:test)
308 endif
309
310 call FinishTesting()
311endfunc
312
Bram Moolenaar42205552017-03-18 19:42:22 +0100313" This function can be called by a test if it wants to abort testing.
314func FinishTesting()
Bram Moolenaarce436de2020-03-21 15:17:20 +0100315 call AfterTheTest('')
Bram Moolenaar42205552017-03-18 19:42:22 +0100316
317 " Don't write viminfo on exit.
318 set viminfo=
319
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200320 " Clean up files created by setup.vim
321 call delete('XfakeHOME', 'rf')
322
Bram Moolenaarce436de2020-03-21 15:17:20 +0100323 if s:fail == 0 && s:fail_expected == 0
Bram Moolenaar42205552017-03-18 19:42:22 +0100324 " Success, create the .res file so that make knows it's done.
325 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
326 write
327 endif
328
329 if len(s:errors) > 0
330 " Append errors to test.log
331 split test.log
332 call append(line('$'), '')
333 call append(line('$'), 'From ' . g:testname . ':')
334 call append(line('$'), s:errors)
335 write
336 endif
337
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200338 if s:done == 0
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200339 if s:filtered > 0
Bram Moolenaardae453f2021-08-07 17:20:16 +0200340 if $TEST_FILTER != ''
341 let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
342 else
343 let message = "ALL tests match $TEST_SKIP_PAT: '" .. $TEST_SKIP_PAT .. "'"
344 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200345 else
346 let message = 'NO tests executed'
347 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200348 else
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200349 if s:filtered > 0
Bram Moolenaardae453f2021-08-07 17:20:16 +0200350 call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER and $TEST_SKIP_PAT")
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200351 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200352 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
353 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200354 if s:done > 0 && has('reltime')
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200355 let message = s:t_bold .. message .. repeat(' ', 40 - len(message))
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200356 let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200357 let message ..= s:t_normal
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200358 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100359 echo message
360 call add(s:messages, message)
361 if s:fail > 0
362 let message = s:fail . ' FAILED:'
363 echo message
364 call add(s:messages, message)
365 call extend(s:messages, s:errors)
366 endif
Bram Moolenaarce436de2020-03-21 15:17:20 +0100367 if s:fail_expected > 0
368 let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
369 echo message
370 call add(s:messages, message)
371 call extend(s:messages, s:errors_expected)
372 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100373
374 " Add SKIPPED messages
375 call extend(s:messages, s:skipped)
376
377 " Append messages to the file "messages"
378 split messages
379 call append(line('$'), '')
380 call append(line('$'), 'From ' . g:testname . ':')
381 call append(line('$'), s:messages)
382 write
383
384 qall!
385endfunc
386
Bram Moolenaar43345542015-11-29 17:35:35 +0100387" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100388" navigates away. g:testname can be used by the tests.
389let g:testname = expand('%')
390let s:done = 0
391let s:fail = 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100392let s:fail_expected = 0
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100393let s:errors = []
Bram Moolenaarce436de2020-03-21 15:17:20 +0100394let s:errors_expected = []
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100395let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200396let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100397if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaarce436de2020-03-21 15:17:20 +0100398 " this test has intentional errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100399 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100400else
401 try
402 source %
Bram Moolenaar9c0cec62019-06-06 13:38:15 +0200403 catch /^\cskipped/
404 call add(s:messages, ' Skipped')
405 call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
Bram Moolenaara2cce862016-01-02 19:50:04 +0100406 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100407 let s:fail += 1
408 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100409 endtry
410endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100411
412" Locate Test_ functions and execute them.
413redir @q
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100414silent function /^Test_
Bram Moolenaar43345542015-11-29 17:35:35 +0100415redir END
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +0100416let s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g'))
Bram Moolenaar43345542015-11-29 17:35:35 +0100417
Bram Moolenaarbefb3662016-02-20 14:41:40 +0100418" If there is an extra argument filter the function names against it.
419if argc() > 1
420 let s:tests = filter(s:tests, 'v:val =~ argv(1)')
421endif
422
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200423" If the environment variable $TEST_FILTER is set then filter the function
424" names against it.
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200425let s:filtered = 0
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200426if $TEST_FILTER != ''
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200427 let s:filtered = len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200428 let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER')
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200429 let s:filtered -= len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200430endif
431
Bram Moolenaarce436de2020-03-21 15:17:20 +0100432let s:may_fail_list = []
433if $TEST_MAY_FAIL != ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200434 " Split the list at commas and add () to make it match g:testfunc.
Bram Moolenaarce436de2020-03-21 15:17:20 +0100435 let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'})
436endif
437
Bram Moolenaarcfc0a352016-01-09 20:23:00 +0100438" Execute the tests in alphabetical order.
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200439for g:testfunc in sort(s:tests)
Bram Moolenaardae453f2021-08-07 17:20:16 +0200440 if $TEST_SKIP_PAT != '' && g:testfunc =~ $TEST_SKIP_PAT
441 call add(s:messages, g:testfunc .. ' matches $TEST_SKIP_PAT')
442 let s:filtered += 1
443 continue
444 endif
445
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200446 " Silence, please!
447 set belloff=all
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100448 let prev_error = ''
449 let total_errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100450 let g:run_nr = 1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200451
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200452 " A test can set g:test_is_flaky to retry running the test.
453 let g:test_is_flaky = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100454
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200455 call RunTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100456
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100457 " Repeat a flaky test. Give up when:
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200458 " - $TEST_NO_RETRY is not empty
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100459 " - it fails again with the same message
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200460 " - it fails five times (with a different message)
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100461 if len(v:errors) > 0
Bram Moolenaar622b3562020-07-27 20:02:41 +0200462 \ && $TEST_NO_RETRY == ''
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100463 \ && g:test_is_flaky
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100464 while 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200465 call add(s:messages, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100466 call extend(s:messages, v:errors)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100467
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100468 call add(total_errors, 'Run ' . g:run_nr . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100469 call extend(total_errors, v:errors)
Bram Moolenaar55058602017-11-21 15:14:51 +0100470
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100471 if g:run_nr == 5 || prev_error == v:errors[0]
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100472 call add(total_errors, 'Flaky test failed too often, giving up')
473 let v:errors = total_errors
474 break
475 endif
476
477 call add(s:messages, 'Flaky test failed, running it again')
478
479 " Flakiness is often caused by the system being very busy. Sleep a
480 " couple of seconds to have a higher chance of succeeding the second
481 " time.
482 sleep 2
483
484 let prev_error = v:errors[0]
485 let v:errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100486 let g:run_nr += 1
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100487
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200488 call RunTheTest(g:testfunc)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100489
490 if len(v:errors) == 0
491 " Test passed on rerun.
492 break
493 endif
494 endwhile
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100495 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100496
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200497 call AfterTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100498endfor
499
Bram Moolenaar42205552017-03-18 19:42:22 +0100500call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100501
502" vim: shiftwidth=2 sts=2 expandtab