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 4843345546SBram Moolenaar" Check that the screen size is at least 24 x 80 characters. 4943345546SBram Moolenaarif &lines < 24 || &columns < 80 500b5dc644SBram Moolenaar let error = 'Screen size too small! Tests require at least 24 lines with 80 characters, got ' .. &lines .. ' lines with ' .. &columns .. ' characters' 5143345546SBram Moolenaar echoerr error 5243345546SBram Moolenaar split test.log 5343345546SBram Moolenaar $put =error 5445aa07d3SBram Moolenaar write 5545aa07d3SBram Moolenaar split messages 560b5dc644SBram Moolenaar call append(line('$'), '') 570b5dc644SBram Moolenaar call append(line('$'), 'From ' . expand('%') . ':') 5845aa07d3SBram Moolenaar call append(line('$'), error) 5945aa07d3SBram Moolenaar write 6045aa07d3SBram Moolenaar qa! 6143345546SBram Moolenaarendif 6243345546SBram Moolenaar 6375ee544fSBram Moolenaarif has('reltime') 6475ee544fSBram Moolenaar let s:start_time = reltime() 6575ee544fSBram Moolenaarendif 6675ee544fSBram Moolenaar 6789b10421SBram Moolenaar" Common with all tests on all systems. 6889b10421SBram Moolenaarsource setup.vim 6989b10421SBram Moolenaar 70c0662466SBram Moolenaar" For consistency run all tests with 'nocompatible' set. 71c0662466SBram Moolenaar" This also enables use of line continuation. 72c0662466SBram Moolenaarset nocp viminfo+=nviminfo 73c0662466SBram Moolenaar 7430276f2bSBram Moolenaar" Use utf-8 by default, instead of whatever the system default happens to be. 75ed79d1e3SBram Moolenaar" Individual tests can overrule this at the top of the file and use 76ed79d1e3SBram Moolenaar" g:orig_encoding if needed. 77ed79d1e3SBram Moolenaarlet g:orig_encoding = &encoding 78ac105ed3SBram Moolenaarset encoding=utf-8 79ac105ed3SBram Moolenaar 80d8f27b30SBram Moolenaar" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for 81d8f27b30SBram Moolenaar" the test_name.vim file itself. Replace it here with a more restrictive one, 82d8f27b30SBram Moolenaar" so we still catch mistakes. 83d8f27b30SBram Moolenaarlet s:test_script_fname = expand('%') 84d8f27b30SBram Moolenaarau! SwapExists * call HandleSwapExists() 85d8f27b30SBram Moolenaarfunc HandleSwapExists() 86b073da89SBram Moolenaar " Ignore finding a swap file for the test script (the user might be 87d8f27b30SBram Moolenaar " editing it and do ":make test_name") and the output file. 88b073da89SBram Moolenaar " Report finding another swap file and chose 'q' to avoid getting stuck. 89d8f27b30SBram Moolenaar if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname 90d8f27b30SBram Moolenaar let v:swapchoice = 'e' 91b073da89SBram Moolenaar else 92b073da89SBram Moolenaar call assert_report('Unexpected swap file: ' .. v:swapname) 93b073da89SBram Moolenaar let v:swapchoice = 'q' 94d8f27b30SBram Moolenaar endif 95d8f27b30SBram Moolenaarendfunc 96d8f27b30SBram Moolenaar 977a073549SBram Moolenaar" Avoid stopping at the "hit enter" prompt 987a073549SBram Moolenaarset nomore 997a073549SBram Moolenaar 100c0662466SBram Moolenaar" Output all messages in English. 101c0662466SBram Moolenaarlang mess C 102c0662466SBram Moolenaar 103f60b796fSBram Moolenaar" Always use forward slashes. 104f60b796fSBram Moolenaarset shellslash 105f60b796fSBram Moolenaar 10628fb79dbSBram Moolenaarlet s:srcdir = expand('%:p:h:h') 10728fb79dbSBram Moolenaar 1088e8df251SBram Moolenaar" Prepare for calling test_garbagecollect_now(). 109ebf7dfa6SBram Moolenaarlet v:testing = 1 110ebf7dfa6SBram Moolenaar 11128fb79dbSBram Moolenaar" Support function: get the alloc ID by name. 11228fb79dbSBram Moolenaarfunction GetAllocId(name) 11328fb79dbSBram Moolenaar exe 'split ' . s:srcdir . '/alloc.h' 114065ee9aeSBram Moolenaar let top = search('typedef enum') 115065ee9aeSBram Moolenaar if top == 0 116065ee9aeSBram Moolenaar call add(v:errors, 'typedef not found in alloc.h') 117065ee9aeSBram Moolenaar endif 11828fb79dbSBram Moolenaar let lnum = search('aid_' . a:name . ',') 11928fb79dbSBram Moolenaar if lnum == 0 12028fb79dbSBram Moolenaar call add(v:errors, 'Alloc ID ' . a:name . ' not defined') 12128fb79dbSBram Moolenaar endif 12228fb79dbSBram Moolenaar close 123065ee9aeSBram Moolenaar return lnum - top - 1 12428fb79dbSBram Moolenaarendfunc 12528fb79dbSBram Moolenaar 12642205551SBram Moolenaarfunc RunTheTest(test) 127b5760a1cSBram Moolenaar echo 'Executing ' . a:test 12875ee544fSBram Moolenaar if has('reltime') 12975ee544fSBram Moolenaar let func_start = reltime() 13075ee544fSBram Moolenaar endif 131e5f2a075SBram Moolenaar 132e5f2a075SBram Moolenaar " Avoid stopping at the "hit enter" prompt 133e5f2a075SBram Moolenaar set nomore 134e5f2a075SBram Moolenaar 135e5f2a075SBram Moolenaar " Avoid a three second wait when a message is about to be overwritten by the 136e5f2a075SBram Moolenaar " mode message. 137e5f2a075SBram Moolenaar set noshowmode 138e5f2a075SBram Moolenaar 139eb992cb9SBram Moolenaar " Clear any overrides. 140eb992cb9SBram Moolenaar call test_override('ALL', 0) 141eb992cb9SBram Moolenaar 142cf1ba35fSBram Moolenaar " Some tests wipe out buffers. To be consistent, always wipe out all 143cf1ba35fSBram Moolenaar " buffers. 144cf1ba35fSBram Moolenaar %bwipe! 145cf1ba35fSBram Moolenaar 146209d3874SBram Moolenaar " The test may change the current directory. Save and restore the 147209d3874SBram Moolenaar " directory after executing the test. 148209d3874SBram Moolenaar let save_cwd = getcwd() 149209d3874SBram Moolenaar 150b5760a1cSBram Moolenaar if exists("*SetUp") 151cc28e2d0SBram Moolenaar try 152b5760a1cSBram Moolenaar call SetUp() 153cc28e2d0SBram Moolenaar catch 154cc28e2d0SBram Moolenaar call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 155cc28e2d0SBram Moolenaar endtry 156b5760a1cSBram Moolenaar endif 157b5760a1cSBram Moolenaar 158f204e05aSBram Moolenaar if a:test =~ 'Test_nocatch_' 159f204e05aSBram Moolenaar " Function handles errors itself. This avoids skipping commands after the 160f204e05aSBram Moolenaar " error. 161f204e05aSBram Moolenaar exe 'call ' . a:test 162f204e05aSBram Moolenaar else 163b5760a1cSBram Moolenaar try 164bfe13cccSBram Moolenaar au VimLeavePre * call EarlyExit(g:testfunc) 165b5760a1cSBram Moolenaar exe 'call ' . a:test 1668903676dSBram Moolenaar au! VimLeavePre 167dac1947bSBram Moolenaar catch /^\cskipped/ 168dac1947bSBram Moolenaar call add(s:messages, ' Skipped') 169dac1947bSBram Moolenaar call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) 170b5760a1cSBram Moolenaar catch 171b5760a1cSBram Moolenaar call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 172b5760a1cSBram Moolenaar endtry 173f204e05aSBram Moolenaar endif 1748ad16da7SBram Moolenaar 1758ad16da7SBram Moolenaar " In case 'insertmode' was set and something went wrong, make sure it is 1768ad16da7SBram Moolenaar " reset to avoid trouble with anything else. 1778ad16da7SBram Moolenaar set noinsertmode 178b5760a1cSBram Moolenaar 179b5760a1cSBram Moolenaar if exists("*TearDown") 180cc28e2d0SBram Moolenaar try 181b5760a1cSBram Moolenaar call TearDown() 182cc28e2d0SBram Moolenaar catch 183cc28e2d0SBram Moolenaar call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 184cc28e2d0SBram Moolenaar endtry 185b5760a1cSBram Moolenaar endif 1867cba71d7SBram Moolenaar 1870b5dc644SBram Moolenaar " Clear any autocommands and put back the catch-all for SwapExists. 188cf1ba35fSBram Moolenaar au! 189d8f27b30SBram Moolenaar au SwapExists * call HandleSwapExists() 190cf1ba35fSBram Moolenaar 191ef6b979bSBram Moolenaar " Check for and close any stray popup windows. 19205ad5ff0SBram Moolenaar if has('popupwin') 193ef6b979bSBram Moolenaar call assert_equal([], popup_list()) 19403a9f848SBram Moolenaar call popup_clear(1) 195ae943150SBram Moolenaar endif 196ae943150SBram Moolenaar 197ce11de87SBram Moolenaar " Close any extra tab pages and windows and make the current one not modified. 198ce11de87SBram Moolenaar while tabpagenr('$') > 1 199cf1ba35fSBram Moolenaar quit! 200ce11de87SBram Moolenaar endwhile 201ce11de87SBram Moolenaar 202358308ddSBram Moolenaar while 1 203358308ddSBram Moolenaar let wincount = winnr('$') 204358308ddSBram Moolenaar if wincount == 1 205358308ddSBram Moolenaar break 206358308ddSBram Moolenaar endif 2077cba71d7SBram Moolenaar bwipe! 208358308ddSBram Moolenaar if wincount == winnr('$') 209358308ddSBram Moolenaar " Did not manage to close a window. 210358308ddSBram Moolenaar only! 211358308ddSBram Moolenaar break 212358308ddSBram Moolenaar endif 2137cba71d7SBram Moolenaar endwhile 214209d3874SBram Moolenaar 215209d3874SBram Moolenaar exe 'cd ' . save_cwd 216640d4f0cSBram Moolenaar 217640d4f0cSBram Moolenaar let message = 'Executed ' . a:test 218640d4f0cSBram Moolenaar if has('reltime') 219*8d943796SBram Moolenaar let message ..= repeat(' ', 50 - len(message)) 220*8d943796SBram Moolenaar let time = reltime(func_start) 221*8d943796SBram Moolenaar if has('float') && reltimefloat(time) > 0.1 222*8d943796SBram Moolenaar let message = &t_md .. message 223*8d943796SBram Moolenaar endif 224*8d943796SBram Moolenaar let message ..= ' in ' .. reltimestr(time) .. ' seconds' 225*8d943796SBram Moolenaar if has('float') && reltimefloat(time) > 0.1 226*8d943796SBram Moolenaar let message ..= &t_me 227*8d943796SBram Moolenaar endif 228640d4f0cSBram Moolenaar endif 229640d4f0cSBram Moolenaar call add(s:messages, message) 230640d4f0cSBram Moolenaar let s:done += 1 231b5760a1cSBram Moolenaarendfunc 23228fb79dbSBram Moolenaar 233ce436de5SBram Moolenaarfunc AfterTheTest(func_name) 23443345546SBram Moolenaar if len(v:errors) > 0 235ce436de5SBram Moolenaar if match(s:may_fail_list, '^' .. a:func_name) >= 0 236ce436de5SBram Moolenaar let s:fail_expected += 1 237bfe13cccSBram Moolenaar call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':') 238ce436de5SBram Moolenaar call extend(s:errors_expected, v:errors) 239ce436de5SBram Moolenaar else 24000af60bbSBram Moolenaar let s:fail += 1 241bfe13cccSBram Moolenaar call add(s:errors, 'Found errors in ' . g:testfunc . ':') 24200af60bbSBram Moolenaar call extend(s:errors, v:errors) 243ce436de5SBram Moolenaar endif 24443345546SBram Moolenaar let v:errors = [] 24543345546SBram Moolenaar endif 24642205551SBram Moolenaarendfunc 24742205551SBram Moolenaar 2488903676dSBram Moolenaarfunc EarlyExit(test) 2498903676dSBram Moolenaar " It's OK for the test we use to test the quit detection. 2508903676dSBram Moolenaar if a:test != 'Test_zz_quit_detected()' 2518903676dSBram Moolenaar call add(v:errors, 'Test caused Vim to exit: ' . a:test) 2528903676dSBram Moolenaar endif 2538903676dSBram Moolenaar 2548903676dSBram Moolenaar call FinishTesting() 2558903676dSBram Moolenaarendfunc 2568903676dSBram Moolenaar 25742205551SBram Moolenaar" This function can be called by a test if it wants to abort testing. 25842205551SBram Moolenaarfunc FinishTesting() 259ce436de5SBram Moolenaar call AfterTheTest('') 26043345546SBram Moolenaar 261fc4ad616SBram Moolenaar " Don't write viminfo on exit. 262fc4ad616SBram Moolenaar set viminfo= 263fc4ad616SBram Moolenaar 264d1ee0043SBram Moolenaar " Clean up files created by setup.vim 265d1ee0043SBram Moolenaar call delete('XfakeHOME', 'rf') 266d1ee0043SBram Moolenaar 267ce436de5SBram Moolenaar if s:fail == 0 && s:fail_expected == 0 26843345546SBram Moolenaar " Success, create the .res file so that make knows it's done. 26900af60bbSBram Moolenaar exe 'split ' . fnamemodify(g:testname, ':r') . '.res' 27043345546SBram Moolenaar write 27143345546SBram Moolenaar endif 27243345546SBram Moolenaar 27300af60bbSBram Moolenaar if len(s:errors) > 0 27443345546SBram Moolenaar " Append errors to test.log 27543345546SBram Moolenaar split test.log 27643345546SBram Moolenaar call append(line('$'), '') 27700af60bbSBram Moolenaar call append(line('$'), 'From ' . g:testname . ':') 27800af60bbSBram Moolenaar call append(line('$'), s:errors) 27943345546SBram Moolenaar write 28043345546SBram Moolenaar endif 28143345546SBram Moolenaar 28229f9ed20SBram Moolenaar if s:done == 0 2837b666c78SBram Moolenaar if s:filtered > 0 2847b666c78SBram Moolenaar let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'" 28529f9ed20SBram Moolenaar else 2867b666c78SBram Moolenaar let message = 'NO tests executed' 2877b666c78SBram Moolenaar endif 2887b666c78SBram Moolenaar else 2897b666c78SBram Moolenaar if s:filtered > 0 2907b666c78SBram Moolenaar call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER") 2917b666c78SBram Moolenaar endif 29200af60bbSBram Moolenaar let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test') 29329f9ed20SBram Moolenaar endif 2947b666c78SBram Moolenaar if s:done > 0 && has('reltime') 295*8d943796SBram Moolenaar let message = &t_md .. message .. repeat(' ', 40 - len(message)) 29675ee544fSBram Moolenaar let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds' 297*8d943796SBram Moolenaar let message ..= &t_me 29875ee544fSBram Moolenaar endif 299096c8bb4SBram Moolenaar echo message 30000af60bbSBram Moolenaar call add(s:messages, message) 30100af60bbSBram Moolenaar if s:fail > 0 30200af60bbSBram Moolenaar let message = s:fail . ' FAILED:' 303096c8bb4SBram Moolenaar echo message 30400af60bbSBram Moolenaar call add(s:messages, message) 30500af60bbSBram Moolenaar call extend(s:messages, s:errors) 30643345546SBram Moolenaar endif 307ce436de5SBram Moolenaar if s:fail_expected > 0 308ce436de5SBram Moolenaar let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):' 309ce436de5SBram Moolenaar echo message 310ce436de5SBram Moolenaar call add(s:messages, message) 311ce436de5SBram Moolenaar call extend(s:messages, s:errors_expected) 312ce436de5SBram Moolenaar endif 31343345546SBram Moolenaar 314dac1947bSBram Moolenaar " Add SKIPPED messages 315dac1947bSBram Moolenaar call extend(s:messages, s:skipped) 316dac1947bSBram Moolenaar 317dac1947bSBram Moolenaar " Append messages to the file "messages" 318096c8bb4SBram Moolenaar split messages 319096c8bb4SBram Moolenaar call append(line('$'), '') 32000af60bbSBram Moolenaar call append(line('$'), 'From ' . g:testname . ':') 32100af60bbSBram Moolenaar call append(line('$'), s:messages) 322096c8bb4SBram Moolenaar write 323096c8bb4SBram Moolenaar 32443345546SBram Moolenaar qall! 32542205551SBram Moolenaarendfunc 32642205551SBram Moolenaar 32742205551SBram Moolenaar" Source the test script. First grab the file name, in case the script 32842205551SBram Moolenaar" navigates away. g:testname can be used by the tests. 32942205551SBram Moolenaarlet g:testname = expand('%') 33042205551SBram Moolenaarlet s:done = 0 33142205551SBram Moolenaarlet s:fail = 0 332ce436de5SBram Moolenaarlet s:fail_expected = 0 33342205551SBram Moolenaarlet s:errors = [] 334ce436de5SBram Moolenaarlet s:errors_expected = [] 33542205551SBram Moolenaarlet s:messages = [] 33642205551SBram Moolenaarlet s:skipped = [] 33742205551SBram Moolenaarif expand('%') =~ 'test_vimscript.vim' 338ce436de5SBram Moolenaar " this test has intentional errors, don't use try/catch. 33942205551SBram Moolenaar source % 34042205551SBram Moolenaarelse 34142205551SBram Moolenaar try 34242205551SBram Moolenaar source % 3439c0cec65SBram Moolenaar catch /^\cskipped/ 3449c0cec65SBram Moolenaar call add(s:messages, ' Skipped') 3459c0cec65SBram Moolenaar call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) 34642205551SBram Moolenaar catch 34742205551SBram Moolenaar let s:fail += 1 34842205551SBram Moolenaar call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint) 34942205551SBram Moolenaar endtry 35042205551SBram Moolenaarendif 35142205551SBram Moolenaar 35242205551SBram Moolenaar" Names of flaky tests. 353dbc0d216SBram Moolenaarlet s:flaky_tests = [ 3540d0c3ca0SBram Moolenaar \ 'Test_autocmd_SafeState()', 35542205551SBram Moolenaar \ 'Test_client_server()', 35642205551SBram Moolenaar \ 'Test_close_and_exit_cb()', 357d80232beSBram Moolenaar \ 'Test_close_output_buffer()', 35842205551SBram Moolenaar \ 'Test_collapse_buffers()', 35965873846SBram Moolenaar \ 'Test_cwd()', 360218959bcSBram Moolenaar \ 'Test_diff_screen()', 36142205551SBram Moolenaar \ 'Test_exit_callback_interval()', 362ea94c855SBram Moolenaar \ 'Test_map_timeout_with_timer_interrupt()', 3631eca6f13SBram Moolenaar \ 'Test_out_cb()', 36442205551SBram Moolenaar \ 'Test_pipe_through_sort_all()', 36542205551SBram Moolenaar \ 'Test_pipe_through_sort_some()', 36644f0bd87SBram Moolenaar \ 'Test_popup_and_window_resize()', 36742205551SBram Moolenaar \ 'Test_quoteplus()', 3687dd48506SBram Moolenaar \ 'Test_quotestar()', 36942205551SBram Moolenaar \ 'Test_reltime()', 3703c8cd4a1SBram Moolenaar \ 'Test_state()', 371f204e05aSBram Moolenaar \ 'Test_terminal_composing_unicode()', 3723876789bSBram Moolenaar \ 'Test_terminal_does_not_truncate_last_newlines()', 3733615abb6SBram Moolenaar \ 'Test_terminal_no_cmd()', 37475a60f74SBram Moolenaar \ 'Test_terminal_noblock()', 3757dd88c51SBram Moolenaar \ 'Test_terminal_redir_file()', 376e219f73eSBram Moolenaar \ 'Test_termwinscroll()', 3779a2fddcfSBram Moolenaar \ 'Test_timer_oneshot()', 3789a2fddcfSBram Moolenaar \ 'Test_timer_paused()', 3799a2fddcfSBram Moolenaar \ 'Test_timer_repeat_many()', 3809a2fddcfSBram Moolenaar \ 'Test_timer_repeat_three()', 3819a2fddcfSBram Moolenaar \ 'Test_timer_stop_all_in_callback()', 3829a2fddcfSBram Moolenaar \ 'Test_timer_stop_in_callback()', 3839a2fddcfSBram Moolenaar \ 'Test_timer_with_partial_callback()', 38442205551SBram Moolenaar \ ] 38542205551SBram Moolenaar 38642205551SBram Moolenaar" Locate Test_ functions and execute them. 38742205551SBram Moolenaarredir @q 38842205551SBram Moolenaarsilent function /^Test_ 38942205551SBram Moolenaarredir END 39061a6d4e4SBram Moolenaarlet s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g')) 39142205551SBram Moolenaar 39242205551SBram Moolenaar" If there is an extra argument filter the function names against it. 39342205551SBram Moolenaarif argc() > 1 39442205551SBram Moolenaar let s:tests = filter(s:tests, 'v:val =~ argv(1)') 39542205551SBram Moolenaarendif 39642205551SBram Moolenaar 397a7f6c3cfSBram Moolenaar" If the environment variable $TEST_FILTER is set then filter the function 398a7f6c3cfSBram Moolenaar" names against it. 3997b666c78SBram Moolenaarlet s:filtered = 0 400a7f6c3cfSBram Moolenaarif $TEST_FILTER != '' 4017b666c78SBram Moolenaar let s:filtered = len(s:tests) 402a7f6c3cfSBram Moolenaar let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER') 4037b666c78SBram Moolenaar let s:filtered -= len(s:tests) 404a7f6c3cfSBram Moolenaarendif 405a7f6c3cfSBram Moolenaar 406ce436de5SBram Moolenaarlet s:may_fail_list = [] 407ce436de5SBram Moolenaarif $TEST_MAY_FAIL != '' 408bfe13cccSBram Moolenaar " Split the list at commas and add () to make it match g:testfunc. 409ce436de5SBram Moolenaar let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'}) 410ce436de5SBram Moolenaarendif 411ce436de5SBram Moolenaar 41242205551SBram Moolenaar" Execute the tests in alphabetical order. 413bfe13cccSBram Moolenaarfor g:testfunc in sort(s:tests) 4144a6fcf80SBram Moolenaar " Silence, please! 4154a6fcf80SBram Moolenaar set belloff=all 416f77af0e6SBram Moolenaar let prev_error = '' 417f77af0e6SBram Moolenaar let total_errors = [] 4183ed9efc2SBram Moolenaar let g:run_nr = 1 4194a6fcf80SBram Moolenaar 420bfe13cccSBram Moolenaar " A test can set g:test_is_flaky to retry running the test. 421bfe13cccSBram Moolenaar let g:test_is_flaky = 0 4223cdcb090SBram Moolenaar 423bfe13cccSBram Moolenaar call RunTheTest(g:testfunc) 42442205551SBram Moolenaar 425f77af0e6SBram Moolenaar " Repeat a flaky test. Give up when: 426f77af0e6SBram Moolenaar " - it fails again with the same message 4271bc353b6SBram Moolenaar " - it fails five times (with a different message) 428dbc0d216SBram Moolenaar if len(v:errors) > 0 429bfe13cccSBram Moolenaar \ && (index(s:flaky_tests, g:testfunc) >= 0 430bfe13cccSBram Moolenaar \ || g:test_is_flaky) 431f77af0e6SBram Moolenaar while 1 432bfe13cccSBram Moolenaar call add(s:messages, 'Found errors in ' . g:testfunc . ':') 4336caf606bSBram Moolenaar call extend(s:messages, v:errors) 43415e737f7SBram Moolenaar 4353ed9efc2SBram Moolenaar call add(total_errors, 'Run ' . g:run_nr . ':') 436f77af0e6SBram Moolenaar call extend(total_errors, v:errors) 437f77af0e6SBram Moolenaar 4383ed9efc2SBram Moolenaar if g:run_nr == 5 || prev_error == v:errors[0] 439f77af0e6SBram Moolenaar call add(total_errors, 'Flaky test failed too often, giving up') 440f77af0e6SBram Moolenaar let v:errors = total_errors 441f77af0e6SBram Moolenaar break 442f77af0e6SBram Moolenaar endif 443f77af0e6SBram Moolenaar 444f77af0e6SBram Moolenaar call add(s:messages, 'Flaky test failed, running it again') 445f77af0e6SBram Moolenaar 446f77af0e6SBram Moolenaar " Flakiness is often caused by the system being very busy. Sleep a 447f77af0e6SBram Moolenaar " couple of seconds to have a higher chance of succeeding the second 448f77af0e6SBram Moolenaar " time. 44955058601SBram Moolenaar sleep 2 45055058601SBram Moolenaar 451f77af0e6SBram Moolenaar let prev_error = v:errors[0] 45242205551SBram Moolenaar let v:errors = [] 4533ed9efc2SBram Moolenaar let g:run_nr += 1 454f77af0e6SBram Moolenaar 455bfe13cccSBram Moolenaar call RunTheTest(g:testfunc) 456f77af0e6SBram Moolenaar 457f77af0e6SBram Moolenaar if len(v:errors) == 0 458f77af0e6SBram Moolenaar " Test passed on rerun. 459f77af0e6SBram Moolenaar break 46015e737f7SBram Moolenaar endif 461f77af0e6SBram Moolenaar endwhile 46242205551SBram Moolenaar endif 46342205551SBram Moolenaar 464bfe13cccSBram Moolenaar call AfterTheTest(g:testfunc) 46542205551SBram Moolenaarendfor 46642205551SBram Moolenaar 46742205551SBram Moolenaarcall FinishTesting() 468cc28e2d0SBram Moolenaar 469cc28e2d0SBram Moolenaar" vim: shiftwidth=2 sts=2 expandtab 470