blob: fdf99ce1afc1ff9c550327ac9eefc39552183867 [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
48" Check that the screen size is at least 24 x 80 characters.
49if &lines < 24 || &columns < 80
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020050 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 +010051 echoerr error
52 split test.log
53 $put =error
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020054 write
55 split messages
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020056 call append(line('$'), '')
57 call append(line('$'), 'From ' . expand('%') . ':')
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020058 call append(line('$'), error)
59 write
60 qa!
Bram Moolenaar43345542015-11-29 17:35:35 +010061endif
62
Bram Moolenaar75ee5442019-06-06 18:05:25 +020063if has('reltime')
64 let s:start_time = reltime()
65endif
66
Bram Moolenaar89b10422016-07-12 22:51:22 +020067" Common with all tests on all systems.
68source setup.vim
69
Bram Moolenaarc0662462015-12-30 15:49:05 +010070" For consistency run all tests with 'nocompatible' set.
71" This also enables use of line continuation.
72set nocp viminfo+=nviminfo
73
Bram Moolenaar30276f22019-01-24 17:59:39 +010074" Use utf-8 by default, instead of whatever the system default happens to be.
Bram Moolenaared79d1e2019-02-22 14:38:58 +010075" Individual tests can overrule this at the top of the file and use
76" g:orig_encoding if needed.
77let g:orig_encoding = &encoding
Bram Moolenaar30276f22019-01-24 17:59:39 +010078set encoding=utf-8
Bram Moolenaarac105ed2016-07-21 20:33:32 +020079
Bram Moolenaard8f27b32018-10-07 15:42:07 +020080" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for
81" the test_name.vim file itself. Replace it here with a more restrictive one,
82" so we still catch mistakes.
83let s:test_script_fname = expand('%')
84au! SwapExists * call HandleSwapExists()
85func HandleSwapExists()
Bram Moolenaarb073da82019-07-13 14:47:26 +020086 " Ignore finding a swap file for the test script (the user might be
Bram Moolenaard8f27b32018-10-07 15:42:07 +020087 " editing it and do ":make test_name") and the output file.
Bram Moolenaarb073da82019-07-13 14:47:26 +020088 " Report finding another swap file and chose 'q' to avoid getting stuck.
Bram Moolenaard8f27b32018-10-07 15:42:07 +020089 if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname
90 let v:swapchoice = 'e'
Bram Moolenaarb073da82019-07-13 14:47:26 +020091 else
92 call assert_report('Unexpected swap file: ' .. v:swapname)
93 let v:swapchoice = 'q'
Bram Moolenaard8f27b32018-10-07 15:42:07 +020094 endif
95endfunc
96
Bram Moolenaar7a073542017-02-01 23:17:36 +010097" Avoid stopping at the "hit enter" prompt
98set nomore
99
Bram Moolenaarc0662462015-12-30 15:49:05 +0100100" Output all messages in English.
101lang mess C
102
Bram Moolenaarf60b7962016-01-16 22:47:23 +0100103" Always use forward slashes.
104set shellslash
105
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100106let s:srcdir = expand('%:p:h:h')
107
Bram Moolenaar8e8df252016-05-25 21:23:21 +0200108" Prepare for calling test_garbagecollect_now().
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200109let v:testing = 1
110
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100111" Support function: get the alloc ID by name.
112function GetAllocId(name)
113 exe 'split ' . s:srcdir . '/alloc.h'
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100114 let top = search('typedef enum')
115 if top == 0
116 call add(v:errors, 'typedef not found in alloc.h')
117 endif
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100118 let lnum = search('aid_' . a:name . ',')
119 if lnum == 0
120 call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
121 endif
122 close
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100123 return lnum - top - 1
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100124endfunc
125
Bram Moolenaar42205552017-03-18 19:42:22 +0100126func RunTheTest(test)
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100127 echo 'Executing ' . a:test
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200128 if has('reltime')
129 let func_start = reltime()
130 endif
Bram Moolenaare5f2a072017-02-01 22:31:49 +0100131
132 " Avoid stopping at the "hit enter" prompt
133 set nomore
134
135 " Avoid a three second wait when a message is about to be overwritten by the
136 " mode message.
137 set noshowmode
138
Bram Moolenaareb992cb2017-03-09 18:20:16 +0100139 " Clear any overrides.
140 call test_override('ALL', 0)
141
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200142 " Some tests wipe out buffers. To be consistent, always wipe out all
143 " buffers.
144 %bwipe!
145
Bram Moolenaar209d3872017-11-16 21:52:51 +0100146 " The test may change the current directory. Save and restore the
147 " directory after executing the test.
148 let save_cwd = getcwd()
149
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100150 if exists("*SetUp")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100151 try
152 call SetUp()
153 catch
154 call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
155 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100156 endif
157
Bram Moolenaarf204e052017-10-26 17:14:01 +0200158 if a:test =~ 'Test_nocatch_'
159 " Function handles errors itself. This avoids skipping commands after the
160 " error.
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100161 exe 'call ' . a:test
Bram Moolenaarf204e052017-10-26 17:14:01 +0200162 else
163 try
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200164 au VimLeavePre * call EarlyExit(g:testfunc)
Bram Moolenaarf204e052017-10-26 17:14:01 +0200165 exe 'call ' . a:test
Bram Moolenaar89036762018-06-12 14:58:39 +0200166 au! VimLeavePre
Bram Moolenaarf204e052017-10-26 17:14:01 +0200167 catch /^\cskipped/
168 call add(s:messages, ' Skipped')
169 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
170 catch
171 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
172 endtry
173 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100174
Bram Moolenaar8ad16da2019-01-06 15:29:57 +0100175 " In case 'insertmode' was set and something went wrong, make sure it is
176 " reset to avoid trouble with anything else.
177 set noinsertmode
178
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100179 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100180 try
181 call TearDown()
182 catch
183 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
184 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100185 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200186
Bram Moolenaar0b5dc642019-08-11 22:56:15 +0200187 " Clear any autocommands and put back the catch-all for SwapExists.
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200188 au!
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200189 au SwapExists * call HandleSwapExists()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200190
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200191 " Check for and close any stray popup windows.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100192 if has('popupwin')
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200193 call assert_equal([], popup_list())
Bram Moolenaar03a9f842020-05-13 13:40:16 +0200194 call popup_clear(1)
Bram Moolenaarae943152019-06-16 22:54:14 +0200195 endif
196
Bram Moolenaarce11de82017-10-26 22:00:00 +0200197 " Close any extra tab pages and windows and make the current one not modified.
198 while tabpagenr('$') > 1
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200199 quit!
Bram Moolenaarce11de82017-10-26 22:00:00 +0200200 endwhile
201
Bram Moolenaar358308d2016-08-24 21:21:26 +0200202 while 1
203 let wincount = winnr('$')
204 if wincount == 1
205 break
206 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200207 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200208 if wincount == winnr('$')
209 " Did not manage to close a window.
210 only!
211 break
212 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200213 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100214
215 exe 'cd ' . save_cwd
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200216
217 let message = 'Executed ' . a:test
218 if has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200219 let message ..= repeat(' ', 50 - len(message))
220 let time = reltime(func_start)
221 if has('float') && reltimefloat(time) > 0.1
222 let message = &t_md .. message
223 endif
224 let message ..= ' in ' .. reltimestr(time) .. ' seconds'
225 if has('float') && reltimefloat(time) > 0.1
226 let message ..= &t_me
227 endif
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200228 endif
229 call add(s:messages, message)
230 let s:done += 1
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100231endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100232
Bram Moolenaarce436de2020-03-21 15:17:20 +0100233func AfterTheTest(func_name)
Bram Moolenaar42205552017-03-18 19:42:22 +0100234 if len(v:errors) > 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100235 if match(s:may_fail_list, '^' .. a:func_name) >= 0
236 let s:fail_expected += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200237 call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100238 call extend(s:errors_expected, v:errors)
239 else
240 let s:fail += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200241 call add(s:errors, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100242 call extend(s:errors, v:errors)
243 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100244 let v:errors = []
245 endif
246endfunc
247
Bram Moolenaar89036762018-06-12 14:58:39 +0200248func EarlyExit(test)
249 " It's OK for the test we use to test the quit detection.
250 if a:test != 'Test_zz_quit_detected()'
251 call add(v:errors, 'Test caused Vim to exit: ' . a:test)
252 endif
253
254 call FinishTesting()
255endfunc
256
Bram Moolenaar42205552017-03-18 19:42:22 +0100257" This function can be called by a test if it wants to abort testing.
258func FinishTesting()
Bram Moolenaarce436de2020-03-21 15:17:20 +0100259 call AfterTheTest('')
Bram Moolenaar42205552017-03-18 19:42:22 +0100260
261 " Don't write viminfo on exit.
262 set viminfo=
263
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200264 " Clean up files created by setup.vim
265 call delete('XfakeHOME', 'rf')
266
Bram Moolenaarce436de2020-03-21 15:17:20 +0100267 if s:fail == 0 && s:fail_expected == 0
Bram Moolenaar42205552017-03-18 19:42:22 +0100268 " Success, create the .res file so that make knows it's done.
269 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
270 write
271 endif
272
273 if len(s:errors) > 0
274 " Append errors to test.log
275 split test.log
276 call append(line('$'), '')
277 call append(line('$'), 'From ' . g:testname . ':')
278 call append(line('$'), s:errors)
279 write
280 endif
281
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200282 if s:done == 0
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200283 if s:filtered > 0
284 let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
285 else
286 let message = 'NO tests executed'
287 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200288 else
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200289 if s:filtered > 0
290 call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER")
291 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200292 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
293 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200294 if s:done > 0 && has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200295 let message = &t_md .. message .. repeat(' ', 40 - len(message))
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200296 let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
Bram Moolenaar8d943792020-06-21 20:39:37 +0200297 let message ..= &t_me
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200298 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100299 echo message
300 call add(s:messages, message)
301 if s:fail > 0
302 let message = s:fail . ' FAILED:'
303 echo message
304 call add(s:messages, message)
305 call extend(s:messages, s:errors)
306 endif
Bram Moolenaarce436de2020-03-21 15:17:20 +0100307 if s:fail_expected > 0
308 let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
309 echo message
310 call add(s:messages, message)
311 call extend(s:messages, s:errors_expected)
312 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100313
314 " Add SKIPPED messages
315 call extend(s:messages, s:skipped)
316
317 " Append messages to the file "messages"
318 split messages
319 call append(line('$'), '')
320 call append(line('$'), 'From ' . g:testname . ':')
321 call append(line('$'), s:messages)
322 write
323
324 qall!
325endfunc
326
Bram Moolenaar43345542015-11-29 17:35:35 +0100327" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100328" navigates away. g:testname can be used by the tests.
329let g:testname = expand('%')
330let s:done = 0
331let s:fail = 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100332let s:fail_expected = 0
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100333let s:errors = []
Bram Moolenaarce436de2020-03-21 15:17:20 +0100334let s:errors_expected = []
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100335let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200336let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100337if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaarce436de2020-03-21 15:17:20 +0100338 " this test has intentional errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100339 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100340else
341 try
342 source %
Bram Moolenaar9c0cec62019-06-06 13:38:15 +0200343 catch /^\cskipped/
344 call add(s:messages, ' Skipped')
345 call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
Bram Moolenaara2cce862016-01-02 19:50:04 +0100346 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100347 let s:fail += 1
348 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100349 endtry
350endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100351
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100352" Names of flaky tests.
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100353let s:flaky_tests = [
Bram Moolenaar0d0c3ca2019-09-25 21:16:15 +0200354 \ 'Test_autocmd_SafeState()',
Bram Moolenaar42205552017-03-18 19:42:22 +0100355 \ 'Test_client_server()',
Bram Moolenaar6fe2eb42017-01-29 21:49:51 +0100356 \ 'Test_close_and_exit_cb()',
Bram Moolenaard80232b2018-12-15 17:46:23 +0100357 \ 'Test_close_output_buffer()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100358 \ 'Test_collapse_buffers()',
Bram Moolenaar65873842018-03-25 17:12:58 +0200359 \ 'Test_cwd()',
Bram Moolenaar218959b2018-11-11 18:51:42 +0100360 \ 'Test_diff_screen()',
Bram Moolenaar0529b3e2017-03-16 22:30:37 +0100361 \ 'Test_exit_callback_interval()',
Bram Moolenaarea94c852019-08-16 21:47:27 +0200362 \ 'Test_map_timeout_with_timer_interrupt()',
Bram Moolenaar1eca6f12017-12-05 14:04:27 +0100363 \ 'Test_out_cb()',
Bram Moolenaarc79d6aa2016-09-25 22:27:37 +0200364 \ 'Test_pipe_through_sort_all()',
Bram Moolenaar4e032e12017-02-01 20:48:13 +0100365 \ 'Test_pipe_through_sort_some()',
Bram Moolenaar44f0bd82019-11-21 18:27:01 +0100366 \ 'Test_popup_and_window_resize()',
Bram Moolenaar0fbff642017-03-05 14:30:52 +0100367 \ 'Test_quoteplus()',
Bram Moolenaar7dd48502017-03-19 20:04:22 +0100368 \ 'Test_quotestar()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100369 \ 'Test_reltime()',
Bram Moolenaar3c8cd4a2019-10-14 22:26:20 +0200370 \ 'Test_state()',
Bram Moolenaarf204e052017-10-26 17:14:01 +0200371 \ 'Test_terminal_composing_unicode()',
Bram Moolenaar38767892019-02-21 18:17:14 +0100372 \ 'Test_terminal_does_not_truncate_last_newlines()',
Bram Moolenaar3615abb2019-02-10 23:04:12 +0100373 \ 'Test_terminal_no_cmd()',
Bram Moolenaar75a60f72017-09-07 22:24:41 +0200374 \ 'Test_terminal_noblock()',
Bram Moolenaar7dd88c52017-11-04 20:46:40 +0100375 \ 'Test_terminal_redir_file()',
Bram Moolenaare219f732019-11-30 15:34:08 +0100376 \ 'Test_termwinscroll()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200377 \ 'Test_timer_oneshot()',
378 \ 'Test_timer_paused()',
379 \ 'Test_timer_repeat_many()',
380 \ 'Test_timer_repeat_three()',
381 \ 'Test_timer_stop_all_in_callback()',
382 \ 'Test_timer_stop_in_callback()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200383 \ 'Test_timer_with_partial_callback()',
Bram Moolenaare1c8c7a2016-09-11 16:48:50 +0200384 \ ]
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100385
Bram Moolenaar43345542015-11-29 17:35:35 +0100386" Locate Test_ functions and execute them.
387redir @q
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100388silent function /^Test_
Bram Moolenaar43345542015-11-29 17:35:35 +0100389redir END
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +0100390let s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g'))
Bram Moolenaar43345542015-11-29 17:35:35 +0100391
Bram Moolenaarbefb3662016-02-20 14:41:40 +0100392" If there is an extra argument filter the function names against it.
393if argc() > 1
394 let s:tests = filter(s:tests, 'v:val =~ argv(1)')
395endif
396
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200397" If the environment variable $TEST_FILTER is set then filter the function
398" names against it.
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200399let s:filtered = 0
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200400if $TEST_FILTER != ''
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200401 let s:filtered = len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200402 let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER')
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200403 let s:filtered -= len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200404endif
405
Bram Moolenaarce436de2020-03-21 15:17:20 +0100406let s:may_fail_list = []
407if $TEST_MAY_FAIL != ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200408 " Split the list at commas and add () to make it match g:testfunc.
Bram Moolenaarce436de2020-03-21 15:17:20 +0100409 let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'})
410endif
411
Bram Moolenaarcfc0a352016-01-09 20:23:00 +0100412" Execute the tests in alphabetical order.
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200413for g:testfunc in sort(s:tests)
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200414 " Silence, please!
415 set belloff=all
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100416 let prev_error = ''
417 let total_errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100418 let g:run_nr = 1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200419
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200420 " A test can set g:test_is_flaky to retry running the test.
421 let g:test_is_flaky = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100422
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200423 call RunTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100424
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100425 " Repeat a flaky test. Give up when:
426 " - it fails again with the same message
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200427 " - it fails five times (with a different message)
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100428 if len(v:errors) > 0
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200429 \ && (index(s:flaky_tests, g:testfunc) >= 0
430 \ || g:test_is_flaky)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100431 while 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200432 call add(s:messages, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100433 call extend(s:messages, v:errors)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100434
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100435 call add(total_errors, 'Run ' . g:run_nr . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100436 call extend(total_errors, v:errors)
Bram Moolenaar55058602017-11-21 15:14:51 +0100437
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100438 if g:run_nr == 5 || prev_error == v:errors[0]
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100439 call add(total_errors, 'Flaky test failed too often, giving up')
440 let v:errors = total_errors
441 break
442 endif
443
444 call add(s:messages, 'Flaky test failed, running it again')
445
446 " Flakiness is often caused by the system being very busy. Sleep a
447 " couple of seconds to have a higher chance of succeeding the second
448 " time.
449 sleep 2
450
451 let prev_error = v:errors[0]
452 let v:errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100453 let g:run_nr += 1
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100454
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200455 call RunTheTest(g:testfunc)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100456
457 if len(v:errors) == 0
458 " Test passed on rerun.
459 break
460 endif
461 endwhile
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100462 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100463
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200464 call AfterTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100465endfor
466
Bram Moolenaar42205552017-03-18 19:42:22 +0100467call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100468
469" vim: shiftwidth=2 sts=2 expandtab