blob: f3609f8514582f38fff1858f42752d83175c14b7 [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 Moolenaar6ca6ca42020-07-27 19:47:07 +020016" While working on a test you can make $TEST_NO_RETRY non-empty to not retry:
17" export TEST_NO_RETRY=yes
18"
Bram Moolenaarce436de2020-03-21 15:17:20 +010019" To ignore failure for tests that are known to fail in a certain environment,
20" set $TEST_MAY_FAIL to a comma separated list of function names. E.g. for
21" sh/bash:
22" export TEST_MAY_FAIL=Test_channel_one,Test_channel_other
23" The failure report will then not be included in the test.log file and
24" "make test" will not fail.
25"
Bram Moolenaar43345542015-11-29 17:35:35 +010026" The test script may contain anything, only functions that start with
27" "Test_" are special. These will be invoked and should contain assert
28" functions. See test_assert.vim for an example.
29"
30" It is possible to source other files that contain "Test_" functions. This
31" can speed up testing, since Vim does not need to restart. But be careful
32" that the tests do not interfere with each other.
33"
34" If an error cannot be detected properly with an assert function add the
35" error to the v:errors list:
36" call add(v:errors, 'test foo failed: Cannot find xyz')
37"
38" If preparation for each Test_ function is needed, define a SetUp function.
39" It will be called before each Test_ function.
40"
41" If cleanup after each Test_ function is needed, define a TearDown function.
42" It will be called after each Test_ function.
Bram Moolenaar00af60b2016-02-13 14:06:14 +010043"
44" When debugging a test it can be useful to add messages to v:errors:
Bram Moolenaar8ad16da2019-01-06 15:29:57 +010045" call add(v:errors, "this happened")
Bram Moolenaar00af60b2016-02-13 14:06:14 +010046
Bram Moolenaar43345542015-11-29 17:35:35 +010047
48" Without the +eval feature we can't run these tests, bail out.
Bram Moolenaar4686b322015-12-28 14:44:10 +010049so small.vim
Bram Moolenaar43345542015-11-29 17:35:35 +010050
Bram Moolenaar18aa13d2020-07-11 13:09:36 +020051" In the GUI we can always change the screen size.
52if has('gui_running')
53 set columns=80 lines=25
54endif
55
Bram Moolenaar43345542015-11-29 17:35:35 +010056" Check that the screen size is at least 24 x 80 characters.
57if &lines < 24 || &columns < 80
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020058 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 +010059 echoerr error
60 split test.log
61 $put =error
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020062 write
63 split messages
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020064 call append(line('$'), '')
65 call append(line('$'), 'From ' . expand('%') . ':')
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020066 call append(line('$'), error)
67 write
68 qa!
Bram Moolenaar43345542015-11-29 17:35:35 +010069endif
70
Bram Moolenaar75ee5442019-06-06 18:05:25 +020071if has('reltime')
72 let s:start_time = reltime()
73endif
74
Bram Moolenaar89b10422016-07-12 22:51:22 +020075" Common with all tests on all systems.
76source setup.vim
77
Bram Moolenaarc0662462015-12-30 15:49:05 +010078" For consistency run all tests with 'nocompatible' set.
79" This also enables use of line continuation.
80set nocp viminfo+=nviminfo
81
Bram Moolenaar30276f22019-01-24 17:59:39 +010082" Use utf-8 by default, instead of whatever the system default happens to be.
Bram Moolenaared79d1e2019-02-22 14:38:58 +010083" Individual tests can overrule this at the top of the file and use
84" g:orig_encoding if needed.
85let g:orig_encoding = &encoding
Bram Moolenaar30276f22019-01-24 17:59:39 +010086set encoding=utf-8
Bram Moolenaarac105ed2016-07-21 20:33:32 +020087
Bram Moolenaard8f27b32018-10-07 15:42:07 +020088" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for
89" the test_name.vim file itself. Replace it here with a more restrictive one,
90" so we still catch mistakes.
91let s:test_script_fname = expand('%')
92au! SwapExists * call HandleSwapExists()
93func HandleSwapExists()
Bram Moolenaarb073da82019-07-13 14:47:26 +020094 " Ignore finding a swap file for the test script (the user might be
Bram Moolenaard8f27b32018-10-07 15:42:07 +020095 " editing it and do ":make test_name") and the output file.
Bram Moolenaarb073da82019-07-13 14:47:26 +020096 " Report finding another swap file and chose 'q' to avoid getting stuck.
Bram Moolenaard8f27b32018-10-07 15:42:07 +020097 if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname
98 let v:swapchoice = 'e'
Bram Moolenaarb073da82019-07-13 14:47:26 +020099 else
100 call assert_report('Unexpected swap file: ' .. v:swapname)
101 let v:swapchoice = 'q'
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200102 endif
103endfunc
104
Bram Moolenaar7a073542017-02-01 23:17:36 +0100105" Avoid stopping at the "hit enter" prompt
106set nomore
107
Bram Moolenaarc0662462015-12-30 15:49:05 +0100108" Output all messages in English.
109lang mess C
110
Bram Moolenaar10e1d012020-07-18 22:03:11 +0200111" suppress menu translation
112if has('gui_running') && exists('did_install_default_menus')
113 source $VIMRUNTIME/delmenu.vim
114 set langmenu=none
115 source $VIMRUNTIME/menu.vim
116endif
117
Bram Moolenaarf60b7962016-01-16 22:47:23 +0100118" Always use forward slashes.
119set shellslash
120
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100121let s:srcdir = expand('%:p:h:h')
122
Bram Moolenaar2690b5a2020-07-22 18:14:58 +0200123if has('win32')
124 " avoid prompt that is long or contains a line break
125 let $PROMPT = '$P$G'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200126 " On MS-Windows t_md and t_me are Vim specific escape sequences.
127 let s:t_bold = "\x1b[1m"
128 let s:t_normal = "\x1b[m"
129else
130 let s:t_bold = &t_md
131 let s:t_normal = &t_me
Bram Moolenaar2690b5a2020-07-22 18:14:58 +0200132endif
133
Bram Moolenaar8e8df252016-05-25 21:23:21 +0200134" Prepare for calling test_garbagecollect_now().
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200135let v:testing = 1
136
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100137" Support function: get the alloc ID by name.
138function GetAllocId(name)
139 exe 'split ' . s:srcdir . '/alloc.h'
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100140 let top = search('typedef enum')
141 if top == 0
142 call add(v:errors, 'typedef not found in alloc.h')
143 endif
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100144 let lnum = search('aid_' . a:name . ',')
145 if lnum == 0
146 call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
147 endif
148 close
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100149 return lnum - top - 1
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100150endfunc
151
Bram Moolenaar42205552017-03-18 19:42:22 +0100152func RunTheTest(test)
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100153 echo 'Executing ' . a:test
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200154 if has('reltime')
155 let func_start = reltime()
156 endif
Bram Moolenaare5f2a072017-02-01 22:31:49 +0100157
158 " Avoid stopping at the "hit enter" prompt
159 set nomore
160
161 " Avoid a three second wait when a message is about to be overwritten by the
162 " mode message.
163 set noshowmode
164
Bram Moolenaareb992cb2017-03-09 18:20:16 +0100165 " Clear any overrides.
166 call test_override('ALL', 0)
167
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200168 " Some tests wipe out buffers. To be consistent, always wipe out all
169 " buffers.
170 %bwipe!
171
Bram Moolenaar209d3872017-11-16 21:52:51 +0100172 " The test may change the current directory. Save and restore the
173 " directory after executing the test.
174 let save_cwd = getcwd()
175
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100176 if exists("*SetUp")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100177 try
178 call SetUp()
179 catch
180 call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
181 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100182 endif
183
Bram Moolenaarf204e052017-10-26 17:14:01 +0200184 if a:test =~ 'Test_nocatch_'
185 " Function handles errors itself. This avoids skipping commands after the
186 " error.
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100187 exe 'call ' . a:test
Bram Moolenaarf204e052017-10-26 17:14:01 +0200188 else
189 try
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200190 au VimLeavePre * call EarlyExit(g:testfunc)
Bram Moolenaarf204e052017-10-26 17:14:01 +0200191 exe 'call ' . a:test
Bram Moolenaar89036762018-06-12 14:58:39 +0200192 au! VimLeavePre
Bram Moolenaarf204e052017-10-26 17:14:01 +0200193 catch /^\cskipped/
194 call add(s:messages, ' Skipped')
195 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
196 catch
197 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
198 endtry
199 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100200
Bram Moolenaar8ad16da2019-01-06 15:29:57 +0100201 " In case 'insertmode' was set and something went wrong, make sure it is
202 " reset to avoid trouble with anything else.
203 set noinsertmode
204
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100205 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100206 try
207 call TearDown()
208 catch
209 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
210 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100211 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200212
Bram Moolenaar0b5dc642019-08-11 22:56:15 +0200213 " Clear any autocommands and put back the catch-all for SwapExists.
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200214 au!
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200215 au SwapExists * call HandleSwapExists()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200216
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200217 " Check for and close any stray popup windows.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100218 if has('popupwin')
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200219 call assert_equal([], popup_list())
Bram Moolenaar03a9f842020-05-13 13:40:16 +0200220 call popup_clear(1)
Bram Moolenaarae943152019-06-16 22:54:14 +0200221 endif
222
Bram Moolenaarce11de82017-10-26 22:00:00 +0200223 " Close any extra tab pages and windows and make the current one not modified.
224 while tabpagenr('$') > 1
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200225 quit!
Bram Moolenaarce11de82017-10-26 22:00:00 +0200226 endwhile
227
Bram Moolenaar358308d2016-08-24 21:21:26 +0200228 while 1
229 let wincount = winnr('$')
230 if wincount == 1
231 break
232 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200233 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200234 if wincount == winnr('$')
235 " Did not manage to close a window.
236 only!
237 break
238 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200239 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100240
241 exe 'cd ' . save_cwd
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200242
243 let message = 'Executed ' . a:test
244 if has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200245 let message ..= repeat(' ', 50 - len(message))
246 let time = reltime(func_start)
247 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200248 let message = s:t_bold .. message
Bram Moolenaar8d943792020-06-21 20:39:37 +0200249 endif
250 let message ..= ' in ' .. reltimestr(time) .. ' seconds'
251 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200252 let message ..= s:t_normal
Bram Moolenaar8d943792020-06-21 20:39:37 +0200253 endif
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200254 endif
255 call add(s:messages, message)
256 let s:done += 1
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100257endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100258
Bram Moolenaarce436de2020-03-21 15:17:20 +0100259func AfterTheTest(func_name)
Bram Moolenaar42205552017-03-18 19:42:22 +0100260 if len(v:errors) > 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100261 if match(s:may_fail_list, '^' .. a:func_name) >= 0
262 let s:fail_expected += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200263 call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100264 call extend(s:errors_expected, v:errors)
265 else
266 let s:fail += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200267 call add(s:errors, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100268 call extend(s:errors, v:errors)
269 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100270 let v:errors = []
271 endif
272endfunc
273
Bram Moolenaar89036762018-06-12 14:58:39 +0200274func EarlyExit(test)
275 " It's OK for the test we use to test the quit detection.
276 if a:test != 'Test_zz_quit_detected()'
277 call add(v:errors, 'Test caused Vim to exit: ' . a:test)
278 endif
279
280 call FinishTesting()
281endfunc
282
Bram Moolenaar42205552017-03-18 19:42:22 +0100283" This function can be called by a test if it wants to abort testing.
284func FinishTesting()
Bram Moolenaarce436de2020-03-21 15:17:20 +0100285 call AfterTheTest('')
Bram Moolenaar42205552017-03-18 19:42:22 +0100286
287 " Don't write viminfo on exit.
288 set viminfo=
289
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200290 " Clean up files created by setup.vim
291 call delete('XfakeHOME', 'rf')
292
Bram Moolenaarce436de2020-03-21 15:17:20 +0100293 if s:fail == 0 && s:fail_expected == 0
Bram Moolenaar42205552017-03-18 19:42:22 +0100294 " Success, create the .res file so that make knows it's done.
295 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
296 write
297 endif
298
299 if len(s:errors) > 0
300 " Append errors to test.log
301 split test.log
302 call append(line('$'), '')
303 call append(line('$'), 'From ' . g:testname . ':')
304 call append(line('$'), s:errors)
305 write
306 endif
307
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200308 if s:done == 0
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200309 if s:filtered > 0
310 let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
311 else
312 let message = 'NO tests executed'
313 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200314 else
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200315 if s:filtered > 0
316 call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER")
317 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200318 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
319 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200320 if s:done > 0 && has('reltime')
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200321 let message = s:t_bold .. message .. repeat(' ', 40 - len(message))
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200322 let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200323 let message ..= s:t_normal
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200324 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100325 echo message
326 call add(s:messages, message)
327 if s:fail > 0
328 let message = s:fail . ' FAILED:'
329 echo message
330 call add(s:messages, message)
331 call extend(s:messages, s:errors)
332 endif
Bram Moolenaarce436de2020-03-21 15:17:20 +0100333 if s:fail_expected > 0
334 let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
335 echo message
336 call add(s:messages, message)
337 call extend(s:messages, s:errors_expected)
338 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100339
340 " Add SKIPPED messages
341 call extend(s:messages, s:skipped)
342
343 " Append messages to the file "messages"
344 split messages
345 call append(line('$'), '')
346 call append(line('$'), 'From ' . g:testname . ':')
347 call append(line('$'), s:messages)
348 write
349
350 qall!
351endfunc
352
Bram Moolenaar43345542015-11-29 17:35:35 +0100353" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100354" navigates away. g:testname can be used by the tests.
355let g:testname = expand('%')
356let s:done = 0
357let s:fail = 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100358let s:fail_expected = 0
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100359let s:errors = []
Bram Moolenaarce436de2020-03-21 15:17:20 +0100360let s:errors_expected = []
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100361let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200362let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100363if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaarce436de2020-03-21 15:17:20 +0100364 " this test has intentional errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100365 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100366else
367 try
368 source %
Bram Moolenaar9c0cec62019-06-06 13:38:15 +0200369 catch /^\cskipped/
370 call add(s:messages, ' Skipped')
371 call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
Bram Moolenaara2cce862016-01-02 19:50:04 +0100372 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100373 let s:fail += 1
374 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100375 endtry
376endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100377
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100378" Names of flaky tests.
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100379let s:flaky_tests = [
Bram Moolenaar0d0c3ca2019-09-25 21:16:15 +0200380 \ 'Test_autocmd_SafeState()',
Bram Moolenaar42205552017-03-18 19:42:22 +0100381 \ 'Test_client_server()',
Bram Moolenaar6fe2eb42017-01-29 21:49:51 +0100382 \ 'Test_close_and_exit_cb()',
Bram Moolenaard80232b2018-12-15 17:46:23 +0100383 \ 'Test_close_output_buffer()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100384 \ 'Test_collapse_buffers()',
Bram Moolenaar65873842018-03-25 17:12:58 +0200385 \ 'Test_cwd()',
Bram Moolenaar218959b2018-11-11 18:51:42 +0100386 \ 'Test_diff_screen()',
Bram Moolenaar0529b3e2017-03-16 22:30:37 +0100387 \ 'Test_exit_callback_interval()',
Bram Moolenaarea94c852019-08-16 21:47:27 +0200388 \ 'Test_map_timeout_with_timer_interrupt()',
Bram Moolenaar1eca6f12017-12-05 14:04:27 +0100389 \ 'Test_out_cb()',
Bram Moolenaarc79d6aa2016-09-25 22:27:37 +0200390 \ 'Test_pipe_through_sort_all()',
Bram Moolenaar4e032e12017-02-01 20:48:13 +0100391 \ 'Test_pipe_through_sort_some()',
Bram Moolenaar44f0bd82019-11-21 18:27:01 +0100392 \ 'Test_popup_and_window_resize()',
Bram Moolenaar0fbff642017-03-05 14:30:52 +0100393 \ 'Test_quoteplus()',
Bram Moolenaar7dd48502017-03-19 20:04:22 +0100394 \ 'Test_quotestar()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100395 \ 'Test_reltime()',
Bram Moolenaar3c8cd4a2019-10-14 22:26:20 +0200396 \ 'Test_state()',
Bram Moolenaarf204e052017-10-26 17:14:01 +0200397 \ 'Test_terminal_composing_unicode()',
Bram Moolenaar38767892019-02-21 18:17:14 +0100398 \ 'Test_terminal_does_not_truncate_last_newlines()',
Bram Moolenaar3615abb2019-02-10 23:04:12 +0100399 \ 'Test_terminal_no_cmd()',
Bram Moolenaar75a60f72017-09-07 22:24:41 +0200400 \ 'Test_terminal_noblock()',
Bram Moolenaar7dd88c52017-11-04 20:46:40 +0100401 \ 'Test_terminal_redir_file()',
Bram Moolenaare219f732019-11-30 15:34:08 +0100402 \ 'Test_termwinscroll()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200403 \ 'Test_timer_oneshot()',
404 \ 'Test_timer_paused()',
405 \ 'Test_timer_repeat_many()',
406 \ 'Test_timer_repeat_three()',
407 \ 'Test_timer_stop_all_in_callback()',
408 \ 'Test_timer_stop_in_callback()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200409 \ 'Test_timer_with_partial_callback()',
Bram Moolenaare1c8c7a2016-09-11 16:48:50 +0200410 \ ]
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100411
Bram Moolenaar43345542015-11-29 17:35:35 +0100412" 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 Moolenaar4a6fcf82017-10-12 21:29:22 +0200440 " Silence, please!
441 set belloff=all
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100442 let prev_error = ''
443 let total_errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100444 let g:run_nr = 1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200445
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200446 " A test can set g:test_is_flaky to retry running the test.
447 let g:test_is_flaky = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100448
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200449 call RunTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100450
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100451 " Repeat a flaky test. Give up when:
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200452 " - $TEST_NO_RETRY is not empty
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100453 " - it fails again with the same message
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200454 " - it fails five times (with a different message)
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100455 if len(v:errors) > 0
Bram Moolenaar622b3562020-07-27 20:02:41 +0200456 \ && $TEST_NO_RETRY == ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200457 \ && (index(s:flaky_tests, g:testfunc) >= 0
458 \ || g:test_is_flaky)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100459 while 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200460 call add(s:messages, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100461 call extend(s:messages, v:errors)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100462
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100463 call add(total_errors, 'Run ' . g:run_nr . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100464 call extend(total_errors, v:errors)
Bram Moolenaar55058602017-11-21 15:14:51 +0100465
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100466 if g:run_nr == 5 || prev_error == v:errors[0]
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100467 call add(total_errors, 'Flaky test failed too often, giving up')
468 let v:errors = total_errors
469 break
470 endif
471
472 call add(s:messages, 'Flaky test failed, running it again')
473
474 " Flakiness is often caused by the system being very busy. Sleep a
475 " couple of seconds to have a higher chance of succeeding the second
476 " time.
477 sleep 2
478
479 let prev_error = v:errors[0]
480 let v:errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100481 let g:run_nr += 1
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100482
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200483 call RunTheTest(g:testfunc)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100484
485 if len(v:errors) == 0
486 " Test passed on rerun.
487 break
488 endif
489 endwhile
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100490 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100491
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200492 call AfterTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100493endfor
494
Bram Moolenaar42205552017-03-18 19:42:22 +0100495call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100496
497" vim: shiftwidth=2 sts=2 expandtab