blob: e43dd8d94471b869270442a32af37602bb05cacb [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 Moolenaarb96a32e2020-08-13 18:59:55 +020049silent! while 0
50 qa!
51silent! endwhile
Bram Moolenaar43345542015-11-29 17:35:35 +010052
Bram Moolenaar18aa13d2020-07-11 13:09:36 +020053" In the GUI we can always change the screen size.
54if has('gui_running')
55 set columns=80 lines=25
56endif
57
Bram Moolenaar43345542015-11-29 17:35:35 +010058" Check that the screen size is at least 24 x 80 characters.
59if &lines < 24 || &columns < 80
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020060 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 +010061 echoerr error
62 split test.log
63 $put =error
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020064 write
65 split messages
Bram Moolenaar0b5dc642019-08-11 22:56:15 +020066 call append(line('$'), '')
67 call append(line('$'), 'From ' . expand('%') . ':')
Bram Moolenaar45aa07d2019-06-15 18:20:38 +020068 call append(line('$'), error)
69 write
70 qa!
Bram Moolenaar43345542015-11-29 17:35:35 +010071endif
72
Bram Moolenaar75ee5442019-06-06 18:05:25 +020073if has('reltime')
74 let s:start_time = reltime()
75endif
76
Bram Moolenaar89b10422016-07-12 22:51:22 +020077" Common with all tests on all systems.
78source setup.vim
79
Bram Moolenaarc0662462015-12-30 15:49:05 +010080" For consistency run all tests with 'nocompatible' set.
81" This also enables use of line continuation.
82set nocp viminfo+=nviminfo
83
Bram Moolenaar30276f22019-01-24 17:59:39 +010084" Use utf-8 by default, instead of whatever the system default happens to be.
Bram Moolenaared79d1e2019-02-22 14:38:58 +010085" Individual tests can overrule this at the top of the file and use
86" g:orig_encoding if needed.
87let g:orig_encoding = &encoding
Bram Moolenaar30276f22019-01-24 17:59:39 +010088set encoding=utf-8
Bram Moolenaarac105ed2016-07-21 20:33:32 +020089
Bram Moolenaard8f27b32018-10-07 15:42:07 +020090" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for
91" the test_name.vim file itself. Replace it here with a more restrictive one,
92" so we still catch mistakes.
93let s:test_script_fname = expand('%')
94au! SwapExists * call HandleSwapExists()
95func HandleSwapExists()
Bram Moolenaar8ce4b7e2020-08-07 18:12:18 +020096 if exists('g:ignoreSwapExists')
97 return
98 endif
Bram Moolenaarb073da82019-07-13 14:47:26 +020099 " Ignore finding a swap file for the test script (the user might be
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200100 " editing it and do ":make test_name") and the output file.
Bram Moolenaarb073da82019-07-13 14:47:26 +0200101 " Report finding another swap file and chose 'q' to avoid getting stuck.
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200102 if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname
103 let v:swapchoice = 'e'
Bram Moolenaarb073da82019-07-13 14:47:26 +0200104 else
105 call assert_report('Unexpected swap file: ' .. v:swapname)
106 let v:swapchoice = 'q'
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200107 endif
108endfunc
109
Bram Moolenaar7a073542017-02-01 23:17:36 +0100110" Avoid stopping at the "hit enter" prompt
111set nomore
112
Bram Moolenaarc0662462015-12-30 15:49:05 +0100113" Output all messages in English.
114lang mess C
115
Bram Moolenaar10e1d012020-07-18 22:03:11 +0200116" suppress menu translation
117if has('gui_running') && exists('did_install_default_menus')
118 source $VIMRUNTIME/delmenu.vim
119 set langmenu=none
120 source $VIMRUNTIME/menu.vim
121endif
122
Bram Moolenaarf60b7962016-01-16 22:47:23 +0100123" Always use forward slashes.
124set shellslash
125
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100126let s:srcdir = expand('%:p:h:h')
127
Bram Moolenaar2690b5a2020-07-22 18:14:58 +0200128if has('win32')
129 " avoid prompt that is long or contains a line break
130 let $PROMPT = '$P$G'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200131 " On MS-Windows t_md and t_me are Vim specific escape sequences.
132 let s:t_bold = "\x1b[1m"
133 let s:t_normal = "\x1b[m"
134else
135 let s:t_bold = &t_md
136 let s:t_normal = &t_me
Bram Moolenaar2690b5a2020-07-22 18:14:58 +0200137endif
138
Bram Moolenaar4b2ce122020-11-21 21:41:41 +0100139if has('mac')
140 " In MacOS, when starting a shell in a terminal, a bash deprecation warning
141 " message is displayed. This breaks the terminal test. Disable the warning
142 " message.
143 let $BASH_SILENCE_DEPRECATION_WARNING = 1
144endif
145
Bram Moolenaar8e8df252016-05-25 21:23:21 +0200146" Prepare for calling test_garbagecollect_now().
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200147let v:testing = 1
148
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100149" Support function: get the alloc ID by name.
150function GetAllocId(name)
151 exe 'split ' . s:srcdir . '/alloc.h'
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100152 let top = search('typedef enum')
153 if top == 0
154 call add(v:errors, 'typedef not found in alloc.h')
155 endif
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100156 let lnum = search('aid_' . a:name . ',')
157 if lnum == 0
158 call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
159 endif
160 close
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100161 return lnum - top - 1
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100162endfunc
163
Bram Moolenaar42205552017-03-18 19:42:22 +0100164func RunTheTest(test)
Bram Moolenaar4c868302021-03-22 16:19:45 +0100165 echoconsole 'Executing ' . a:test
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200166 if has('reltime')
167 let func_start = reltime()
168 endif
Bram Moolenaare5f2a072017-02-01 22:31:49 +0100169
170 " Avoid stopping at the "hit enter" prompt
171 set nomore
172
173 " Avoid a three second wait when a message is about to be overwritten by the
174 " mode message.
175 set noshowmode
176
Bram Moolenaareb992cb2017-03-09 18:20:16 +0100177 " Clear any overrides.
178 call test_override('ALL', 0)
179
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200180 " Some tests wipe out buffers. To be consistent, always wipe out all
181 " buffers.
182 %bwipe!
183
Bram Moolenaar209d3872017-11-16 21:52:51 +0100184 " The test may change the current directory. Save and restore the
185 " directory after executing the test.
186 let save_cwd = getcwd()
187
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100188 if exists("*SetUp")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100189 try
190 call SetUp()
191 catch
192 call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
193 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100194 endif
195
Bram Moolenaarf204e052017-10-26 17:14:01 +0200196 if a:test =~ 'Test_nocatch_'
197 " Function handles errors itself. This avoids skipping commands after the
198 " error.
Bram Moolenaar776b9542021-03-10 22:27:48 +0100199 let g:skipped_reason = ''
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100200 exe 'call ' . a:test
Bram Moolenaar776b9542021-03-10 22:27:48 +0100201 if g:skipped_reason != ''
202 call add(s:messages, ' Skipped')
203 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . g:skipped_reason)
204 endif
Bram Moolenaarf204e052017-10-26 17:14:01 +0200205 else
206 try
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200207 au VimLeavePre * call EarlyExit(g:testfunc)
Bram Moolenaarf204e052017-10-26 17:14:01 +0200208 exe 'call ' . a:test
Bram Moolenaar89036762018-06-12 14:58:39 +0200209 au! VimLeavePre
Bram Moolenaarf204e052017-10-26 17:14:01 +0200210 catch /^\cskipped/
211 call add(s:messages, ' Skipped')
212 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
213 catch
214 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
215 endtry
216 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100217
Bram Moolenaar8ad16da2019-01-06 15:29:57 +0100218 " In case 'insertmode' was set and something went wrong, make sure it is
219 " reset to avoid trouble with anything else.
220 set noinsertmode
221
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100222 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100223 try
224 call TearDown()
225 catch
226 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
227 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100228 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200229
Bram Moolenaar0b5dc642019-08-11 22:56:15 +0200230 " Clear any autocommands and put back the catch-all for SwapExists.
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200231 au!
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200232 au SwapExists * call HandleSwapExists()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200233
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200234 " Check for and close any stray popup windows.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100235 if has('popupwin')
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200236 call assert_equal([], popup_list())
Bram Moolenaar03a9f842020-05-13 13:40:16 +0200237 call popup_clear(1)
Bram Moolenaarae943152019-06-16 22:54:14 +0200238 endif
239
Bram Moolenaarce11de82017-10-26 22:00:00 +0200240 " Close any extra tab pages and windows and make the current one not modified.
241 while tabpagenr('$') > 1
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200242 let winid = win_getid()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200243 quit!
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200244 if winid == win_getid()
245 echoerr 'Could not quit window'
246 break
247 endif
Bram Moolenaarce11de82017-10-26 22:00:00 +0200248 endwhile
249
Bram Moolenaar358308d2016-08-24 21:21:26 +0200250 while 1
251 let wincount = winnr('$')
252 if wincount == 1
253 break
254 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200255 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200256 if wincount == winnr('$')
257 " Did not manage to close a window.
258 only!
259 break
260 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200261 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100262
263 exe 'cd ' . save_cwd
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200264
265 let message = 'Executed ' . a:test
266 if has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200267 let message ..= repeat(' ', 50 - len(message))
268 let time = reltime(func_start)
269 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200270 let message = s:t_bold .. message
Bram Moolenaar8d943792020-06-21 20:39:37 +0200271 endif
272 let message ..= ' in ' .. reltimestr(time) .. ' seconds'
273 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200274 let message ..= s:t_normal
Bram Moolenaar8d943792020-06-21 20:39:37 +0200275 endif
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200276 endif
277 call add(s:messages, message)
278 let s:done += 1
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100279endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100280
Bram Moolenaarce436de2020-03-21 15:17:20 +0100281func AfterTheTest(func_name)
Bram Moolenaar42205552017-03-18 19:42:22 +0100282 if len(v:errors) > 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100283 if match(s:may_fail_list, '^' .. a:func_name) >= 0
284 let s:fail_expected += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200285 call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100286 call extend(s:errors_expected, v:errors)
287 else
288 let s:fail += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200289 call add(s:errors, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100290 call extend(s:errors, v:errors)
291 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100292 let v:errors = []
293 endif
294endfunc
295
Bram Moolenaar89036762018-06-12 14:58:39 +0200296func EarlyExit(test)
297 " It's OK for the test we use to test the quit detection.
298 if a:test != 'Test_zz_quit_detected()'
299 call add(v:errors, 'Test caused Vim to exit: ' . a:test)
300 endif
301
302 call FinishTesting()
303endfunc
304
Bram Moolenaar42205552017-03-18 19:42:22 +0100305" This function can be called by a test if it wants to abort testing.
306func FinishTesting()
Bram Moolenaarce436de2020-03-21 15:17:20 +0100307 call AfterTheTest('')
Bram Moolenaar42205552017-03-18 19:42:22 +0100308
309 " Don't write viminfo on exit.
310 set viminfo=
311
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200312 " Clean up files created by setup.vim
313 call delete('XfakeHOME', 'rf')
314
Bram Moolenaarce436de2020-03-21 15:17:20 +0100315 if s:fail == 0 && s:fail_expected == 0
Bram Moolenaar42205552017-03-18 19:42:22 +0100316 " Success, create the .res file so that make knows it's done.
317 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
318 write
319 endif
320
321 if len(s:errors) > 0
322 " Append errors to test.log
323 split test.log
324 call append(line('$'), '')
325 call append(line('$'), 'From ' . g:testname . ':')
326 call append(line('$'), s:errors)
327 write
328 endif
329
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200330 if s:done == 0
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200331 if s:filtered > 0
332 let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
333 else
334 let message = 'NO tests executed'
335 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200336 else
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200337 if s:filtered > 0
338 call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER")
339 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200340 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
341 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200342 if s:done > 0 && has('reltime')
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200343 let message = s:t_bold .. message .. repeat(' ', 40 - len(message))
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200344 let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200345 let message ..= s:t_normal
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200346 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100347 echo message
348 call add(s:messages, message)
349 if s:fail > 0
350 let message = s:fail . ' FAILED:'
351 echo message
352 call add(s:messages, message)
353 call extend(s:messages, s:errors)
354 endif
Bram Moolenaarce436de2020-03-21 15:17:20 +0100355 if s:fail_expected > 0
356 let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
357 echo message
358 call add(s:messages, message)
359 call extend(s:messages, s:errors_expected)
360 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100361
362 " Add SKIPPED messages
363 call extend(s:messages, s:skipped)
364
365 " Append messages to the file "messages"
366 split messages
367 call append(line('$'), '')
368 call append(line('$'), 'From ' . g:testname . ':')
369 call append(line('$'), s:messages)
370 write
371
372 qall!
373endfunc
374
Bram Moolenaar43345542015-11-29 17:35:35 +0100375" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100376" navigates away. g:testname can be used by the tests.
377let g:testname = expand('%')
378let s:done = 0
379let s:fail = 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100380let s:fail_expected = 0
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100381let s:errors = []
Bram Moolenaarce436de2020-03-21 15:17:20 +0100382let s:errors_expected = []
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100383let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200384let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100385if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaarce436de2020-03-21 15:17:20 +0100386 " this test has intentional errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100387 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100388else
389 try
390 source %
Bram Moolenaar9c0cec62019-06-06 13:38:15 +0200391 catch /^\cskipped/
392 call add(s:messages, ' Skipped')
393 call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
Bram Moolenaara2cce862016-01-02 19:50:04 +0100394 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100395 let s:fail += 1
396 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100397 endtry
398endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100399
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100400" Names of flaky tests.
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100401let s:flaky_tests = [
Bram Moolenaar7d697962020-08-31 21:30:32 +0200402 \ 'Test_BufWrite_lockmarks()',
Bram Moolenaar0d0c3ca2019-09-25 21:16:15 +0200403 \ 'Test_autocmd_SafeState()',
Bram Moolenaar7d697962020-08-31 21:30:32 +0200404 \ 'Test_bufunload_all()',
Bram Moolenaar42205552017-03-18 19:42:22 +0100405 \ 'Test_client_server()',
Bram Moolenaar6fe2eb42017-01-29 21:49:51 +0100406 \ 'Test_close_and_exit_cb()',
Bram Moolenaard80232b2018-12-15 17:46:23 +0100407 \ 'Test_close_output_buffer()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100408 \ 'Test_collapse_buffers()',
Bram Moolenaar65873842018-03-25 17:12:58 +0200409 \ 'Test_cwd()',
Bram Moolenaar218959b2018-11-11 18:51:42 +0100410 \ 'Test_diff_screen()',
Bram Moolenaar0529b3e2017-03-16 22:30:37 +0100411 \ 'Test_exit_callback_interval()',
Bram Moolenaarea94c852019-08-16 21:47:27 +0200412 \ 'Test_map_timeout_with_timer_interrupt()',
Bram Moolenaar1eca6f12017-12-05 14:04:27 +0100413 \ 'Test_out_cb()',
Bram Moolenaarc79d6aa2016-09-25 22:27:37 +0200414 \ 'Test_pipe_through_sort_all()',
Bram Moolenaar4e032e12017-02-01 20:48:13 +0100415 \ 'Test_pipe_through_sort_some()',
Bram Moolenaar44f0bd82019-11-21 18:27:01 +0100416 \ 'Test_popup_and_window_resize()',
Bram Moolenaar0fbff642017-03-05 14:30:52 +0100417 \ 'Test_quoteplus()',
Bram Moolenaar7dd48502017-03-19 20:04:22 +0100418 \ 'Test_quotestar()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100419 \ 'Test_reltime()',
Bram Moolenaar3c8cd4a2019-10-14 22:26:20 +0200420 \ 'Test_state()',
Bram Moolenaarf204e052017-10-26 17:14:01 +0200421 \ 'Test_terminal_composing_unicode()',
Bram Moolenaar38767892019-02-21 18:17:14 +0100422 \ 'Test_terminal_does_not_truncate_last_newlines()',
Bram Moolenaar3615abb2019-02-10 23:04:12 +0100423 \ 'Test_terminal_no_cmd()',
Bram Moolenaar75a60f72017-09-07 22:24:41 +0200424 \ 'Test_terminal_noblock()',
Bram Moolenaar7dd88c52017-11-04 20:46:40 +0100425 \ 'Test_terminal_redir_file()',
Bram Moolenaare219f732019-11-30 15:34:08 +0100426 \ 'Test_termwinscroll()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200427 \ 'Test_timer_oneshot()',
428 \ 'Test_timer_paused()',
429 \ 'Test_timer_repeat_many()',
430 \ 'Test_timer_repeat_three()',
431 \ 'Test_timer_stop_all_in_callback()',
432 \ 'Test_timer_stop_in_callback()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200433 \ 'Test_timer_with_partial_callback()',
Bram Moolenaare1c8c7a2016-09-11 16:48:50 +0200434 \ ]
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100435
Bram Moolenaar43345542015-11-29 17:35:35 +0100436" Locate Test_ functions and execute them.
437redir @q
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100438silent function /^Test_
Bram Moolenaar43345542015-11-29 17:35:35 +0100439redir END
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +0100440let s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g'))
Bram Moolenaar43345542015-11-29 17:35:35 +0100441
Bram Moolenaarbefb3662016-02-20 14:41:40 +0100442" If there is an extra argument filter the function names against it.
443if argc() > 1
444 let s:tests = filter(s:tests, 'v:val =~ argv(1)')
445endif
446
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200447" If the environment variable $TEST_FILTER is set then filter the function
448" names against it.
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200449let s:filtered = 0
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200450if $TEST_FILTER != ''
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200451 let s:filtered = len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200452 let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER')
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200453 let s:filtered -= len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200454endif
455
Bram Moolenaarce436de2020-03-21 15:17:20 +0100456let s:may_fail_list = []
457if $TEST_MAY_FAIL != ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200458 " Split the list at commas and add () to make it match g:testfunc.
Bram Moolenaarce436de2020-03-21 15:17:20 +0100459 let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'})
460endif
461
Bram Moolenaarcfc0a352016-01-09 20:23:00 +0100462" Execute the tests in alphabetical order.
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200463for g:testfunc in sort(s:tests)
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200464 " Silence, please!
465 set belloff=all
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100466 let prev_error = ''
467 let total_errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100468 let g:run_nr = 1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200469
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200470 " A test can set g:test_is_flaky to retry running the test.
471 let g:test_is_flaky = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100472
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200473 call RunTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100474
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100475 " Repeat a flaky test. Give up when:
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200476 " - $TEST_NO_RETRY is not empty
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100477 " - it fails again with the same message
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200478 " - it fails five times (with a different message)
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100479 if len(v:errors) > 0
Bram Moolenaar622b3562020-07-27 20:02:41 +0200480 \ && $TEST_NO_RETRY == ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200481 \ && (index(s:flaky_tests, g:testfunc) >= 0
482 \ || g:test_is_flaky)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100483 while 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200484 call add(s:messages, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100485 call extend(s:messages, v:errors)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100486
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100487 call add(total_errors, 'Run ' . g:run_nr . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100488 call extend(total_errors, v:errors)
Bram Moolenaar55058602017-11-21 15:14:51 +0100489
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100490 if g:run_nr == 5 || prev_error == v:errors[0]
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100491 call add(total_errors, 'Flaky test failed too often, giving up')
492 let v:errors = total_errors
493 break
494 endif
495
496 call add(s:messages, 'Flaky test failed, running it again')
497
498 " Flakiness is often caused by the system being very busy. Sleep a
499 " couple of seconds to have a higher chance of succeeding the second
500 " time.
501 sleep 2
502
503 let prev_error = v:errors[0]
504 let v:errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100505 let g:run_nr += 1
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100506
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200507 call RunTheTest(g:testfunc)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100508
509 if len(v:errors) == 0
510 " Test passed on rerun.
511 break
512 endif
513 endwhile
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100514 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100515
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200516 call AfterTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100517endfor
518
Bram Moolenaar42205552017-03-18 19:42:22 +0100519call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100520
521" vim: shiftwidth=2 sts=2 expandtab