blob: 2ef0f554fe792f6eb8a1dc5fcade0a2b6c3ce670 [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.
96let s:test_script_fname = expand('%')
97au! SwapExists * call HandleSwapExists()
98func HandleSwapExists()
Bram Moolenaar8ce4b7e2020-08-07 18:12:18 +020099 if exists('g:ignoreSwapExists')
100 return
101 endif
Bram Moolenaarb073da82019-07-13 14:47:26 +0200102 " Ignore finding a swap file for the test script (the user might be
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200103 " editing it and do ":make test_name") and the output file.
Bram Moolenaarb073da82019-07-13 14:47:26 +0200104 " Report finding another swap file and chose 'q' to avoid getting stuck.
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200105 if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname
106 let v:swapchoice = 'e'
Bram Moolenaarb073da82019-07-13 14:47:26 +0200107 else
108 call assert_report('Unexpected swap file: ' .. v:swapname)
109 let v:swapchoice = 'q'
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200110 endif
111endfunc
112
Bram Moolenaar7a073542017-02-01 23:17:36 +0100113" Avoid stopping at the "hit enter" prompt
114set nomore
115
Bram Moolenaarc0662462015-12-30 15:49:05 +0100116" Output all messages in English.
117lang mess C
118
Bram Moolenaar10e1d012020-07-18 22:03:11 +0200119" suppress menu translation
120if has('gui_running') && exists('did_install_default_menus')
121 source $VIMRUNTIME/delmenu.vim
122 set langmenu=none
123 source $VIMRUNTIME/menu.vim
124endif
125
Bram Moolenaarf60b7962016-01-16 22:47:23 +0100126" Always use forward slashes.
127set shellslash
128
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100129let s:srcdir = expand('%:p:h:h')
130
Bram Moolenaar2690b5a2020-07-22 18:14:58 +0200131if has('win32')
132 " avoid prompt that is long or contains a line break
133 let $PROMPT = '$P$G'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200134 " On MS-Windows t_md and t_me are Vim specific escape sequences.
135 let s:t_bold = "\x1b[1m"
136 let s:t_normal = "\x1b[m"
137else
138 let s:t_bold = &t_md
139 let s:t_normal = &t_me
Bram Moolenaar2690b5a2020-07-22 18:14:58 +0200140endif
141
Bram Moolenaar4b2ce122020-11-21 21:41:41 +0100142if has('mac')
143 " In MacOS, when starting a shell in a terminal, a bash deprecation warning
144 " message is displayed. This breaks the terminal test. Disable the warning
145 " message.
146 let $BASH_SILENCE_DEPRECATION_WARNING = 1
147endif
148
Bram Moolenaar8e8df252016-05-25 21:23:21 +0200149" Prepare for calling test_garbagecollect_now().
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200150let v:testing = 1
151
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100152" Support function: get the alloc ID by name.
153function GetAllocId(name)
154 exe 'split ' . s:srcdir . '/alloc.h'
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100155 let top = search('typedef enum')
156 if top == 0
157 call add(v:errors, 'typedef not found in alloc.h')
158 endif
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100159 let lnum = search('aid_' . a:name . ',')
160 if lnum == 0
161 call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
162 endif
163 close
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100164 return lnum - top - 1
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100165endfunc
166
Bram Moolenaar42205552017-03-18 19:42:22 +0100167func RunTheTest(test)
Bram Moolenaar4c868302021-03-22 16:19:45 +0100168 echoconsole 'Executing ' . a:test
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200169 if has('reltime')
170 let func_start = reltime()
171 endif
Bram Moolenaare5f2a072017-02-01 22:31:49 +0100172
173 " Avoid stopping at the "hit enter" prompt
174 set nomore
175
176 " Avoid a three second wait when a message is about to be overwritten by the
177 " mode message.
178 set noshowmode
179
Bram Moolenaareb992cb2017-03-09 18:20:16 +0100180 " Clear any overrides.
181 call test_override('ALL', 0)
182
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200183 " Some tests wipe out buffers. To be consistent, always wipe out all
184 " buffers.
185 %bwipe!
186
Bram Moolenaar209d3872017-11-16 21:52:51 +0100187 " The test may change the current directory. Save and restore the
188 " directory after executing the test.
189 let save_cwd = getcwd()
190
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100191 if exists("*SetUp")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100192 try
193 call SetUp()
194 catch
195 call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
196 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100197 endif
198
Bram Moolenaarf204e052017-10-26 17:14:01 +0200199 if a:test =~ 'Test_nocatch_'
200 " Function handles errors itself. This avoids skipping commands after the
201 " error.
Bram Moolenaar776b9542021-03-10 22:27:48 +0100202 let g:skipped_reason = ''
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100203 exe 'call ' . a:test
Bram Moolenaar776b9542021-03-10 22:27:48 +0100204 if g:skipped_reason != ''
205 call add(s:messages, ' Skipped')
206 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . g:skipped_reason)
207 endif
Bram Moolenaarf204e052017-10-26 17:14:01 +0200208 else
209 try
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200210 au VimLeavePre * call EarlyExit(g:testfunc)
Bram Moolenaarf204e052017-10-26 17:14:01 +0200211 exe 'call ' . a:test
Bram Moolenaar89036762018-06-12 14:58:39 +0200212 au! VimLeavePre
Bram Moolenaarf204e052017-10-26 17:14:01 +0200213 catch /^\cskipped/
214 call add(s:messages, ' Skipped')
215 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
216 catch
217 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
218 endtry
219 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100220
Bram Moolenaar8ad16da2019-01-06 15:29:57 +0100221 " In case 'insertmode' was set and something went wrong, make sure it is
222 " reset to avoid trouble with anything else.
223 set noinsertmode
224
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100225 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100226 try
227 call TearDown()
228 catch
229 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
230 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100231 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200232
Bram Moolenaar0b5dc642019-08-11 22:56:15 +0200233 " Clear any autocommands and put back the catch-all for SwapExists.
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200234 au!
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200235 au SwapExists * call HandleSwapExists()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200236
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200237 " Check for and close any stray popup windows.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100238 if has('popupwin')
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200239 call assert_equal([], popup_list())
Bram Moolenaar03a9f842020-05-13 13:40:16 +0200240 call popup_clear(1)
Bram Moolenaarae943152019-06-16 22:54:14 +0200241 endif
242
Bram Moolenaarce11de82017-10-26 22:00:00 +0200243 " Close any extra tab pages and windows and make the current one not modified.
244 while tabpagenr('$') > 1
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200245 let winid = win_getid()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200246 quit!
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200247 if winid == win_getid()
248 echoerr 'Could not quit window'
249 break
250 endif
Bram Moolenaarce11de82017-10-26 22:00:00 +0200251 endwhile
252
Bram Moolenaar358308d2016-08-24 21:21:26 +0200253 while 1
254 let wincount = winnr('$')
255 if wincount == 1
256 break
257 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200258 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200259 if wincount == winnr('$')
260 " Did not manage to close a window.
261 only!
262 break
263 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200264 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100265
266 exe 'cd ' . save_cwd
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200267
268 let message = 'Executed ' . a:test
269 if has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200270 let message ..= repeat(' ', 50 - len(message))
271 let time = reltime(func_start)
272 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200273 let message = s:t_bold .. message
Bram Moolenaar8d943792020-06-21 20:39:37 +0200274 endif
275 let message ..= ' in ' .. reltimestr(time) .. ' seconds'
276 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200277 let message ..= s:t_normal
Bram Moolenaar8d943792020-06-21 20:39:37 +0200278 endif
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200279 endif
280 call add(s:messages, message)
281 let s:done += 1
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100282endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100283
Bram Moolenaarce436de2020-03-21 15:17:20 +0100284func AfterTheTest(func_name)
Bram Moolenaar42205552017-03-18 19:42:22 +0100285 if len(v:errors) > 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100286 if match(s:may_fail_list, '^' .. a:func_name) >= 0
287 let s:fail_expected += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200288 call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100289 call extend(s:errors_expected, v:errors)
290 else
291 let s:fail += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200292 call add(s:errors, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100293 call extend(s:errors, v:errors)
294 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100295 let v:errors = []
296 endif
297endfunc
298
Bram Moolenaar89036762018-06-12 14:58:39 +0200299func EarlyExit(test)
300 " It's OK for the test we use to test the quit detection.
301 if a:test != 'Test_zz_quit_detected()'
302 call add(v:errors, 'Test caused Vim to exit: ' . a:test)
303 endif
304
305 call FinishTesting()
306endfunc
307
Bram Moolenaar42205552017-03-18 19:42:22 +0100308" This function can be called by a test if it wants to abort testing.
309func FinishTesting()
Bram Moolenaarce436de2020-03-21 15:17:20 +0100310 call AfterTheTest('')
Bram Moolenaar42205552017-03-18 19:42:22 +0100311
312 " Don't write viminfo on exit.
313 set viminfo=
314
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200315 " Clean up files created by setup.vim
316 call delete('XfakeHOME', 'rf')
317
Bram Moolenaarce436de2020-03-21 15:17:20 +0100318 if s:fail == 0 && s:fail_expected == 0
Bram Moolenaar42205552017-03-18 19:42:22 +0100319 " Success, create the .res file so that make knows it's done.
320 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
321 write
322 endif
323
324 if len(s:errors) > 0
325 " Append errors to test.log
326 split test.log
327 call append(line('$'), '')
328 call append(line('$'), 'From ' . g:testname . ':')
329 call append(line('$'), s:errors)
330 write
331 endif
332
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200333 if s:done == 0
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200334 if s:filtered > 0
Bram Moolenaardae453f2021-08-07 17:20:16 +0200335 if $TEST_FILTER != ''
336 let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
337 else
338 let message = "ALL tests match $TEST_SKIP_PAT: '" .. $TEST_SKIP_PAT .. "'"
339 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200340 else
341 let message = 'NO tests executed'
342 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200343 else
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200344 if s:filtered > 0
Bram Moolenaardae453f2021-08-07 17:20:16 +0200345 call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER and $TEST_SKIP_PAT")
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200346 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200347 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
348 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200349 if s:done > 0 && has('reltime')
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200350 let message = s:t_bold .. message .. repeat(' ', 40 - len(message))
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200351 let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200352 let message ..= s:t_normal
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200353 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100354 echo message
355 call add(s:messages, message)
356 if s:fail > 0
357 let message = s:fail . ' FAILED:'
358 echo message
359 call add(s:messages, message)
360 call extend(s:messages, s:errors)
361 endif
Bram Moolenaarce436de2020-03-21 15:17:20 +0100362 if s:fail_expected > 0
363 let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
364 echo message
365 call add(s:messages, message)
366 call extend(s:messages, s:errors_expected)
367 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100368
369 " Add SKIPPED messages
370 call extend(s:messages, s:skipped)
371
372 " Append messages to the file "messages"
373 split messages
374 call append(line('$'), '')
375 call append(line('$'), 'From ' . g:testname . ':')
376 call append(line('$'), s:messages)
377 write
378
379 qall!
380endfunc
381
Bram Moolenaar43345542015-11-29 17:35:35 +0100382" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100383" navigates away. g:testname can be used by the tests.
384let g:testname = expand('%')
385let s:done = 0
386let s:fail = 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100387let s:fail_expected = 0
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100388let s:errors = []
Bram Moolenaarce436de2020-03-21 15:17:20 +0100389let s:errors_expected = []
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100390let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200391let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100392if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaarce436de2020-03-21 15:17:20 +0100393 " this test has intentional errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100394 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100395else
396 try
397 source %
Bram Moolenaar9c0cec62019-06-06 13:38:15 +0200398 catch /^\cskipped/
399 call add(s:messages, ' Skipped')
400 call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
Bram Moolenaara2cce862016-01-02 19:50:04 +0100401 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100402 let s:fail += 1
403 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100404 endtry
405endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100406
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100407" Names of flaky tests.
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100408let s:flaky_tests = [
Bram Moolenaar7d697962020-08-31 21:30:32 +0200409 \ 'Test_BufWrite_lockmarks()',
Bram Moolenaar0d0c3ca2019-09-25 21:16:15 +0200410 \ 'Test_autocmd_SafeState()',
Bram Moolenaar7d697962020-08-31 21:30:32 +0200411 \ 'Test_bufunload_all()',
Bram Moolenaar42205552017-03-18 19:42:22 +0100412 \ 'Test_client_server()',
Bram Moolenaar6fe2eb42017-01-29 21:49:51 +0100413 \ 'Test_close_and_exit_cb()',
Bram Moolenaard80232b2018-12-15 17:46:23 +0100414 \ 'Test_close_output_buffer()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100415 \ 'Test_collapse_buffers()',
Bram Moolenaar65873842018-03-25 17:12:58 +0200416 \ 'Test_cwd()',
Bram Moolenaar218959b2018-11-11 18:51:42 +0100417 \ 'Test_diff_screen()',
Bram Moolenaar0529b3e2017-03-16 22:30:37 +0100418 \ 'Test_exit_callback_interval()',
Bram Moolenaarea94c852019-08-16 21:47:27 +0200419 \ 'Test_map_timeout_with_timer_interrupt()',
Bram Moolenaar1eca6f12017-12-05 14:04:27 +0100420 \ 'Test_out_cb()',
Bram Moolenaarc79d6aa2016-09-25 22:27:37 +0200421 \ 'Test_pipe_through_sort_all()',
Bram Moolenaar4e032e12017-02-01 20:48:13 +0100422 \ 'Test_pipe_through_sort_some()',
Bram Moolenaar44f0bd82019-11-21 18:27:01 +0100423 \ 'Test_popup_and_window_resize()',
Bram Moolenaar0fbff642017-03-05 14:30:52 +0100424 \ 'Test_quoteplus()',
Bram Moolenaar7dd48502017-03-19 20:04:22 +0100425 \ 'Test_quotestar()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100426 \ 'Test_reltime()',
Bram Moolenaar3c8cd4a2019-10-14 22:26:20 +0200427 \ 'Test_state()',
Bram Moolenaarf204e052017-10-26 17:14:01 +0200428 \ 'Test_terminal_composing_unicode()',
Bram Moolenaar38767892019-02-21 18:17:14 +0100429 \ 'Test_terminal_does_not_truncate_last_newlines()',
Bram Moolenaar3615abb2019-02-10 23:04:12 +0100430 \ 'Test_terminal_no_cmd()',
Bram Moolenaar75a60f72017-09-07 22:24:41 +0200431 \ 'Test_terminal_noblock()',
Bram Moolenaar7dd88c52017-11-04 20:46:40 +0100432 \ 'Test_terminal_redir_file()',
Bram Moolenaare219f732019-11-30 15:34:08 +0100433 \ 'Test_termwinscroll()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200434 \ 'Test_timer_oneshot()',
435 \ 'Test_timer_paused()',
436 \ 'Test_timer_repeat_many()',
437 \ 'Test_timer_repeat_three()',
438 \ 'Test_timer_stop_all_in_callback()',
439 \ 'Test_timer_stop_in_callback()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200440 \ 'Test_timer_with_partial_callback()',
Bram Moolenaare1c8c7a2016-09-11 16:48:50 +0200441 \ ]
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100442
Bram Moolenaar43345542015-11-29 17:35:35 +0100443" Locate Test_ functions and execute them.
444redir @q
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100445silent function /^Test_
Bram Moolenaar43345542015-11-29 17:35:35 +0100446redir END
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +0100447let s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g'))
Bram Moolenaar43345542015-11-29 17:35:35 +0100448
Bram Moolenaarbefb3662016-02-20 14:41:40 +0100449" If there is an extra argument filter the function names against it.
450if argc() > 1
451 let s:tests = filter(s:tests, 'v:val =~ argv(1)')
452endif
453
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200454" If the environment variable $TEST_FILTER is set then filter the function
455" names against it.
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200456let s:filtered = 0
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200457if $TEST_FILTER != ''
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200458 let s:filtered = len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200459 let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER')
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200460 let s:filtered -= len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200461endif
462
Bram Moolenaarce436de2020-03-21 15:17:20 +0100463let s:may_fail_list = []
464if $TEST_MAY_FAIL != ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200465 " Split the list at commas and add () to make it match g:testfunc.
Bram Moolenaarce436de2020-03-21 15:17:20 +0100466 let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'})
467endif
468
Bram Moolenaarcfc0a352016-01-09 20:23:00 +0100469" Execute the tests in alphabetical order.
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200470for g:testfunc in sort(s:tests)
Bram Moolenaardae453f2021-08-07 17:20:16 +0200471 if $TEST_SKIP_PAT != '' && g:testfunc =~ $TEST_SKIP_PAT
472 call add(s:messages, g:testfunc .. ' matches $TEST_SKIP_PAT')
473 let s:filtered += 1
474 continue
475 endif
476
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200477 " Silence, please!
478 set belloff=all
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100479 let prev_error = ''
480 let total_errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100481 let g:run_nr = 1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200482
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200483 " A test can set g:test_is_flaky to retry running the test.
484 let g:test_is_flaky = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100485
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200486 call RunTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100487
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100488 " Repeat a flaky test. Give up when:
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200489 " - $TEST_NO_RETRY is not empty
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100490 " - it fails again with the same message
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200491 " - it fails five times (with a different message)
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100492 if len(v:errors) > 0
Bram Moolenaar622b3562020-07-27 20:02:41 +0200493 \ && $TEST_NO_RETRY == ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200494 \ && (index(s:flaky_tests, g:testfunc) >= 0
495 \ || g:test_is_flaky)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100496 while 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200497 call add(s:messages, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100498 call extend(s:messages, v:errors)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100499
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100500 call add(total_errors, 'Run ' . g:run_nr . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100501 call extend(total_errors, v:errors)
Bram Moolenaar55058602017-11-21 15:14:51 +0100502
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100503 if g:run_nr == 5 || prev_error == v:errors[0]
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100504 call add(total_errors, 'Flaky test failed too often, giving up')
505 let v:errors = total_errors
506 break
507 endif
508
509 call add(s:messages, 'Flaky test failed, running it again')
510
511 " Flakiness is often caused by the system being very busy. Sleep a
512 " couple of seconds to have a higher chance of succeeding the second
513 " time.
514 sleep 2
515
516 let prev_error = v:errors[0]
517 let v:errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100518 let g:run_nr += 1
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100519
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200520 call RunTheTest(g:testfunc)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100521
522 if len(v:errors) == 0
523 " Test passed on rerun.
524 break
525 endif
526 endwhile
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100527 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100528
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200529 call AfterTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100530endfor
531
Bram Moolenaar42205552017-03-18 19:42:22 +0100532call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100533
534" vim: shiftwidth=2 sts=2 expandtab