xref: /vim-8.2.3635/src/testdir/runtest.vim (revision cf2d8dee)
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