blob: 608fca46603ac5e6823b4df8a618c1963c08181e [file] [log] [blame]
Bram Moolenaar43345542015-11-29 17:35:35 +01001" 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"
Bram Moolenaarbefb3662016-02-20 14:41:40 +01005" 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"
Bram Moolenaar43345542015-11-29 17:35:35 +010010" 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.
Bram Moolenaar00af60b2016-02-13 14:06:14 +010027"
28" When debugging a test it can be useful to add messages to v:errors:
29" call add(v:errors, "this happened")
30
Bram Moolenaar43345542015-11-29 17:35:35 +010031
32" Without the +eval feature we can't run these tests, bail out.
Bram Moolenaar4686b322015-12-28 14:44:10 +010033so small.vim
Bram Moolenaar43345542015-11-29 17:35:35 +010034
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
Bram Moolenaar89b10422016-07-12 22:51:22 +020045" Common with all tests on all systems.
46source setup.vim
47
Bram Moolenaarc0662462015-12-30 15:49:05 +010048" For consistency run all tests with 'nocompatible' set.
49" This also enables use of line continuation.
50set nocp viminfo+=nviminfo
51
Bram Moolenaareb992cb2017-03-09 18:20:16 +010052" Use utf-8 or latin1 by default, instead of whatever the system default
Bram Moolenaarac105ed2016-07-21 20:33:32 +020053" happens to be. Individual tests can overrule this at the top of the file.
54if has('multi_byte')
55 set encoding=utf-8
56else
57 set encoding=latin1
58endif
59
Bram Moolenaar7a073542017-02-01 23:17:36 +010060" Avoid stopping at the "hit enter" prompt
61set nomore
62
Bram Moolenaarc0662462015-12-30 15:49:05 +010063" Output all messages in English.
64lang mess C
65
Bram Moolenaarf60b7962016-01-16 22:47:23 +010066" Always use forward slashes.
67set shellslash
68
Bram Moolenaar28fb79d2016-01-09 22:28:33 +010069let s:srcdir = expand('%:p:h:h')
70
Bram Moolenaar8e8df252016-05-25 21:23:21 +020071" Prepare for calling test_garbagecollect_now().
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +020072let v:testing = 1
73
Bram Moolenaar28fb79d2016-01-09 22:28:33 +010074" Support function: get the alloc ID by name.
75function GetAllocId(name)
76 exe 'split ' . s:srcdir . '/alloc.h'
Bram Moolenaar065ee9a2016-01-15 20:53:38 +010077 let top = search('typedef enum')
78 if top == 0
79 call add(v:errors, 'typedef not found in alloc.h')
80 endif
Bram Moolenaar28fb79d2016-01-09 22:28:33 +010081 let lnum = search('aid_' . a:name . ',')
82 if lnum == 0
83 call add(v:errors, 'Alloc ID ' . a:name . ' not defined')
84 endif
85 close
Bram Moolenaar065ee9a2016-01-15 20:53:38 +010086 return lnum - top - 1
Bram Moolenaar28fb79d2016-01-09 22:28:33 +010087endfunc
88
Bram Moolenaar42205552017-03-18 19:42:22 +010089func RunTheTest(test)
Bram Moolenaarb5760a12016-03-03 13:10:44 +010090 echo 'Executing ' . a:test
Bram Moolenaare5f2a072017-02-01 22:31:49 +010091
92 " Avoid stopping at the "hit enter" prompt
93 set nomore
94
95 " Avoid a three second wait when a message is about to be overwritten by the
96 " mode message.
97 set noshowmode
98
Bram Moolenaareb992cb2017-03-09 18:20:16 +010099 " Clear any overrides.
100 call test_override('ALL', 0)
101
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200102 " Some tests wipe out buffers. To be consistent, always wipe out all
103 " buffers.
104 %bwipe!
105
Bram Moolenaar209d3872017-11-16 21:52:51 +0100106 " The test may change the current directory. Save and restore the
107 " directory after executing the test.
108 let save_cwd = getcwd()
109
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100110 if exists("*SetUp")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100111 try
112 call SetUp()
113 catch
114 call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
115 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100116 endif
117
118 call add(s:messages, 'Executing ' . a:test)
119 let s:done += 1
Bram Moolenaarf204e052017-10-26 17:14:01 +0200120
121 if a:test =~ 'Test_nocatch_'
122 " Function handles errors itself. This avoids skipping commands after the
123 " error.
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100124 exe 'call ' . a:test
Bram Moolenaarf204e052017-10-26 17:14:01 +0200125 else
126 try
127 exe 'call ' . a:test
128 catch /^\cskipped/
129 call add(s:messages, ' Skipped')
130 call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
131 catch
132 call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
133 endtry
134 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100135
136 if exists("*TearDown")
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100137 try
138 call TearDown()
139 catch
140 call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
141 endtry
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100142 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200143
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200144 " Clear any autocommands
145 au!
146
Bram Moolenaarce11de82017-10-26 22:00:00 +0200147 " Close any extra tab pages and windows and make the current one not modified.
148 while tabpagenr('$') > 1
Bram Moolenaarcf1ba352017-10-27 00:55:04 +0200149 quit!
Bram Moolenaarce11de82017-10-26 22:00:00 +0200150 endwhile
151
Bram Moolenaar358308d2016-08-24 21:21:26 +0200152 while 1
153 let wincount = winnr('$')
154 if wincount == 1
155 break
156 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200157 bwipe!
Bram Moolenaar358308d2016-08-24 21:21:26 +0200158 if wincount == winnr('$')
159 " Did not manage to close a window.
160 only!
161 break
162 endif
Bram Moolenaar7cba71d2016-08-02 23:04:49 +0200163 endwhile
Bram Moolenaar209d3872017-11-16 21:52:51 +0100164
165 exe 'cd ' . save_cwd
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100166endfunc
Bram Moolenaar28fb79d2016-01-09 22:28:33 +0100167
Bram Moolenaar42205552017-03-18 19:42:22 +0100168func AfterTheTest()
169 if len(v:errors) > 0
170 let s:fail += 1
171 call add(s:errors, 'Found errors in ' . s:test . ':')
172 call extend(s:errors, v:errors)
173 let v:errors = []
174 endif
175endfunc
176
177" This function can be called by a test if it wants to abort testing.
178func FinishTesting()
179 call AfterTheTest()
180
181 " Don't write viminfo on exit.
182 set viminfo=
183
Bram Moolenaard1ee0042017-07-29 20:39:53 +0200184 " Clean up files created by setup.vim
185 call delete('XfakeHOME', 'rf')
186
Bram Moolenaar42205552017-03-18 19:42:22 +0100187 if s:fail == 0
188 " Success, create the .res file so that make knows it's done.
189 exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
190 write
191 endif
192
193 if len(s:errors) > 0
194 " Append errors to test.log
195 split test.log
196 call append(line('$'), '')
197 call append(line('$'), 'From ' . g:testname . ':')
198 call append(line('$'), s:errors)
199 write
200 endif
201
202 let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
203 echo message
204 call add(s:messages, message)
205 if s:fail > 0
206 let message = s:fail . ' FAILED:'
207 echo message
208 call add(s:messages, message)
209 call extend(s:messages, s:errors)
210 endif
211
212 " Add SKIPPED messages
213 call extend(s:messages, s:skipped)
214
215 " Append messages to the file "messages"
216 split messages
217 call append(line('$'), '')
218 call append(line('$'), 'From ' . g:testname . ':')
219 call append(line('$'), s:messages)
220 write
221
222 qall!
223endfunc
224
Bram Moolenaar43345542015-11-29 17:35:35 +0100225" Source the test script. First grab the file name, in case the script
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100226" navigates away. g:testname can be used by the tests.
227let g:testname = expand('%')
228let s:done = 0
229let s:fail = 0
230let s:errors = []
231let s:messages = []
Bram Moolenaardac19472016-09-03 22:35:40 +0200232let s:skipped = []
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100233if expand('%') =~ 'test_vimscript.vim'
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100234 " this test has intentional s:errors, don't use try/catch.
Bram Moolenaar4686b322015-12-28 14:44:10 +0100235 source %
Bram Moolenaara2cce862016-01-02 19:50:04 +0100236else
237 try
238 source %
239 catch
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100240 let s:fail += 1
241 call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100242 endtry
243endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100244
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100245" Names of flaky tests.
Bram Moolenaare1c8c7a2016-09-11 16:48:50 +0200246let s:flaky = [
Bram Moolenaar42205552017-03-18 19:42:22 +0100247 \ 'Test_client_server()',
Bram Moolenaar6fe2eb42017-01-29 21:49:51 +0100248 \ 'Test_close_and_exit_cb()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100249 \ 'Test_collapse_buffers()',
250 \ 'Test_communicate()',
Bram Moolenaar0529b3e2017-03-16 22:30:37 +0100251 \ 'Test_exit_callback_interval()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100252 \ 'Test_nb_basic()',
Bram Moolenaard512e172017-02-27 21:35:53 +0100253 \ 'Test_oneshot()',
Bram Moolenaar1eca6f12017-12-05 14:04:27 +0100254 \ 'Test_out_cb()',
Bram Moolenaar24820692017-12-02 16:38:12 +0100255 \ 'Test_paused()',
Bram Moolenaarc79d6aa2016-09-25 22:27:37 +0200256 \ 'Test_pipe_through_sort_all()',
Bram Moolenaar4e032e12017-02-01 20:48:13 +0100257 \ 'Test_pipe_through_sort_some()',
Bram Moolenaar0fbff642017-03-05 14:30:52 +0100258 \ 'Test_quoteplus()',
Bram Moolenaar7dd48502017-03-19 20:04:22 +0100259 \ 'Test_quotestar()',
Bram Moolenaarb2455592017-02-01 18:00:13 +0100260 \ 'Test_reltime()',
Bram Moolenaarf204e052017-10-26 17:14:01 +0200261 \ 'Test_terminal_composing_unicode()',
Bram Moolenaar75a60f72017-09-07 22:24:41 +0200262 \ 'Test_terminal_noblock()',
Bram Moolenaar7dd88c52017-11-04 20:46:40 +0100263 \ 'Test_terminal_redir_file()',
Bram Moolenaar24820692017-12-02 16:38:12 +0100264 \ 'Test_terminal_tmap()',
Bram Moolenaard09be322017-07-30 21:37:58 +0200265 \ 'Test_with_partial_callback()',
Bram Moolenaare1c8c7a2016-09-11 16:48:50 +0200266 \ ]
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100267
Bram Moolenaar43345542015-11-29 17:35:35 +0100268" Locate Test_ functions and execute them.
269redir @q
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100270silent function /^Test_
Bram Moolenaar43345542015-11-29 17:35:35 +0100271redir END
Bram Moolenaar00af60b2016-02-13 14:06:14 +0100272let s:tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g'))
Bram Moolenaar43345542015-11-29 17:35:35 +0100273
Bram Moolenaarbefb3662016-02-20 14:41:40 +0100274" If there is an extra argument filter the function names against it.
275if argc() > 1
276 let s:tests = filter(s:tests, 'v:val =~ argv(1)')
277endif
278
Bram Moolenaarcfc0a352016-01-09 20:23:00 +0100279" Execute the tests in alphabetical order.
Bram Moolenaar93bf5582016-02-18 22:25:47 +0100280for s:test in sort(s:tests)
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +0200281 " Silence, please!
282 set belloff=all
283
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100284 call RunTheTest(s:test)
Bram Moolenaar43345542015-11-29 17:35:35 +0100285
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100286 if len(v:errors) > 0 && index(s:flaky, s:test) >= 0
Bram Moolenaar6caf6062017-03-18 20:45:05 +0100287 call add(s:messages, 'Found errors in ' . s:test . ':')
288 call extend(s:messages, v:errors)
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100289 call add(s:messages, 'Flaky test failed, running it again')
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100290 let first_run = v:errors
291
Bram Moolenaar55058602017-11-21 15:14:51 +0100292 " Flakiness is often caused by the system being very busy. Sleep a couple
293 " of seconds to have a higher chance of succeeding the second time.
294 sleep 2
295
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100296 let v:errors = []
297 call RunTheTest(s:test)
Bram Moolenaar15e737f2017-03-18 21:22:47 +0100298 if len(v:errors) > 0
299 let second_run = v:errors
300 let v:errors = ['First run:']
301 call extend(v:errors, first_run)
302 call add(v:errors, 'Second run:')
303 call extend(v:errors, second_run)
304 endif
Bram Moolenaarb5760a12016-03-03 13:10:44 +0100305 endif
Bram Moolenaar43345542015-11-29 17:35:35 +0100306
Bram Moolenaar42205552017-03-18 19:42:22 +0100307 call AfterTheTest()
Bram Moolenaar43345542015-11-29 17:35:35 +0100308endfor
309
Bram Moolenaar42205552017-03-18 19:42:22 +0100310call FinishTesting()
Bram Moolenaarcc28e2d2016-11-17 17:56:13 +0100311
312" vim: shiftwidth=2 sts=2 expandtab