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 108*10e1d01aSBram Moolenaar" suppress menu translation 109*10e1d01aSBram Moolenaarif has('gui_running') && exists('did_install_default_menus') 110*10e1d01aSBram Moolenaar source $VIMRUNTIME/delmenu.vim 111*10e1d01aSBram Moolenaar set langmenu=none 112*10e1d01aSBram Moolenaar source $VIMRUNTIME/menu.vim 113*10e1d01aSBram Moolenaarendif 114*10e1d01aSBram Moolenaar 115f60b796fSBram Moolenaar" Always use forward slashes. 116f60b796fSBram Moolenaarset shellslash 117f60b796fSBram Moolenaar 11828fb79dbSBram Moolenaarlet s:srcdir = expand('%:p:h:h') 11928fb79dbSBram Moolenaar 1208e8df251SBram Moolenaar" Prepare for calling test_garbagecollect_now(). 121ebf7dfa6SBram Moolenaarlet v:testing = 1 122ebf7dfa6SBram Moolenaar 12328fb79dbSBram Moolenaar" Support function: get the alloc ID by name. 12428fb79dbSBram Moolenaarfunction GetAllocId(name) 12528fb79dbSBram Moolenaar exe 'split ' . s:srcdir . '/alloc.h' 126065ee9aeSBram Moolenaar let top = search('typedef enum') 127065ee9aeSBram Moolenaar if top == 0 128065ee9aeSBram Moolenaar call add(v:errors, 'typedef not found in alloc.h') 129065ee9aeSBram Moolenaar endif 13028fb79dbSBram Moolenaar let lnum = search('aid_' . a:name . ',') 13128fb79dbSBram Moolenaar if lnum == 0 13228fb79dbSBram Moolenaar call add(v:errors, 'Alloc ID ' . a:name . ' not defined') 13328fb79dbSBram Moolenaar endif 13428fb79dbSBram Moolenaar close 135065ee9aeSBram Moolenaar return lnum - top - 1 13628fb79dbSBram Moolenaarendfunc 13728fb79dbSBram Moolenaar 13842205551SBram Moolenaarfunc RunTheTest(test) 139b5760a1cSBram Moolenaar echo 'Executing ' . a:test 14075ee544fSBram Moolenaar if has('reltime') 14175ee544fSBram Moolenaar let func_start = reltime() 14275ee544fSBram Moolenaar endif 143e5f2a075SBram Moolenaar 144e5f2a075SBram Moolenaar " Avoid stopping at the "hit enter" prompt 145e5f2a075SBram Moolenaar set nomore 146e5f2a075SBram Moolenaar 147e5f2a075SBram Moolenaar " Avoid a three second wait when a message is about to be overwritten by the 148e5f2a075SBram Moolenaar " mode message. 149e5f2a075SBram Moolenaar set noshowmode 150e5f2a075SBram Moolenaar 151eb992cb9SBram Moolenaar " Clear any overrides. 152eb992cb9SBram Moolenaar call test_override('ALL', 0) 153eb992cb9SBram Moolenaar 154cf1ba35fSBram Moolenaar " Some tests wipe out buffers. To be consistent, always wipe out all 155cf1ba35fSBram Moolenaar " buffers. 156cf1ba35fSBram Moolenaar %bwipe! 157cf1ba35fSBram Moolenaar 158209d3874SBram Moolenaar " The test may change the current directory. Save and restore the 159209d3874SBram Moolenaar " directory after executing the test. 160209d3874SBram Moolenaar let save_cwd = getcwd() 161209d3874SBram Moolenaar 162b5760a1cSBram Moolenaar if exists("*SetUp") 163cc28e2d0SBram Moolenaar try 164b5760a1cSBram Moolenaar call SetUp() 165cc28e2d0SBram Moolenaar catch 166cc28e2d0SBram Moolenaar call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 167cc28e2d0SBram Moolenaar endtry 168b5760a1cSBram Moolenaar endif 169b5760a1cSBram Moolenaar 170f204e05aSBram Moolenaar if a:test =~ 'Test_nocatch_' 171f204e05aSBram Moolenaar " Function handles errors itself. This avoids skipping commands after the 172f204e05aSBram Moolenaar " error. 173f204e05aSBram Moolenaar exe 'call ' . a:test 174f204e05aSBram Moolenaar else 175b5760a1cSBram Moolenaar try 176bfe13cccSBram Moolenaar au VimLeavePre * call EarlyExit(g:testfunc) 177b5760a1cSBram Moolenaar exe 'call ' . a:test 1788903676dSBram Moolenaar au! VimLeavePre 179dac1947bSBram Moolenaar catch /^\cskipped/ 180dac1947bSBram Moolenaar call add(s:messages, ' Skipped') 181dac1947bSBram Moolenaar call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) 182b5760a1cSBram Moolenaar catch 183b5760a1cSBram Moolenaar call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 184b5760a1cSBram Moolenaar endtry 185f204e05aSBram Moolenaar endif 1868ad16da7SBram Moolenaar 1878ad16da7SBram Moolenaar " In case 'insertmode' was set and something went wrong, make sure it is 1888ad16da7SBram Moolenaar " reset to avoid trouble with anything else. 1898ad16da7SBram Moolenaar set noinsertmode 190b5760a1cSBram Moolenaar 191b5760a1cSBram Moolenaar if exists("*TearDown") 192cc28e2d0SBram Moolenaar try 193b5760a1cSBram Moolenaar call TearDown() 194cc28e2d0SBram Moolenaar catch 195cc28e2d0SBram Moolenaar call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 196cc28e2d0SBram Moolenaar endtry 197b5760a1cSBram Moolenaar endif 1987cba71d7SBram Moolenaar 1990b5dc644SBram Moolenaar " Clear any autocommands and put back the catch-all for SwapExists. 200cf1ba35fSBram Moolenaar au! 201d8f27b30SBram Moolenaar au SwapExists * call HandleSwapExists() 202cf1ba35fSBram Moolenaar 203ef6b979bSBram Moolenaar " Check for and close any stray popup windows. 20405ad5ff0SBram Moolenaar if has('popupwin') 205ef6b979bSBram Moolenaar call assert_equal([], popup_list()) 20603a9f848SBram Moolenaar call popup_clear(1) 207ae943150SBram Moolenaar endif 208ae943150SBram Moolenaar 209ce11de87SBram Moolenaar " Close any extra tab pages and windows and make the current one not modified. 210ce11de87SBram Moolenaar while tabpagenr('$') > 1 211cf1ba35fSBram Moolenaar quit! 212ce11de87SBram Moolenaar endwhile 213ce11de87SBram Moolenaar 214358308ddSBram Moolenaar while 1 215358308ddSBram Moolenaar let wincount = winnr('$') 216358308ddSBram Moolenaar if wincount == 1 217358308ddSBram Moolenaar break 218358308ddSBram Moolenaar endif 2197cba71d7SBram Moolenaar bwipe! 220358308ddSBram Moolenaar if wincount == winnr('$') 221358308ddSBram Moolenaar " Did not manage to close a window. 222358308ddSBram Moolenaar only! 223358308ddSBram Moolenaar break 224358308ddSBram Moolenaar endif 2257cba71d7SBram Moolenaar endwhile 226209d3874SBram Moolenaar 227209d3874SBram Moolenaar exe 'cd ' . save_cwd 228640d4f0cSBram Moolenaar 229640d4f0cSBram Moolenaar let message = 'Executed ' . a:test 230640d4f0cSBram Moolenaar if has('reltime') 2318d943796SBram Moolenaar let message ..= repeat(' ', 50 - len(message)) 2328d943796SBram Moolenaar let time = reltime(func_start) 2338d943796SBram Moolenaar if has('float') && reltimefloat(time) > 0.1 2348d943796SBram Moolenaar let message = &t_md .. message 2358d943796SBram Moolenaar endif 2368d943796SBram Moolenaar let message ..= ' in ' .. reltimestr(time) .. ' seconds' 2378d943796SBram Moolenaar if has('float') && reltimefloat(time) > 0.1 2388d943796SBram Moolenaar let message ..= &t_me 2398d943796SBram Moolenaar endif 240640d4f0cSBram Moolenaar endif 241640d4f0cSBram Moolenaar call add(s:messages, message) 242640d4f0cSBram Moolenaar let s:done += 1 243b5760a1cSBram Moolenaarendfunc 24428fb79dbSBram Moolenaar 245ce436de5SBram Moolenaarfunc AfterTheTest(func_name) 24643345546SBram Moolenaar if len(v:errors) > 0 247ce436de5SBram Moolenaar if match(s:may_fail_list, '^' .. a:func_name) >= 0 248ce436de5SBram Moolenaar let s:fail_expected += 1 249bfe13cccSBram Moolenaar call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':') 250ce436de5SBram Moolenaar call extend(s:errors_expected, v:errors) 251ce436de5SBram Moolenaar else 25200af60bbSBram Moolenaar let s:fail += 1 253bfe13cccSBram Moolenaar call add(s:errors, 'Found errors in ' . g:testfunc . ':') 25400af60bbSBram Moolenaar call extend(s:errors, v:errors) 255ce436de5SBram Moolenaar endif 25643345546SBram Moolenaar let v:errors = [] 25743345546SBram Moolenaar endif 25842205551SBram Moolenaarendfunc 25942205551SBram Moolenaar 2608903676dSBram Moolenaarfunc EarlyExit(test) 2618903676dSBram Moolenaar " It's OK for the test we use to test the quit detection. 2628903676dSBram Moolenaar if a:test != 'Test_zz_quit_detected()' 2638903676dSBram Moolenaar call add(v:errors, 'Test caused Vim to exit: ' . a:test) 2648903676dSBram Moolenaar endif 2658903676dSBram Moolenaar 2668903676dSBram Moolenaar call FinishTesting() 2678903676dSBram Moolenaarendfunc 2688903676dSBram Moolenaar 26942205551SBram Moolenaar" This function can be called by a test if it wants to abort testing. 27042205551SBram Moolenaarfunc FinishTesting() 271ce436de5SBram Moolenaar call AfterTheTest('') 27243345546SBram Moolenaar 273fc4ad616SBram Moolenaar " Don't write viminfo on exit. 274fc4ad616SBram Moolenaar set viminfo= 275fc4ad616SBram Moolenaar 276d1ee0043SBram Moolenaar " Clean up files created by setup.vim 277d1ee0043SBram Moolenaar call delete('XfakeHOME', 'rf') 278d1ee0043SBram Moolenaar 279ce436de5SBram Moolenaar if s:fail == 0 && s:fail_expected == 0 28043345546SBram Moolenaar " Success, create the .res file so that make knows it's done. 28100af60bbSBram Moolenaar exe 'split ' . fnamemodify(g:testname, ':r') . '.res' 28243345546SBram Moolenaar write 28343345546SBram Moolenaar endif 28443345546SBram Moolenaar 28500af60bbSBram Moolenaar if len(s:errors) > 0 28643345546SBram Moolenaar " Append errors to test.log 28743345546SBram Moolenaar split test.log 28843345546SBram Moolenaar call append(line('$'), '') 28900af60bbSBram Moolenaar call append(line('$'), 'From ' . g:testname . ':') 29000af60bbSBram Moolenaar call append(line('$'), s:errors) 29143345546SBram Moolenaar write 29243345546SBram Moolenaar endif 29343345546SBram Moolenaar 29429f9ed20SBram Moolenaar if s:done == 0 2957b666c78SBram Moolenaar if s:filtered > 0 2967b666c78SBram Moolenaar let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'" 29729f9ed20SBram Moolenaar else 2987b666c78SBram Moolenaar let message = 'NO tests executed' 2997b666c78SBram Moolenaar endif 3007b666c78SBram Moolenaar else 3017b666c78SBram Moolenaar if s:filtered > 0 3027b666c78SBram Moolenaar call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER") 3037b666c78SBram Moolenaar endif 30400af60bbSBram Moolenaar let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test') 30529f9ed20SBram Moolenaar endif 3067b666c78SBram Moolenaar if s:done > 0 && has('reltime') 3078d943796SBram Moolenaar let message = &t_md .. message .. repeat(' ', 40 - len(message)) 30875ee544fSBram Moolenaar let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds' 3098d943796SBram Moolenaar let message ..= &t_me 31075ee544fSBram Moolenaar endif 311096c8bb4SBram Moolenaar echo message 31200af60bbSBram Moolenaar call add(s:messages, message) 31300af60bbSBram Moolenaar if s:fail > 0 31400af60bbSBram Moolenaar let message = s:fail . ' FAILED:' 315096c8bb4SBram Moolenaar echo message 31600af60bbSBram Moolenaar call add(s:messages, message) 31700af60bbSBram Moolenaar call extend(s:messages, s:errors) 31843345546SBram Moolenaar endif 319ce436de5SBram Moolenaar if s:fail_expected > 0 320ce436de5SBram Moolenaar let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):' 321ce436de5SBram Moolenaar echo message 322ce436de5SBram Moolenaar call add(s:messages, message) 323ce436de5SBram Moolenaar call extend(s:messages, s:errors_expected) 324ce436de5SBram Moolenaar endif 32543345546SBram Moolenaar 326dac1947bSBram Moolenaar " Add SKIPPED messages 327dac1947bSBram Moolenaar call extend(s:messages, s:skipped) 328dac1947bSBram Moolenaar 329dac1947bSBram Moolenaar " Append messages to the file "messages" 330096c8bb4SBram Moolenaar split messages 331096c8bb4SBram Moolenaar call append(line('$'), '') 33200af60bbSBram Moolenaar call append(line('$'), 'From ' . g:testname . ':') 33300af60bbSBram Moolenaar call append(line('$'), s:messages) 334096c8bb4SBram Moolenaar write 335096c8bb4SBram Moolenaar 33643345546SBram Moolenaar qall! 33742205551SBram Moolenaarendfunc 33842205551SBram Moolenaar 33942205551SBram Moolenaar" Source the test script. First grab the file name, in case the script 34042205551SBram Moolenaar" navigates away. g:testname can be used by the tests. 34142205551SBram Moolenaarlet g:testname = expand('%') 34242205551SBram Moolenaarlet s:done = 0 34342205551SBram Moolenaarlet s:fail = 0 344ce436de5SBram Moolenaarlet s:fail_expected = 0 34542205551SBram Moolenaarlet s:errors = [] 346ce436de5SBram Moolenaarlet s:errors_expected = [] 34742205551SBram Moolenaarlet s:messages = [] 34842205551SBram Moolenaarlet s:skipped = [] 34942205551SBram Moolenaarif expand('%') =~ 'test_vimscript.vim' 350ce436de5SBram Moolenaar " this test has intentional errors, don't use try/catch. 35142205551SBram Moolenaar source % 35242205551SBram Moolenaarelse 35342205551SBram Moolenaar try 35442205551SBram Moolenaar source % 3559c0cec65SBram Moolenaar catch /^\cskipped/ 3569c0cec65SBram Moolenaar call add(s:messages, ' Skipped') 3579c0cec65SBram Moolenaar call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) 35842205551SBram Moolenaar catch 35942205551SBram Moolenaar let s:fail += 1 36042205551SBram Moolenaar call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint) 36142205551SBram Moolenaar endtry 36242205551SBram Moolenaarendif 36342205551SBram Moolenaar 36442205551SBram Moolenaar" Names of flaky tests. 365dbc0d216SBram Moolenaarlet s:flaky_tests = [ 3660d0c3ca0SBram Moolenaar \ 'Test_autocmd_SafeState()', 36742205551SBram Moolenaar \ 'Test_client_server()', 36842205551SBram Moolenaar \ 'Test_close_and_exit_cb()', 369d80232beSBram Moolenaar \ 'Test_close_output_buffer()', 37042205551SBram Moolenaar \ 'Test_collapse_buffers()', 37165873846SBram Moolenaar \ 'Test_cwd()', 372218959bcSBram Moolenaar \ 'Test_diff_screen()', 37342205551SBram Moolenaar \ 'Test_exit_callback_interval()', 374ea94c855SBram Moolenaar \ 'Test_map_timeout_with_timer_interrupt()', 3751eca6f13SBram Moolenaar \ 'Test_out_cb()', 37642205551SBram Moolenaar \ 'Test_pipe_through_sort_all()', 37742205551SBram Moolenaar \ 'Test_pipe_through_sort_some()', 37844f0bd87SBram Moolenaar \ 'Test_popup_and_window_resize()', 37942205551SBram Moolenaar \ 'Test_quoteplus()', 3807dd48506SBram Moolenaar \ 'Test_quotestar()', 38142205551SBram Moolenaar \ 'Test_reltime()', 3823c8cd4a1SBram Moolenaar \ 'Test_state()', 383f204e05aSBram Moolenaar \ 'Test_terminal_composing_unicode()', 3843876789bSBram Moolenaar \ 'Test_terminal_does_not_truncate_last_newlines()', 3853615abb6SBram Moolenaar \ 'Test_terminal_no_cmd()', 38675a60f74SBram Moolenaar \ 'Test_terminal_noblock()', 3877dd88c51SBram Moolenaar \ 'Test_terminal_redir_file()', 388e219f73eSBram Moolenaar \ 'Test_termwinscroll()', 3899a2fddcfSBram Moolenaar \ 'Test_timer_oneshot()', 3909a2fddcfSBram Moolenaar \ 'Test_timer_paused()', 3919a2fddcfSBram Moolenaar \ 'Test_timer_repeat_many()', 3929a2fddcfSBram Moolenaar \ 'Test_timer_repeat_three()', 3939a2fddcfSBram Moolenaar \ 'Test_timer_stop_all_in_callback()', 3949a2fddcfSBram Moolenaar \ 'Test_timer_stop_in_callback()', 3959a2fddcfSBram Moolenaar \ 'Test_timer_with_partial_callback()', 39642205551SBram Moolenaar \ ] 39742205551SBram Moolenaar 39842205551SBram Moolenaar" Locate Test_ functions and execute them. 39942205551SBram Moolenaarredir @q 40042205551SBram Moolenaarsilent function /^Test_ 40142205551SBram Moolenaarredir END 40261a6d4e4SBram Moolenaarlet s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g')) 40342205551SBram Moolenaar 40442205551SBram Moolenaar" If there is an extra argument filter the function names against it. 40542205551SBram Moolenaarif argc() > 1 40642205551SBram Moolenaar let s:tests = filter(s:tests, 'v:val =~ argv(1)') 40742205551SBram Moolenaarendif 40842205551SBram Moolenaar 409a7f6c3cfSBram Moolenaar" If the environment variable $TEST_FILTER is set then filter the function 410a7f6c3cfSBram Moolenaar" names against it. 4117b666c78SBram Moolenaarlet s:filtered = 0 412a7f6c3cfSBram Moolenaarif $TEST_FILTER != '' 4137b666c78SBram Moolenaar let s:filtered = len(s:tests) 414a7f6c3cfSBram Moolenaar let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER') 4157b666c78SBram Moolenaar let s:filtered -= len(s:tests) 416a7f6c3cfSBram Moolenaarendif 417a7f6c3cfSBram Moolenaar 418ce436de5SBram Moolenaarlet s:may_fail_list = [] 419ce436de5SBram Moolenaarif $TEST_MAY_FAIL != '' 420bfe13cccSBram Moolenaar " Split the list at commas and add () to make it match g:testfunc. 421ce436de5SBram Moolenaar let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'}) 422ce436de5SBram Moolenaarendif 423ce436de5SBram Moolenaar 42442205551SBram Moolenaar" Execute the tests in alphabetical order. 425bfe13cccSBram Moolenaarfor g:testfunc in sort(s:tests) 4264a6fcf80SBram Moolenaar " Silence, please! 4274a6fcf80SBram Moolenaar set belloff=all 428f77af0e6SBram Moolenaar let prev_error = '' 429f77af0e6SBram Moolenaar let total_errors = [] 4303ed9efc2SBram Moolenaar let g:run_nr = 1 4314a6fcf80SBram Moolenaar 432bfe13cccSBram Moolenaar " A test can set g:test_is_flaky to retry running the test. 433bfe13cccSBram Moolenaar let g:test_is_flaky = 0 4343cdcb090SBram Moolenaar 435bfe13cccSBram Moolenaar call RunTheTest(g:testfunc) 43642205551SBram Moolenaar 437f77af0e6SBram Moolenaar " Repeat a flaky test. Give up when: 438f77af0e6SBram Moolenaar " - it fails again with the same message 4391bc353b6SBram Moolenaar " - it fails five times (with a different message) 440dbc0d216SBram Moolenaar if len(v:errors) > 0 441bfe13cccSBram Moolenaar \ && (index(s:flaky_tests, g:testfunc) >= 0 442bfe13cccSBram Moolenaar \ || g:test_is_flaky) 443f77af0e6SBram Moolenaar while 1 444bfe13cccSBram Moolenaar call add(s:messages, 'Found errors in ' . g:testfunc . ':') 4456caf606bSBram Moolenaar call extend(s:messages, v:errors) 44615e737f7SBram Moolenaar 4473ed9efc2SBram Moolenaar call add(total_errors, 'Run ' . g:run_nr . ':') 448f77af0e6SBram Moolenaar call extend(total_errors, v:errors) 449f77af0e6SBram Moolenaar 4503ed9efc2SBram Moolenaar if g:run_nr == 5 || prev_error == v:errors[0] 451f77af0e6SBram Moolenaar call add(total_errors, 'Flaky test failed too often, giving up') 452f77af0e6SBram Moolenaar let v:errors = total_errors 453f77af0e6SBram Moolenaar break 454f77af0e6SBram Moolenaar endif 455f77af0e6SBram Moolenaar 456f77af0e6SBram Moolenaar call add(s:messages, 'Flaky test failed, running it again') 457f77af0e6SBram Moolenaar 458f77af0e6SBram Moolenaar " Flakiness is often caused by the system being very busy. Sleep a 459f77af0e6SBram Moolenaar " couple of seconds to have a higher chance of succeeding the second 460f77af0e6SBram Moolenaar " time. 46155058601SBram Moolenaar sleep 2 46255058601SBram Moolenaar 463f77af0e6SBram Moolenaar let prev_error = v:errors[0] 46442205551SBram Moolenaar let v:errors = [] 4653ed9efc2SBram Moolenaar let g:run_nr += 1 466f77af0e6SBram Moolenaar 467bfe13cccSBram Moolenaar call RunTheTest(g:testfunc) 468f77af0e6SBram Moolenaar 469f77af0e6SBram Moolenaar if len(v:errors) == 0 470f77af0e6SBram Moolenaar " Test passed on rerun. 471f77af0e6SBram Moolenaar break 47215e737f7SBram Moolenaar endif 473f77af0e6SBram Moolenaar endwhile 47442205551SBram Moolenaar endif 47542205551SBram Moolenaar 476bfe13cccSBram Moolenaar call AfterTheTest(g:testfunc) 47742205551SBram Moolenaarendfor 47842205551SBram Moolenaar 47942205551SBram Moolenaarcall FinishTesting() 480cc28e2d0SBram Moolenaar 481cc28e2d0SBram Moolenaar" vim: shiftwidth=2 sts=2 expandtab 482