blob: 369d931f166a0fb127343b17d430188715d4c701 [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 Moolenaarb5760a12016-03-03 13:10:44 +0100165 echo '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 Moolenaarb5760a12016-03-03 13:10:44 +0100199 exe 'call ' . a:test
Bram Moolenaarf204e052017-10-26 17:14:01 +0200200 else
201 try
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200202 au VimLeavePre * call EarlyExit(g:testfunc)
Bram Moolenaarf204e052017-10-26 17:14:01 +0200203 exe 'call ' . a:test
Bram Moolenaar89036762018-06-12 14:58:39 +0200204 au! VimLeavePre
Bram Moolenaarf204e052017-10-26 17:14:01 +0200205 catch /^\cskipped/
206 call add(s:messages, ' Skipped')
207 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
208 catch
209 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
210 endtry
211 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100212
Bram Moolenaar8ad16da2019-01-06 15:29:57 +0100213 " In case 'insertmode' was set and something went wrong, make sure it is
214 " reset to avoid trouble with anything else.
215 set noinsertmode
216
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100217 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100218 try
219 call TearDown()
220 catch
221 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
222 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100223 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200224
Bram Moolenaar0b5dc642019-08-11 22:56:15 +0200225 " Clear any autocommands and put back the catch-all for SwapExists.
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200226 au!
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200227 au SwapExists * call HandleSwapExists()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200228
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200229 " Check for and close any stray popup windows.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100230 if has('popupwin')
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200231 call assert_equal([], popup_list())
Bram Moolenaar03a9f842020-05-13 13:40:16 +0200232 call popup_clear(1)
Bram Moolenaarae943152019-06-16 22:54:14 +0200233 endif
234
Bram Moolenaarce11de82017-10-26 22:00:00 +0200235 " Close any extra tab pages and windows and make the current one not modified.
236 while tabpagenr('$') > 1
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200237 let winid = win_getid()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200238 quit!
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200239 if winid == win_getid()
240 echoerr 'Could not quit window'
241 break
242 endif
Bram Moolenaarce11de82017-10-26 22:00:00 +0200243 endwhile
244
Bram Moolenaar358308d2016-08-24 21:21:26 +0200245 while 1
246 let wincount = winnr('$')
247 if wincount == 1
248 break
249 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200250 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200251 if wincount == winnr('$')
252 " Did not manage to close a window.
253 only!
254 break
255 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200256 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100257
258 exe 'cd ' . save_cwd
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200259
260 let message = 'Executed ' . a:test
261 if has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200262 let message ..= repeat(' ', 50 - len(message))
263 let time = reltime(func_start)
264 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200265 let message = s:t_bold .. message
Bram Moolenaar8d943792020-06-21 20:39:37 +0200266 endif
267 let message ..= ' in ' .. reltimestr(time) .. ' seconds'
268 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200269 let message ..= s:t_normal
Bram Moolenaar8d943792020-06-21 20:39:37 +0200270 endif
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200271 endif
272 call add(s:messages, message)
273 let s:done += 1
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100274endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100275
Bram Moolenaarce436de2020-03-21 15:17:20 +0100276func AfterTheTest(func_name)
Bram Moolenaar42205552017-03-18 19:42:22 +0100277 if len(v:errors) > 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100278 if match(s:may_fail_list, '^' .. a:func_name) >= 0
279 let s:fail_expected += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200280 call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100281 call extend(s:errors_expected, v:errors)
282 else
283 let s:fail += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200284 call add(s:errors, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100285 call extend(s:errors, v:errors)
286 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100287 let v:errors = []
288 endif
289endfunc
290
Bram Moolenaar89036762018-06-12 14:58:39 +0200291func EarlyExit(test)
292 " It's OK for the test we use to test the quit detection.
293 if a:test != 'Test_zz_quit_detected()'
294 call add(v:errors, 'Test caused Vim to exit: ' . a:test)
295 endif
296
297 call FinishTesting()
298endfunc
299
Bram Moolenaar42205552017-03-18 19:42:22 +0100300" This function can be called by a test if it wants to abort testing.
301func FinishTesting()
Bram Moolenaarce436de2020-03-21 15:17:20 +0100302 call AfterTheTest('')
Bram Moolenaar42205552017-03-18 19:42:22 +0100303
304 " Don't write viminfo on exit.
305 set viminfo=
306
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200307 " Clean up files created by setup.vim
308 call delete('XfakeHOME', 'rf')
309
Bram Moolenaarce436de2020-03-21 15:17:20 +0100310 if s:fail == 0 && s:fail_expected == 0
Bram Moolenaar42205552017-03-18 19:42:22 +0100311 " Success, create the .res file so that make knows it's done.
312 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
313 write
314 endif
315
316 if len(s:errors) > 0
317 " Append errors to test.log
318 split test.log
319 call append(line('$'), '')
320 call append(line('$'), 'From ' . g:testname . ':')
321 call append(line('$'), s:errors)
322 write
323 endif
324
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200325 if s:done == 0
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200326 if s:filtered > 0
327 let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
328 else
329 let message = 'NO tests executed'
330 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200331 else
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200332 if s:filtered > 0
333 call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER")
334 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200335 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
336 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200337 if s:done > 0 && has('reltime')
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200338 let message = s:t_bold .. message .. repeat(' ', 40 - len(message))
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200339 let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200340 let message ..= s:t_normal
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200341 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100342 echo message
343 call add(s:messages, message)
344 if s:fail > 0
345 let message = s:fail . ' FAILED:'
346 echo message
347 call add(s:messages, message)
348 call extend(s:messages, s:errors)
349 endif
Bram Moolenaarce436de2020-03-21 15:17:20 +0100350 if s:fail_expected > 0
351 let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
352 echo message
353 call add(s:messages, message)
354 call extend(s:messages, s:errors_expected)
355 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100356
357 " Add SKIPPED messages
358 call extend(s:messages, s:skipped)
359
360 " Append messages to the file "messages"
361 split messages
362 call append(line('$'), '')
363 call append(line('$'), 'From ' . g:testname . ':')
364 call append(line('$'), s:messages)
365 write
366
367 qall!
368endfunc
369
Bram Moolenaar43345542015-11-29 17:35:35 +0100370" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100371" navigates away. g:testname can be used by the tests.
372let g:testname = expand('%')
373let s:done = 0
374let s:fail = 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100375let s:fail_expected = 0
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100376let s:errors = []
Bram Moolenaarce436de2020-03-21 15:17:20 +0100377let s:errors_expected = []
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100378let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200379let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100380if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaarce436de2020-03-21 15:17:20 +0100381 " this test has intentional errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100382 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100383else
384 try
385 source %
Bram Moolenaar9c0cec62019-06-06 13:38:15 +0200386 catch /^\cskipped/
387 call add(s:messages, ' Skipped')
388 call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
Bram Moolenaara2cce862016-01-02 19:50:04 +0100389 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100390 let s:fail += 1
391 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100392 endtry
393endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100394
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100395" Names of flaky tests.
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100396let s:flaky_tests = [
Bram Moolenaar7d697962020-08-31 21:30:32 +0200397 \ 'Test_BufWrite_lockmarks()',
Bram Moolenaar0d0c3ca2019-09-25 21:16:15 +0200398 \ 'Test_autocmd_SafeState()',
Bram Moolenaar7d697962020-08-31 21:30:32 +0200399 \ 'Test_bufunload_all()',
Bram Moolenaar42205552017-03-18 19:42:22 +0100400 \ 'Test_client_server()',
Bram Moolenaar6fe2eb42017-01-29 21:49:51 +0100401 \ 'Test_close_and_exit_cb()',
Bram Moolenaard80232b2018-12-15 17:46:23 +0100402 \ 'Test_close_output_buffer()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100403 \ 'Test_collapse_buffers()',
Bram Moolenaar65873842018-03-25 17:12:58 +0200404 \ 'Test_cwd()',
Bram Moolenaar218959b2018-11-11 18:51:42 +0100405 \ 'Test_diff_screen()',
Bram Moolenaar0529b3e2017-03-16 22:30:37 +0100406 \ 'Test_exit_callback_interval()',
Bram Moolenaarea94c852019-08-16 21:47:27 +0200407 \ 'Test_map_timeout_with_timer_interrupt()',
Bram Moolenaar1eca6f12017-12-05 14:04:27 +0100408 \ 'Test_out_cb()',
Bram Moolenaarc79d6aa2016-09-25 22:27:37 +0200409 \ 'Test_pipe_through_sort_all()',
Bram Moolenaar4e032e12017-02-01 20:48:13 +0100410 \ 'Test_pipe_through_sort_some()',
Bram Moolenaar44f0bd82019-11-21 18:27:01 +0100411 \ 'Test_popup_and_window_resize()',
Bram Moolenaar0fbff642017-03-05 14:30:52 +0100412 \ 'Test_quoteplus()',
Bram Moolenaar7dd48502017-03-19 20:04:22 +0100413 \ 'Test_quotestar()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100414 \ 'Test_reltime()',
Bram Moolenaar3c8cd4a2019-10-14 22:26:20 +0200415 \ 'Test_state()',
Bram Moolenaarf204e052017-10-26 17:14:01 +0200416 \ 'Test_terminal_composing_unicode()',
Bram Moolenaar38767892019-02-21 18:17:14 +0100417 \ 'Test_terminal_does_not_truncate_last_newlines()',
Bram Moolenaar3615abb2019-02-10 23:04:12 +0100418 \ 'Test_terminal_no_cmd()',
Bram Moolenaar75a60f72017-09-07 22:24:41 +0200419 \ 'Test_terminal_noblock()',
Bram Moolenaar7dd88c52017-11-04 20:46:40 +0100420 \ 'Test_terminal_redir_file()',
Bram Moolenaare219f732019-11-30 15:34:08 +0100421 \ 'Test_termwinscroll()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200422 \ 'Test_timer_oneshot()',
423 \ 'Test_timer_paused()',
424 \ 'Test_timer_repeat_many()',
425 \ 'Test_timer_repeat_three()',
426 \ 'Test_timer_stop_all_in_callback()',
427 \ 'Test_timer_stop_in_callback()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200428 \ 'Test_timer_with_partial_callback()',
Bram Moolenaare1c8c7a2016-09-11 16:48:50 +0200429 \ ]
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100430
Bram Moolenaar43345542015-11-29 17:35:35 +0100431" Locate Test_ functions and execute them.
432redir @q
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100433silent function /^Test_
Bram Moolenaar43345542015-11-29 17:35:35 +0100434redir END
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +0100435let s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g'))
Bram Moolenaar43345542015-11-29 17:35:35 +0100436
Bram Moolenaarbefb3662016-02-20 14:41:40 +0100437" If there is an extra argument filter the function names against it.
438if argc() > 1
439 let s:tests = filter(s:tests, 'v:val =~ argv(1)')
440endif
441
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200442" If the environment variable $TEST_FILTER is set then filter the function
443" names against it.
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200444let s:filtered = 0
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200445if $TEST_FILTER != ''
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200446 let s:filtered = len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200447 let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER')
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200448 let s:filtered -= len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200449endif
450
Bram Moolenaarce436de2020-03-21 15:17:20 +0100451let s:may_fail_list = []
452if $TEST_MAY_FAIL != ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200453 " Split the list at commas and add () to make it match g:testfunc.
Bram Moolenaarce436de2020-03-21 15:17:20 +0100454 let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'})
455endif
456
Bram Moolenaarcfc0a352016-01-09 20:23:00 +0100457" Execute the tests in alphabetical order.
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200458for g:testfunc in sort(s:tests)
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200459 " Silence, please!
460 set belloff=all
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100461 let prev_error = ''
462 let total_errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100463 let g:run_nr = 1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200464
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200465 " A test can set g:test_is_flaky to retry running the test.
466 let g:test_is_flaky = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100467
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200468 call RunTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100469
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100470 " Repeat a flaky test. Give up when:
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200471 " - $TEST_NO_RETRY is not empty
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100472 " - it fails again with the same message
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200473 " - it fails five times (with a different message)
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100474 if len(v:errors) > 0
Bram Moolenaar622b3562020-07-27 20:02:41 +0200475 \ && $TEST_NO_RETRY == ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200476 \ && (index(s:flaky_tests, g:testfunc) >= 0
477 \ || g:test_is_flaky)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100478 while 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200479 call add(s:messages, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100480 call extend(s:messages, v:errors)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100481
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100482 call add(total_errors, 'Run ' . g:run_nr . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100483 call extend(total_errors, v:errors)
Bram Moolenaar55058602017-11-21 15:14:51 +0100484
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100485 if g:run_nr == 5 || prev_error == v:errors[0]
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100486 call add(total_errors, 'Flaky test failed too often, giving up')
487 let v:errors = total_errors
488 break
489 endif
490
491 call add(s:messages, 'Flaky test failed, running it again')
492
493 " Flakiness is often caused by the system being very busy. Sleep a
494 " couple of seconds to have a higher chance of succeeding the second
495 " time.
496 sleep 2
497
498 let prev_error = v:errors[0]
499 let v:errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100500 let g:run_nr += 1
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100501
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200502 call RunTheTest(g:testfunc)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100503
504 if len(v:errors) == 0
505 " Test passed on rerun.
506 break
507 endif
508 endwhile
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100509 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100510
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200511 call AfterTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100512endfor
513
Bram Moolenaar42205552017-03-18 19:42:22 +0100514call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100515
516" vim: shiftwidth=2 sts=2 expandtab