blob: f2f86c06863d8d92eaa8679d43c13871a9788066 [file] [log] [blame]
Bram Moolenaar46acad72023-06-11 19:04:18 +01001" Runs all the syntax tests for which there is no "done/name" file.
2"
3" Current directory must be runtime/syntax.
4
5" Only do this with the +eval feature
6if 1
7
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +01008" Remember the directory where we started. Will change to "testdir" below.
9let syntaxDir = getcwd()
10
11let s:messagesFname = fnameescape(syntaxDir .. '/testdir/messages')
12
13let s:messages = []
14
15" Add one message to the list of messages
16func Message(msg)
17 echomsg a:msg
18 call add(s:messages, a:msg)
19endfunc
20
21" Report a fatal message and exit
22func Fatal(msg)
23 echoerr a:msg
24 call AppendMessages(a:msg)
25 qall!
26endfunc
27
28" Append s:messages to the messages file and make it empty.
29func AppendMessages(header)
30 exe 'split ' .. s:messagesFname
31 call append(line('$'), '')
32 call append(line('$'), a:header)
33 call append(line('$'), s:messages)
34 let s:messages = []
35 wq
36endfunc
37
38" Relevant messages are written to the "messages" file.
39" If the file already exists it is appended to.
40exe 'split ' .. s:messagesFname
41call append(line('$'), repeat('=-', 70))
42call append(line('$'), '')
Bram Moolenaar031d6322023-06-22 22:38:54 +010043let s:test_run_message = 'Test run on ' .. strftime("%Y %b %d %H:%M:%S")
44call append(line('$'), s:test_run_message)
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +010045wq
46
47if syntaxDir !~ '[/\\]runtime[/\\]syntax\>'
48 call Fatal('Current directory must be "runtime/syntax"')
Bram Moolenaar46acad72023-06-11 19:04:18 +010049endif
50if !isdirectory('testdir')
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +010051 call Fatal('"testdir" directory not found')
Bram Moolenaar46acad72023-06-11 19:04:18 +010052endif
53
54" Use the script for source code screendump testing. It sources other scripts,
55" therefore we must "cd" there.
56cd ../../src/testdir
57source screendump.vim
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +010058exe 'cd ' .. fnameescape(syntaxDir)
Bram Moolenaar46acad72023-06-11 19:04:18 +010059
60" For these tests we need to be able to run terminal Vim with 256 colors. On
61" MS-Windows the console only has 16 colors and the GUI can't run in a
62" terminal.
63if !CanRunVimInTerminal()
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +010064 call Fatal('Cannot make screendumps, aborting')
Bram Moolenaar46acad72023-06-11 19:04:18 +010065endif
66
67cd testdir
68if !isdirectory('done')
69 call mkdir('done')
70endif
71
72set nocp
73set nowrapscan
74set report=9999
75set modeline
76set debug=throw
77set nomore
78
79au! SwapExists * call HandleSwapExists()
80func HandleSwapExists()
81 " Ignore finding a swap file for the test input, the user might be editing
82 " it and that's OK.
83 if expand('<afile>') =~ 'input[/\\].*\..*'
84 let v:swapchoice = 'e'
85 endif
86endfunc
87
Aliaksei Budavei84184462024-05-21 01:10:26 +030088def IsWinNumOneAtEOF(in_name_and_out_name: string): bool
89 # Expect defaults from term_util#RunVimInTerminal().
90 if winwidth(1) != 75 || winheight(1) != 20
91 ch_log(printf('Aborting for %s: (75 x 20) != (%d x %d)',
92 in_name_and_out_name,
93 winwidth(1),
94 winheight(1)))
95 return true
96 endif
97 # A two-fold role: (1) redraw whenever the first test file is of 19 lines or
98 # less long (not applicable to c.c); (2) redraw in case the terminal buffer
99 # cannot redraw itself just yet (else expect extra files generated).
100 redraw
101 const pos: string = join([
102 screenstring(20, 71),
103 screenstring(20, 72),
104 screenstring(20, 73),
105 screenstring(20, 74),
106 screenstring(20, 75)], '')
107 return (pos == ' All ' || pos == ' Bot ')
108enddef
109
Christian Brabandt56824432024-02-28 21:24:25 +0100110func RunTest()
111 let ok_count = 0
112 let failed_tests = []
113 let skipped_count = 0
114 let MAX_FAILED_COUNT = 5
Aliaksei Budaveif6069a72024-03-05 22:34:36 +0300115 " Create a map of setup configuration filenames with their basenames as keys.
116 let setup = glob('input/setup/*.vim', 1, 1)
117 \ ->reduce({d, f -> extend(d, {fnamemodify(f, ':t:r'): f})}, {})
118
Christian Brabandt56824432024-02-28 21:24:25 +0100119 for fname in glob('input/*.*', 1, 1)
120 if fname =~ '\~$'
121 " backup file, skip
122 continue
Bram Moolenaar7d0dbd02023-06-24 00:56:50 +0100123 endif
124
Christian Brabandt56824432024-02-28 21:24:25 +0100125 let root = fnamemodify(fname, ':t:r')
126 let filetype = substitute(root, '\([^_.]*\)[_.].*', '\1', '')
127 let failed_root = 'failed/' .. root
Bram Moolenaar46acad72023-06-11 19:04:18 +0100128
Christian Brabandt56824432024-02-28 21:24:25 +0100129 " Execute the test if the "done" file does not exist or when the input file
130 " is newer.
131 let in_time = getftime(fname)
132 let out_time = getftime('done/' .. root)
133 if out_time < 0 || in_time > out_time
134 call ch_log('running tests for: ' .. fname)
Bram Moolenaar7d0dbd02023-06-24 00:56:50 +0100135
Christian Brabandt56824432024-02-28 21:24:25 +0100136 for dumpname in glob(failed_root .. '_\d*\.dump', 1, 1)
137 call delete(dumpname)
138 endfor
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +0100139 call delete('done/' .. root)
140
Christian Brabandt56824432024-02-28 21:24:25 +0100141 let lines =<< trim END
Christian Brabandt56824432024-02-28 21:24:25 +0100142 " extra info for shell variables
143 func ShellInfo()
144 let msg = ''
145 for [key, val] in items(b:)
146 if key =~ '^is_'
147 let msg ..= key .. ': ' .. val .. ', '
148 endif
149 endfor
150 if msg != ''
151 echomsg msg
152 endif
153 endfunc
154
155 au! SwapExists * call HandleSwapExists()
156 func HandleSwapExists()
157 " Ignore finding a swap file for the test input, the user might be
158 " editing it and that's OK.
159 if expand('<afile>') =~ 'input[/\\].*\..*'
160 let v:swapchoice = 'e'
161 endif
162 endfunc
163
164 func LoadFiletype(type)
165 for file in glob("ftplugin/" .. a:type .. "*.vim", 1, 1)
166 exe "source " .. file
167 endfor
168 redraw!
169 endfunc
170
Aliaksei Budavei93edd252024-03-05 22:34:36 +0300171 func SetUpVim()
172 call cursor(1, 1)
Aliaksei Budaveia2addeb2024-03-18 20:39:32 +0100173 " Defend against rogue VIM_TEST_SETUP commands.
Aliaksei Budavei93edd252024-03-05 22:34:36 +0300174 for _ in range(20)
Aliaksei Budaveia2addeb2024-03-18 20:39:32 +0100175 let lnum = search('\C\<VIM_TEST_SETUP\>', 'eW', 20)
Aliaksei Budavei93edd252024-03-05 22:34:36 +0300176 if lnum < 1
177 break
178 endif
Aliaksei Budaveia2addeb2024-03-18 20:39:32 +0100179 exe substitute(getline(lnum), '\C.*\<VIM_TEST_SETUP\>', '', '')
Aliaksei Budavei93edd252024-03-05 22:34:36 +0300180 endfor
181 call cursor(1, 1)
182 " BEGIN [runtime/defaults.vim]
Aliaksei Budaveia2addeb2024-03-18 20:39:32 +0100183 " Also, disable italic highlighting to avoid issues on some terminals.
Aliaksei Budavei84184462024-05-21 01:10:26 +0300184 set display=lastline ruler scrolloff=5 t_ZH= t_ZR=
Aliaksei Budavei93edd252024-03-05 22:34:36 +0300185 syntax on
186 " END [runtime/defaults.vim]
187 redraw!
188 endfunc
Aliaksei Budavei84184462024-05-21 01:10:26 +0300189
190 def ScrollToSecondPage(estate: number, op_wh: number, op_so: number)
191 if line('.') != 1 || line('w$') >= line('$')
192 return
193 endif
194 try
195 set scrolloff=0
196 # Advance mark "c"[ursor] along with the cursor.
197 norm! Lmc
198 if foldclosed('.') < 0 &&
199 (strdisplaywidth(getline('.')) + &l:fdc * winheight(1)) >= estate
200 # Make for an exit for a screenful long line.
201 norm! j^
202 return
203 else
204 # Place the cursor on the actually last visible line.
205 while winline() < op_wh
206 const lastnum: number = winline()
207 norm! gjmc
208 if lastnum > winline()
209 break
210 endif
211 endwhile
212 norm! zt
213 endif
214 finally
215 # COMPATIBILITY: Scroll up around "scrolloff" lines.
216 &scrolloff = max([1, op_so])
217 endtry
218 norm! ^
219 enddef
220
221 def ScrollToNextPage(estate: number, op_wh: number, op_so: number)
222 if line('.') == 1 || line('w$') >= line('$')
223 return
224 endif
225 try
226 set scrolloff=0
227 # Advance mark "c"[ursor] along with the cursor.
228 norm! Lmc
229 if foldclosed('.') < 0 &&
230 (strdisplaywidth(getline('.')) + &l:fdc * winheight(1)) >= estate
231 # Make for an exit for a screenful long line.
232 norm! j^
233 return
234 else
235 # Place the cursor on the actually last visible line.
236 while winline() < op_wh
237 const lastnum: number = winline()
238 norm! gjmc
239 if lastnum > winline()
240 break
241 endif
242 endwhile
243 endif
244 finally
245 # COMPATIBILITY: Scroll up/down around "scrolloff" lines.
246 &scrolloff = max([1, op_so])
247 endtry
248 norm! zt
249 const marknum: number = line("'c")
250 # Eschew &smoothscroll since line("`c") is not supported.
251 # Remember that "w0" can point to the first line of a _closed_ fold
252 # whereas the last line of a _closed_ fold can be marked.
253 if line('w0') > marknum
254 while line('w0') > marknum
255 exe "norm! \<C-y>"
256 endwhile
257 if line('w0') != marknum
258 exe "norm! \<C-e>H"
259 endif
260 # Handle non-wrapped lines.
261 elseif line('w0') < marknum
262 while line('w0') < marknum
263 exe "norm! \<C-e>"
264 endwhile
265 if line('w0') != marknum
266 exe "norm! \<C-y>H"
267 endif
268 endif
269 norm! ^
270 enddef
Christian Brabandt56824432024-02-28 21:24:25 +0100271 END
272 call writefile(lines, 'Xtestscript')
273
274 " close all but the last window
275 while winnr('$') > 1
276 close
277 endwhile
278
279 " Redraw to make sure that messages are cleared and there is enough space
280 " for the terminal window.
281 redraw
282
Aliaksei Budavei93edd252024-03-05 22:34:36 +0300283 " Let "Xtestscript#SetUpVim()" turn the syntax on.
Aliaksei Budaveif6069a72024-03-05 22:34:36 +0300284 let prefix = '-Nu NONE -S Xtestscript'
285 let path = get(setup, root, '')
286 " Source the found setup configuration file.
287 let args = !empty(path)
288 \ ? prefix .. ' -S ' .. path
289 \ : prefix
290 let buf = RunVimInTerminal(args, {})
Christian Brabandt56824432024-02-28 21:24:25 +0100291 " edit the file only after catching the SwapExists event
292 call term_sendkeys(buf, ":edit " .. fname .. "\<CR>")
Aliaksei Budavei93edd252024-03-05 22:34:36 +0300293 " set up the testing environment
294 call term_sendkeys(buf, ":call SetUpVim()\<CR>")
Christian Brabandt56824432024-02-28 21:24:25 +0100295 " load filetype specific settings
296 call term_sendkeys(buf, ":call LoadFiletype('" .. filetype .. "')\<CR>")
297
298 if filetype == 'sh'
299 call term_sendkeys(buf, ":call ShellInfo()\<CR>")
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +0100300 endif
Christian Brabandt56824432024-02-28 21:24:25 +0100301
302 " Screendump at the start of the file: failed/root_00.dump
303 let root_00 = root .. '_00'
Aliaksei Budavei84184462024-05-21 01:10:26 +0300304 let in_name_and_out_name = fname .. ': failed/' .. root_00 .. '.dump'
305 call ch_log('First screendump for ' .. in_name_and_out_name)
Christian Brabandt56824432024-02-28 21:24:25 +0100306 let fail = VerifyScreenDump(buf, root_00, {})
307
Aliaksei Budavei84184462024-05-21 01:10:26 +0300308 " Clear the shell info if there are not enough lines to cause a scroll
309 if filetype == 'sh' && IsWinNumOneAtEOF(in_name_and_out_name)
Aliaksei Budaveicc5482e2024-05-21 01:12:22 +0300310 call term_sendkeys(buf, ":redraw!\<CR>")
Christian Brabandt56824432024-02-28 21:24:25 +0100311 endif
312
313 " Make a Screendump every 18 lines of the file: failed/root_NN.dump
Christian Brabandt56824432024-02-28 21:24:25 +0100314 let nr = 1
Aliaksei Budavei84184462024-05-21 01:10:26 +0300315 let root_next = printf('%s_%02d', root, nr)
316 let in_name_and_out_name = fname .. ': failed/' .. root_next .. '.dump'
317
318 if !IsWinNumOneAtEOF(in_name_and_out_name)
319 call term_sendkeys(buf, ":call ScrollToSecondPage((18 * 75 + 1), 19, 5) | redraw!\<CR>")
320 call ch_log('Next screendump for ' .. in_name_and_out_name)
Christian Brabandt56824432024-02-28 21:24:25 +0100321 let fail += VerifyScreenDump(buf, root_next, {})
322 let nr += 1
Aliaksei Budavei84184462024-05-21 01:10:26 +0300323 let root_next = printf('%s_%02d', root, nr)
324 let in_name_and_out_name = fname .. ': failed/' .. root_next .. '.dump'
325
326 while !IsWinNumOneAtEOF(in_name_and_out_name)
327 call term_sendkeys(buf, ":call ScrollToNextPage((18 * 75 + 1), 19, 5) | redraw!\<CR>")
328 call ch_log('Next screendump for ' .. in_name_and_out_name)
329 let fail += VerifyScreenDump(buf, root_next, {})
330 let nr += 1
331 let root_next = printf('%s_%02d', root, nr)
332 let in_name_and_out_name = fname .. ': failed/' .. root_next .. '.dump'
333 endwhile
334 endif
Christian Brabandt56824432024-02-28 21:24:25 +0100335
336 " Screendump at the end of the file: failed/root_99.dump
337 call term_sendkeys(buf, 'Gzb')
338 let root_last = root .. '_99'
339 call ch_log('Last screendump for ' .. fname .. ': failed/' .. root_last .. '.dump')
340 let fail += VerifyScreenDump(buf, root_last, {})
341
342 call StopVimInTerminal(buf)
343 call delete('Xtestscript')
344
345 " redraw here to avoid the following messages to get mixed up with screen
346 " output.
347 redraw
348
349 " Add any assert errors to s:messages.
350 if len(v:errors) > 0
351 call extend(s:messages, v:errors)
352 " Echo the errors here, in case the script aborts or the "messages" file
353 " is not displayed later.
354 echomsg v:errors
355 let v:errors = []
356 let fail += 1
357 endif
358
359 if fail == 0
360 call Message("Test " .. root .. " OK")
361
362 call writefile(['OK'], 'done/' .. root)
363
364 let ok_count += 1
365 else
366 call Message("Test " .. root .. " FAILED")
367
368 call delete('done/' .. root)
369
370 eval failed_tests->add(root)
371 if len(failed_tests) > MAX_FAILED_COUNT
372 call Message('')
373 call Message('Too many errors, aborting')
374 endif
375 endif
376 else
377 call Message("Test " .. root .. " skipped")
378 let skipped_count += 1
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +0100379 endif
Christian Brabandt56824432024-02-28 21:24:25 +0100380
381 " Append messages to the file "testdir/messages"
382 call AppendMessages('Input file ' .. fname .. ':')
383
384 if len(failed_tests) > MAX_FAILED_COUNT
385 break
386 endif
387 endfor
388
389 call Message(s:test_run_message)
390 call Message('OK: ' .. ok_count)
391 call Message('FAILED: ' .. len(failed_tests) .. ': ' .. string(failed_tests))
392 call Message('skipped: ' .. skipped_count)
393 call AppendMessages('== SUMMARY ==')
394
395 if len(failed_tests) > 0
396 " have make report an error
397 cquit
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +0100398 endif
Christian Brabandt56824432024-02-28 21:24:25 +0100399endfunc
Bram Moolenaar1aa5f1c2023-06-22 21:57:51 +0100400
Christian Brabandt56824432024-02-28 21:24:25 +0100401call RunTest()
Christian Brabandt627c9502024-02-10 13:02:17 +0100402
403" Matching "if 1" at the start.
404endif
405
Bram Moolenaar46acad72023-06-11 19:04:18 +0100406qall!
Christian Brabandt56824432024-02-28 21:24:25 +0100407
408" vim:ts=8