blob: bc3cfc83d46936b0f7983c423fe404ac0b522982 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim script language tests
2" Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
Bram Moolenaara6296202020-08-05 11:23:13 +02003" Last Change: 2020 Jun 07
Bram Moolenaar071d4272004-06-13 20:20:40 +00004
5"-------------------------------------------------------------------------------
6" Test environment {{{1
7"-------------------------------------------------------------------------------
8
9
10" Adding new tests easily. {{{2
11"
12" Writing new tests is eased considerably with the following functions and
13" abbreviations (see "Commands for recording the execution path", "Automatic
14" argument generation").
15"
16" To get the abbreviations, execute the command
17"
18" :let test49_set_env = 1 | source test49.vim
19"
20" To get them always (from src/testdir), put a line
21"
22" au! BufRead test49.vim let test49_set_env = 1 | source test49.vim
23"
24" into the local .vimrc file in the src/testdir directory.
25"
26if exists("test49_set_env") && test49_set_env
27
28 " Automatic argument generation for the test environment commands.
29
30 function! Xsum()
31 let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "")
32 " Evaluate arithmetic expression.
33 if addend != ""
34 exec "let g:Xsum = g:Xsum + " . addend
35 endif
36 endfunction
37
38 function! Xcheck()
39 let g:Xsum=0
40 ?XpathINIT?,.call Xsum()
41 exec "norm A "
42 return g:Xsum
43 endfunction
44
45 iab Xcheck Xcheck<Space><C-R>=Xcheck()<CR><C-O>x
46
47 function! Xcomment(num)
48 let str = ""
49 let tabwidth = &sts ? &sts : &ts
50 let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth
51 while tabs > 0
52 let str = str . "\t"
53 let tabs = tabs - 1
54 endwhile
55 let str = str . '" X:'
56 return str
57 endfunction
58
59 function! Xloop()
60 let back = line(".") . "|norm" . virtcol(".") . "|"
61 norm 0
62 let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW")
63 exec back
64 let theline = getline(last)
65 if theline =~ 'X\(loop\|path\)INIT'
66 let num = 1
67 else
68 let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "")
69 endif
70 ?X\(loop\|path\)INIT?
71 \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/
72 exec back
73 exec "norm a "
74 return num . Xcomment(strlen(num))
75 endfunction
76
77 iab Xloop Xloop<Space><C-R>=Xloop()<CR><C-O>x
78
79 function! Xpath(loopinit)
80 let back = line(".") . "|norm" . virtcol(".") . "|"
81 norm 0
82 let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW")
83 exec back
84 let theline = getline(last)
85 if theline =~ 'XpathINIT'
86 let num = 1
87 elseif theline =~ 'Xpath\>'
88 let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "")
89 else
90 let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*'
91 let num = substitute(theline, pattern, '\1', "")
92 let factor = substitute(theline, pattern, '\2', "")
93 " The "<C-O>x" from the "Xpath" iab and the character triggering its
94 " expansion are in the input buffer. Save and clear typeahead so
95 " that it is not read away by the call to "input()" below. Restore
96 " afterwards.
97 call inputsave()
98 let loops = input("Number of iterations in previous loop? ")
99 call inputrestore()
100 while (loops > 0)
101 let num = num * factor
102 let loops = loops - 1
103 endwhile
104 endif
105 exec "norm a "
106 if a:loopinit
107 return num . " 1"
108 endif
109 return num . Xcomment(strlen(num))
110 endfunction
111
112 iab Xpath Xpath<Space><C-R>=Xpath(0)<CR><C-O>x
113 iab XloopINIT XloopINIT<Space><C-R>=Xpath(1)<CR><C-O>x
114
115 " Also useful (see ExtraVim below):
116 aug ExtraVim
117 au!
118 au BufEnter <sfile> syn region ExtraVim
119 \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+
120 \ transparent keepend
121 au BufEnter <sfile> syn match ExtraComment /^"/
122 \ contained containedin=ExtraVim
123 au BufEnter <sfile> hi link ExtraComment vimComment
124 aug END
125
126 aug Xpath
127 au BufEnter <sfile> syn keyword Xpath
128 \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout
129 au BufEnter <sfile> hi link Xpath Special
130 aug END
131
132 do BufEnter <sfile>
133
134 " Do not execute the tests when sourcing this file for getting the functions
135 " and abbreviations above, which are intended for easily adding new test
136 " cases; they are not needed for test execution. Unlet the variable
137 " controlling this so that an explicit ":source" command for this file will
138 " execute the tests.
139 unlet test49_set_env
140 finish
141
142endif
143
144
145" Commands for recording the execution path. {{{2
146"
147" The Xpath/Xloop commands can be used for computing the eXecution path by
148" adding (different) powers of 2 from those script lines, for which the
149" execution should be checked. Xloop provides different addends for each
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000150" execution of a loop. Permitted values are 2^0 to 2^30, so that 31 execution
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151" points (multiply counted inside loops) can be tested.
152"
153" Note that the arguments of the following commands can be generated
154" automatically, see below.
155"
156" Usage: {{{3
157"
158" - Use XpathINIT at the beginning of the test.
159"
160" - Use Xpath to check if a line is executed.
161" Argument: power of 2 (decimal).
162"
163" - To check multiple execution of loops use Xloop for automatically
164" computing Xpath values:
165"
166" - Use XloopINIT before the loop.
167" Two arguments:
168" - the first Xpath value (power of 2) to be used (Xnext),
169" - factor for computing a new Xnext value when reexecuting a loop
170" (by a ":continue" or ":endwhile"); this should be 2^n where
171" n is the number of Xloop commands inside the loop.
172" If XloopINIT! is used, the first execution of XloopNEXT is
173" a no-operation.
174"
175" - Use Xloop inside the loop:
176" One argument:
177" The argument and the Xnext value are multiplied to build the
178" next Xpath value. No new Xnext value is prepared. The argument
179" should be 2^(n-1) for the nth Xloop command inside the loop.
180" If the loop has only one Xloop command, the argument can be
Bram Moolenaarf48ee3c2019-12-06 22:18:20 +0100181" omitted (default: 1).
Bram Moolenaar071d4272004-06-13 20:20:40 +0000182"
183" - Use XloopNEXT before ":continue" and ":endwhile". This computes a new
184" Xnext value for the next execution of the loop by multiplying the old
185" one with the factor specified in the XloopINIT command. No Argument.
186" Alternatively, when XloopINIT! is used, a single XloopNEXT at the
187" beginning of the loop can be used.
188"
189" Nested loops are not supported.
190"
191" - Use Xcheck at end of each test. It prints the test number, the expected
192" execution path value, the test result ("OK" or "FAIL"), and, if the tests
193" fails, the actual execution path.
194" One argument:
195" Expected Xpath/Xloop sum for the correct execution path.
196" In order that this value can be computed automatically, do the
197" following: For each line in the test with an Xpath and Xloop
198" command, add a comment starting with "X:" and specifying an
199" expression that evaluates to the value contributed by this line to
200" the correct execution path. (For copying an Xpath argument of at
201" least two digits into the comment, press <C-P>.) At the end of the
202" test, just type "Xcheck" and press <Esc>.
203"
204" - In order to add additional information to the test output file, use the
205" Xout command. Argument(s) like ":echo".
206"
207" Automatic argument generation: {{{3
208"
209" The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be
210" generated automatically, so that new tests can easily be written without
211" mental arithmetic. The Xcheck argument is computed from the "X:" comments
212" of the preceding Xpath and Xloop commands. See the commands and
213" abbreviations at the beginning of this file.
214"
215" Implementation: {{{3
216" XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout.
217"
218" The variants for existing g:ExtraVimResult are needed when executing a script
219" in an extra Vim process, see ExtraVim below.
220
221" EXTRA_VIM_START - do not change or remove this line.
222
223com! XpathINIT let g:Xpath = 0
224
225if exists("g:ExtraVimResult")
226 com! -count -bar Xpath exec "!echo <count> >>" . g:ExtraVimResult
227else
228 com! -count -bar Xpath let g:Xpath = g:Xpath + <count>
229endif
230
231com! -count -nargs=1 -bang
232 \ XloopINIT let g:Xnext = <count> |
233 \ let g:Xfactor = <args> |
234 \ let g:Xskip = strlen("<bang>")
235
236if exists("g:ExtraVimResult")
237 com! -count=1 -bar Xloop exec "!echo " . (g:Xnext * <count>) . " >>" .
238 \ g:ExtraVimResult
239else
240 com! -count=1 -bar Xloop let g:Xpath = g:Xpath + g:Xnext * <count>
241endif
242
243com! XloopNEXT let g:Xnext = g:Xnext *
244 \ (g:Xskip ? 1 : g:Xfactor) |
245 \ let g:Xskip = 0
246
247let @r = ""
248let Xtest = 1
249com! -count Xcheck let Xresult = "*** Test " .
250 \ (Xtest<10?" ":Xtest<100?" ":"") .
251 \ Xtest . ": " . (
252 \ (Xpath==<count>) ? "OK (".Xpath.")" :
253 \ "FAIL (".Xpath." instead of <count>)"
254 \ ) |
255 \ let @R = Xresult . "\n" |
256 \ echo Xresult |
257 \ let Xtest = Xtest + 1
258
259if exists("g:ExtraVimResult")
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000260 com! -nargs=+ Xoutq exec "!echo @R:'" .
261 \ substitute(substitute(<q-args>,
262 \ "'", '&\\&&', "g"), "\n", "@NL@", "g")
263 \ . "' >>" . g:ExtraVimResult
Bram Moolenaar071d4272004-06-13 20:20:40 +0000264else
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000265 com! -nargs=+ Xoutq let @R = "--- Test " .
Bram Moolenaar071d4272004-06-13 20:20:40 +0000266 \ (g:Xtest<10?" ":g:Xtest<100?" ":"") .
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000267 \ g:Xtest . ": " . substitute(<q-args>,
268 \ "\n", "&\t ", "g") . "\n"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000269endif
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000270com! -nargs=+ Xout exec 'Xoutq' <args>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000271
272" Switch off storing of lines for undoing changes. Speeds things up a little.
273set undolevels=-1
274
275" EXTRA_VIM_STOP - do not change or remove this line.
276
277
278" ExtraVim() - Run a script file in an extra Vim process. {{{2
279"
280" This is useful for testing immediate abortion of the script processing due to
281" an error in a command dynamically enclosed by a :try/:tryend region or when an
282" exception is thrown but not caught or when an interrupt occurs. It can also
283" be used for testing :finish.
284"
285" An interrupt location can be specified by an "INTERRUPT" comment. A number
286" telling how often this location is reached (in a loop or in several function
287" calls) should be specified as argument. When missing, once per script
288" invocation or function call is assumed. INTERRUPT locations are tested by
289" setting a breakpoint in that line and using the ">quit" debug command when
290" the breakpoint is reached. A function for which an INTERRUPT location is
291" specified must be defined before calling it (or executing it as a script by
292" using ExecAsScript below).
293"
294" This function is only called in normal modus ("g:ExtraVimResult" undefined).
295"
296" Tests to be executed as an extra script should be written as follows:
297"
298" column 1 column 1
299" | |
300" v v
301"
302" XpathINIT XpathINIT
303" if ExtraVim() if ExtraVim()
304" ... " ...
305" ... " ...
306" endif endif
307" Xcheck <number> Xcheck <number>
308"
309" Double quotes in column 1 are removed before the script is executed.
310" They should be used if the test has unbalanced conditionals (:if/:endif,
311" :while:/endwhile, :try/:endtry) or for a line with a syntax error. The
312" extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual.
313"
314" A file name may be specified as argument. All messages of the extra Vim
315" process are then redirected to the file. An existing file is overwritten.
316"
317let ExtraVimCount = 0
318let ExtraVimBase = expand("<sfile>")
319let ExtraVimTestEnv = ""
320"
Bram Moolenaar1e115362019-01-09 23:01:02 +0100321function ExtraVim(...)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000322 " Count how often this function is called.
323 let g:ExtraVimCount = g:ExtraVimCount + 1
324
325 " Disable folds to prevent that the ranges in the ":write" commands below
326 " are extended up to the end of a closed fold. This also speeds things up
327 " considerably.
328 set nofoldenable
329
330 " Open a buffer for this test script and copy the test environment to
331 " a temporary file. Take account of parts relevant for the extra script
332 " execution only.
333 let current_buffnr = bufnr("%")
334 execute "view +1" g:ExtraVimBase
335 if g:ExtraVimCount == 1
336 let g:ExtraVimTestEnv = tempname()
337 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w"
338 \ g:ExtraVimTestEnv "|']+"
339 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
340 \ g:ExtraVimTestEnv "|']+"
341 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
342 \ g:ExtraVimTestEnv "|']+"
343 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
344 \ g:ExtraVimTestEnv "|']+"
345 endif
346
347 " Start the extra Vim script with a ":source" command for the test
348 " environment. The source line number where the extra script will be
349 " appended, needs to be passed as variable "ExtraVimBegin" to the script.
350 let extra_script = tempname()
351 exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script
352 let extra_begin = 1
353
354 " Starting behind the test environment, skip over the first g:ExtraVimCount
355 " occurrences of "if ExtraVim()" and copy the following lines up to the
356 " matching "endif" to the extra Vim script.
357 execute "/E" . "ND_OF_TEST_ENVIRONMENT/"
358 exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n"
359 execute ".,/^endif/-write >>" . extra_script
360
361 " Open a buffer for the extra Vim script, delete all ^", and write the
362 " script if was actually modified.
363 execute "edit +" . (extra_begin + 1) extra_script
364 ,$s/^"//e
365 update
366
367 " Count the INTERRUPTs and build the breakpoint and quit commands.
368 let breakpoints = ""
369 let debug_quits = ""
370 let in_func = 0
371 exec extra_begin
372 while search(
373 \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|'
374 \ . '^\s*\\\|^\s*endf\%[unction]\>\|'
375 \ . '\%(^\s*fu\%[nction]!\=\s*\)\@<!\%(\u\|s:\)\w*\s*(\|'
376 \ . 'ExecAsScript\s\+\%(\u\|s:\)\w*',
377 \ "W") > 0
378 let theline = getline(".")
379 if theline =~ '^\s*fu'
380 " Function definition.
381 let in_func = 1
382 let func_start = line(".")
383 let func_name = substitute(theline,
384 \ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "")
Bram Moolenaar071d4272004-06-13 20:20:40 +0000385 elseif theline =~ '^\s*endf'
386 " End of function definition.
387 let in_func = 0
388 else
389 let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)',
390 \ '\1', "")
391 if finding =~ '^"\s*INTERRUPT\h\@!'
392 " Interrupt comment. Compose as many quit commands as
393 " specified.
394 let cnt = substitute(finding,
395 \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "")
396 let quits = ""
397 while cnt > 0
398 " Use "\r" rather than "\n" to separate the quit commands.
399 " "\r" is not interpreted as command separator by the ":!"
400 " command below but works to separate commands in the
401 " external vim.
402 let quits = quits . "q\r"
403 let cnt = cnt - 1
404 endwhile
405 if in_func
406 " Add the function breakpoint and note the number of quits
407 " to be used, if specified, or one for every call else.
408 let breakpoints = breakpoints . " -c 'breakadd func " .
Bram Moolenaare224ffa2006-03-01 00:01:28 +0000409 \ (line(".") - func_start) . " " .
Bram Moolenaar071d4272004-06-13 20:20:40 +0000410 \ func_name . "'"
411 if quits != ""
412 let debug_quits = debug_quits . quits
413 elseif !exists("quits{func_name}")
414 let quits{func_name} = "q\r"
415 else
416 let quits{func_name} = quits{func_name} . "q\r"
417 endif
418 else
419 " Add the file breakpoint and the quits to be used for it.
420 let breakpoints = breakpoints . " -c 'breakadd file " .
421 \ line(".") . " " . extra_script . "'"
422 if quits == ""
423 let quits = "q\r"
424 endif
425 let debug_quits = debug_quits . quits
426 endif
427 else
428 " Add the quits to be used for calling the function or executing
429 " it as script file.
430 if finding =~ '^ExecAsScript'
431 " Sourcing function as script.
432 let finding = substitute(finding,
433 \ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "")
434 else
435 " Function call.
436 let finding = substitute(finding,
437 \ '^\(\%(\u\|s:\)\w*\).*', '\1', "")
438 endif
439 if exists("quits{finding}")
440 let debug_quits = debug_quits . quits{finding}
441 endif
442 endif
443 endif
444 endwhile
445
446 " Close the buffer for the script and create an (empty) resultfile.
447 bwipeout
448 let resultfile = tempname()
449 exec "!>" . resultfile
450
451 " Run the script in an extra vim. Switch to extra modus by passing the
452 " resultfile in ExtraVimResult. Redirect messages to the file specified as
453 " argument if any. Use ":debuggreedy" so that the commands provided on the
454 " pipe are consumed at the debug prompt. Use "-N" to enable command-line
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000455 " continuation ("C" in 'cpo'). Add "nviminfo" to 'viminfo' to avoid
Bram Moolenaar071d4272004-06-13 20:20:40 +0000456 " messing up the user's viminfo file.
457 let redirect = a:0 ?
458 \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : ""
Bram Moolenaar1ac41a52019-10-10 13:30:12 +0200459 exec "!echo '" . debug_quits . "q' | " .. v:progpath .. " -u NONE -N -Xes" . redirect .
Bram Moolenaar071d4272004-06-13 20:20:40 +0000460 \ " -c 'debuggreedy|set viminfo+=nviminfo'" .
461 \ " -c 'let ExtraVimBegin = " . extra_begin . "'" .
462 \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints .
463 \ " -S " . extra_script
464
465 " Build the resulting sum for resultfile and add it to g:Xpath. Add Xout
466 " information provided by the extra Vim process to the test output.
467 let sum = 0
468 exec "edit" resultfile
469 let line = 1
470 while line <= line("$")
471 let theline = getline(line)
472 if theline =~ '^@R:'
473 exec 'Xout "' . substitute(substitute(
474 \ escape(escape(theline, '"'), '\"'),
475 \ '^@R:', '', ""), '@NL@', "\n", "g") . '"'
476 else
477 let sum = sum + getline(line)
478 endif
479 let line = line + 1
480 endwhile
481 bwipeout
482 let g:Xpath = g:Xpath + sum
483
484 " Delete the extra script and the resultfile.
485 call delete(extra_script)
486 call delete(resultfile)
487
488 " Switch back to the buffer that was active when this function was entered.
489 exec "buffer" current_buffnr
490
491 " Return 0. This protects extra scripts from being run in the main Vim
492 " process.
493 return 0
494endfunction
495
496
497" ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script {{{2
498"
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000499" Evaluates v:throwpoint and returns the throwpoint relative to the beginning of
Bram Moolenaar071d4272004-06-13 20:20:40 +0000500" an ExtraVim script as passed by ExtraVim() in ExtraVimBegin.
501"
502" EXTRA_VIM_START - do not change or remove this line.
Bram Moolenaar1e115362019-01-09 23:01:02 +0100503function ExtraVimThrowpoint()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000504 if !exists("g:ExtraVimBegin")
505 Xout "ExtraVimThrowpoint() used outside ExtraVim() script."
506 return v:throwpoint
507 endif
508
509 if v:throwpoint =~ '^function\>'
510 return v:throwpoint
511 endif
512
513 return "line " .
514 \ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) .
515 \ " of ExtraVim() script"
516endfunction
517" EXTRA_VIM_STOP - do not change or remove this line.
518
519
520" MakeScript() - Make a script file from a function. {{{2
521"
522" Create a script that consists of the body of the function a:funcname.
523" Replace any ":return" by a ":finish", any argument variable by a global
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200524" variable, and every ":call" by a ":source" for the next following argument
Bram Moolenaar071d4272004-06-13 20:20:40 +0000525" in the variable argument list. This function is useful if similar tests are
526" to be made for a ":return" from a function call or a ":finish" in a script
527" file.
528"
529" In order to execute a function specifying an INTERRUPT location (see ExtraVim)
530" as a script file, use ExecAsScript below.
531"
532" EXTRA_VIM_START - do not change or remove this line.
Bram Moolenaar1e115362019-01-09 23:01:02 +0100533function MakeScript(funcname, ...)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000534 let script = tempname()
535 execute "redir! >" . script
536 execute "function" a:funcname
537 redir END
538 execute "edit" script
539 " Delete the "function" and the "endfunction" lines. Do not include the
540 " word "function" in the pattern since it might be translated if LANG is
541 " set. When MakeScript() is being debugged, this deletes also the debugging
542 " output of its line 3 and 4.
543 exec '1,/.*' . a:funcname . '(.*)/d'
544 /^\d*\s*endfunction\>/,$d
545 %s/^\d*//e
546 %s/return/finish/e
547 %s/\<a:\(\h\w*\)/g:\1/ge
548 normal gg0
549 let cnt = 0
550 while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
551 let cnt = cnt + 1
552 s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
553 endwhile
554 g/^\s*$/d
555 write
556 bwipeout
557 return script
558endfunction
559" EXTRA_VIM_STOP - do not change or remove this line.
560
561
562" ExecAsScript - Source a temporary script made from a function. {{{2
563"
564" Make a temporary script file from the function a:funcname, ":source" it, and
565" delete it afterwards.
566"
567" When inside ":if ExtraVim()", add a file breakpoint for each INTERRUPT
568" location specified in the function.
569"
570" EXTRA_VIM_START - do not change or remove this line.
Bram Moolenaar1e115362019-01-09 23:01:02 +0100571function ExecAsScript(funcname)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000572 " Make a script from the function passed as argument.
573 let script = MakeScript(a:funcname)
574
575 " When running in an extra Vim process, add a file breakpoint for each
576 " function breakpoint set when the extra Vim process was invoked by
577 " ExtraVim().
578 if exists("g:ExtraVimResult")
579 let bplist = tempname()
580 execute "redir! >" . bplist
581 breaklist
582 redir END
583 execute "edit" bplist
584 " Get the line number from the function breakpoint. Works also when
585 " LANG is set.
586 execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d'
587 %s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e
588 let cnt = 0
589 while cnt < line("$")
590 let cnt = cnt + 1
591 if getline(cnt) != ""
592 execute "breakadd file" getline(cnt) script
593 endif
594 endwhile
595 bwipeout!
596 call delete(bplist)
597 endif
598
599 " Source and delete the script.
600 exec "source" script
601 call delete(script)
602endfunction
603
604com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
605" EXTRA_VIM_STOP - do not change or remove this line.
606
607
608" END_OF_TEST_ENVIRONMENT - do not change or remove this line.
609
Bram Moolenaar071d4272004-06-13 20:20:40 +0000610function! MESSAGES(...)
611 try
612 exec "edit" g:msgfile
613 catch /^Vim(edit):/
614 return 0
615 endtry
616
617 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
618 let match = 1
619 norm gg
620
621 let num = a:0 / 2
622 let cnt = 1
623 while cnt <= num
624 let enr = a:{2*cnt - 1}
625 let emsg= a:{2*cnt}
626 let cnt = cnt + 1
627
628 if enr == ""
629 Xout "TODO: Add message number for:" emsg
630 elseif enr == "INT"
631 let enr = ""
632 endif
633 if enr == "" && !english
634 continue
635 endif
636 let pattern = (enr != "") ? enr . ':.*' : ''
637 if english
638 let pattern = pattern . emsg
639 endif
640 if !search(pattern, "W")
641 let match = 0
642 Xout "No match for:" pattern
643 endif
644 norm $
645 endwhile
646
647 bwipeout!
648 return match
649endfunction
650
Bram Moolenaarefb64822020-08-10 22:15:30 +0200651" Following tests were moved to test_vimscript.vim:
652" 1-24, 27-31, 34-40, 49-50, 52-68, 76-81, 87
653" Following tests were moved to test_trycatch.vim:
654" 25-26, 32-33, 41-48, 51, 69-75
655let Xtest = 82
Bram Moolenaar071d4272004-06-13 20:20:40 +0000656
657"-------------------------------------------------------------------------------
658" Test 82: Ignoring :catch clauses after an error or interrupt {{{1
659"
660" When an exception is thrown and an error or interrupt occurs before
661" the matching :catch clause is reached, the exception is discarded
662" and the :catch clause is ignored (also for the error or interrupt
663" exception being thrown then).
664"-------------------------------------------------------------------------------
665
666XpathINIT
667
668if ExtraVim()
669 try
670 try
671 Xpath 1 " X: 1
672 throw "arrgh"
673 Xpath 2 " X: 0
674" if 1
675 Xpath 4 " X: 0
676 " error after :throw: missing :endif
677 catch /.*/
678 Xpath 8 " X: 0
679 Xout v:exception "in" ExtraVimThrowpoint()
680 catch /.*/
681 Xpath 16 " X: 0
682 Xout v:exception "in" ExtraVimThrowpoint()
683 endtry
684 Xpath 32 " X: 0
685 catch /arrgh/
686 Xpath 64 " X: 0
687 endtry
688 Xpath 128 " X: 0
689endif
690
691if ExtraVim()
692 function! E()
693 try
694 try
695 Xpath 256 " X: 256
696 throw "arrgh"
697 Xpath 512 " X: 0
698" if 1
699 Xpath 1024 " X: 0
700 " error after :throw: missing :endif
701 catch /.*/
702 Xpath 2048 " X: 0
703 Xout v:exception "in" ExtraVimThrowpoint()
704 catch /.*/
705 Xpath 4096 " X: 0
706 Xout v:exception "in" ExtraVimThrowpoint()
707 endtry
708 Xpath 8192 " X: 0
709 catch /arrgh/
710 Xpath 16384 " X: 0
711 endtry
712 endfunction
713
714 call E()
715 Xpath 32768 " X: 0
716endif
717
718if ExtraVim()
719 try
720 try
721 Xpath 65536 " X: 65536
722 throw "arrgh"
723 Xpath 131072 " X: 0
724 catch /.*/ "INTERRUPT
725 Xpath 262144 " X: 0
726 Xout v:exception "in" ExtraVimThrowpoint()
727 catch /.*/
728 Xpath 524288 " X: 0
729 Xout v:exception "in" ExtraVimThrowpoint()
730 endtry
731 Xpath 1048576 " X: 0
732 catch /arrgh/
733 Xpath 2097152 " X: 0
734 endtry
735 Xpath 4194304 " X: 0
736endif
737
738if ExtraVim()
739 function I()
740 try
741 try
742 Xpath 8388608 " X: 8388608
743 throw "arrgh"
744 Xpath 16777216 " X: 0
745 catch /.*/ "INTERRUPT
746 Xpath 33554432 " X: 0
747 Xout v:exception "in" ExtraVimThrowpoint()
748 catch /.*/
749 Xpath 67108864 " X: 0
750 Xout v:exception "in" ExtraVimThrowpoint()
751 endtry
752 Xpath 134217728 " X: 0
753 catch /arrgh/
754 Xpath 268435456 " X: 0
755 endtry
756 endfunction
757
758 call I()
759 Xpath 536870912 " X: 0
760endif
761
762Xcheck 8454401
763
764
765"-------------------------------------------------------------------------------
766" Test 83: Executing :finally clauses after an error or interrupt {{{1
767"
768" When an exception is thrown and an error or interrupt occurs before
769" the :finally of the innermost :try is reached, the exception is
770" discarded and the :finally clause is executed.
771"-------------------------------------------------------------------------------
772
773XpathINIT
774
775if ExtraVim()
776 try
777 Xpath 1 " X: 1
778 try
779 Xpath 2 " X: 2
780 throw "arrgh"
781 Xpath 4 " X: 0
782" if 1
783 Xpath 8 " X: 0
784 " error after :throw: missing :endif
785 finally
786 Xpath 16 " X: 16
787 endtry
788 Xpath 32 " X: 0
789 catch /arrgh/
790 Xpath 64 " X: 0
791 endtry
792 Xpath 128 " X: 0
793endif
794
795if ExtraVim()
796 try
797 Xpath 256 " X: 256
798 try
799 Xpath 512 " X: 512
800 throw "arrgh"
801 Xpath 1024 " X: 0
802 finally "INTERRUPT
803 Xpath 2048 " X: 2048
804 endtry
805 Xpath 4096 " X: 0
806 catch /arrgh/
807 Xpath 8192 " X: 0
808 endtry
809 Xpath 16384 " X: 0
810endif
811
812Xcheck 2835
813
814
815"-------------------------------------------------------------------------------
816" Test 84: Exceptions in autocommand sequences. {{{1
817"
818" When an exception occurs in a sequence of autocommands for
819" a specific event, the rest of the sequence is not executed. The
820" command that triggered the autocommand execution aborts, and the
821" exception is propagated to the caller.
822"
823" For the FuncUndefined event under a function call expression or
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000824" :call command, the function is not executed, even when it has
Bram Moolenaar071d4272004-06-13 20:20:40 +0000825" been defined by the autocommands before the exception occurred.
826"-------------------------------------------------------------------------------
827
828XpathINIT
829
830if ExtraVim()
831
832 function! INT()
833 "INTERRUPT
834 let dummy = 0
835 endfunction
836
837 aug TMP
838 autocmd!
839
840 autocmd User x1 Xpath 1 " X: 1
841 autocmd User x1 throw "x1"
842 autocmd User x1 Xpath 2 " X: 0
843
844 autocmd User x2 Xpath 4 " X: 4
845 autocmd User x2 asdf
846 autocmd User x2 Xpath 8 " X: 0
847
848 autocmd User x3 Xpath 16 " X: 16
849 autocmd User x3 call INT()
850 autocmd User x3 Xpath 32 " X: 0
851
852 autocmd FuncUndefined U1 function! U1()
853 autocmd FuncUndefined U1 Xpath 64 " X: 0
854 autocmd FuncUndefined U1 endfunction
855 autocmd FuncUndefined U1 Xpath 128 " X: 128
856 autocmd FuncUndefined U1 throw "U1"
857 autocmd FuncUndefined U1 Xpath 256 " X: 0
858
859 autocmd FuncUndefined U2 function! U2()
860 autocmd FuncUndefined U2 Xpath 512 " X: 0
861 autocmd FuncUndefined U2 endfunction
862 autocmd FuncUndefined U2 Xpath 1024 " X: 1024
863 autocmd FuncUndefined U2 ASDF
864 autocmd FuncUndefined U2 Xpath 2048 " X: 0
865
866 autocmd FuncUndefined U3 function! U3()
867 autocmd FuncUndefined U3 Xpath 4096 " X: 0
868 autocmd FuncUndefined U3 endfunction
869 autocmd FuncUndefined U3 Xpath 8192 " X: 8192
870 autocmd FuncUndefined U3 call INT()
871 autocmd FuncUndefined U3 Xpath 16384 " X: 0
872 aug END
873
874 try
875 try
876 Xpath 32768 " X: 32768
877 doautocmd User x1
878 catch /x1/
879 Xpath 65536 " X: 65536
880 endtry
881
882 while 1
883 try
884 Xpath 131072 " X: 131072
885 let caught = 0
886 doautocmd User x2
887 catch /asdf/
888 let caught = 1
889 finally
890 Xpath 262144 " X: 262144
891 if !caught && !$VIMNOERRTHROW
892 Xpath 524288 " X: 0
893 " Propagate uncaught error exception,
894 else
895 " ... but break loop for caught error exception,
896 " or discard error and break loop if $VIMNOERRTHROW
897 break
898 endif
899 endtry
900 endwhile
901
902 while 1
903 try
904 Xpath 1048576 " X: 1048576
905 let caught = 0
906 doautocmd User x3
907 catch /Vim:Interrupt/
908 let caught = 1
909 finally
910 Xpath 2097152 " X: 2097152
911 if !caught && !$VIMNOINTTHROW
912 Xpath 4194304 " X: 0
913 " Propagate uncaught interrupt exception,
914 else
915 " ... but break loop for caught interrupt exception,
916 " or discard interrupt and break loop if $VIMNOINTTHROW
917 break
918 endif
919 endtry
920 endwhile
921
922 if exists("*U1") | delfunction U1 | endif
923 if exists("*U2") | delfunction U2 | endif
924 if exists("*U3") | delfunction U3 | endif
925
926 try
927 Xpath 8388608 " X: 8388608
928 call U1()
929 catch /U1/
930 Xpath 16777216 " X: 16777216
931 endtry
932
933 while 1
934 try
935 Xpath 33554432 " X: 33554432
936 let caught = 0
937 call U2()
938 catch /ASDF/
939 let caught = 1
940 finally
941 Xpath 67108864 " X: 67108864
942 if !caught && !$VIMNOERRTHROW
943 Xpath 134217728 " X: 0
944 " Propagate uncaught error exception,
945 else
946 " ... but break loop for caught error exception,
947 " or discard error and break loop if $VIMNOERRTHROW
948 break
949 endif
950 endtry
951 endwhile
952
953 while 1
954 try
955 Xpath 268435456 " X: 268435456
956 let caught = 0
957 call U3()
958 catch /Vim:Interrupt/
959 let caught = 1
960 finally
961 Xpath 536870912 " X: 536870912
962 if !caught && !$VIMNOINTTHROW
963 Xpath 1073741824 " X: 0
964 " Propagate uncaught interrupt exception,
965 else
966 " ... but break loop for caught interrupt exception,
967 " or discard interrupt and break loop if $VIMNOINTTHROW
968 break
969 endif
970 endtry
971 endwhile
972 catch /.*/
973 " The Xpath command does not accept 2^31 (negative); display explicitly:
974 exec "!echo 2147483648 >>" . g:ExtraVimResult
975 Xout "Caught" v:exception "in" v:throwpoint
976 endtry
977
978 unlet caught
979 delfunction INT
980 delfunction U1
981 delfunction U2
982 delfunction U3
983 au! TMP
984 aug! TMP
985endif
986
987Xcheck 934782101
988
989
990"-------------------------------------------------------------------------------
991" Test 85: Error exceptions in autocommands for I/O command events {{{1
992"
993" When an I/O command is inside :try/:endtry, autocommands to be
994" executed after it should be skipped on an error (exception) in the
995" command itself or in autocommands to be executed before the command.
996" In the latter case, the I/O command should not be executed either.
997" Example 1: BufWritePre, :write, BufWritePost
998" Example 2: FileReadPre, :read, FileReadPost.
999"-------------------------------------------------------------------------------
1000
1001XpathINIT
1002
1003function! MSG(enr, emsg)
1004 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
1005 if a:enr == ""
1006 Xout "TODO: Add message number for:" a:emsg
1007 let v:errmsg = ":" . v:errmsg
1008 endif
1009 let match = 1
1010 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
1011 let match = 0
1012 if v:errmsg == ""
1013 Xout "Message missing."
1014 else
1015 let v:errmsg = escape(v:errmsg, '"')
1016 Xout "Unexpected message:" v:errmsg
1017 endif
1018 endif
1019 return match
1020endfunction
1021
1022" Remove the autocommands for the events specified as arguments in all used
1023" autogroups.
Bram Moolenaar1e115362019-01-09 23:01:02 +01001024function Delete_autocommands(...)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001025 let augfile = tempname()
1026 while 1
1027 try
1028 exec "redir >" . augfile
1029 aug
1030 redir END
1031 exec "edit" augfile
1032 g/^$/d
1033 norm G$
1034 let wrap = "w"
1035 while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0
1036 let wrap = "W"
1037 exec "norm y/ \n"
1038 let argno = 1
1039 while argno <= a:0
1040 exec "au!" escape(@", " ") a:{argno}
1041 let argno = argno + 1
1042 endwhile
1043 endwhile
1044 catch /.*/
1045 finally
1046 bwipeout!
1047 call delete(augfile)
1048 break " discard errors for $VIMNOERRTHROW
1049 endtry
1050 endwhile
1051endfunction
1052
1053call Delete_autocommands("BufWritePre", "BufWritePost")
1054
1055while 1
1056 try
1057 try
1058 let post = 0
1059 aug TMP
1060 au! BufWritePost * let post = 1
1061 aug END
1062 let caught = 0
1063 write /n/o/n/e/x/i/s/t/e/n/t
1064 catch /^Vim(write):/
1065 let caught = 1
1066 let v:errmsg = substitute(v:exception, '^Vim(write):', '', "")
1067 finally
1068 Xpath 1 " X: 1
1069 if !caught && !$VIMNOERRTHROW
1070 Xpath 2 " X: 0
1071 endif
1072 let v:errmsg = substitute(v:errmsg, '^"/n/o/n/e/x/i/s/t/e/n/t" ',
1073 \ '', "")
1074 if !MSG('E212', "Can't open file for writing")
1075 Xpath 4 " X: 0
1076 endif
1077 if post
1078 Xpath 8 " X: 0
1079 Xout "BufWritePost commands executed after write error"
1080 endif
1081 au! TMP
1082 aug! TMP
1083 endtry
1084 catch /.*/
1085 Xpath 16 " X: 0
1086 Xout v:exception "in" v:throwpoint
1087 finally
1088 break " discard error for $VIMNOERRTHROW
1089 endtry
1090endwhile
1091
1092while 1
1093 try
1094 try
1095 let post = 0
1096 aug TMP
1097 au! BufWritePre * asdf
1098 au! BufWritePost * let post = 1
1099 aug END
1100 let tmpfile = tempname()
1101 let caught = 0
1102 exec "write" tmpfile
1103 catch /^Vim\((write)\)\=:/
1104 let caught = 1
1105 let v:errmsg = substitute(v:exception, '^Vim\((write)\)\=:', '', "")
1106 finally
1107 Xpath 32 " X: 32
1108 if !caught && !$VIMNOERRTHROW
1109 Xpath 64 " X: 0
1110 endif
1111 let v:errmsg = substitute(v:errmsg, '^"'.tmpfile.'" ', '', "")
1112 if !MSG('E492', "Not an editor command")
1113 Xpath 128 " X: 0
1114 endif
1115 if filereadable(tmpfile)
1116 Xpath 256 " X: 0
1117 Xout ":write command not suppressed after BufWritePre error"
1118 endif
1119 if post
1120 Xpath 512 " X: 0
1121 Xout "BufWritePost commands executed after BufWritePre error"
1122 endif
1123 au! TMP
1124 aug! TMP
1125 endtry
1126 catch /.*/
1127 Xpath 1024 " X: 0
1128 Xout v:exception "in" v:throwpoint
1129 finally
1130 break " discard error for $VIMNOERRTHROW
1131 endtry
1132endwhile
1133
1134call delete(tmpfile)
1135
1136call Delete_autocommands("BufWritePre", "BufWritePost",
1137 \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
1138
1139while 1
1140 try
1141 try
1142 let post = 0
1143 aug TMP
1144 au! FileReadPost * let post = 1
1145 aug END
1146 let caught = 0
1147 read /n/o/n/e/x/i/s/t/e/n/t
1148 catch /^Vim(read):/
1149 let caught = 1
1150 let v:errmsg = substitute(v:exception, '^Vim(read):', '', "")
1151 finally
1152 Xpath 2048 " X: 2048
1153 if !caught && !$VIMNOERRTHROW
1154 Xpath 4096 " X: 0
1155 endif
1156 let v:errmsg = substitute(v:errmsg, ' /n/o/n/e/x/i/s/t/e/n/t$',
1157 \ '', "")
1158 if !MSG('E484', "Can't open file")
1159 Xpath 8192 " X: 0
1160 endif
1161 if post
1162 Xpath 16384 " X: 0
1163 Xout "FileReadPost commands executed after write error"
1164 endif
1165 au! TMP
1166 aug! TMP
1167 endtry
1168 catch /.*/
1169 Xpath 32768 " X: 0
1170 Xout v:exception "in" v:throwpoint
1171 finally
1172 break " discard error for $VIMNOERRTHROW
1173 endtry
1174endwhile
1175
1176while 1
1177 try
1178 let infile = tempname()
1179 let tmpfile = tempname()
1180 exec "!echo XYZ >" . infile
1181 exec "edit" tmpfile
1182 try
1183 Xpath 65536 " X: 65536
1184 try
1185 let post = 0
1186 aug TMP
1187 au! FileReadPre * asdf
1188 au! FileReadPost * let post = 1
1189 aug END
1190 let caught = 0
1191 exec "0read" infile
1192 catch /^Vim\((read)\)\=:/
1193 let caught = 1
1194 let v:errmsg = substitute(v:exception, '^Vim\((read)\)\=:', '',
1195 \ "")
1196 finally
1197 Xpath 131072 " X: 131072
1198 if !caught && !$VIMNOERRTHROW
1199 Xpath 262144 " X: 0
1200 endif
1201 let v:errmsg = substitute(v:errmsg, ' '.infile.'$', '', "")
1202 if !MSG('E492', "Not an editor command")
1203 Xpath 524288 " X: 0
1204 endif
1205 if getline("1") == "XYZ"
1206 Xpath 1048576 " X: 0
1207 Xout ":read command not suppressed after FileReadPre error"
1208 endif
1209 if post
1210 Xpath 2097152 " X: 0
1211 Xout "FileReadPost commands executed after " .
1212 \ "FileReadPre error"
1213 endif
1214 au! TMP
1215 aug! TMP
1216 endtry
1217 finally
1218 bwipeout!
1219 endtry
1220 catch /.*/
1221 Xpath 4194304 " X: 0
1222 Xout v:exception "in" v:throwpoint
1223 finally
1224 break " discard error for $VIMNOERRTHROW
1225 endtry
1226endwhile
1227
1228call delete(infile)
1229call delete(tmpfile)
1230unlet! caught post infile tmpfile
1231delfunction MSG
1232delfunction Delete_autocommands
1233
1234Xcheck 198689
1235
Bram Moolenaar41b884b2012-11-14 22:38:08 +01001236"-------------------------------------------------------------------------------
Bram Moolenaar32c8f1c2012-12-05 19:00:06 +01001237" Test 86: setloclist crash {{{1
Bram Moolenaar41b884b2012-11-14 22:38:08 +01001238"
1239" Executing a setloclist() on BufUnload shouldn't crash Vim
1240"-------------------------------------------------------------------------------
1241
1242func F
1243 au BufUnload * :call setloclist(0, [{'bufnr':1, 'lnum':1, 'col':1, 'text': 'tango down'}])
1244
Bram Moolenaarcc908ad2013-06-06 18:55:49 +02001245 :lvimgrep /.*/ *.mak
Bram Moolenaar41b884b2012-11-14 22:38:08 +01001246endfunc
1247
1248XpathINIT
1249
1250ExecAsScript F
1251
1252delfunction F
1253Xout "No Crash for vimgrep on BufUnload"
1254Xcheck 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00001255
Bram Moolenaar1f068232019-11-03 16:17:26 +01001256" Test 87 was moved to test_vimscript.vim
1257let Xtest = 88
Bram Moolenaarb8f84612013-02-26 22:54:11 +01001258
Bram Moolenaarb8f84612013-02-26 22:54:11 +01001259
1260"-------------------------------------------------------------------------------
1261" Test 88: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1
Bram Moolenaar071d4272004-06-13 20:20:40 +00001262"
1263" It is possible to configure Vim for throwing exceptions on error
1264" or interrupt, controlled by variables $VIMNOERRTHROW and
1265" $VIMNOINTTHROW. This is just for increasing the number of tests.
1266" All tests here should run for all four combinations of setting
1267" these variables to 0 or 1. The variables are intended for the
1268" development phase only. In the final release, Vim should be
1269" configured to always use error and interrupt exceptions.
1270"
1271" The test result is "OK",
1272"
1273" - if the $VIMNOERRTHROW and the $VIMNOINTTHROW control are not
1274" configured and exceptions are thrown on error and on
1275" interrupt.
1276"
1277" - if the $VIMNOERRTHROW or the $VIMNOINTTHROW control is
1278" configured and works as intended.
1279"
1280" What actually happens, is shown in the test output.
1281"
1282" Otherwise, the test result is "FAIL", and the test output describes
1283" the problem.
1284"
1285" IMPORTANT: This must be the last test because it sets $VIMNOERRTHROW and
1286" $VIMNOINTTHROW.
1287"-------------------------------------------------------------------------------
1288
1289XpathINIT
1290
1291if ExtraVim()
1292
1293 function! ThrowOnError()
1294 XloopNEXT
1295 let caught = 0
1296 try
1297 Xloop 1 " X: 1 + 8 + 64
1298 asdf
1299 catch /.*/
1300 let caught = 1 " error exception caught
1301 finally
1302 Xloop 2 " X: 2 + 16 + 128
1303 return caught " discard aborting error
1304 endtry
1305 Xloop 4 " X: 0
1306 endfunction
1307
1308 let quits_skipped = 0
1309
1310 function! ThrowOnInterrupt()
1311 XloopNEXT
1312 let caught = 0
1313 try
1314 Xloop 1 " X: (1 + 8 + 64) * 512
1315 "INTERRUPT3
1316 let dummy = 0
1317 let g:quits_skipped = g:quits_skipped + 1
1318 catch /.*/
1319 let caught = 1 " interrupt exception caught
1320 finally
1321 Xloop 2 " X: (2 + 16 + 128) * 512
1322 return caught " discard interrupt
1323 endtry
1324 Xloop 4 " X: 0
1325 endfunction
1326
1327 function! CheckThrow(Type)
1328 execute 'return ThrowOn' . a:Type . '()'
1329 endfunction
1330
1331 function! CheckConfiguration(type) " type is "error" or "interrupt"
1332
1333 let type = a:type
1334 let Type = substitute(type, '.*', '\u&', "")
1335 let VAR = '$VIMNO' . substitute(type, '\(...\).*', '\U\1', "") . 'THROW'
1336
1337 if type == "error"
1338 XloopINIT! 1 8
1339 elseif type == "interrupt"
1340 XloopINIT! 512 8
1341 endif
1342
1343 exec 'let requested_for_tests = exists(VAR) && ' . VAR . ' == 0'
1344 exec 'let suppressed_for_tests = ' . VAR . ' != 0'
1345 let used_in_tests = CheckThrow(Type)
1346
1347 exec 'let ' . VAR . ' = 0'
1348 let request_works = CheckThrow(Type)
1349
1350 exec 'let ' . VAR . ' = 1'
1351 let suppress_works = !CheckThrow(Type)
1352
1353 if type == "error"
1354 XloopINIT! 262144 8
1355 elseif type == "interrupt"
1356 XloopINIT! 2097152 8
1357
1358 if g:quits_skipped != 0
1359 Xloop 1 " X: 0*2097152
1360 Xout "Test environment error. Interrupt breakpoints skipped: "
1361 \ . g:quits_skipped . ".\n"
1362 \ . "Cannot check whether interrupt exceptions are thrown."
1363 return
1364 endif
1365 endif
1366
1367 let failure =
1368 \ !suppressed_for_tests && !used_in_tests
1369 \ || !request_works
1370
1371 let contradiction =
1372 \ used_in_tests
1373 \ ? suppressed_for_tests && !request_works
1374 \ : !suppressed_for_tests
1375
1376 if failure
1377 " Failure in configuration.
1378 Xloop 2 " X: 0 * 2* (262144 + 2097152)
1379 elseif contradiction
1380 " Failure in test logic. Should not happen.
1381 Xloop 4 " X: 0 * 4 * (262144 + 2097152)
1382 endif
1383
1384 let var_control_configured =
1385 \ request_works != used_in_tests
1386 \ || suppress_works == used_in_tests
1387
1388 let var_control_not_configured =
1389 \ requested_for_tests || suppressed_for_tests
1390 \ ? request_works && !suppress_works
1391 \ : request_works == used_in_tests
1392 \ && suppress_works != used_in_tests
1393
1394 let with = used_in_tests ? "with" : "without"
1395
1396 let set = suppressed_for_tests ? "non-zero" :
1397 \ requested_for_tests ? "0" : "unset"
1398
1399 let although = contradiction && !var_control_not_configured
1400 \ ? ",\nalthough "
1401 \ : ".\n"
1402
1403 let output = "All tests were run " . with . " throwing exceptions on "
1404 \ . type . although
1405
1406 if !var_control_not_configured
1407 let output = output . VAR . " was " . set . "."
1408
1409 if !request_works && !requested_for_tests
1410 let output = output .
1411 \ "\n" . Type . " exceptions are not thrown when " . VAR .
1412 \ " is\nset to 0."
1413 endif
1414
1415 if !suppress_works && (!used_in_tests ||
1416 \ !request_works &&
1417 \ !requested_for_tests && !suppressed_for_tests)
1418 let output = output .
1419 \ "\n" . Type . " exceptions are thrown when " . VAR .
1420 \ " is set to 1."
1421 endif
1422
1423 if !failure && var_control_configured
1424 let output = output .
1425 \ "\nRun tests also with " . substitute(VAR, '^\$', '', "")
1426 \ . "=" . used_in_tests . "."
1427 \ . "\nThis is for testing in the development phase only."
1428 \ . " Remove the \n"
1429 \ . VAR . " control in the final release."
1430 endif
1431 else
1432 let output = output .
1433 \ "The " . VAR . " control is not configured."
1434 endif
1435
1436 Xout output
1437 endfunction
1438
1439 call CheckConfiguration("error")
1440 Xpath 16777216 " X: 16777216
1441 call CheckConfiguration("interrupt")
1442 Xpath 33554432 " X: 33554432
1443endif
1444
1445Xcheck 50443995
1446
1447" IMPORTANT: No test should be added after this test because it changes
1448" $VIMNOERRTHROW and $VIMNOINTTHROW.
1449
1450
1451"-------------------------------------------------------------------------------
1452" Modelines {{{1
1453" vim: ts=8 sw=4 tw=80 fdm=marker
Bram Moolenaar071d4272004-06-13 20:20:40 +00001454"-------------------------------------------------------------------------------