blob: bb0325fe89e2c6487cd3c32b84ba4535e7c8171b [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
Bakudankun29f3a452021-12-11 12:28:08 +000080" Always use forward slashes.
81set shellslash
82
Bram Moolenaar89b10422016-07-12 22:51:22 +020083" Common with all tests on all systems.
84source setup.vim
85
Bram Moolenaarc0662462015-12-30 15:49:05 +010086" For consistency run all tests with 'nocompatible' set.
87" This also enables use of line continuation.
88set nocp viminfo+=nviminfo
89
Bram Moolenaar30276f22019-01-24 17:59:39 +010090" Use utf-8 by default, instead of whatever the system default happens to be.
Bram Moolenaared79d1e2019-02-22 14:38:58 +010091" Individual tests can overrule this at the top of the file and use
92" g:orig_encoding if needed.
93let g:orig_encoding = &encoding
Bram Moolenaar30276f22019-01-24 17:59:39 +010094set encoding=utf-8
Bram Moolenaarac105ed2016-07-21 20:33:32 +020095
Bram Moolenaard8f27b32018-10-07 15:42:07 +020096" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for
97" the test_name.vim file itself. Replace it here with a more restrictive one,
98" so we still catch mistakes.
Christian Brabandt4b2c8042021-11-03 22:31:44 +000099if has("win32")
100 " replace any '/' directory separators by '\\'
101 let s:test_script_fname = substitute(expand('%'), '/', '\\', 'g')
102else
103 let s:test_script_fname = expand('%')
104endif
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200105au! SwapExists * call HandleSwapExists()
106func HandleSwapExists()
Bram Moolenaar8ce4b7e2020-08-07 18:12:18 +0200107 if exists('g:ignoreSwapExists')
108 return
109 endif
Bram Moolenaarb073da82019-07-13 14:47:26 +0200110 " Ignore finding a swap file for the test script (the user might be
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200111 " editing it and do ":make test_name") and the output file.
Bram Moolenaarb073da82019-07-13 14:47:26 +0200112 " Report finding another swap file and chose 'q' to avoid getting stuck.
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200113 if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname
114 let v:swapchoice = 'e'
Bram Moolenaarb073da82019-07-13 14:47:26 +0200115 else
116 call assert_report('Unexpected swap file: ' .. v:swapname)
117 let v:swapchoice = 'q'
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200118 endif
119endfunc
120
Bram Moolenaar7a073542017-02-01 23:17:36 +0100121" Avoid stopping at the "hit enter" prompt
122set nomore
123
Bram Moolenaarc0662462015-12-30 15:49:05 +0100124" Output all messages in English.
125lang mess C
126
Bram Moolenaar10e1d012020-07-18 22:03:11 +0200127" suppress menu translation
128if has('gui_running') && exists('did_install_default_menus')
129 source $VIMRUNTIME/delmenu.vim
130 set langmenu=none
131 source $VIMRUNTIME/menu.vim
132endif
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 Moolenaarfa4873c2022-06-30 22:13:59 +0100157" By default, copy each buffer line into allocated memory, so that valgrind can
158" detect accessing memory before and after it.
159call test_override('alloc_lines', 1)
160
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100161" Support function: get the alloc ID by name.
162function GetAllocId(name)
163 exe 'split ' . s:srcdir . '/alloc.h'
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100164 let top = search('typedef enum')
165 if top == 0
166 call add(v:errors, 'typedef not found in alloc.h')
167 endif
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100168 let lnum = search('aid_' . a:name . ',')
169 if lnum == 0
170 call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
171 endif
172 close
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100173 return lnum - top - 1
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100174endfunc
175
Bram Moolenaardaaa3d92022-09-22 15:13:00 +0100176let g:func_start = reltime()
177
Bram Moolenaar42205552017-03-18 19:42:22 +0100178func RunTheTest(test)
Bram Moolenaardaaa3d92022-09-22 15:13:00 +0100179 let prefix = ''
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200180 if has('reltime')
Bram Moolenaardaaa3d92022-09-22 15:13:00 +0100181 let prefix = 'took ' .. reltimestr(reltime(g:func_start)) .. '; now '
182 let g:func_start = reltime()
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200183 endif
Bram Moolenaardaaa3d92022-09-22 15:13:00 +0100184 echoconsole prefix .. 'Executing ' .. a:test
Bram Moolenaare5f2a072017-02-01 22:31:49 +0100185
186 " Avoid stopping at the "hit enter" prompt
187 set nomore
188
189 " Avoid a three second wait when a message is about to be overwritten by the
190 " mode message.
191 set noshowmode
192
Bram Moolenaarfa4873c2022-06-30 22:13:59 +0100193 " Clear any overrides, except "alloc_lines".
Bram Moolenaareb992cb2017-03-09 18:20:16 +0100194 call test_override('ALL', 0)
195
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200196 " Some tests wipe out buffers. To be consistent, always wipe out all
197 " buffers.
198 %bwipe!
199
Bram Moolenaar209d3872017-11-16 21:52:51 +0100200 " The test may change the current directory. Save and restore the
201 " directory after executing the test.
202 let save_cwd = getcwd()
203
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100204 if exists("*SetUp")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100205 try
206 call SetUp()
207 catch
208 call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
209 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100210 endif
211
Bram Moolenaar8bea1712022-06-15 20:49:35 +0100212 au VimLeavePre * call EarlyExit(g:testfunc)
Bram Moolenaarf204e052017-10-26 17:14:01 +0200213 if a:test =~ 'Test_nocatch_'
214 " Function handles errors itself. This avoids skipping commands after the
215 " error.
Bram Moolenaar776b9542021-03-10 22:27:48 +0100216 let g:skipped_reason = ''
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100217 exe 'call ' . a:test
Bram Moolenaar776b9542021-03-10 22:27:48 +0100218 if g:skipped_reason != ''
219 call add(s:messages, ' Skipped')
220 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . g:skipped_reason)
221 endif
Bram Moolenaarf204e052017-10-26 17:14:01 +0200222 else
223 try
224 exe 'call ' . a:test
225 catch /^\cskipped/
226 call add(s:messages, ' Skipped')
227 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
228 catch
229 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
230 endtry
231 endif
Bram Moolenaar8bea1712022-06-15 20:49:35 +0100232 au! VimLeavePre
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100233
Bram Moolenaara22c56a2022-09-20 15:10:31 +0100234 if a:test =~ '_terminal_'
235 " Terminal tests sometimes hang, give extra information
236 echoconsole 'After executing ' .. a:test
237 endif
238
Bram Moolenaar8ad16da2019-01-06 15:29:57 +0100239 " In case 'insertmode' was set and something went wrong, make sure it is
240 " reset to avoid trouble with anything else.
241 set noinsertmode
242
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100243 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100244 try
245 call TearDown()
246 catch
247 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
248 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100249 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200250
Bram Moolenaar0b5dc642019-08-11 22:56:15 +0200251 " Clear any autocommands and put back the catch-all for SwapExists.
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200252 au!
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200253 au SwapExists * call HandleSwapExists()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200254
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200255 " Check for and close any stray popup windows.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100256 if has('popupwin')
Bram Moolenaarf05a1e52022-08-02 11:48:53 +0100257 call assert_equal([], popup_list(), 'Popup is still present')
Bram Moolenaar03a9f842020-05-13 13:40:16 +0200258 call popup_clear(1)
Bram Moolenaarae943152019-06-16 22:54:14 +0200259 endif
260
Bram Moolenaar2d12c252022-06-13 21:42:45 +0100261 if filereadable('guidialogfile')
Bram Moolenaar217ea512022-06-14 17:13:59 +0100262 call add(v:errors, "Unexpected dialog: " .. readfile('guidialogfile')->join('<NL>'))
Bram Moolenaar2d12c252022-06-13 21:42:45 +0100263 call delete('guidialogfile')
264 endif
265
Bram Moolenaarce11de82017-10-26 22:00:00 +0200266 " Close any extra tab pages and windows and make the current one not modified.
267 while tabpagenr('$') > 1
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200268 let winid = win_getid()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200269 quit!
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200270 if winid == win_getid()
271 echoerr 'Could not quit window'
272 break
273 endif
Bram Moolenaarce11de82017-10-26 22:00:00 +0200274 endwhile
275
Bram Moolenaar358308d2016-08-24 21:21:26 +0200276 while 1
277 let wincount = winnr('$')
278 if wincount == 1
279 break
280 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200281 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200282 if wincount == winnr('$')
283 " Did not manage to close a window.
284 only!
285 break
286 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200287 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100288
289 exe 'cd ' . save_cwd
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200290
Bram Moolenaara22c56a2022-09-20 15:10:31 +0100291 if a:test =~ '_terminal_'
292 " Terminal tests sometimes hang, give extra information
293 echoconsole 'Finished ' . a:test
294 endif
295
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200296 let message = 'Executed ' . a:test
297 if has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200298 let message ..= repeat(' ', 50 - len(message))
Bram Moolenaardaaa3d92022-09-22 15:13:00 +0100299 let time = reltime(g:func_start)
Bram Moolenaar73e28dc2022-09-17 21:08:33 +0100300 if reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200301 let message = s:t_bold .. message
Bram Moolenaar8d943792020-06-21 20:39:37 +0200302 endif
303 let message ..= ' in ' .. reltimestr(time) .. ' seconds'
Bram Moolenaar73e28dc2022-09-17 21:08:33 +0100304 if reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200305 let message ..= s:t_normal
Bram Moolenaar8d943792020-06-21 20:39:37 +0200306 endif
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200307 endif
308 call add(s:messages, message)
309 let s:done += 1
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100310endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100311
Bram Moolenaarce436de2020-03-21 15:17:20 +0100312func AfterTheTest(func_name)
Bram Moolenaar42205552017-03-18 19:42:22 +0100313 if len(v:errors) > 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100314 if match(s:may_fail_list, '^' .. a:func_name) >= 0
315 let s:fail_expected += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200316 call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100317 call extend(s:errors_expected, v:errors)
318 else
319 let s:fail += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200320 call add(s:errors, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100321 call extend(s:errors, v:errors)
322 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100323 let v:errors = []
324 endif
325endfunc
326
Bram Moolenaar89036762018-06-12 14:58:39 +0200327func EarlyExit(test)
328 " It's OK for the test we use to test the quit detection.
329 if a:test != 'Test_zz_quit_detected()'
Bram Moolenaar1c67f3a2021-12-30 13:32:09 +0000330 call add(v:errors, v:errmsg)
Bram Moolenaar89036762018-06-12 14:58:39 +0200331 call add(v:errors, 'Test caused Vim to exit: ' . a:test)
332 endif
333
334 call FinishTesting()
335endfunc
336
Bram Moolenaar42205552017-03-18 19:42:22 +0100337" This function can be called by a test if it wants to abort testing.
338func FinishTesting()
Bram Moolenaarce436de2020-03-21 15:17:20 +0100339 call AfterTheTest('')
Bram Moolenaar42205552017-03-18 19:42:22 +0100340
341 " Don't write viminfo on exit.
342 set viminfo=
343
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200344 " Clean up files created by setup.vim
345 call delete('XfakeHOME', 'rf')
346
Bram Moolenaarce436de2020-03-21 15:17:20 +0100347 if s:fail == 0 && s:fail_expected == 0
Bram Moolenaar42205552017-03-18 19:42:22 +0100348 " Success, create the .res file so that make knows it's done.
349 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
350 write
351 endif
352
353 if len(s:errors) > 0
354 " Append errors to test.log
355 split test.log
356 call append(line('$'), '')
357 call append(line('$'), 'From ' . g:testname . ':')
358 call append(line('$'), s:errors)
359 write
360 endif
361
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200362 if s:done == 0
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200363 if s:filtered > 0
Bram Moolenaardae453f2021-08-07 17:20:16 +0200364 if $TEST_FILTER != ''
365 let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
366 else
367 let message = "ALL tests match $TEST_SKIP_PAT: '" .. $TEST_SKIP_PAT .. "'"
368 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200369 else
370 let message = 'NO tests executed'
371 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200372 else
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200373 if s:filtered > 0
Bram Moolenaardae453f2021-08-07 17:20:16 +0200374 call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER and $TEST_SKIP_PAT")
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200375 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200376 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
377 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200378 if s:done > 0 && has('reltime')
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200379 let message = s:t_bold .. message .. repeat(' ', 40 - len(message))
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200380 let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200381 let message ..= s:t_normal
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200382 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100383 echo message
384 call add(s:messages, message)
385 if s:fail > 0
386 let message = s:fail . ' FAILED:'
387 echo message
388 call add(s:messages, message)
389 call extend(s:messages, s:errors)
390 endif
Bram Moolenaarce436de2020-03-21 15:17:20 +0100391 if s:fail_expected > 0
392 let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
393 echo message
394 call add(s:messages, message)
395 call extend(s:messages, s:errors_expected)
396 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100397
398 " Add SKIPPED messages
399 call extend(s:messages, s:skipped)
400
401 " Append messages to the file "messages"
402 split messages
403 call append(line('$'), '')
404 call append(line('$'), 'From ' . g:testname . ':')
405 call append(line('$'), s:messages)
406 write
407
408 qall!
409endfunc
410
Bram Moolenaar43345542015-11-29 17:35:35 +0100411" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100412" navigates away. g:testname can be used by the tests.
413let g:testname = expand('%')
414let s:done = 0
415let s:fail = 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100416let s:fail_expected = 0
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100417let s:errors = []
Bram Moolenaarce436de2020-03-21 15:17:20 +0100418let s:errors_expected = []
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100419let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200420let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100421if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaarce436de2020-03-21 15:17:20 +0100422 " this test has intentional errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100423 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100424else
425 try
426 source %
Bram Moolenaar9c0cec62019-06-06 13:38:15 +0200427 catch /^\cskipped/
428 call add(s:messages, ' Skipped')
429 call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
Bram Moolenaara2cce862016-01-02 19:50:04 +0100430 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100431 let s:fail += 1
432 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100433 endtry
434endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100435
Bram Moolenaar7e0be3e2022-03-20 13:40:41 +0000436" Delete the .res file, it may change behavior for completion
437call delete(fnamemodify(g:testname, ':r') .. '.res')
438
Bram Moolenaar43345542015-11-29 17:35:35 +0100439" Locate Test_ functions and execute them.
440redir @q
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100441silent function /^Test_
Bram Moolenaar43345542015-11-29 17:35:35 +0100442redir END
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +0100443let s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g'))
Bram Moolenaar43345542015-11-29 17:35:35 +0100444
Bram Moolenaarbefb3662016-02-20 14:41:40 +0100445" If there is an extra argument filter the function names against it.
446if argc() > 1
447 let s:tests = filter(s:tests, 'v:val =~ argv(1)')
448endif
449
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200450" If the environment variable $TEST_FILTER is set then filter the function
451" names against it.
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200452let s:filtered = 0
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200453if $TEST_FILTER != ''
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200454 let s:filtered = len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200455 let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER')
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200456 let s:filtered -= len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200457endif
458
Bram Moolenaarce436de2020-03-21 15:17:20 +0100459let s:may_fail_list = []
460if $TEST_MAY_FAIL != ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200461 " Split the list at commas and add () to make it match g:testfunc.
Bram Moolenaarce436de2020-03-21 15:17:20 +0100462 let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'})
463endif
464
Bram Moolenaarcfc0a352016-01-09 20:23:00 +0100465" Execute the tests in alphabetical order.
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200466for g:testfunc in sort(s:tests)
Bram Moolenaardae453f2021-08-07 17:20:16 +0200467 if $TEST_SKIP_PAT != '' && g:testfunc =~ $TEST_SKIP_PAT
468 call add(s:messages, g:testfunc .. ' matches $TEST_SKIP_PAT')
469 let s:filtered += 1
470 continue
471 endif
472
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200473 " Silence, please!
474 set belloff=all
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100475 let prev_error = ''
476 let total_errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100477 let g:run_nr = 1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200478
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200479 " A test can set g:test_is_flaky to retry running the test.
480 let g:test_is_flaky = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100481
Bram Moolenaar5fbbec12022-09-03 22:08:11 +0100482 let starttime = strftime("%H:%M:%S")
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200483 call RunTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100484
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100485 " Repeat a flaky test. Give up when:
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200486 " - $TEST_NO_RETRY is not empty
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100487 " - it fails again with the same message
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200488 " - it fails five times (with a different message)
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100489 if len(v:errors) > 0
Bram Moolenaar622b3562020-07-27 20:02:41 +0200490 \ && $TEST_NO_RETRY == ''
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100491 \ && g:test_is_flaky
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100492 while 1
Bram Moolenaar06d32a02022-09-03 13:58:47 +0100493 call add(s:messages, 'Found errors in ' .. g:testfunc .. ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100494 call extend(s:messages, v:errors)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100495
Bram Moolenaar65258d32022-09-09 15:09:59 +0100496 let endtime = strftime("%H:%M:%S")
497 call add(total_errors, $'Run {g:run_nr}, {starttime} - {endtime}:')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100498 call extend(total_errors, v:errors)
Bram Moolenaar55058602017-11-21 15:14:51 +0100499
Bram Moolenaar96ba25a2022-07-04 17:34:33 +0100500 if g:run_nr >= 5 || prev_error == v:errors[0]
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100501 call add(total_errors, 'Flaky test failed too often, giving up')
502 let v:errors = total_errors
503 break
504 endif
505
506 call add(s:messages, 'Flaky test failed, running it again')
507
508 " Flakiness is often caused by the system being very busy. Sleep a
509 " couple of seconds to have a higher chance of succeeding the second
510 " time.
511 sleep 2
512
513 let prev_error = v:errors[0]
514 let v:errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100515 let g:run_nr += 1
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100516
Bram Moolenaar5fbbec12022-09-03 22:08:11 +0100517 let starttime = strftime("%H:%M:%S")
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200518 call RunTheTest(g:testfunc)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100519
520 if len(v:errors) == 0
521 " Test passed on rerun.
522 break
523 endif
524 endwhile
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100525 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100526
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200527 call AfterTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100528endfor
529
Bram Moolenaar42205552017-03-18 19:42:22 +0100530call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100531
532" vim: shiftwidth=2 sts=2 expandtab