xref: /vim-8.2.3635/src/testdir/runtest.vim (revision 2690b5ae)
143345546SBram Moolenaar" This script is sourced while editing the .vim file with the tests.
243345546SBram Moolenaar" When the script is successful the .res file will be created.
343345546SBram Moolenaar" Errors are appended to the test.log file.
443345546SBram Moolenaar"
5befb366aSBram Moolenaar" To execute only specific test functions, add a second argument.  It will be
6e219f73eSBram Moolenaar" matched against the names of the Test_ function.  E.g.:
7befb366aSBram Moolenaar"	../vim -u NONE -S runtest.vim test_channel.vim open_delay
8befb366aSBram Moolenaar" The output can be found in the "messages" file.
9befb366aSBram Moolenaar"
10ce436de5SBram Moolenaar" If the environment variable $TEST_FILTER is set then only test functions
11ce436de5SBram Moolenaar" matching this pattern are executed.  E.g. for sh/bash:
12ce436de5SBram Moolenaar"     export TEST_FILTER=Test_channel
13ce436de5SBram Moolenaar" For csh:
14ce436de5SBram Moolenaar"     setenv TEST_FILTER Test_channel
15ce436de5SBram Moolenaar"
16ce436de5SBram Moolenaar" To ignore failure for tests that are known to fail in a certain environment,
17ce436de5SBram Moolenaar" set $TEST_MAY_FAIL to a comma separated list of function names.  E.g. for
18ce436de5SBram Moolenaar" sh/bash:
19ce436de5SBram Moolenaar"     export TEST_MAY_FAIL=Test_channel_one,Test_channel_other
20ce436de5SBram Moolenaar" The failure report will then not be included in the test.log file and
21ce436de5SBram Moolenaar" "make test" will not fail.
22ce436de5SBram Moolenaar"
2343345546SBram Moolenaar" The test script may contain anything, only functions that start with
2443345546SBram Moolenaar" "Test_" are special.  These will be invoked and should contain assert
2543345546SBram Moolenaar" functions.  See test_assert.vim for an example.
2643345546SBram Moolenaar"
2743345546SBram Moolenaar" It is possible to source other files that contain "Test_" functions.  This
2843345546SBram Moolenaar" can speed up testing, since Vim does not need to restart.  But be careful
2943345546SBram Moolenaar" that the tests do not interfere with each other.
3043345546SBram Moolenaar"
3143345546SBram Moolenaar" If an error cannot be detected properly with an assert function add the
3243345546SBram Moolenaar" error to the v:errors list:
3343345546SBram Moolenaar"   call add(v:errors, 'test foo failed: Cannot find xyz')
3443345546SBram Moolenaar"
3543345546SBram Moolenaar" If preparation for each Test_ function is needed, define a SetUp function.
3643345546SBram Moolenaar" It will be called before each Test_ function.
3743345546SBram Moolenaar"
3843345546SBram Moolenaar" If cleanup after each Test_ function is needed, define a TearDown function.
3943345546SBram Moolenaar" It will be called after each Test_ function.
4000af60bbSBram Moolenaar"
4100af60bbSBram Moolenaar" When debugging a test it can be useful to add messages to v:errors:
4200af60bbSBram Moolenaar"	call add(v:errors, "this happened")
4300af60bbSBram Moolenaar
4443345546SBram Moolenaar
4543345546SBram Moolenaar" Without the +eval feature we can't run these tests, bail out.
464686b323SBram Moolenaarso small.vim
4743345546SBram Moolenaar
4818aa13d1SBram Moolenaar" In the GUI we can always change the screen size.
4918aa13d1SBram Moolenaarif has('gui_running')
5018aa13d1SBram Moolenaar  set columns=80 lines=25
5118aa13d1SBram Moolenaarendif
5218aa13d1SBram Moolenaar
5343345546SBram Moolenaar" Check that the screen size is at least 24 x 80 characters.
5443345546SBram Moolenaarif &lines < 24 || &columns < 80
550b5dc644SBram Moolenaar  let error = 'Screen size too small! Tests require at least 24 lines with 80 characters, got ' .. &lines .. ' lines with ' .. &columns .. ' characters'
5643345546SBram Moolenaar  echoerr error
5743345546SBram Moolenaar  split test.log
5843345546SBram Moolenaar  $put =error
5945aa07d3SBram Moolenaar  write
6045aa07d3SBram Moolenaar  split messages
610b5dc644SBram Moolenaar  call append(line('$'), '')
620b5dc644SBram Moolenaar  call append(line('$'), 'From ' . expand('%') . ':')
6345aa07d3SBram Moolenaar  call append(line('$'), error)
6445aa07d3SBram Moolenaar  write
6545aa07d3SBram Moolenaar  qa!
6643345546SBram Moolenaarendif
6743345546SBram Moolenaar
6875ee544fSBram Moolenaarif has('reltime')
6975ee544fSBram Moolenaar  let s:start_time = reltime()
7075ee544fSBram Moolenaarendif
7175ee544fSBram Moolenaar
7289b10421SBram Moolenaar" Common with all tests on all systems.
7389b10421SBram Moolenaarsource setup.vim
7489b10421SBram Moolenaar
75c0662466SBram Moolenaar" For consistency run all tests with 'nocompatible' set.
76c0662466SBram Moolenaar" This also enables use of line continuation.
77c0662466SBram Moolenaarset nocp viminfo+=nviminfo
78c0662466SBram Moolenaar
7930276f2bSBram Moolenaar" Use utf-8 by default, instead of whatever the system default happens to be.
80ed79d1e3SBram Moolenaar" Individual tests can overrule this at the top of the file and use
81ed79d1e3SBram Moolenaar" g:orig_encoding if needed.
82ed79d1e3SBram Moolenaarlet g:orig_encoding = &encoding
83ac105ed3SBram Moolenaarset encoding=utf-8
84ac105ed3SBram Moolenaar
85d8f27b30SBram Moolenaar" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for
86d8f27b30SBram Moolenaar" the test_name.vim file itself. Replace it here with a more restrictive one,
87d8f27b30SBram Moolenaar" so we still catch mistakes.
88d8f27b30SBram Moolenaarlet s:test_script_fname = expand('%')
89d8f27b30SBram Moolenaarau! SwapExists * call HandleSwapExists()
90d8f27b30SBram Moolenaarfunc HandleSwapExists()
91b073da89SBram Moolenaar  " Ignore finding a swap file for the test script (the user might be
92d8f27b30SBram Moolenaar  " editing it and do ":make test_name") and the output file.
93b073da89SBram Moolenaar  " Report finding another swap file and chose 'q' to avoid getting stuck.
94d8f27b30SBram Moolenaar  if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname
95d8f27b30SBram Moolenaar    let v:swapchoice = 'e'
96b073da89SBram Moolenaar  else
97b073da89SBram Moolenaar    call assert_report('Unexpected swap file: ' .. v:swapname)
98b073da89SBram Moolenaar    let v:swapchoice = 'q'
99d8f27b30SBram Moolenaar  endif
100d8f27b30SBram Moolenaarendfunc
101d8f27b30SBram Moolenaar
1027a073549SBram Moolenaar" Avoid stopping at the "hit enter" prompt
1037a073549SBram Moolenaarset nomore
1047a073549SBram Moolenaar
105c0662466SBram Moolenaar" Output all messages in English.
106c0662466SBram Moolenaarlang mess C
107c0662466SBram Moolenaar
10810e1d01aSBram Moolenaar" suppress menu translation
10910e1d01aSBram Moolenaarif has('gui_running') && exists('did_install_default_menus')
11010e1d01aSBram Moolenaar  source $VIMRUNTIME/delmenu.vim
11110e1d01aSBram Moolenaar  set langmenu=none
11210e1d01aSBram Moolenaar  source $VIMRUNTIME/menu.vim
11310e1d01aSBram Moolenaarendif
11410e1d01aSBram Moolenaar
115f60b796fSBram Moolenaar" Always use forward slashes.
116f60b796fSBram Moolenaarset shellslash
117f60b796fSBram Moolenaar
11828fb79dbSBram Moolenaarlet s:srcdir = expand('%:p:h:h')
11928fb79dbSBram Moolenaar
120*2690b5aeSBram Moolenaarif has('win32')
121*2690b5aeSBram Moolenaar  " avoid prompt that is long or contains a line break
122*2690b5aeSBram Moolenaar  let $PROMPT = '$P$G'
123*2690b5aeSBram Moolenaarendif
124*2690b5aeSBram Moolenaar
1258e8df251SBram Moolenaar" Prepare for calling test_garbagecollect_now().
126ebf7dfa6SBram Moolenaarlet v:testing = 1
127ebf7dfa6SBram Moolenaar
12828fb79dbSBram Moolenaar" Support function: get the alloc ID by name.
12928fb79dbSBram Moolenaarfunction GetAllocId(name)
13028fb79dbSBram Moolenaar  exe 'split ' . s:srcdir . '/alloc.h'
131065ee9aeSBram Moolenaar  let top = search('typedef enum')
132065ee9aeSBram Moolenaar  if top == 0
133065ee9aeSBram Moolenaar    call add(v:errors, 'typedef not found in alloc.h')
134065ee9aeSBram Moolenaar  endif
13528fb79dbSBram Moolenaar  let lnum = search('aid_' . a:name . ',')
13628fb79dbSBram Moolenaar  if lnum == 0
13728fb79dbSBram Moolenaar    call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
13828fb79dbSBram Moolenaar  endif
13928fb79dbSBram Moolenaar  close
140065ee9aeSBram Moolenaar  return lnum - top - 1
14128fb79dbSBram Moolenaarendfunc
14228fb79dbSBram Moolenaar
14342205551SBram Moolenaarfunc RunTheTest(test)
144b5760a1cSBram Moolenaar  echo 'Executing ' . a:test
14575ee544fSBram Moolenaar  if has('reltime')
14675ee544fSBram Moolenaar    let func_start = reltime()
14775ee544fSBram Moolenaar  endif
148e5f2a075SBram Moolenaar
149e5f2a075SBram Moolenaar  " Avoid stopping at the "hit enter" prompt
150e5f2a075SBram Moolenaar  set nomore
151e5f2a075SBram Moolenaar
152e5f2a075SBram Moolenaar  " Avoid a three second wait when a message is about to be overwritten by the
153e5f2a075SBram Moolenaar  " mode message.
154e5f2a075SBram Moolenaar  set noshowmode
155e5f2a075SBram Moolenaar
156eb992cb9SBram Moolenaar  " Clear any overrides.
157eb992cb9SBram Moolenaar  call test_override('ALL', 0)
158eb992cb9SBram Moolenaar
159cf1ba35fSBram Moolenaar  " Some tests wipe out buffers.  To be consistent, always wipe out all
160cf1ba35fSBram Moolenaar  " buffers.
161cf1ba35fSBram Moolenaar  %bwipe!
162cf1ba35fSBram Moolenaar
163209d3874SBram Moolenaar  " The test may change the current directory. Save and restore the
164209d3874SBram Moolenaar  " directory after executing the test.
165209d3874SBram Moolenaar  let save_cwd = getcwd()
166209d3874SBram Moolenaar
167b5760a1cSBram Moolenaar  if exists("*SetUp")
168cc28e2d0SBram Moolenaar    try
169b5760a1cSBram Moolenaar      call SetUp()
170cc28e2d0SBram Moolenaar    catch
171cc28e2d0SBram Moolenaar      call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
172cc28e2d0SBram Moolenaar    endtry
173b5760a1cSBram Moolenaar  endif
174b5760a1cSBram Moolenaar
175f204e05aSBram Moolenaar  if a:test =~ 'Test_nocatch_'
176f204e05aSBram Moolenaar    " Function handles errors itself.  This avoids skipping commands after the
177f204e05aSBram Moolenaar    " error.
178f204e05aSBram Moolenaar    exe 'call ' . a:test
179f204e05aSBram Moolenaar  else
180b5760a1cSBram Moolenaar    try
181bfe13cccSBram Moolenaar      au VimLeavePre * call EarlyExit(g:testfunc)
182b5760a1cSBram Moolenaar      exe 'call ' . a:test
1838903676dSBram Moolenaar      au! VimLeavePre
184dac1947bSBram Moolenaar    catch /^\cskipped/
185dac1947bSBram Moolenaar      call add(s:messages, '    Skipped')
186dac1947bSBram Moolenaar      call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '',  ''))
187b5760a1cSBram Moolenaar    catch
188b5760a1cSBram Moolenaar      call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
189b5760a1cSBram Moolenaar    endtry
190f204e05aSBram Moolenaar  endif
1918ad16da7SBram Moolenaar
1928ad16da7SBram Moolenaar  " In case 'insertmode' was set and something went wrong, make sure it is
1938ad16da7SBram Moolenaar  " reset to avoid trouble with anything else.
1948ad16da7SBram Moolenaar  set noinsertmode
195b5760a1cSBram Moolenaar
196b5760a1cSBram Moolenaar  if exists("*TearDown")
197cc28e2d0SBram Moolenaar    try
198b5760a1cSBram Moolenaar      call TearDown()
199cc28e2d0SBram Moolenaar    catch
200cc28e2d0SBram Moolenaar      call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
201cc28e2d0SBram Moolenaar    endtry
202b5760a1cSBram Moolenaar  endif
2037cba71d7SBram Moolenaar
2040b5dc644SBram Moolenaar  " Clear any autocommands and put back the catch-all for SwapExists.
205cf1ba35fSBram Moolenaar  au!
206d8f27b30SBram Moolenaar  au SwapExists * call HandleSwapExists()
207cf1ba35fSBram Moolenaar
208ef6b979bSBram Moolenaar  " Check for and close any stray popup windows.
20905ad5ff0SBram Moolenaar  if has('popupwin')
210ef6b979bSBram Moolenaar    call assert_equal([], popup_list())
21103a9f848SBram Moolenaar    call popup_clear(1)
212ae943150SBram Moolenaar  endif
213ae943150SBram Moolenaar
214ce11de87SBram Moolenaar  " Close any extra tab pages and windows and make the current one not modified.
215ce11de87SBram Moolenaar  while tabpagenr('$') > 1
216cf1ba35fSBram Moolenaar    quit!
217ce11de87SBram Moolenaar  endwhile
218ce11de87SBram Moolenaar
219358308ddSBram Moolenaar  while 1
220358308ddSBram Moolenaar    let wincount = winnr('$')
221358308ddSBram Moolenaar    if wincount == 1
222358308ddSBram Moolenaar      break
223358308ddSBram Moolenaar    endif
2247cba71d7SBram Moolenaar    bwipe!
225358308ddSBram Moolenaar    if wincount == winnr('$')
226358308ddSBram Moolenaar      " Did not manage to close a window.
227358308ddSBram Moolenaar      only!
228358308ddSBram Moolenaar      break
229358308ddSBram Moolenaar    endif
2307cba71d7SBram Moolenaar  endwhile
231209d3874SBram Moolenaar
232209d3874SBram Moolenaar  exe 'cd ' . save_cwd
233640d4f0cSBram Moolenaar
234640d4f0cSBram Moolenaar  let message = 'Executed ' . a:test
235640d4f0cSBram Moolenaar  if has('reltime')
2368d943796SBram Moolenaar    let message ..= repeat(' ', 50 - len(message))
2378d943796SBram Moolenaar    let time = reltime(func_start)
2388d943796SBram Moolenaar    if has('float') && reltimefloat(time) > 0.1
2398d943796SBram Moolenaar      let message = &t_md .. message
2408d943796SBram Moolenaar    endif
2418d943796SBram Moolenaar    let message ..= ' in ' .. reltimestr(time) .. ' seconds'
2428d943796SBram Moolenaar    if has('float') && reltimefloat(time) > 0.1
2438d943796SBram Moolenaar      let message ..= &t_me
2448d943796SBram Moolenaar    endif
245640d4f0cSBram Moolenaar  endif
246640d4f0cSBram Moolenaar  call add(s:messages, message)
247640d4f0cSBram Moolenaar  let s:done += 1
248b5760a1cSBram Moolenaarendfunc
24928fb79dbSBram Moolenaar
250ce436de5SBram Moolenaarfunc AfterTheTest(func_name)
25143345546SBram Moolenaar  if len(v:errors) > 0
252ce436de5SBram Moolenaar    if match(s:may_fail_list, '^' .. a:func_name) >= 0
253ce436de5SBram Moolenaar      let s:fail_expected += 1
254bfe13cccSBram Moolenaar      call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':')
255ce436de5SBram Moolenaar      call extend(s:errors_expected, v:errors)
256ce436de5SBram Moolenaar    else
25700af60bbSBram Moolenaar      let s:fail += 1
258bfe13cccSBram Moolenaar      call add(s:errors, 'Found errors in ' . g:testfunc . ':')
25900af60bbSBram Moolenaar      call extend(s:errors, v:errors)
260ce436de5SBram Moolenaar    endif
26143345546SBram Moolenaar    let v:errors = []
26243345546SBram Moolenaar  endif
26342205551SBram Moolenaarendfunc
26442205551SBram Moolenaar
2658903676dSBram Moolenaarfunc EarlyExit(test)
2668903676dSBram Moolenaar  " It's OK for the test we use to test the quit detection.
2678903676dSBram Moolenaar  if a:test != 'Test_zz_quit_detected()'
2688903676dSBram Moolenaar    call add(v:errors, 'Test caused Vim to exit: ' . a:test)
2698903676dSBram Moolenaar  endif
2708903676dSBram Moolenaar
2718903676dSBram Moolenaar  call FinishTesting()
2728903676dSBram Moolenaarendfunc
2738903676dSBram Moolenaar
27442205551SBram Moolenaar" This function can be called by a test if it wants to abort testing.
27542205551SBram Moolenaarfunc FinishTesting()
276ce436de5SBram Moolenaar  call AfterTheTest('')
27743345546SBram Moolenaar
278fc4ad616SBram Moolenaar  " Don't write viminfo on exit.
279fc4ad616SBram Moolenaar  set viminfo=
280fc4ad616SBram Moolenaar
281d1ee0043SBram Moolenaar  " Clean up files created by setup.vim
282d1ee0043SBram Moolenaar  call delete('XfakeHOME', 'rf')
283d1ee0043SBram Moolenaar
284ce436de5SBram Moolenaar  if s:fail == 0 && s:fail_expected == 0
28543345546SBram Moolenaar    " Success, create the .res file so that make knows it's done.
28600af60bbSBram Moolenaar    exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
28743345546SBram Moolenaar    write
28843345546SBram Moolenaar  endif
28943345546SBram Moolenaar
29000af60bbSBram Moolenaar  if len(s:errors) > 0
29143345546SBram Moolenaar    " Append errors to test.log
29243345546SBram Moolenaar    split test.log
29343345546SBram Moolenaar    call append(line('$'), '')
29400af60bbSBram Moolenaar    call append(line('$'), 'From ' . g:testname . ':')
29500af60bbSBram Moolenaar    call append(line('$'), s:errors)
29643345546SBram Moolenaar    write
29743345546SBram Moolenaar  endif
29843345546SBram Moolenaar
29929f9ed20SBram Moolenaar  if s:done == 0
3007b666c78SBram Moolenaar    if s:filtered > 0
3017b666c78SBram Moolenaar      let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
30229f9ed20SBram Moolenaar    else
3037b666c78SBram Moolenaar      let message = 'NO tests executed'
3047b666c78SBram Moolenaar    endif
3057b666c78SBram Moolenaar  else
3067b666c78SBram Moolenaar    if s:filtered > 0
3077b666c78SBram Moolenaar      call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER")
3087b666c78SBram Moolenaar    endif
30900af60bbSBram Moolenaar    let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
31029f9ed20SBram Moolenaar  endif
3117b666c78SBram Moolenaar  if s:done > 0 && has('reltime')
3128d943796SBram Moolenaar    let message = &t_md .. message .. repeat(' ', 40 - len(message))
31375ee544fSBram Moolenaar    let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
3148d943796SBram Moolenaar    let message ..= &t_me
31575ee544fSBram Moolenaar  endif
316096c8bb4SBram Moolenaar  echo message
31700af60bbSBram Moolenaar  call add(s:messages, message)
31800af60bbSBram Moolenaar  if s:fail > 0
31900af60bbSBram Moolenaar    let message = s:fail . ' FAILED:'
320096c8bb4SBram Moolenaar    echo message
32100af60bbSBram Moolenaar    call add(s:messages, message)
32200af60bbSBram Moolenaar    call extend(s:messages, s:errors)
32343345546SBram Moolenaar  endif
324ce436de5SBram Moolenaar  if s:fail_expected > 0
325ce436de5SBram Moolenaar    let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):'
326ce436de5SBram Moolenaar    echo message
327ce436de5SBram Moolenaar    call add(s:messages, message)
328ce436de5SBram Moolenaar    call extend(s:messages, s:errors_expected)
329ce436de5SBram Moolenaar  endif
33043345546SBram Moolenaar
331dac1947bSBram Moolenaar  " Add SKIPPED messages
332dac1947bSBram Moolenaar  call extend(s:messages, s:skipped)
333dac1947bSBram Moolenaar
334dac1947bSBram Moolenaar  " Append messages to the file "messages"
335096c8bb4SBram Moolenaar  split messages
336096c8bb4SBram Moolenaar  call append(line('$'), '')
33700af60bbSBram Moolenaar  call append(line('$'), 'From ' . g:testname . ':')
33800af60bbSBram Moolenaar  call append(line('$'), s:messages)
339096c8bb4SBram Moolenaar  write
340096c8bb4SBram Moolenaar
34143345546SBram Moolenaar  qall!
34242205551SBram Moolenaarendfunc
34342205551SBram Moolenaar
34442205551SBram Moolenaar" Source the test script.  First grab the file name, in case the script
34542205551SBram Moolenaar" navigates away.  g:testname can be used by the tests.
34642205551SBram Moolenaarlet g:testname = expand('%')
34742205551SBram Moolenaarlet s:done = 0
34842205551SBram Moolenaarlet s:fail = 0
349ce436de5SBram Moolenaarlet s:fail_expected = 0
35042205551SBram Moolenaarlet s:errors = []
351ce436de5SBram Moolenaarlet s:errors_expected = []
35242205551SBram Moolenaarlet s:messages = []
35342205551SBram Moolenaarlet s:skipped = []
35442205551SBram Moolenaarif expand('%') =~ 'test_vimscript.vim'
355ce436de5SBram Moolenaar  " this test has intentional errors, don't use try/catch.
35642205551SBram Moolenaar  source %
35742205551SBram Moolenaarelse
35842205551SBram Moolenaar  try
35942205551SBram Moolenaar    source %
3609c0cec65SBram Moolenaar  catch /^\cskipped/
3619c0cec65SBram Moolenaar    call add(s:messages, '    Skipped')
3629c0cec65SBram Moolenaar    call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '',  ''))
36342205551SBram Moolenaar  catch
36442205551SBram Moolenaar    let s:fail += 1
36542205551SBram Moolenaar    call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
36642205551SBram Moolenaar  endtry
36742205551SBram Moolenaarendif
36842205551SBram Moolenaar
36942205551SBram Moolenaar" Names of flaky tests.
370dbc0d216SBram Moolenaarlet s:flaky_tests = [
3710d0c3ca0SBram Moolenaar      \ 'Test_autocmd_SafeState()',
37242205551SBram Moolenaar      \ 'Test_client_server()',
37342205551SBram Moolenaar      \ 'Test_close_and_exit_cb()',
374d80232beSBram Moolenaar      \ 'Test_close_output_buffer()',
37542205551SBram Moolenaar      \ 'Test_collapse_buffers()',
37665873846SBram Moolenaar      \ 'Test_cwd()',
377218959bcSBram Moolenaar      \ 'Test_diff_screen()',
37842205551SBram Moolenaar      \ 'Test_exit_callback_interval()',
379ea94c855SBram Moolenaar      \ 'Test_map_timeout_with_timer_interrupt()',
3801eca6f13SBram Moolenaar      \ 'Test_out_cb()',
38142205551SBram Moolenaar      \ 'Test_pipe_through_sort_all()',
38242205551SBram Moolenaar      \ 'Test_pipe_through_sort_some()',
38344f0bd87SBram Moolenaar      \ 'Test_popup_and_window_resize()',
38442205551SBram Moolenaar      \ 'Test_quoteplus()',
3857dd48506SBram Moolenaar      \ 'Test_quotestar()',
38642205551SBram Moolenaar      \ 'Test_reltime()',
3873c8cd4a1SBram Moolenaar      \ 'Test_state()',
388f204e05aSBram Moolenaar      \ 'Test_terminal_composing_unicode()',
3893876789bSBram Moolenaar      \ 'Test_terminal_does_not_truncate_last_newlines()',
3903615abb6SBram Moolenaar      \ 'Test_terminal_no_cmd()',
39175a60f74SBram Moolenaar      \ 'Test_terminal_noblock()',
3927dd88c51SBram Moolenaar      \ 'Test_terminal_redir_file()',
393e219f73eSBram Moolenaar      \ 'Test_termwinscroll()',
3949a2fddcfSBram Moolenaar      \ 'Test_timer_oneshot()',
3959a2fddcfSBram Moolenaar      \ 'Test_timer_paused()',
3969a2fddcfSBram Moolenaar      \ 'Test_timer_repeat_many()',
3979a2fddcfSBram Moolenaar      \ 'Test_timer_repeat_three()',
3989a2fddcfSBram Moolenaar      \ 'Test_timer_stop_all_in_callback()',
3999a2fddcfSBram Moolenaar      \ 'Test_timer_stop_in_callback()',
4009a2fddcfSBram Moolenaar      \ 'Test_timer_with_partial_callback()',
40142205551SBram Moolenaar      \ ]
40242205551SBram Moolenaar
40342205551SBram Moolenaar" Locate Test_ functions and execute them.
40442205551SBram Moolenaarredir @q
40542205551SBram Moolenaarsilent function /^Test_
40642205551SBram Moolenaarredir END
40761a6d4e4SBram Moolenaarlet s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g'))
40842205551SBram Moolenaar
40942205551SBram Moolenaar" If there is an extra argument filter the function names against it.
41042205551SBram Moolenaarif argc() > 1
41142205551SBram Moolenaar  let s:tests = filter(s:tests, 'v:val =~ argv(1)')
41242205551SBram Moolenaarendif
41342205551SBram Moolenaar
414a7f6c3cfSBram Moolenaar" If the environment variable $TEST_FILTER is set then filter the function
415a7f6c3cfSBram Moolenaar" names against it.
4167b666c78SBram Moolenaarlet s:filtered = 0
417a7f6c3cfSBram Moolenaarif $TEST_FILTER != ''
4187b666c78SBram Moolenaar  let s:filtered = len(s:tests)
419a7f6c3cfSBram Moolenaar  let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER')
4207b666c78SBram Moolenaar  let s:filtered -= len(s:tests)
421a7f6c3cfSBram Moolenaarendif
422a7f6c3cfSBram Moolenaar
423ce436de5SBram Moolenaarlet s:may_fail_list = []
424ce436de5SBram Moolenaarif $TEST_MAY_FAIL != ''
425bfe13cccSBram Moolenaar  " Split the list at commas and add () to make it match g:testfunc.
426ce436de5SBram Moolenaar  let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'})
427ce436de5SBram Moolenaarendif
428ce436de5SBram Moolenaar
42942205551SBram Moolenaar" Execute the tests in alphabetical order.
430bfe13cccSBram Moolenaarfor g:testfunc in sort(s:tests)
4314a6fcf80SBram Moolenaar  " Silence, please!
4324a6fcf80SBram Moolenaar  set belloff=all
433f77af0e6SBram Moolenaar  let prev_error = ''
434f77af0e6SBram Moolenaar  let total_errors = []
4353ed9efc2SBram Moolenaar  let g:run_nr = 1
4364a6fcf80SBram Moolenaar
437bfe13cccSBram Moolenaar  " A test can set g:test_is_flaky to retry running the test.
438bfe13cccSBram Moolenaar  let g:test_is_flaky = 0
4393cdcb090SBram Moolenaar
440bfe13cccSBram Moolenaar  call RunTheTest(g:testfunc)
44142205551SBram Moolenaar
442f77af0e6SBram Moolenaar  " Repeat a flaky test.  Give up when:
443f77af0e6SBram Moolenaar  " - it fails again with the same message
4441bc353b6SBram Moolenaar  " - it fails five times (with a different message)
445dbc0d216SBram Moolenaar  if len(v:errors) > 0
446bfe13cccSBram Moolenaar        \ && (index(s:flaky_tests, g:testfunc) >= 0
447bfe13cccSBram Moolenaar        \      || g:test_is_flaky)
448f77af0e6SBram Moolenaar    while 1
449bfe13cccSBram Moolenaar      call add(s:messages, 'Found errors in ' . g:testfunc . ':')
4506caf606bSBram Moolenaar      call extend(s:messages, v:errors)
45115e737f7SBram Moolenaar
4523ed9efc2SBram Moolenaar      call add(total_errors, 'Run ' . g:run_nr . ':')
453f77af0e6SBram Moolenaar      call extend(total_errors, v:errors)
454f77af0e6SBram Moolenaar
4553ed9efc2SBram Moolenaar      if g:run_nr == 5 || prev_error == v:errors[0]
456f77af0e6SBram Moolenaar        call add(total_errors, 'Flaky test failed too often, giving up')
457f77af0e6SBram Moolenaar        let v:errors = total_errors
458f77af0e6SBram Moolenaar        break
459f77af0e6SBram Moolenaar      endif
460f77af0e6SBram Moolenaar
461f77af0e6SBram Moolenaar      call add(s:messages, 'Flaky test failed, running it again')
462f77af0e6SBram Moolenaar
463f77af0e6SBram Moolenaar      " Flakiness is often caused by the system being very busy.  Sleep a
464f77af0e6SBram Moolenaar      " couple of seconds to have a higher chance of succeeding the second
465f77af0e6SBram Moolenaar      " time.
46655058601SBram Moolenaar      sleep 2
46755058601SBram Moolenaar
468f77af0e6SBram Moolenaar      let prev_error = v:errors[0]
46942205551SBram Moolenaar      let v:errors = []
4703ed9efc2SBram Moolenaar      let g:run_nr += 1
471f77af0e6SBram Moolenaar
472bfe13cccSBram Moolenaar      call RunTheTest(g:testfunc)
473f77af0e6SBram Moolenaar
474f77af0e6SBram Moolenaar      if len(v:errors) == 0
475f77af0e6SBram Moolenaar        " Test passed on rerun.
476f77af0e6SBram Moolenaar        break
47715e737f7SBram Moolenaar      endif
478f77af0e6SBram Moolenaar    endwhile
47942205551SBram Moolenaar  endif
48042205551SBram Moolenaar
481bfe13cccSBram Moolenaar  call AfterTheTest(g:testfunc)
48242205551SBram Moolenaarendfor
48342205551SBram Moolenaar
48442205551SBram Moolenaarcall FinishTesting()
485cc28e2d0SBram Moolenaar
486cc28e2d0SBram Moolenaar" vim: shiftwidth=2 sts=2 expandtab
487