blob: 6b09b975dec6ba7d491681ea6c37f496a682d6a4 [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 Moolenaar8e8df252016-05-25 21:23:21 +0200139" Prepare for calling test_garbagecollect_now().
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200140let v:testing = 1
141
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100142" Support function: get the alloc ID by name.
143function GetAllocId(name)
144 exe 'split ' . s:srcdir . '/alloc.h'
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100145 let top = search('typedef enum')
146 if top == 0
147 call add(v:errors, 'typedef not found in alloc.h')
148 endif
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100149 let lnum = search('aid_' . a:name . ',')
150 if lnum == 0
151 call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
152 endif
153 close
Bram Moolenaar065ee9a2016-01-15 20:53:38 +0100154 return lnum - top - 1
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100155endfunc
156
Bram Moolenaar42205552017-03-18 19:42:22 +0100157func RunTheTest(test)
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100158 echo 'Executing ' . a:test
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200159 if has('reltime')
160 let func_start = reltime()
161 endif
Bram Moolenaare5f2a072017-02-01 22:31:49 +0100162
163 " Avoid stopping at the "hit enter" prompt
164 set nomore
165
166 " Avoid a three second wait when a message is about to be overwritten by the
167 " mode message.
168 set noshowmode
169
Bram Moolenaareb992cb2017-03-09 18:20:16 +0100170 " Clear any overrides.
171 call test_override('ALL', 0)
172
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200173 " Some tests wipe out buffers. To be consistent, always wipe out all
174 " buffers.
175 %bwipe!
176
Bram Moolenaar209d3872017-11-16 21:52:51 +0100177 " The test may change the current directory. Save and restore the
178 " directory after executing the test.
179 let save_cwd = getcwd()
180
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100181 if exists("*SetUp")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100182 try
183 call SetUp()
184 catch
185 call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
186 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100187 endif
188
Bram Moolenaarf204e052017-10-26 17:14:01 +0200189 if a:test =~ 'Test_nocatch_'
190 " Function handles errors itself. This avoids skipping commands after the
191 " error.
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100192 exe 'call ' . a:test
Bram Moolenaarf204e052017-10-26 17:14:01 +0200193 else
194 try
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200195 au VimLeavePre * call EarlyExit(g:testfunc)
Bram Moolenaarf204e052017-10-26 17:14:01 +0200196 exe 'call ' . a:test
Bram Moolenaar89036762018-06-12 14:58:39 +0200197 au! VimLeavePre
Bram Moolenaarf204e052017-10-26 17:14:01 +0200198 catch /^\cskipped/
199 call add(s:messages, ' Skipped')
200 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
201 catch
202 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
203 endtry
204 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100205
Bram Moolenaar8ad16da2019-01-06 15:29:57 +0100206 " In case 'insertmode' was set and something went wrong, make sure it is
207 " reset to avoid trouble with anything else.
208 set noinsertmode
209
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100210 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100211 try
212 call TearDown()
213 catch
214 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
215 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100216 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200217
Bram Moolenaar0b5dc642019-08-11 22:56:15 +0200218 " Clear any autocommands and put back the catch-all for SwapExists.
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200219 au!
Bram Moolenaard8f27b32018-10-07 15:42:07 +0200220 au SwapExists * call HandleSwapExists()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200221
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200222 " Check for and close any stray popup windows.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100223 if has('popupwin')
Bram Moolenaaref6b9792020-05-13 16:34:15 +0200224 call assert_equal([], popup_list())
Bram Moolenaar03a9f842020-05-13 13:40:16 +0200225 call popup_clear(1)
Bram Moolenaarae943152019-06-16 22:54:14 +0200226 endif
227
Bram Moolenaarce11de82017-10-26 22:00:00 +0200228 " Close any extra tab pages and windows and make the current one not modified.
229 while tabpagenr('$') > 1
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200230 let winid = win_getid()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200231 quit!
Bram Moolenaarbdf931c2020-10-01 22:37:40 +0200232 if winid == win_getid()
233 echoerr 'Could not quit window'
234 break
235 endif
Bram Moolenaarce11de82017-10-26 22:00:00 +0200236 endwhile
237
Bram Moolenaar358308d2016-08-24 21:21:26 +0200238 while 1
239 let wincount = winnr('$')
240 if wincount == 1
241 break
242 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200243 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200244 if wincount == winnr('$')
245 " Did not manage to close a window.
246 only!
247 break
248 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200249 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100250
251 exe 'cd ' . save_cwd
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200252
253 let message = 'Executed ' . a:test
254 if has('reltime')
Bram Moolenaar8d943792020-06-21 20:39:37 +0200255 let message ..= repeat(' ', 50 - len(message))
256 let time = reltime(func_start)
257 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200258 let message = s:t_bold .. message
Bram Moolenaar8d943792020-06-21 20:39:37 +0200259 endif
260 let message ..= ' in ' .. reltimestr(time) .. ' seconds'
261 if has('float') && reltimefloat(time) > 0.1
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200262 let message ..= s:t_normal
Bram Moolenaar8d943792020-06-21 20:39:37 +0200263 endif
Bram Moolenaar640d4f02019-06-10 17:43:46 +0200264 endif
265 call add(s:messages, message)
266 let s:done += 1
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100267endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100268
Bram Moolenaarce436de2020-03-21 15:17:20 +0100269func AfterTheTest(func_name)
Bram Moolenaar42205552017-03-18 19:42:22 +0100270 if len(v:errors) > 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100271 if match(s:may_fail_list, '^' .. a:func_name) >= 0
272 let s:fail_expected += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200273 call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100274 call extend(s:errors_expected, v:errors)
275 else
276 let s:fail += 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200277 call add(s:errors, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarce436de2020-03-21 15:17:20 +0100278 call extend(s:errors, v:errors)
279 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100280 let v:errors = []
281 endif
282endfunc
283
Bram Moolenaar89036762018-06-12 14:58:39 +0200284func EarlyExit(test)
285 " It's OK for the test we use to test the quit detection.
286 if a:test != 'Test_zz_quit_detected()'
287 call add(v:errors, 'Test caused Vim to exit: ' . a:test)
288 endif
289
290 call FinishTesting()
291endfunc
292
Bram Moolenaar42205552017-03-18 19:42:22 +0100293" This function can be called by a test if it wants to abort testing.
294func FinishTesting()
Bram Moolenaarce436de2020-03-21 15:17:20 +0100295 call AfterTheTest('')
Bram Moolenaar42205552017-03-18 19:42:22 +0100296
297 " Don't write viminfo on exit.
298 set viminfo=
299
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200300 " Clean up files created by setup.vim
301 call delete('XfakeHOME', 'rf')
302
Bram Moolenaarce436de2020-03-21 15:17:20 +0100303 if s:fail == 0 && s:fail_expected == 0
Bram Moolenaar42205552017-03-18 19:42:22 +0100304 " Success, create the .res file so that make knows it's done.
305 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
306 write
307 endif
308
309 if len(s:errors) > 0
310 " Append errors to test.log
311 split test.log
312 call append(line('$'), '')
313 call append(line('$'), 'From ' . g:testname . ':')
314 call append(line('$'), s:errors)
315 write
316 endif
317
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200318 if s:done == 0
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200319 if s:filtered > 0
320 let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
321 else
322 let message = 'NO tests executed'
323 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200324 else
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200325 if s:filtered > 0
326 call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER")
327 endif
Bram Moolenaar29f9ed22018-04-10 19:20:31 +0200328 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
329 endif
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200330 if s:done > 0 && has('reltime')
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200331 let message = s:t_bold .. message .. repeat(' ', 40 - len(message))
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200332 let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
Bram Moolenaar45df2a02020-07-29 15:03:01 +0200333 let message ..= s:t_normal
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200334 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100335 echo message
336 call add(s:messages, message)
337 if s:fail > 0
338 let message = s:fail . ' FAILED:'
339 echo message
340 call add(s:messages, message)
341 call extend(s:messages, s:errors)
342 endif
Bram Moolenaarce436de2020-03-21 15:17:20 +0100343 if s:fail_expected > 0
344 let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
345 echo message
346 call add(s:messages, message)
347 call extend(s:messages, s:errors_expected)
348 endif
Bram Moolenaar42205552017-03-18 19:42:22 +0100349
350 " Add SKIPPED messages
351 call extend(s:messages, s:skipped)
352
353 " Append messages to the file "messages"
354 split messages
355 call append(line('$'), '')
356 call append(line('$'), 'From ' . g:testname . ':')
357 call append(line('$'), s:messages)
358 write
359
360 qall!
361endfunc
362
Bram Moolenaar43345542015-11-29 17:35:35 +0100363" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100364" navigates away. g:testname can be used by the tests.
365let g:testname = expand('%')
366let s:done = 0
367let s:fail = 0
Bram Moolenaarce436de2020-03-21 15:17:20 +0100368let s:fail_expected = 0
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100369let s:errors = []
Bram Moolenaarce436de2020-03-21 15:17:20 +0100370let s:errors_expected = []
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100371let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200372let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100373if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaarce436de2020-03-21 15:17:20 +0100374 " this test has intentional errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100375 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100376else
377 try
378 source %
Bram Moolenaar9c0cec62019-06-06 13:38:15 +0200379 catch /^\cskipped/
380 call add(s:messages, ' Skipped')
381 call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
Bram Moolenaara2cce862016-01-02 19:50:04 +0100382 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100383 let s:fail += 1
384 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100385 endtry
386endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100387
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100388" Names of flaky tests.
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100389let s:flaky_tests = [
Bram Moolenaar7d697962020-08-31 21:30:32 +0200390 \ 'Test_BufWrite_lockmarks()',
Bram Moolenaar0d0c3ca2019-09-25 21:16:15 +0200391 \ 'Test_autocmd_SafeState()',
Bram Moolenaar7d697962020-08-31 21:30:32 +0200392 \ 'Test_bufunload_all()',
Bram Moolenaar42205552017-03-18 19:42:22 +0100393 \ 'Test_client_server()',
Bram Moolenaar6fe2eb42017-01-29 21:49:51 +0100394 \ 'Test_close_and_exit_cb()',
Bram Moolenaard80232b2018-12-15 17:46:23 +0100395 \ 'Test_close_output_buffer()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100396 \ 'Test_collapse_buffers()',
Bram Moolenaar65873842018-03-25 17:12:58 +0200397 \ 'Test_cwd()',
Bram Moolenaar218959b2018-11-11 18:51:42 +0100398 \ 'Test_diff_screen()',
Bram Moolenaar0529b3e2017-03-16 22:30:37 +0100399 \ 'Test_exit_callback_interval()',
Bram Moolenaarea94c852019-08-16 21:47:27 +0200400 \ 'Test_map_timeout_with_timer_interrupt()',
Bram Moolenaar1eca6f12017-12-05 14:04:27 +0100401 \ 'Test_out_cb()',
Bram Moolenaarc79d6aa2016-09-25 22:27:37 +0200402 \ 'Test_pipe_through_sort_all()',
Bram Moolenaar4e032e12017-02-01 20:48:13 +0100403 \ 'Test_pipe_through_sort_some()',
Bram Moolenaar44f0bd82019-11-21 18:27:01 +0100404 \ 'Test_popup_and_window_resize()',
Bram Moolenaar0fbff642017-03-05 14:30:52 +0100405 \ 'Test_quoteplus()',
Bram Moolenaar7dd48502017-03-19 20:04:22 +0100406 \ 'Test_quotestar()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100407 \ 'Test_reltime()',
Bram Moolenaar3c8cd4a2019-10-14 22:26:20 +0200408 \ 'Test_state()',
Bram Moolenaarf204e052017-10-26 17:14:01 +0200409 \ 'Test_terminal_composing_unicode()',
Bram Moolenaar38767892019-02-21 18:17:14 +0100410 \ 'Test_terminal_does_not_truncate_last_newlines()',
Bram Moolenaar3615abb2019-02-10 23:04:12 +0100411 \ 'Test_terminal_no_cmd()',
Bram Moolenaar75a60f72017-09-07 22:24:41 +0200412 \ 'Test_terminal_noblock()',
Bram Moolenaar7dd88c52017-11-04 20:46:40 +0100413 \ 'Test_terminal_redir_file()',
Bram Moolenaare219f732019-11-30 15:34:08 +0100414 \ 'Test_termwinscroll()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200415 \ 'Test_timer_oneshot()',
416 \ 'Test_timer_paused()',
417 \ 'Test_timer_repeat_many()',
418 \ 'Test_timer_repeat_three()',
419 \ 'Test_timer_stop_all_in_callback()',
420 \ 'Test_timer_stop_in_callback()',
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200421 \ 'Test_timer_with_partial_callback()',
Bram Moolenaare1c8c7a2016-09-11 16:48:50 +0200422 \ ]
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100423
Bram Moolenaar43345542015-11-29 17:35:35 +0100424" Locate Test_ functions and execute them.
425redir @q
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100426silent function /^Test_
Bram Moolenaar43345542015-11-29 17:35:35 +0100427redir END
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +0100428let s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g'))
Bram Moolenaar43345542015-11-29 17:35:35 +0100429
Bram Moolenaarbefb3662016-02-20 14:41:40 +0100430" If there is an extra argument filter the function names against it.
431if argc() > 1
432 let s:tests = filter(s:tests, 'v:val =~ argv(1)')
433endif
434
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200435" If the environment variable $TEST_FILTER is set then filter the function
436" names against it.
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200437let s:filtered = 0
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200438if $TEST_FILTER != ''
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200439 let s:filtered = len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200440 let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER')
Bram Moolenaar7b666c72019-09-27 21:25:00 +0200441 let s:filtered -= len(s:tests)
Bram Moolenaara7f6c3c2019-09-27 15:34:16 +0200442endif
443
Bram Moolenaarce436de2020-03-21 15:17:20 +0100444let s:may_fail_list = []
445if $TEST_MAY_FAIL != ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200446 " Split the list at commas and add () to make it match g:testfunc.
Bram Moolenaarce436de2020-03-21 15:17:20 +0100447 let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'})
448endif
449
Bram Moolenaarcfc0a352016-01-09 20:23:00 +0100450" Execute the tests in alphabetical order.
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200451for g:testfunc in sort(s:tests)
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200452 " Silence, please!
453 set belloff=all
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100454 let prev_error = ''
455 let total_errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100456 let g:run_nr = 1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200457
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200458 " A test can set g:test_is_flaky to retry running the test.
459 let g:test_is_flaky = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100460
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200461 call RunTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100462
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100463 " Repeat a flaky test. Give up when:
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200464 " - $TEST_NO_RETRY is not empty
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100465 " - it fails again with the same message
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200466 " - it fails five times (with a different message)
Bram Moolenaardbc0d212018-11-16 18:22:45 +0100467 if len(v:errors) > 0
Bram Moolenaar622b3562020-07-27 20:02:41 +0200468 \ && $TEST_NO_RETRY == ''
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200469 \ && (index(s:flaky_tests, g:testfunc) >= 0
470 \ || g:test_is_flaky)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100471 while 1
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200472 call add(s:messages, 'Found errors in ' . g:testfunc . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100473 call extend(s:messages, v:errors)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100474
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100475 call add(total_errors, 'Run ' . g:run_nr . ':')
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100476 call extend(total_errors, v:errors)
Bram Moolenaar55058602017-11-21 15:14:51 +0100477
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100478 if g:run_nr == 5 || prev_error == v:errors[0]
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100479 call add(total_errors, 'Flaky test failed too often, giving up')
480 let v:errors = total_errors
481 break
482 endif
483
484 call add(s:messages, 'Flaky test failed, running it again')
485
486 " Flakiness is often caused by the system being very busy. Sleep a
487 " couple of seconds to have a higher chance of succeeding the second
488 " time.
489 sleep 2
490
491 let prev_error = v:errors[0]
492 let v:errors = []
Bram Moolenaar3ed9efc2020-03-26 16:50:57 +0100493 let g:run_nr += 1
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100494
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200495 call RunTheTest(g:testfunc)
Bram Moolenaarf77af0e2018-11-16 16:52:16 +0100496
497 if len(v:errors) == 0
498 " Test passed on rerun.
499 break
500 endif
501 endwhile
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100502 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100503
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +0200504 call AfterTheTest(g:testfunc)
Bram Moolenaar43345542015-11-29 17:35:35 +0100505endfor
506
Bram Moolenaar42205552017-03-18 19:42:22 +0100507call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100508
509" vim: shiftwidth=2 sts=2 expandtab