1" This script is sourced while editing the .vim file with the tests. 2" When the script is successful the .res file will be created. 3" Errors are appended to the test.log file. 4" 5" To execute only specific test functions, add a second argument. It will be 6" matched against the names of the Test_ funtion. E.g.: 7" ../vim -u NONE -S runtest.vim test_channel.vim open_delay 8" The output can be found in the "messages" file. 9" 10" The test script may contain anything, only functions that start with 11" "Test_" are special. These will be invoked and should contain assert 12" functions. See test_assert.vim for an example. 13" 14" It is possible to source other files that contain "Test_" functions. This 15" can speed up testing, since Vim does not need to restart. But be careful 16" that the tests do not interfere with each other. 17" 18" If an error cannot be detected properly with an assert function add the 19" error to the v:errors list: 20" call add(v:errors, 'test foo failed: Cannot find xyz') 21" 22" If preparation for each Test_ function is needed, define a SetUp function. 23" It will be called before each Test_ function. 24" 25" If cleanup after each Test_ function is needed, define a TearDown function. 26" It will be called after each Test_ function. 27" 28" When debugging a test it can be useful to add messages to v:errors: 29" call add(v:errors, "this happened") 30 31 32" Without the +eval feature we can't run these tests, bail out. 33so small.vim 34 35" Check that the screen size is at least 24 x 80 characters. 36if &lines < 24 || &columns < 80 37 let error = 'Screen size too small! Tests require at least 24 lines with 80 characters' 38 echoerr error 39 split test.log 40 $put =error 41 w 42 cquit 43endif 44 45" For consistency run all tests with 'nocompatible' set. 46" This also enables use of line continuation. 47set nocp viminfo+=nviminfo 48 49" Avoid stopping at the "hit enter" prompt 50set nomore 51 52" Output all messages in English. 53lang mess C 54 55" Always use forward slashes. 56set shellslash 57 58let s:srcdir = expand('%:p:h:h') 59 60" Support function: get the alloc ID by name. 61function GetAllocId(name) 62 exe 'split ' . s:srcdir . '/alloc.h' 63 let top = search('typedef enum') 64 if top == 0 65 call add(v:errors, 'typedef not found in alloc.h') 66 endif 67 let lnum = search('aid_' . a:name . ',') 68 if lnum == 0 69 call add(v:errors, 'Alloc ID ' . a:name . ' not defined') 70 endif 71 close 72 return lnum - top - 1 73endfunc 74 75function RunTheTest(test) 76 echo 'Executing ' . a:test 77 if exists("*SetUp") 78 call SetUp() 79 endif 80 81 call add(s:messages, 'Executing ' . a:test) 82 let s:done += 1 83 try 84 exe 'call ' . a:test 85 catch 86 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 87 endtry 88 89 if exists("*TearDown") 90 call TearDown() 91 endif 92endfunc 93 94" Source the test script. First grab the file name, in case the script 95" navigates away. g:testname can be used by the tests. 96let g:testname = expand('%') 97let s:done = 0 98let s:fail = 0 99let s:errors = [] 100let s:messages = [] 101if expand('%') =~ 'test_viml.vim' 102 " this test has intentional s:errors, don't use try/catch. 103 source % 104else 105 try 106 source % 107 catch 108 let s:fail += 1 109 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint) 110 endtry 111endif 112 113" Names of flaky tests. 114let s:flaky = ['Test_reltime()'] 115 116" Locate Test_ functions and execute them. 117set nomore 118redir @q 119silent function /^Test_ 120redir END 121let s:tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g')) 122 123" If there is an extra argument filter the function names against it. 124if argc() > 1 125 let s:tests = filter(s:tests, 'v:val =~ argv(1)') 126endif 127 128" Execute the tests in alphabetical order. 129for s:test in sort(s:tests) 130 call RunTheTest(s:test) 131 132 if len(v:errors) > 0 && index(s:flaky, s:test) >= 0 133 call add(s:messages, 'Flaky test failed, running it again') 134 let v:errors = [] 135 call RunTheTest(s:test) 136 endif 137 138 if len(v:errors) > 0 139 let s:fail += 1 140 call add(s:errors, 'Found errors in ' . s:test . ':') 141 call extend(s:errors, v:errors) 142 let v:errors = [] 143 endif 144 145endfor 146 147if s:fail == 0 148 " Success, create the .res file so that make knows it's done. 149 exe 'split ' . fnamemodify(g:testname, ':r') . '.res' 150 write 151endif 152 153if len(s:errors) > 0 154 " Append errors to test.log 155 split test.log 156 call append(line('$'), '') 157 call append(line('$'), 'From ' . g:testname . ':') 158 call append(line('$'), s:errors) 159 write 160endif 161 162let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test') 163echo message 164call add(s:messages, message) 165if s:fail > 0 166 let message = s:fail . ' FAILED:' 167 echo message 168 call add(s:messages, message) 169 call extend(s:messages, s:errors) 170endif 171 172" Append messages to "messages" 173split messages 174call append(line('$'), '') 175call append(line('$'), 'From ' . g:testname . ':') 176call append(line('$'), s:messages) 177write 178 179qall! 180