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" 166ca6ca48SBram Moolenaar" While working on a test you can make $TEST_NO_RETRY non-empty to not retry: 176ca6ca48SBram Moolenaar" export TEST_NO_RETRY=yes 186ca6ca48SBram Moolenaar" 19ce436de5SBram Moolenaar" To ignore failure for tests that are known to fail in a certain environment, 20ce436de5SBram Moolenaar" set $TEST_MAY_FAIL to a comma separated list of function names. E.g. for 21ce436de5SBram Moolenaar" sh/bash: 22ce436de5SBram Moolenaar" export TEST_MAY_FAIL=Test_channel_one,Test_channel_other 23ce436de5SBram Moolenaar" The failure report will then not be included in the test.log file and 24ce436de5SBram Moolenaar" "make test" will not fail. 25ce436de5SBram Moolenaar" 2643345546SBram Moolenaar" The test script may contain anything, only functions that start with 2743345546SBram Moolenaar" "Test_" are special. These will be invoked and should contain assert 2843345546SBram Moolenaar" functions. See test_assert.vim for an example. 2943345546SBram Moolenaar" 3043345546SBram Moolenaar" It is possible to source other files that contain "Test_" functions. This 3143345546SBram Moolenaar" can speed up testing, since Vim does not need to restart. But be careful 3243345546SBram Moolenaar" that the tests do not interfere with each other. 3343345546SBram Moolenaar" 3443345546SBram Moolenaar" If an error cannot be detected properly with an assert function add the 3543345546SBram Moolenaar" error to the v:errors list: 3643345546SBram Moolenaar" call add(v:errors, 'test foo failed: Cannot find xyz') 3743345546SBram Moolenaar" 3843345546SBram Moolenaar" If preparation for each Test_ function is needed, define a SetUp function. 3943345546SBram Moolenaar" It will be called before each Test_ function. 4043345546SBram Moolenaar" 4143345546SBram Moolenaar" If cleanup after each Test_ function is needed, define a TearDown function. 4243345546SBram Moolenaar" It will be called after each Test_ function. 4300af60bbSBram Moolenaar" 4400af60bbSBram Moolenaar" When debugging a test it can be useful to add messages to v:errors: 4500af60bbSBram Moolenaar" call add(v:errors, "this happened") 4600af60bbSBram Moolenaar 4743345546SBram Moolenaar 4843345546SBram Moolenaar" Without the +eval feature we can't run these tests, bail out. 494686b323SBram Moolenaarso small.vim 5043345546SBram Moolenaar 5118aa13d1SBram Moolenaar" In the GUI we can always change the screen size. 5218aa13d1SBram Moolenaarif has('gui_running') 5318aa13d1SBram Moolenaar set columns=80 lines=25 5418aa13d1SBram Moolenaarendif 5518aa13d1SBram Moolenaar 5643345546SBram Moolenaar" Check that the screen size is at least 24 x 80 characters. 5743345546SBram Moolenaarif &lines < 24 || &columns < 80 580b5dc644SBram Moolenaar let error = 'Screen size too small! Tests require at least 24 lines with 80 characters, got ' .. &lines .. ' lines with ' .. &columns .. ' characters' 5943345546SBram Moolenaar echoerr error 6043345546SBram Moolenaar split test.log 6143345546SBram Moolenaar $put =error 6245aa07d3SBram Moolenaar write 6345aa07d3SBram Moolenaar split messages 640b5dc644SBram Moolenaar call append(line('$'), '') 650b5dc644SBram Moolenaar call append(line('$'), 'From ' . expand('%') . ':') 6645aa07d3SBram Moolenaar call append(line('$'), error) 6745aa07d3SBram Moolenaar write 6845aa07d3SBram Moolenaar qa! 6943345546SBram Moolenaarendif 7043345546SBram Moolenaar 7175ee544fSBram Moolenaarif has('reltime') 7275ee544fSBram Moolenaar let s:start_time = reltime() 7375ee544fSBram Moolenaarendif 7475ee544fSBram Moolenaar 7589b10421SBram Moolenaar" Common with all tests on all systems. 7689b10421SBram Moolenaarsource setup.vim 7789b10421SBram Moolenaar 78c0662466SBram Moolenaar" For consistency run all tests with 'nocompatible' set. 79c0662466SBram Moolenaar" This also enables use of line continuation. 80c0662466SBram Moolenaarset nocp viminfo+=nviminfo 81c0662466SBram Moolenaar 8230276f2bSBram Moolenaar" Use utf-8 by default, instead of whatever the system default happens to be. 83ed79d1e3SBram Moolenaar" Individual tests can overrule this at the top of the file and use 84ed79d1e3SBram Moolenaar" g:orig_encoding if needed. 85ed79d1e3SBram Moolenaarlet g:orig_encoding = &encoding 86ac105ed3SBram Moolenaarset encoding=utf-8 87ac105ed3SBram Moolenaar 88d8f27b30SBram Moolenaar" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for 89d8f27b30SBram Moolenaar" the test_name.vim file itself. Replace it here with a more restrictive one, 90d8f27b30SBram Moolenaar" so we still catch mistakes. 91d8f27b30SBram Moolenaarlet s:test_script_fname = expand('%') 92d8f27b30SBram Moolenaarau! SwapExists * call HandleSwapExists() 93d8f27b30SBram Moolenaarfunc HandleSwapExists() 94b073da89SBram Moolenaar " Ignore finding a swap file for the test script (the user might be 95d8f27b30SBram Moolenaar " editing it and do ":make test_name") and the output file. 96b073da89SBram Moolenaar " Report finding another swap file and chose 'q' to avoid getting stuck. 97d8f27b30SBram Moolenaar if expand('<afile>') == 'messages' || expand('<afile>') =~ s:test_script_fname 98d8f27b30SBram Moolenaar let v:swapchoice = 'e' 99b073da89SBram Moolenaar else 100b073da89SBram Moolenaar call assert_report('Unexpected swap file: ' .. v:swapname) 101b073da89SBram Moolenaar let v:swapchoice = 'q' 102d8f27b30SBram Moolenaar endif 103d8f27b30SBram Moolenaarendfunc 104d8f27b30SBram Moolenaar 1057a073549SBram Moolenaar" Avoid stopping at the "hit enter" prompt 1067a073549SBram Moolenaarset nomore 1077a073549SBram Moolenaar 108c0662466SBram Moolenaar" Output all messages in English. 109c0662466SBram Moolenaarlang mess C 110c0662466SBram Moolenaar 11110e1d01aSBram Moolenaar" suppress menu translation 11210e1d01aSBram Moolenaarif has('gui_running') && exists('did_install_default_menus') 11310e1d01aSBram Moolenaar source $VIMRUNTIME/delmenu.vim 11410e1d01aSBram Moolenaar set langmenu=none 11510e1d01aSBram Moolenaar source $VIMRUNTIME/menu.vim 11610e1d01aSBram Moolenaarendif 11710e1d01aSBram Moolenaar 118f60b796fSBram Moolenaar" Always use forward slashes. 119f60b796fSBram Moolenaarset shellslash 120f60b796fSBram Moolenaar 12128fb79dbSBram Moolenaarlet s:srcdir = expand('%:p:h:h') 12228fb79dbSBram Moolenaar 1232690b5aeSBram Moolenaarif has('win32') 1242690b5aeSBram Moolenaar " avoid prompt that is long or contains a line break 1252690b5aeSBram Moolenaar let $PROMPT = '$P$G' 126*45df2a01SBram Moolenaar " On MS-Windows t_md and t_me are Vim specific escape sequences. 127*45df2a01SBram Moolenaar let s:t_bold = "\x1b[1m" 128*45df2a01SBram Moolenaar let s:t_normal = "\x1b[m" 129*45df2a01SBram Moolenaarelse 130*45df2a01SBram Moolenaar let s:t_bold = &t_md 131*45df2a01SBram Moolenaar let s:t_normal = &t_me 1322690b5aeSBram Moolenaarendif 1332690b5aeSBram Moolenaar 1348e8df251SBram Moolenaar" Prepare for calling test_garbagecollect_now(). 135ebf7dfa6SBram Moolenaarlet v:testing = 1 136ebf7dfa6SBram Moolenaar 13728fb79dbSBram Moolenaar" Support function: get the alloc ID by name. 13828fb79dbSBram Moolenaarfunction GetAllocId(name) 13928fb79dbSBram Moolenaar exe 'split ' . s:srcdir . '/alloc.h' 140065ee9aeSBram Moolenaar let top = search('typedef enum') 141065ee9aeSBram Moolenaar if top == 0 142065ee9aeSBram Moolenaar call add(v:errors, 'typedef not found in alloc.h') 143065ee9aeSBram Moolenaar endif 14428fb79dbSBram Moolenaar let lnum = search('aid_' . a:name . ',') 14528fb79dbSBram Moolenaar if lnum == 0 14628fb79dbSBram Moolenaar call add(v:errors, 'Alloc ID ' . a:name . ' not defined') 14728fb79dbSBram Moolenaar endif 14828fb79dbSBram Moolenaar close 149065ee9aeSBram Moolenaar return lnum - top - 1 15028fb79dbSBram Moolenaarendfunc 15128fb79dbSBram Moolenaar 15242205551SBram Moolenaarfunc RunTheTest(test) 153b5760a1cSBram Moolenaar echo 'Executing ' . a:test 15475ee544fSBram Moolenaar if has('reltime') 15575ee544fSBram Moolenaar let func_start = reltime() 15675ee544fSBram Moolenaar endif 157e5f2a075SBram Moolenaar 158e5f2a075SBram Moolenaar " Avoid stopping at the "hit enter" prompt 159e5f2a075SBram Moolenaar set nomore 160e5f2a075SBram Moolenaar 161e5f2a075SBram Moolenaar " Avoid a three second wait when a message is about to be overwritten by the 162e5f2a075SBram Moolenaar " mode message. 163e5f2a075SBram Moolenaar set noshowmode 164e5f2a075SBram Moolenaar 165eb992cb9SBram Moolenaar " Clear any overrides. 166eb992cb9SBram Moolenaar call test_override('ALL', 0) 167eb992cb9SBram Moolenaar 168cf1ba35fSBram Moolenaar " Some tests wipe out buffers. To be consistent, always wipe out all 169cf1ba35fSBram Moolenaar " buffers. 170cf1ba35fSBram Moolenaar %bwipe! 171cf1ba35fSBram Moolenaar 172209d3874SBram Moolenaar " The test may change the current directory. Save and restore the 173209d3874SBram Moolenaar " directory after executing the test. 174209d3874SBram Moolenaar let save_cwd = getcwd() 175209d3874SBram Moolenaar 176b5760a1cSBram Moolenaar if exists("*SetUp") 177cc28e2d0SBram Moolenaar try 178b5760a1cSBram Moolenaar call SetUp() 179cc28e2d0SBram Moolenaar catch 180cc28e2d0SBram Moolenaar call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 181cc28e2d0SBram Moolenaar endtry 182b5760a1cSBram Moolenaar endif 183b5760a1cSBram Moolenaar 184f204e05aSBram Moolenaar if a:test =~ 'Test_nocatch_' 185f204e05aSBram Moolenaar " Function handles errors itself. This avoids skipping commands after the 186f204e05aSBram Moolenaar " error. 187f204e05aSBram Moolenaar exe 'call ' . a:test 188f204e05aSBram Moolenaar else 189b5760a1cSBram Moolenaar try 190bfe13cccSBram Moolenaar au VimLeavePre * call EarlyExit(g:testfunc) 191b5760a1cSBram Moolenaar exe 'call ' . a:test 1928903676dSBram Moolenaar au! VimLeavePre 193dac1947bSBram Moolenaar catch /^\cskipped/ 194dac1947bSBram Moolenaar call add(s:messages, ' Skipped') 195dac1947bSBram Moolenaar call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) 196b5760a1cSBram Moolenaar catch 197b5760a1cSBram Moolenaar call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 198b5760a1cSBram Moolenaar endtry 199f204e05aSBram Moolenaar endif 2008ad16da7SBram Moolenaar 2018ad16da7SBram Moolenaar " In case 'insertmode' was set and something went wrong, make sure it is 2028ad16da7SBram Moolenaar " reset to avoid trouble with anything else. 2038ad16da7SBram Moolenaar set noinsertmode 204b5760a1cSBram Moolenaar 205b5760a1cSBram Moolenaar if exists("*TearDown") 206cc28e2d0SBram Moolenaar try 207b5760a1cSBram Moolenaar call TearDown() 208cc28e2d0SBram Moolenaar catch 209cc28e2d0SBram Moolenaar call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 210cc28e2d0SBram Moolenaar endtry 211b5760a1cSBram Moolenaar endif 2127cba71d7SBram Moolenaar 2130b5dc644SBram Moolenaar " Clear any autocommands and put back the catch-all for SwapExists. 214cf1ba35fSBram Moolenaar au! 215d8f27b30SBram Moolenaar au SwapExists * call HandleSwapExists() 216cf1ba35fSBram Moolenaar 217ef6b979bSBram Moolenaar " Check for and close any stray popup windows. 21805ad5ff0SBram Moolenaar if has('popupwin') 219ef6b979bSBram Moolenaar call assert_equal([], popup_list()) 22003a9f848SBram Moolenaar call popup_clear(1) 221ae943150SBram Moolenaar endif 222ae943150SBram Moolenaar 223ce11de87SBram Moolenaar " Close any extra tab pages and windows and make the current one not modified. 224ce11de87SBram Moolenaar while tabpagenr('$') > 1 225cf1ba35fSBram Moolenaar quit! 226ce11de87SBram Moolenaar endwhile 227ce11de87SBram Moolenaar 228358308ddSBram Moolenaar while 1 229358308ddSBram Moolenaar let wincount = winnr('$') 230358308ddSBram Moolenaar if wincount == 1 231358308ddSBram Moolenaar break 232358308ddSBram Moolenaar endif 2337cba71d7SBram Moolenaar bwipe! 234358308ddSBram Moolenaar if wincount == winnr('$') 235358308ddSBram Moolenaar " Did not manage to close a window. 236358308ddSBram Moolenaar only! 237358308ddSBram Moolenaar break 238358308ddSBram Moolenaar endif 2397cba71d7SBram Moolenaar endwhile 240209d3874SBram Moolenaar 241209d3874SBram Moolenaar exe 'cd ' . save_cwd 242640d4f0cSBram Moolenaar 243640d4f0cSBram Moolenaar let message = 'Executed ' . a:test 244640d4f0cSBram Moolenaar if has('reltime') 2458d943796SBram Moolenaar let message ..= repeat(' ', 50 - len(message)) 2468d943796SBram Moolenaar let time = reltime(func_start) 2478d943796SBram Moolenaar if has('float') && reltimefloat(time) > 0.1 248*45df2a01SBram Moolenaar let message = s:t_bold .. message 2498d943796SBram Moolenaar endif 2508d943796SBram Moolenaar let message ..= ' in ' .. reltimestr(time) .. ' seconds' 2518d943796SBram Moolenaar if has('float') && reltimefloat(time) > 0.1 252*45df2a01SBram Moolenaar let message ..= s:t_normal 2538d943796SBram Moolenaar endif 254640d4f0cSBram Moolenaar endif 255640d4f0cSBram Moolenaar call add(s:messages, message) 256640d4f0cSBram Moolenaar let s:done += 1 257b5760a1cSBram Moolenaarendfunc 25828fb79dbSBram Moolenaar 259ce436de5SBram Moolenaarfunc AfterTheTest(func_name) 26043345546SBram Moolenaar if len(v:errors) > 0 261ce436de5SBram Moolenaar if match(s:may_fail_list, '^' .. a:func_name) >= 0 262ce436de5SBram Moolenaar let s:fail_expected += 1 263bfe13cccSBram Moolenaar call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':') 264ce436de5SBram Moolenaar call extend(s:errors_expected, v:errors) 265ce436de5SBram Moolenaar else 26600af60bbSBram Moolenaar let s:fail += 1 267bfe13cccSBram Moolenaar call add(s:errors, 'Found errors in ' . g:testfunc . ':') 26800af60bbSBram Moolenaar call extend(s:errors, v:errors) 269ce436de5SBram Moolenaar endif 27043345546SBram Moolenaar let v:errors = [] 27143345546SBram Moolenaar endif 27242205551SBram Moolenaarendfunc 27342205551SBram Moolenaar 2748903676dSBram Moolenaarfunc EarlyExit(test) 2758903676dSBram Moolenaar " It's OK for the test we use to test the quit detection. 2768903676dSBram Moolenaar if a:test != 'Test_zz_quit_detected()' 2778903676dSBram Moolenaar call add(v:errors, 'Test caused Vim to exit: ' . a:test) 2788903676dSBram Moolenaar endif 2798903676dSBram Moolenaar 2808903676dSBram Moolenaar call FinishTesting() 2818903676dSBram Moolenaarendfunc 2828903676dSBram Moolenaar 28342205551SBram Moolenaar" This function can be called by a test if it wants to abort testing. 28442205551SBram Moolenaarfunc FinishTesting() 285ce436de5SBram Moolenaar call AfterTheTest('') 28643345546SBram Moolenaar 287fc4ad616SBram Moolenaar " Don't write viminfo on exit. 288fc4ad616SBram Moolenaar set viminfo= 289fc4ad616SBram Moolenaar 290d1ee0043SBram Moolenaar " Clean up files created by setup.vim 291d1ee0043SBram Moolenaar call delete('XfakeHOME', 'rf') 292d1ee0043SBram Moolenaar 293ce436de5SBram Moolenaar if s:fail == 0 && s:fail_expected == 0 29443345546SBram Moolenaar " Success, create the .res file so that make knows it's done. 29500af60bbSBram Moolenaar exe 'split ' . fnamemodify(g:testname, ':r') . '.res' 29643345546SBram Moolenaar write 29743345546SBram Moolenaar endif 29843345546SBram Moolenaar 29900af60bbSBram Moolenaar if len(s:errors) > 0 30043345546SBram Moolenaar " Append errors to test.log 30143345546SBram Moolenaar split test.log 30243345546SBram Moolenaar call append(line('$'), '') 30300af60bbSBram Moolenaar call append(line('$'), 'From ' . g:testname . ':') 30400af60bbSBram Moolenaar call append(line('$'), s:errors) 30543345546SBram Moolenaar write 30643345546SBram Moolenaar endif 30743345546SBram Moolenaar 30829f9ed20SBram Moolenaar if s:done == 0 3097b666c78SBram Moolenaar if s:filtered > 0 3107b666c78SBram Moolenaar let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'" 31129f9ed20SBram Moolenaar else 3127b666c78SBram Moolenaar let message = 'NO tests executed' 3137b666c78SBram Moolenaar endif 3147b666c78SBram Moolenaar else 3157b666c78SBram Moolenaar if s:filtered > 0 3167b666c78SBram Moolenaar call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER") 3177b666c78SBram Moolenaar endif 31800af60bbSBram Moolenaar let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test') 31929f9ed20SBram Moolenaar endif 3207b666c78SBram Moolenaar if s:done > 0 && has('reltime') 321*45df2a01SBram Moolenaar let message = s:t_bold .. message .. repeat(' ', 40 - len(message)) 32275ee544fSBram Moolenaar let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds' 323*45df2a01SBram Moolenaar let message ..= s:t_normal 32475ee544fSBram Moolenaar endif 325096c8bb4SBram Moolenaar echo message 32600af60bbSBram Moolenaar call add(s:messages, message) 32700af60bbSBram Moolenaar if s:fail > 0 32800af60bbSBram Moolenaar let message = s:fail . ' FAILED:' 329096c8bb4SBram Moolenaar echo message 33000af60bbSBram Moolenaar call add(s:messages, message) 33100af60bbSBram Moolenaar call extend(s:messages, s:errors) 33243345546SBram Moolenaar endif 333ce436de5SBram Moolenaar if s:fail_expected > 0 334ce436de5SBram Moolenaar let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):' 335ce436de5SBram Moolenaar echo message 336ce436de5SBram Moolenaar call add(s:messages, message) 337ce436de5SBram Moolenaar call extend(s:messages, s:errors_expected) 338ce436de5SBram Moolenaar endif 33943345546SBram Moolenaar 340dac1947bSBram Moolenaar " Add SKIPPED messages 341dac1947bSBram Moolenaar call extend(s:messages, s:skipped) 342dac1947bSBram Moolenaar 343dac1947bSBram Moolenaar " Append messages to the file "messages" 344096c8bb4SBram Moolenaar split messages 345096c8bb4SBram Moolenaar call append(line('$'), '') 34600af60bbSBram Moolenaar call append(line('$'), 'From ' . g:testname . ':') 34700af60bbSBram Moolenaar call append(line('$'), s:messages) 348096c8bb4SBram Moolenaar write 349096c8bb4SBram Moolenaar 35043345546SBram Moolenaar qall! 35142205551SBram Moolenaarendfunc 35242205551SBram Moolenaar 35342205551SBram Moolenaar" Source the test script. First grab the file name, in case the script 35442205551SBram Moolenaar" navigates away. g:testname can be used by the tests. 35542205551SBram Moolenaarlet g:testname = expand('%') 35642205551SBram Moolenaarlet s:done = 0 35742205551SBram Moolenaarlet s:fail = 0 358ce436de5SBram Moolenaarlet s:fail_expected = 0 35942205551SBram Moolenaarlet s:errors = [] 360ce436de5SBram Moolenaarlet s:errors_expected = [] 36142205551SBram Moolenaarlet s:messages = [] 36242205551SBram Moolenaarlet s:skipped = [] 36342205551SBram Moolenaarif expand('%') =~ 'test_vimscript.vim' 364ce436de5SBram Moolenaar " this test has intentional errors, don't use try/catch. 36542205551SBram Moolenaar source % 36642205551SBram Moolenaarelse 36742205551SBram Moolenaar try 36842205551SBram Moolenaar source % 3699c0cec65SBram Moolenaar catch /^\cskipped/ 3709c0cec65SBram Moolenaar call add(s:messages, ' Skipped') 3719c0cec65SBram Moolenaar call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) 37242205551SBram Moolenaar catch 37342205551SBram Moolenaar let s:fail += 1 37442205551SBram Moolenaar call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint) 37542205551SBram Moolenaar endtry 37642205551SBram Moolenaarendif 37742205551SBram Moolenaar 37842205551SBram Moolenaar" Names of flaky tests. 379dbc0d216SBram Moolenaarlet s:flaky_tests = [ 3800d0c3ca0SBram Moolenaar \ 'Test_autocmd_SafeState()', 38142205551SBram Moolenaar \ 'Test_client_server()', 38242205551SBram Moolenaar \ 'Test_close_and_exit_cb()', 383d80232beSBram Moolenaar \ 'Test_close_output_buffer()', 38442205551SBram Moolenaar \ 'Test_collapse_buffers()', 38565873846SBram Moolenaar \ 'Test_cwd()', 386218959bcSBram Moolenaar \ 'Test_diff_screen()', 38742205551SBram Moolenaar \ 'Test_exit_callback_interval()', 388ea94c855SBram Moolenaar \ 'Test_map_timeout_with_timer_interrupt()', 3891eca6f13SBram Moolenaar \ 'Test_out_cb()', 39042205551SBram Moolenaar \ 'Test_pipe_through_sort_all()', 39142205551SBram Moolenaar \ 'Test_pipe_through_sort_some()', 39244f0bd87SBram Moolenaar \ 'Test_popup_and_window_resize()', 39342205551SBram Moolenaar \ 'Test_quoteplus()', 3947dd48506SBram Moolenaar \ 'Test_quotestar()', 39542205551SBram Moolenaar \ 'Test_reltime()', 3963c8cd4a1SBram Moolenaar \ 'Test_state()', 397f204e05aSBram Moolenaar \ 'Test_terminal_composing_unicode()', 3983876789bSBram Moolenaar \ 'Test_terminal_does_not_truncate_last_newlines()', 3993615abb6SBram Moolenaar \ 'Test_terminal_no_cmd()', 40075a60f74SBram Moolenaar \ 'Test_terminal_noblock()', 4017dd88c51SBram Moolenaar \ 'Test_terminal_redir_file()', 402e219f73eSBram Moolenaar \ 'Test_termwinscroll()', 4039a2fddcfSBram Moolenaar \ 'Test_timer_oneshot()', 4049a2fddcfSBram Moolenaar \ 'Test_timer_paused()', 4059a2fddcfSBram Moolenaar \ 'Test_timer_repeat_many()', 4069a2fddcfSBram Moolenaar \ 'Test_timer_repeat_three()', 4079a2fddcfSBram Moolenaar \ 'Test_timer_stop_all_in_callback()', 4089a2fddcfSBram Moolenaar \ 'Test_timer_stop_in_callback()', 4099a2fddcfSBram Moolenaar \ 'Test_timer_with_partial_callback()', 41042205551SBram Moolenaar \ ] 41142205551SBram Moolenaar 41242205551SBram Moolenaar" Locate Test_ functions and execute them. 41342205551SBram Moolenaarredir @q 41442205551SBram Moolenaarsilent function /^Test_ 41542205551SBram Moolenaarredir END 41661a6d4e4SBram Moolenaarlet s:tests = split(substitute(@q, '\(function\|def\) \(\k*()\)', '\2', 'g')) 41742205551SBram Moolenaar 41842205551SBram Moolenaar" If there is an extra argument filter the function names against it. 41942205551SBram Moolenaarif argc() > 1 42042205551SBram Moolenaar let s:tests = filter(s:tests, 'v:val =~ argv(1)') 42142205551SBram Moolenaarendif 42242205551SBram Moolenaar 423a7f6c3cfSBram Moolenaar" If the environment variable $TEST_FILTER is set then filter the function 424a7f6c3cfSBram Moolenaar" names against it. 4257b666c78SBram Moolenaarlet s:filtered = 0 426a7f6c3cfSBram Moolenaarif $TEST_FILTER != '' 4277b666c78SBram Moolenaar let s:filtered = len(s:tests) 428a7f6c3cfSBram Moolenaar let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER') 4297b666c78SBram Moolenaar let s:filtered -= len(s:tests) 430a7f6c3cfSBram Moolenaarendif 431a7f6c3cfSBram Moolenaar 432ce436de5SBram Moolenaarlet s:may_fail_list = [] 433ce436de5SBram Moolenaarif $TEST_MAY_FAIL != '' 434bfe13cccSBram Moolenaar " Split the list at commas and add () to make it match g:testfunc. 435ce436de5SBram Moolenaar let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'}) 436ce436de5SBram Moolenaarendif 437ce436de5SBram Moolenaar 43842205551SBram Moolenaar" Execute the tests in alphabetical order. 439bfe13cccSBram Moolenaarfor g:testfunc in sort(s:tests) 4404a6fcf80SBram Moolenaar " Silence, please! 4414a6fcf80SBram Moolenaar set belloff=all 442f77af0e6SBram Moolenaar let prev_error = '' 443f77af0e6SBram Moolenaar let total_errors = [] 4443ed9efc2SBram Moolenaar let g:run_nr = 1 4454a6fcf80SBram Moolenaar 446bfe13cccSBram Moolenaar " A test can set g:test_is_flaky to retry running the test. 447bfe13cccSBram Moolenaar let g:test_is_flaky = 0 4483cdcb090SBram Moolenaar 449bfe13cccSBram Moolenaar call RunTheTest(g:testfunc) 45042205551SBram Moolenaar 451f77af0e6SBram Moolenaar " Repeat a flaky test. Give up when: 4526ca6ca48SBram Moolenaar " - $TEST_NO_RETRY is not empty 453f77af0e6SBram Moolenaar " - it fails again with the same message 4541bc353b6SBram Moolenaar " - it fails five times (with a different message) 455dbc0d216SBram Moolenaar if len(v:errors) > 0 456622b3568SBram Moolenaar \ && $TEST_NO_RETRY == '' 457bfe13cccSBram Moolenaar \ && (index(s:flaky_tests, g:testfunc) >= 0 458bfe13cccSBram Moolenaar \ || g:test_is_flaky) 459f77af0e6SBram Moolenaar while 1 460bfe13cccSBram Moolenaar call add(s:messages, 'Found errors in ' . g:testfunc . ':') 4616caf606bSBram Moolenaar call extend(s:messages, v:errors) 46215e737f7SBram Moolenaar 4633ed9efc2SBram Moolenaar call add(total_errors, 'Run ' . g:run_nr . ':') 464f77af0e6SBram Moolenaar call extend(total_errors, v:errors) 465f77af0e6SBram Moolenaar 4663ed9efc2SBram Moolenaar if g:run_nr == 5 || prev_error == v:errors[0] 467f77af0e6SBram Moolenaar call add(total_errors, 'Flaky test failed too often, giving up') 468f77af0e6SBram Moolenaar let v:errors = total_errors 469f77af0e6SBram Moolenaar break 470f77af0e6SBram Moolenaar endif 471f77af0e6SBram Moolenaar 472f77af0e6SBram Moolenaar call add(s:messages, 'Flaky test failed, running it again') 473f77af0e6SBram Moolenaar 474f77af0e6SBram Moolenaar " Flakiness is often caused by the system being very busy. Sleep a 475f77af0e6SBram Moolenaar " couple of seconds to have a higher chance of succeeding the second 476f77af0e6SBram Moolenaar " time. 47755058601SBram Moolenaar sleep 2 47855058601SBram Moolenaar 479f77af0e6SBram Moolenaar let prev_error = v:errors[0] 48042205551SBram Moolenaar let v:errors = [] 4813ed9efc2SBram Moolenaar let g:run_nr += 1 482f77af0e6SBram Moolenaar 483bfe13cccSBram Moolenaar call RunTheTest(g:testfunc) 484f77af0e6SBram Moolenaar 485f77af0e6SBram Moolenaar if len(v:errors) == 0 486f77af0e6SBram Moolenaar " Test passed on rerun. 487f77af0e6SBram Moolenaar break 48815e737f7SBram Moolenaar endif 489f77af0e6SBram Moolenaar endwhile 49042205551SBram Moolenaar endif 49142205551SBram Moolenaar 492bfe13cccSBram Moolenaar call AfterTheTest(g:testfunc) 49342205551SBram Moolenaarendfor 49442205551SBram Moolenaar 49542205551SBram Moolenaarcall FinishTesting() 496cc28e2d0SBram Moolenaar 497cc28e2d0SBram Moolenaar" vim: shiftwidth=2 sts=2 expandtab 498