blob: 18790d24ca09c63ed2150f250f0833203b7fb900 [file] [log] [blame]
Bram Moolenaar5d7ead32018-02-27 17:17:42 +01001" Test various aspects of the Vim script language.
Bram Moolenaar4119cf82016-01-17 14:59:01 +01002" Most of this was formerly in test49.
Bram Moolenaarf49e2402015-12-30 15:59:25 +01003
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02004source check.vim
Bram Moolenaar93344c22019-08-14 21:12:05 +02005source shared.vim
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02006
Bram Moolenaarf49e2402015-12-30 15:59:25 +01007"-------------------------------------------------------------------------------
8" Test environment {{{1
9"-------------------------------------------------------------------------------
10
Bram Moolenaar1e115362019-01-09 23:01:02 +010011com! XpathINIT let g:Xpath = ''
Bram Moolenaarf49e2402015-12-30 15:59:25 +010012com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . <args>
13
14" Append a message to the "messages" file
Bram Moolenaar1e115362019-01-09 23:01:02 +010015func Xout(text)
Bram Moolenaarf49e2402015-12-30 15:59:25 +010016 split messages
17 $put =a:text
18 wq
19endfunc
20
21com! -nargs=1 Xout call Xout(<args>)
22
23" MakeScript() - Make a script file from a function. {{{2
24"
25" Create a script that consists of the body of the function a:funcname.
26" Replace any ":return" by a ":finish", any argument variable by a global
Bram Moolenaare21c1582019-03-02 11:57:09 +010027" variable, and every ":call" by a ":source" for the next following argument
Bram Moolenaarf49e2402015-12-30 15:59:25 +010028" in the variable argument list. This function is useful if similar tests are
29" to be made for a ":return" from a function call or a ":finish" in a script
30" file.
Bram Moolenaar1e115362019-01-09 23:01:02 +010031func MakeScript(funcname, ...)
Bram Moolenaarf49e2402015-12-30 15:59:25 +010032 let script = tempname()
33 execute "redir! >" . script
34 execute "function" a:funcname
35 redir END
36 execute "edit" script
37 " Delete the "function" and the "endfunction" lines. Do not include the
38 " word "function" in the pattern since it might be translated if LANG is
39 " set. When MakeScript() is being debugged, this deletes also the debugging
40 " output of its line 3 and 4.
41 exec '1,/.*' . a:funcname . '(.*)/d'
42 /^\d*\s*endfunction\>/,$d
43 %s/^\d*//e
44 %s/return/finish/e
45 %s/\<a:\(\h\w*\)/g:\1/ge
46 normal gg0
47 let cnt = 0
48 while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
49 let cnt = cnt + 1
50 s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
51 endwhile
52 g/^\s*$/d
53 write
54 bwipeout
55 return script
Bram Moolenaar1e115362019-01-09 23:01:02 +010056endfunc
Bram Moolenaarf49e2402015-12-30 15:59:25 +010057
58" ExecAsScript - Source a temporary script made from a function. {{{2
59"
60" Make a temporary script file from the function a:funcname, ":source" it, and
Bram Moolenaarf4f79b82016-01-25 20:38:30 +010061" delete it afterwards. However, if an exception is thrown the file may remain,
62" the caller should call DeleteTheScript() afterwards.
63let s:script_name = ''
Bram Moolenaarf49e2402015-12-30 15:59:25 +010064function! ExecAsScript(funcname)
65 " Make a script from the function passed as argument.
Bram Moolenaarf4f79b82016-01-25 20:38:30 +010066 let s:script_name = MakeScript(a:funcname)
Bram Moolenaarf49e2402015-12-30 15:59:25 +010067
68 " Source and delete the script.
Bram Moolenaarf4f79b82016-01-25 20:38:30 +010069 exec "source" s:script_name
70 call delete(s:script_name)
71 let s:script_name = ''
Bram Moolenaarf49e2402015-12-30 15:59:25 +010072endfunction
73
Bram Moolenaarf4f79b82016-01-25 20:38:30 +010074function! DeleteTheScript()
75 if s:script_name
76 call delete(s:script_name)
77 let s:script_name = ''
78 endif
79endfunc
80
Bram Moolenaarf49e2402015-12-30 15:59:25 +010081com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
82
83
84"-------------------------------------------------------------------------------
85" Test 1: :endwhile in function {{{1
86"
87" Detect if a broken loop is (incorrectly) reactivated by the
88" :endwhile. Use a :return to prevent an endless loop, and make
89" this test first to get a meaningful result on an error before other
90" tests will hang.
91"-------------------------------------------------------------------------------
92
93function! T1_F()
94 Xpath 'a'
95 let first = 1
96 while 1
97 Xpath 'b'
98 if first
99 Xpath 'c'
100 let first = 0
101 break
102 else
103 Xpath 'd'
104 return
105 endif
106 endwhile
107endfunction
108
109function! T1_G()
110 Xpath 'h'
111 let first = 1
112 while 1
113 Xpath 'i'
114 if first
115 Xpath 'j'
116 let first = 0
117 break
118 else
119 Xpath 'k'
120 return
121 endif
122 if 1 " unmatched :if
123 endwhile
124endfunction
125
126func Test_endwhile_function()
127 XpathINIT
128 call T1_F()
129 Xpath 'F'
130
131 try
132 call T1_G()
133 catch
134 " Catch missing :endif
135 call assert_true(v:exception =~ 'E171')
136 Xpath 'x'
137 endtry
138 Xpath 'G'
139
140 call assert_equal('abcFhijxG', g:Xpath)
141endfunc
142
143"-------------------------------------------------------------------------------
144" Test 2: :endwhile in script {{{1
145"
146" Detect if a broken loop is (incorrectly) reactivated by the
147" :endwhile. Use a :finish to prevent an endless loop, and place
148" this test before others that might hang to get a meaningful result
149" on an error.
150"
151" This test executes the bodies of the functions T1_F and T1_G from
152" the previous test as script files (:return replaced by :finish).
153"-------------------------------------------------------------------------------
154
155func Test_endwhile_script()
156 XpathINIT
157 ExecAsScript T1_F
158 Xpath 'F'
Bram Moolenaarf4f79b82016-01-25 20:38:30 +0100159 call DeleteTheScript()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100160
161 try
162 ExecAsScript T1_G
163 catch
164 " Catch missing :endif
165 call assert_true(v:exception =~ 'E171')
166 Xpath 'x'
167 endtry
168 Xpath 'G'
Bram Moolenaarf4f79b82016-01-25 20:38:30 +0100169 call DeleteTheScript()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100170
171 call assert_equal('abcFhijxG', g:Xpath)
172endfunc
173
174"-------------------------------------------------------------------------------
175" Test 3: :if, :elseif, :while, :continue, :break {{{1
176"-------------------------------------------------------------------------------
177
178function Test_if_while()
179 XpathINIT
180 if 1
181 Xpath 'a'
182 let loops = 3
183 while loops > -1 " main loop: loops == 3, 2, 1 (which breaks)
184 if loops <= 0
185 let break_err = 1
186 let loops = -1
187 else
188 Xpath 'b' . loops
189 endif
190 if (loops == 2)
191 while loops == 2 " dummy loop
192 Xpath 'c' . loops
193 let loops = loops - 1
194 continue " stop dummy loop
195 Xpath 'd' . loops
196 endwhile
197 continue " continue main loop
198 Xpath 'e' . loops
199 elseif (loops == 1)
200 let p = 1
201 while p " dummy loop
202 Xpath 'f' . loops
203 let p = 0
204 break " break dummy loop
205 Xpath 'g' . loops
206 endwhile
207 Xpath 'h' . loops
208 unlet p
209 break " break main loop
210 Xpath 'i' . loops
211 endif
212 if (loops > 0)
213 Xpath 'j' . loops
214 endif
215 while loops == 3 " dummy loop
216 let loops = loops - 1
217 endwhile " end dummy loop
218 endwhile " end main loop
219 Xpath 'k'
220 else
221 Xpath 'l'
222 endif
223 Xpath 'm'
224 if exists("break_err")
225 Xpath 'm'
226 unlet break_err
227 endif
228
229 unlet loops
230
231 call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
232endfunc
233
234"-------------------------------------------------------------------------------
235" Test 4: :return {{{1
236"-------------------------------------------------------------------------------
237
238function! T4_F()
239 if 1
240 Xpath 'a'
241 let loops = 3
242 while loops > 0 " 3: 2: 1:
243 Xpath 'b' . loops
244 if (loops == 2)
245 Xpath 'c' . loops
246 return
247 Xpath 'd' . loops
248 endif
249 Xpath 'e' . loops
250 let loops = loops - 1
251 endwhile
252 Xpath 'f'
253 else
254 Xpath 'g'
255 endif
256endfunction
257
258function Test_return()
259 XpathINIT
260 call T4_F()
261 Xpath '4'
262
263 call assert_equal('ab3e3b2c24', g:Xpath)
264endfunction
265
266
267"-------------------------------------------------------------------------------
268" Test 5: :finish {{{1
269"
270" This test executes the body of the function T4_F from the previous
271" test as a script file (:return replaced by :finish).
272"-------------------------------------------------------------------------------
273
274function Test_finish()
275 XpathINIT
276 ExecAsScript T4_F
277 Xpath '5'
Bram Moolenaarf4f79b82016-01-25 20:38:30 +0100278 call DeleteTheScript()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100279
280 call assert_equal('ab3e3b2c25', g:Xpath)
281endfunction
282
283
284
285"-------------------------------------------------------------------------------
286" Test 6: Defining functions in :while loops {{{1
287"
288" Functions can be defined inside other functions. An inner function
289" gets defined when the outer function is executed. Functions may
290" also be defined inside while loops. Expressions in braces for
291" defining the function name are allowed.
292"
293" The functions are defined when sourcing the script, only the
294" resulting path is checked in the test function.
295"-------------------------------------------------------------------------------
296
297XpathINIT
298
299" The command CALL collects the argument of all its invocations in "calls"
300" when used from a function (that is, when the global variable "calls" needs
301" the "g:" prefix). This is to check that the function code is skipped when
302" the function is defined. For inner functions, do so only if the outer
303" function is not being executed.
304"
305let calls = ""
306com! -nargs=1 CALL
Bram Moolenaar1e115362019-01-09 23:01:02 +0100307 \ if !exists("calls") && !exists("outer") |
308 \ let g:calls = g:calls . <args> |
309 \ endif
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100310
311let i = 0
312while i < 3
313 let i = i + 1
314 if i == 1
315 Xpath 'a'
316 function! F1(arg)
317 CALL a:arg
318 let outer = 1
319
320 let j = 0
321 while j < 1
322 Xpath 'b'
323 let j = j + 1
324 function! G1(arg)
325 CALL a:arg
326 endfunction
327 Xpath 'c'
328 endwhile
329 endfunction
330 Xpath 'd'
331
332 continue
333 endif
334
335 Xpath 'e' . i
336 function! F{i}(i, arg)
337 CALL a:arg
338 let outer = 1
339
340 if a:i == 3
341 Xpath 'f'
342 endif
343 let k = 0
344 while k < 3
345 Xpath 'g' . k
346 let k = k + 1
347 function! G{a:i}{k}(arg)
348 CALL a:arg
349 endfunction
350 Xpath 'h' . k
351 endwhile
352 endfunction
353 Xpath 'i'
354
355endwhile
356
357if exists("*G1")
358 Xpath 'j'
359endif
360if exists("*F1")
361 call F1("F1")
362 if exists("*G1")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100363 call G1("G1")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100364 endif
365endif
366
367if exists("G21") || exists("G22") || exists("G23")
368 Xpath 'k'
369endif
370if exists("*F2")
371 call F2(2, "F2")
372 if exists("*G21")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100373 call G21("G21")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100374 endif
375 if exists("*G22")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100376 call G22("G22")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100377 endif
378 if exists("*G23")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100379 call G23("G23")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100380 endif
381endif
382
383if exists("G31") || exists("G32") || exists("G33")
384 Xpath 'l'
385endif
386if exists("*F3")
387 call F3(3, "F3")
388 if exists("*G31")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100389 call G31("G31")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100390 endif
391 if exists("*G32")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100392 call G32("G32")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100393 endif
394 if exists("*G33")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100395 call G33("G33")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100396 endif
397endif
398
399Xpath 'm'
400
401let g:test6_result = g:Xpath
402let g:test6_calls = calls
403
404unlet calls
405delfunction F1
406delfunction G1
407delfunction F2
408delfunction G21
409delfunction G22
410delfunction G23
411delfunction G31
412delfunction G32
413delfunction G33
414
415function Test_defining_functions()
416 call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
417 call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
418endfunc
419
420"-------------------------------------------------------------------------------
Bram Moolenaara2cce862016-01-02 19:50:04 +0100421" Test 7: Continuing on errors outside functions {{{1
422"
423" On an error outside a function, the script processing continues
424" at the line following the outermost :endif or :endwhile. When not
425" inside an :if or :while, the script processing continues at the next
426" line.
427"-------------------------------------------------------------------------------
428
429XpathINIT
430
431if 1
432 Xpath 'a'
433 while 1
434 Xpath 'b'
435 asdf
436 Xpath 'c'
437 break
438 endwhile | Xpath 'd'
439 Xpath 'e'
440endif | Xpath 'f'
441Xpath 'g'
442
443while 1
444 Xpath 'h'
445 if 1
446 Xpath 'i'
447 asdf
448 Xpath 'j'
449 endif | Xpath 'k'
450 Xpath 'l'
451 break
452endwhile | Xpath 'm'
453Xpath 'n'
454
455asdf
456Xpath 'o'
457
458asdf | Xpath 'p'
459Xpath 'q'
460
461let g:test7_result = g:Xpath
462
463func Test_error_in_script()
464 call assert_equal('abghinoq', g:test7_result)
465endfunc
466
467"-------------------------------------------------------------------------------
468" Test 8: Aborting and continuing on errors inside functions {{{1
469"
470" On an error inside a function without the "abort" attribute, the
471" script processing continues at the next line (unless the error was
472" in a :return command). On an error inside a function with the
473" "abort" attribute, the function is aborted and the script processing
474" continues after the function call; the value -1 is returned then.
475"-------------------------------------------------------------------------------
476
477XpathINIT
478
479function! T8_F()
480 if 1
481 Xpath 'a'
482 while 1
483 Xpath 'b'
484 asdf
485 Xpath 'c'
486 asdf | Xpath 'd'
487 Xpath 'e'
488 break
489 endwhile
490 Xpath 'f'
491 endif | Xpath 'g'
492 Xpath 'h'
493
494 while 1
495 Xpath 'i'
496 if 1
497 Xpath 'j'
498 asdf
499 Xpath 'k'
500 asdf | Xpath 'l'
501 Xpath 'm'
502 endif
503 Xpath 'n'
504 break
505 endwhile | Xpath 'o'
506 Xpath 'p'
507
508 return novar " returns (default return value 0)
509 Xpath 'q'
510 return 1 " not reached
511endfunction
512
513function! T8_G() abort
514 if 1
515 Xpath 'r'
516 while 1
517 Xpath 's'
518 asdf " returns -1
519 Xpath 't'
520 break
521 endwhile
522 Xpath 'v'
523 endif | Xpath 'w'
524 Xpath 'x'
525
526 return -4 " not reached
527endfunction
528
529function! T8_H() abort
530 while 1
531 Xpath 'A'
532 if 1
533 Xpath 'B'
534 asdf " returns -1
535 Xpath 'C'
536 endif
537 Xpath 'D'
538 break
539 endwhile | Xpath 'E'
540 Xpath 'F'
541
542 return -4 " not reached
543endfunction
544
545" Aborted functions (T8_G and T8_H) return -1.
546let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
547Xpath 'X'
548let g:test8_result = g:Xpath
549
550func Test_error_in_function()
551 call assert_equal(13, g:test8_sum)
552 call assert_equal('abcefghijkmnoprsABX', g:test8_result)
553
554 delfunction T8_F
555 delfunction T8_G
556 delfunction T8_H
557endfunc
558
559
560"-------------------------------------------------------------------------------
561" Test 9: Continuing after aborted functions {{{1
562"
563" When a function with the "abort" attribute is aborted due to an
564" error, the next function back in the call hierarchy without an
565" "abort" attribute continues; the value -1 is returned then.
566"-------------------------------------------------------------------------------
567
568XpathINIT
569
570function! F() abort
571 Xpath 'a'
572 let result = G() " not aborted
573 Xpath 'b'
574 if result != 2
575 Xpath 'c'
576 endif
577 return 1
578endfunction
579
580function! G() " no abort attribute
581 Xpath 'd'
582 if H() != -1 " aborted
583 Xpath 'e'
584 endif
585 Xpath 'f'
586 return 2
587endfunction
588
589function! H() abort
590 Xpath 'g'
591 call I() " aborted
592 Xpath 'h'
593 return 4
594endfunction
595
596function! I() abort
597 Xpath 'i'
598 asdf " error
599 Xpath 'j'
600 return 8
601endfunction
602
603if F() != 1
604 Xpath 'k'
605endif
606
607let g:test9_result = g:Xpath
608
609delfunction F
610delfunction G
611delfunction H
612delfunction I
613
614func Test_func_abort()
615 call assert_equal('adgifb', g:test9_result)
616endfunc
617
618
619"-------------------------------------------------------------------------------
620" Test 10: :if, :elseif, :while argument parsing {{{1
621"
622" A '"' or '|' in an argument expression must not be mixed up with
623" a comment or a next command after a bar. Parsing errors should
624" be recognized.
625"-------------------------------------------------------------------------------
626
627XpathINIT
628
629function! MSG(enr, emsg)
630 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
631 if a:enr == ""
632 Xout "TODO: Add message number for:" a:emsg
633 let v:errmsg = ":" . v:errmsg
634 endif
635 let match = 1
636 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
637 let match = 0
638 if v:errmsg == ""
639 Xout "Message missing."
640 else
Bram Moolenaara4208962019-08-24 20:50:19 +0200641 let v:errmsg = v:errmsg->escape('"')
Bram Moolenaara2cce862016-01-02 19:50:04 +0100642 Xout "Unexpected message:" v:errmsg
643 endif
644 endif
645 return match
Bram Moolenaar1e115362019-01-09 23:01:02 +0100646endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100647
648if 1 || strlen("\"") | Xpath 'a'
649 Xpath 'b'
650endif
651Xpath 'c'
652
653if 0
654elseif 1 || strlen("\"") | Xpath 'd'
655 Xpath 'e'
656endif
657Xpath 'f'
658
659while 1 || strlen("\"") | Xpath 'g'
660 Xpath 'h'
661 break
662endwhile
663Xpath 'i'
664
665let v:errmsg = ""
666if 1 ||| strlen("\"") | Xpath 'j'
667 Xpath 'k'
668endif
669Xpath 'l'
670if !MSG('E15', "Invalid expression")
671 Xpath 'm'
672endif
673
674let v:errmsg = ""
675if 0
676elseif 1 ||| strlen("\"") | Xpath 'n'
677 Xpath 'o'
678endif
679Xpath 'p'
680if !MSG('E15', "Invalid expression")
681 Xpath 'q'
682endif
683
684let v:errmsg = ""
685while 1 ||| strlen("\"") | Xpath 'r'
686 Xpath 's'
687 break
688endwhile
689Xpath 't'
690if !MSG('E15', "Invalid expression")
691 Xpath 'u'
692endif
693
694let g:test10_result = g:Xpath
695delfunction MSG
696
697func Test_expr_parsing()
698 call assert_equal('abcdefghilpt', g:test10_result)
699endfunc
700
701
702"-------------------------------------------------------------------------------
703" Test 11: :if, :elseif, :while argument evaluation after abort {{{1
704"
705" When code is skipped over due to an error, the boolean argument to
706" an :if, :elseif, or :while must not be evaluated.
707"-------------------------------------------------------------------------------
708
709XpathINIT
710
711let calls = 0
712
713function! P(num)
714 let g:calls = g:calls + a:num " side effect on call
715 return 0
716endfunction
717
718if 1
719 Xpath 'a'
720 asdf " error
721 Xpath 'b'
722 if P(1) " should not be called
723 Xpath 'c'
724 elseif !P(2) " should not be called
725 Xpath 'd'
726 else
727 Xpath 'e'
728 endif
729 Xpath 'f'
730 while P(4) " should not be called
731 Xpath 'g'
732 endwhile
733 Xpath 'h'
734endif
735Xpath 'x'
736
737let g:test11_calls = calls
738let g:test11_result = g:Xpath
739
740unlet calls
741delfunction P
742
743func Test_arg_abort()
744 call assert_equal(0, g:test11_calls)
745 call assert_equal('ax', g:test11_result)
746endfunc
747
748
749"-------------------------------------------------------------------------------
750" Test 12: Expressions in braces in skipped code {{{1
751"
752" In code skipped over due to an error or inactive conditional,
753" an expression in braces as part of a variable or function name
754" should not be evaluated.
755"-------------------------------------------------------------------------------
756
757XpathINIT
758
759function! NULL()
760 Xpath 'a'
761 return 0
762endfunction
763
764function! ZERO()
765 Xpath 'b'
766 return 0
767endfunction
768
769function! F0()
770 Xpath 'c'
771endfunction
772
773function! F1(arg)
774 Xpath 'e'
775endfunction
776
777let V0 = 1
778
779Xpath 'f'
780echo 0 ? F{NULL() + V{ZERO()}}() : 1
781
782Xpath 'g'
783if 0
784 Xpath 'h'
785 call F{NULL() + V{ZERO()}}()
786endif
787
788Xpath 'i'
789if 1
790 asdf " error
791 Xpath 'j'
792 call F1(F{NULL() + V{ZERO()}}())
793endif
794
795Xpath 'k'
796if 1
797 asdf " error
798 Xpath 'l'
799 call F{NULL() + V{ZERO()}}()
800endif
801
802let g:test12_result = g:Xpath
803
804func Test_braces_skipped()
805 call assert_equal('fgik', g:test12_result)
806endfunc
807
808
809"-------------------------------------------------------------------------------
810" Test 13: Failure in argument evaluation for :while {{{1
811"
812" A failure in the expression evaluation for the condition of a :while
813" causes the whole :while loop until the matching :endwhile being
814" ignored. Continuation is at the next following line.
815"-------------------------------------------------------------------------------
816
817XpathINIT
818
819Xpath 'a'
820while asdf
821 Xpath 'b'
822 while 1
823 Xpath 'c'
824 break
825 endwhile
826 Xpath 'd'
827 break
828endwhile
829Xpath 'e'
830
831while asdf | Xpath 'f' | endwhile | Xpath 'g'
832Xpath 'h'
833let g:test13_result = g:Xpath
834
835func Test_while_fail()
836 call assert_equal('aeh', g:test13_result)
837endfunc
838
839
840"-------------------------------------------------------------------------------
841" Test 14: Failure in argument evaluation for :if {{{1
842"
843" A failure in the expression evaluation for the condition of an :if
844" does not cause the corresponding :else or :endif being matched to
845" a previous :if/:elseif. Neither of both branches of the failed :if
846" are executed.
847"-------------------------------------------------------------------------------
848
849XpathINIT
850
851function! F()
852 Xpath 'a'
853 let x = 0
854 if x " false
855 Xpath 'b'
856 elseif !x " always true
857 Xpath 'c'
858 let x = 1
859 if g:boolvar " possibly undefined
860 Xpath 'd'
861 else
862 Xpath 'e'
863 endif
864 Xpath 'f'
865 elseif x " never executed
866 Xpath 'g'
867 endif
868 Xpath 'h'
869endfunction
870
871let boolvar = 1
872call F()
873Xpath '-'
874
875unlet boolvar
876call F()
877let g:test14_result = g:Xpath
878
879delfunction F
880
881func Test_if_fail()
882 call assert_equal('acdfh-acfh', g:test14_result)
883endfunc
884
885
886"-------------------------------------------------------------------------------
887" Test 15: Failure in argument evaluation for :if (bar) {{{1
888"
889" Like previous test, except that the failing :if ... | ... | :endif
890" is in a single line.
891"-------------------------------------------------------------------------------
892
893XpathINIT
894
895function! F()
896 Xpath 'a'
897 let x = 0
898 if x " false
899 Xpath 'b'
900 elseif !x " always true
901 Xpath 'c'
902 let x = 1
903 if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
904 Xpath 'f'
905 elseif x " never executed
906 Xpath 'g'
907 endif
908 Xpath 'h'
909endfunction
910
911let boolvar = 1
912call F()
913Xpath '-'
914
915unlet boolvar
916call F()
917let g:test15_result = g:Xpath
918
919delfunction F
920
921func Test_if_bar_fail()
922 call assert_equal('acdfh-acfh', g:test15_result)
923endfunc
924
Bram Moolenaar4119cf82016-01-17 14:59:01 +0100925"-------------------------------------------------------------------------------
926" Test 90: Recognizing {} in variable name. {{{1
927"-------------------------------------------------------------------------------
928
929func Test_curlies()
930 let s:var = 66
931 let ns = 's'
932 call assert_equal(66, {ns}:var)
933
934 let g:a = {}
935 let g:b = 't'
936 let g:a[g:b] = 77
937 call assert_equal(77, g:a['t'])
938endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100939
940"-------------------------------------------------------------------------------
Bram Moolenaarf95534c2016-01-23 21:59:52 +0100941" Test 91: using type(). {{{1
942"-------------------------------------------------------------------------------
943
944func Test_type()
945 call assert_equal(0, type(0))
946 call assert_equal(1, type(""))
947 call assert_equal(2, type(function("tr")))
Bram Moolenaar953cc7f2016-03-19 18:52:29 +0100948 call assert_equal(2, type(function("tr", [8])))
Bram Moolenaarf95534c2016-01-23 21:59:52 +0100949 call assert_equal(3, type([]))
950 call assert_equal(4, type({}))
951 call assert_equal(5, type(0.0))
952 call assert_equal(6, type(v:false))
953 call assert_equal(6, type(v:true))
954 call assert_equal(7, type(v:none))
955 call assert_equal(7, type(v:null))
Bram Moolenaarf562e722016-07-19 17:25:25 +0200956 call assert_equal(8, v:t_job)
957 call assert_equal(9, v:t_channel)
958 call assert_equal(v:t_number, type(0))
959 call assert_equal(v:t_string, type(""))
960 call assert_equal(v:t_func, type(function("tr")))
961 call assert_equal(v:t_func, type(function("tr", [8])))
962 call assert_equal(v:t_list, type([]))
963 call assert_equal(v:t_dict, type({}))
964 call assert_equal(v:t_float, type(0.0))
965 call assert_equal(v:t_bool, type(v:false))
966 call assert_equal(v:t_bool, type(v:true))
967 call assert_equal(v:t_none, type(v:none))
968 call assert_equal(v:t_none, type(v:null))
969
Bram Moolenaar17a13432016-01-24 14:22:10 +0100970
971 call assert_equal(0, 0 + v:false)
972 call assert_equal(1, 0 + v:true)
973 call assert_equal(0, 0 + v:none)
974 call assert_equal(0, 0 + v:null)
975
Bram Moolenaarf48aa162016-01-24 17:54:24 +0100976 call assert_equal('v:false', '' . v:false)
977 call assert_equal('v:true', '' . v:true)
978 call assert_equal('v:none', '' . v:none)
979 call assert_equal('v:null', '' . v:null)
Bram Moolenaar6039c7f2016-01-24 15:05:32 +0100980
981 call assert_true(v:false == 0)
982 call assert_false(v:false != 0)
983 call assert_true(v:true == 1)
984 call assert_false(v:true != 1)
985 call assert_false(v:true == v:false)
986 call assert_true(v:true != v:false)
987
988 call assert_true(v:null == 0)
989 call assert_false(v:null != 0)
990 call assert_true(v:none == 0)
991 call assert_false(v:none != 0)
Bram Moolenaar04369222016-01-24 17:21:29 +0100992
993 call assert_true(v:false is v:false)
994 call assert_true(v:true is v:true)
995 call assert_true(v:none is v:none)
996 call assert_true(v:null is v:null)
997
998 call assert_false(v:false isnot v:false)
999 call assert_false(v:true isnot v:true)
1000 call assert_false(v:none isnot v:none)
1001 call assert_false(v:null isnot v:null)
1002
1003 call assert_false(v:false is 0)
1004 call assert_false(v:true is 1)
1005 call assert_false(v:true is v:false)
1006 call assert_false(v:none is 0)
1007 call assert_false(v:null is 0)
1008 call assert_false(v:null is v:none)
1009
1010 call assert_true(v:false isnot 0)
1011 call assert_true(v:true isnot 1)
1012 call assert_true(v:true isnot v:false)
1013 call assert_true(v:none isnot 0)
1014 call assert_true(v:null isnot 0)
1015 call assert_true(v:null isnot v:none)
Bram Moolenaar65591002016-01-24 21:51:57 +01001016
1017 call assert_equal(v:false, eval(string(v:false)))
1018 call assert_equal(v:true, eval(string(v:true)))
1019 call assert_equal(v:none, eval(string(v:none)))
1020 call assert_equal(v:null, eval(string(v:null)))
Bram Moolenaar767d8c12016-01-25 20:22:54 +01001021
Bram Moolenaar15550002016-01-31 18:45:24 +01001022 call assert_equal(v:false, copy(v:false))
1023 call assert_equal(v:true, copy(v:true))
1024 call assert_equal(v:none, copy(v:none))
1025 call assert_equal(v:null, copy(v:null))
1026
1027 call assert_equal([v:false], deepcopy([v:false]))
1028 call assert_equal([v:true], deepcopy([v:true]))
1029 call assert_equal([v:none], deepcopy([v:none]))
1030 call assert_equal([v:null], deepcopy([v:null]))
1031
Bram Moolenaar767d8c12016-01-25 20:22:54 +01001032 call assert_true(empty(v:false))
1033 call assert_false(empty(v:true))
1034 call assert_true(empty(v:null))
1035 call assert_true(empty(v:none))
Bram Moolenaar6650a692016-01-26 19:59:10 +01001036
1037 func ChangeYourMind()
Bram Moolenaar1e115362019-01-09 23:01:02 +01001038 try
1039 return v:true
1040 finally
1041 return 'something else'
1042 endtry
Bram Moolenaar6650a692016-01-26 19:59:10 +01001043 endfunc
1044
1045 call ChangeYourMind()
Bram Moolenaarf95534c2016-01-23 21:59:52 +01001046endfunc
1047
1048"-------------------------------------------------------------------------------
Bram Moolenaarea8c2192016-02-07 19:27:53 +01001049" Test 92: skipping code {{{1
1050"-------------------------------------------------------------------------------
1051
1052func Test_skip()
1053 let Fn = function('Test_type')
1054 call assert_false(0 && Fn[1])
1055 call assert_false(0 && string(Fn))
1056 call assert_false(0 && len(Fn))
1057 let l = []
1058 call assert_false(0 && l[1])
1059 call assert_false(0 && string(l))
1060 call assert_false(0 && len(l))
1061 let f = 1.0
1062 call assert_false(0 && f[1])
1063 call assert_false(0 && string(f))
1064 call assert_false(0 && len(f))
1065 let sp = v:null
1066 call assert_false(0 && sp[1])
1067 call assert_false(0 && string(sp))
1068 call assert_false(0 && len(sp))
1069
1070endfunc
1071
1072"-------------------------------------------------------------------------------
Bram Moolenaar18dfb442016-05-31 22:31:23 +02001073" Test 93: :echo and string() {{{1
1074"-------------------------------------------------------------------------------
1075
1076func Test_echo_and_string()
1077 " String
1078 let a = 'foo bar'
1079 redir => result
1080 echo a
1081 echo string(a)
1082 redir END
1083 let l = split(result, "\n")
1084 call assert_equal(["foo bar",
1085 \ "'foo bar'"], l)
1086
1087 " Float
1088 if has('float')
1089 let a = -1.2e0
1090 redir => result
1091 echo a
1092 echo string(a)
1093 redir END
1094 let l = split(result, "\n")
1095 call assert_equal(["-1.2",
1096 \ "-1.2"], l)
1097 endif
1098
1099 " Funcref
1100 redir => result
1101 echo function('string')
1102 echo string(function('string'))
1103 redir END
1104 let l = split(result, "\n")
1105 call assert_equal(["string",
1106 \ "function('string')"], l)
1107
1108 " Recursive dictionary
1109 let a = {}
1110 let a["a"] = a
1111 redir => result
1112 echo a
1113 echo string(a)
1114 redir END
1115 let l = split(result, "\n")
1116 call assert_equal(["{'a': {...}}",
1117 \ "{'a': {...}}"], l)
1118
1119 " Recursive list
1120 let a = [0]
1121 let a[0] = a
1122 redir => result
1123 echo a
1124 echo string(a)
1125 redir END
1126 let l = split(result, "\n")
1127 call assert_equal(["[[...]]",
1128 \ "[[...]]"], l)
1129
1130 " Empty dictionaries in a list
1131 let a = {}
1132 redir => result
1133 echo [a, a, a]
1134 echo string([a, a, a])
1135 redir END
1136 let l = split(result, "\n")
1137 call assert_equal(["[{}, {}, {}]",
1138 \ "[{}, {}, {}]"], l)
1139
1140 " Empty dictionaries in a dictionary
1141 let a = {}
1142 let b = {"a": a, "b": a}
1143 redir => result
1144 echo b
1145 echo string(b)
1146 redir END
1147 let l = split(result, "\n")
1148 call assert_equal(["{'a': {}, 'b': {}}",
1149 \ "{'a': {}, 'b': {}}"], l)
1150
1151 " Empty lists in a list
1152 let a = []
1153 redir => result
1154 echo [a, a, a]
1155 echo string([a, a, a])
1156 redir END
1157 let l = split(result, "\n")
1158 call assert_equal(["[[], [], []]",
1159 \ "[[], [], []]"], l)
1160
1161 " Empty lists in a dictionary
1162 let a = []
1163 let b = {"a": a, "b": a}
1164 redir => result
1165 echo b
1166 echo string(b)
1167 redir END
1168 let l = split(result, "\n")
1169 call assert_equal(["{'a': [], 'b': []}",
1170 \ "{'a': [], 'b': []}"], l)
1171
1172 " Dictionaries in a list
1173 let a = {"one": "yes", "two": "yes", "three": "yes"}
1174 redir => result
1175 echo [a, a, a]
1176 echo string([a, a, a])
1177 redir END
1178 let l = split(result, "\n")
1179 call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
1180 \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
1181
1182 " Dictionaries in a dictionary
1183 let a = {"one": "yes", "two": "yes", "three": "yes"}
1184 let b = {"a": a, "b": a}
1185 redir => result
1186 echo b
1187 echo string(b)
1188 redir END
1189 let l = split(result, "\n")
1190 call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
1191 \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
1192
1193 " Lists in a list
1194 let a = [1, 2, 3]
1195 redir => result
1196 echo [a, a, a]
1197 echo string([a, a, a])
1198 redir END
1199 let l = split(result, "\n")
1200 call assert_equal(["[[1, 2, 3], [...], [...]]",
1201 \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
1202
1203 " Lists in a dictionary
1204 let a = [1, 2, 3]
1205 let b = {"a": a, "b": a}
1206 redir => result
1207 echo b
1208 echo string(b)
1209 redir END
1210 let l = split(result, "\n")
1211 call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
1212 \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
1213
1214endfunc
1215
1216"-------------------------------------------------------------------------------
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001217" Test 94: 64-bit Numbers {{{1
1218"-------------------------------------------------------------------------------
1219
1220func Test_num64()
1221 if !has('num64')
1222 return
1223 endif
1224
1225 call assert_notequal( 4294967296, 0)
1226 call assert_notequal(-4294967296, 0)
1227 call assert_equal( 4294967296, 0xFFFFffff + 1)
1228 call assert_equal(-4294967296, -0xFFFFffff - 1)
1229
1230 call assert_equal( 9223372036854775807, 1 / 0)
1231 call assert_equal(-9223372036854775807, -1 / 0)
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001232 call assert_equal(-9223372036854775807 - 1, 0 / 0)
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001233
1234 call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
1235 call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
1236
1237 let rng = range(0xFFFFffff, 0x100000001)
1238 call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
1239 call assert_equal(0x100000001, max(rng))
1240 call assert_equal(0xFFFFffff, min(rng))
1241 call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
1242endfunc
1243
1244"-------------------------------------------------------------------------------
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001245" Test 95: lines of :append, :change, :insert {{{1
1246"-------------------------------------------------------------------------------
1247
1248function! DefineFunction(name, body)
1249 let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
1250 exec func
1251endfunction
1252
1253func Test_script_lines()
1254 " :append
1255 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01001256 call DefineFunction('T_Append', [
1257 \ 'append',
1258 \ 'py <<EOS',
1259 \ '.',
1260 \ ])
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001261 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01001262 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001263 endtry
1264 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01001265 call DefineFunction('T_Append', [
1266 \ 'append',
1267 \ 'abc',
1268 \ ])
1269 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001270 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01001271 call assert_exception('Vim(function):E126: Missing :endfunction')
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001272 endtry
1273
1274 " :change
1275 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01001276 call DefineFunction('T_Change', [
1277 \ 'change',
1278 \ 'py <<EOS',
1279 \ '.',
1280 \ ])
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001281 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01001282 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001283 endtry
1284 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01001285 call DefineFunction('T_Change', [
1286 \ 'change',
1287 \ 'abc',
1288 \ ])
1289 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001290 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01001291 call assert_exception('Vim(function):E126: Missing :endfunction')
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001292 endtry
1293
1294 " :insert
1295 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01001296 call DefineFunction('T_Insert', [
1297 \ 'insert',
1298 \ 'py <<EOS',
1299 \ '.',
1300 \ ])
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001301 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01001302 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001303 endtry
1304 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01001305 call DefineFunction('T_Insert', [
1306 \ 'insert',
1307 \ 'abc',
1308 \ ])
1309 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001310 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01001311 call assert_exception('Vim(function):E126: Missing :endfunction')
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001312 endtry
1313endfunc
1314
1315"-------------------------------------------------------------------------------
Bram Moolenaar478af672017-04-10 22:22:42 +02001316" Test 96: line continuation {{{1
1317"
Bram Moolenaar1e115362019-01-09 23:01:02 +01001318" Undefined behavior was detected by ubsan with line continuation
1319" after an empty line.
Bram Moolenaar478af672017-04-10 22:22:42 +02001320"-------------------------------------------------------------------------------
1321func Test_script_emty_line_continuation()
1322
1323 \
1324endfunc
1325
1326"-------------------------------------------------------------------------------
Bram Moolenaar863e80b2017-06-04 20:30:00 +02001327" Test 97: bitwise functions {{{1
1328"-------------------------------------------------------------------------------
1329func Test_bitwise_functions()
1330 " and
1331 call assert_equal(127, and(127, 127))
1332 call assert_equal(16, and(127, 16))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02001333 eval 127->and(16)->assert_equal(16)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02001334 call assert_equal(0, and(127, 128))
1335 call assert_fails("call and(1.0, 1)", 'E805:')
1336 call assert_fails("call and([], 1)", 'E745:')
1337 call assert_fails("call and({}, 1)", 'E728:')
1338 call assert_fails("call and(1, 1.0)", 'E805:')
1339 call assert_fails("call and(1, [])", 'E745:')
1340 call assert_fails("call and(1, {})", 'E728:')
1341 " or
1342 call assert_equal(23, or(16, 7))
1343 call assert_equal(15, or(8, 7))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02001344 eval 8->or(7)->assert_equal(15)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02001345 call assert_equal(123, or(0, 123))
1346 call assert_fails("call or(1.0, 1)", 'E805:')
1347 call assert_fails("call or([], 1)", 'E745:')
1348 call assert_fails("call or({}, 1)", 'E728:')
1349 call assert_fails("call or(1, 1.0)", 'E805:')
1350 call assert_fails("call or(1, [])", 'E745:')
1351 call assert_fails("call or(1, {})", 'E728:')
1352 " xor
1353 call assert_equal(0, xor(127, 127))
1354 call assert_equal(111, xor(127, 16))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02001355 eval 127->xor(16)->assert_equal(111)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02001356 call assert_equal(255, xor(127, 128))
1357 call assert_fails("call xor(1.0, 1)", 'E805:')
1358 call assert_fails("call xor([], 1)", 'E745:')
1359 call assert_fails("call xor({}, 1)", 'E728:')
1360 call assert_fails("call xor(1, 1.0)", 'E805:')
1361 call assert_fails("call xor(1, [])", 'E745:')
1362 call assert_fails("call xor(1, {})", 'E728:')
1363 " invert
1364 call assert_equal(65408, and(invert(127), 65535))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02001365 eval 127->invert()->and(65535)->assert_equal(65408)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02001366 call assert_equal(65519, and(invert(16), 65535))
1367 call assert_equal(65407, and(invert(128), 65535))
1368 call assert_fails("call invert(1.0)", 'E805:')
1369 call assert_fails("call invert([])", 'E745:')
1370 call assert_fails("call invert({})", 'E728:')
1371endfunc
1372
Bram Moolenaar663bb232017-06-22 19:12:10 +02001373" Test trailing text after :endfunction {{{1
1374func Test_endfunction_trailing()
1375 call assert_false(exists('*Xtest'))
1376
1377 exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'"
1378 call assert_true(exists('*Xtest'))
1379 call assert_equal('yes', done)
1380 delfunc Xtest
1381 unlet done
1382
1383 exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'"
1384 call assert_true(exists('*Xtest'))
1385 call assert_equal('yes', done)
1386 delfunc Xtest
1387 unlet done
1388
Bram Moolenaar53564f72017-06-24 14:48:11 +02001389 " trailing line break
1390 exe "func Xtest()\necho 'hello'\nendfunc\n"
1391 call assert_true(exists('*Xtest'))
1392 delfunc Xtest
1393
Bram Moolenaar663bb232017-06-22 19:12:10 +02001394 set verbose=1
1395 exe "func Xtest()\necho 'hello'\nendfunc \" garbage"
Bram Moolenaarf8be4612017-06-23 20:52:40 +02001396 call assert_notmatch('W22:', split(execute('1messages'), "\n")[0])
Bram Moolenaar663bb232017-06-22 19:12:10 +02001397 call assert_true(exists('*Xtest'))
1398 delfunc Xtest
1399
Bram Moolenaarf8be4612017-06-23 20:52:40 +02001400 exe "func Xtest()\necho 'hello'\nendfunc garbage"
1401 call assert_match('W22:', split(execute('1messages'), "\n")[0])
Bram Moolenaar663bb232017-06-22 19:12:10 +02001402 call assert_true(exists('*Xtest'))
1403 delfunc Xtest
1404 set verbose=0
Bram Moolenaar53564f72017-06-24 14:48:11 +02001405
1406 function Foo()
1407 echo 'hello'
1408 endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
1409 delfunc Foo
Bram Moolenaar663bb232017-06-22 19:12:10 +02001410endfunc
1411
Bram Moolenaard6abcd12017-06-22 19:15:24 +02001412func Test_delfunction_force()
1413 delfunc! Xtest
1414 delfunc! Xtest
1415 func Xtest()
1416 echo 'nothing'
1417 endfunc
1418 delfunc! Xtest
1419 delfunc! Xtest
1420endfunc
1421
Bram Moolenaar6f9a4762017-06-22 20:39:17 +02001422" Test using bang after user command {{{1
1423func Test_user_command_with_bang()
1424 command -bang Nieuw let nieuw = 1
1425 Ni!
1426 call assert_equal(1, nieuw)
1427 unlet nieuw
1428 delcommand Nieuw
1429endfunc
1430
Bram Moolenaarbb3e6412017-09-23 19:24:46 +02001431" Test for script-local function
1432func <SID>DoLast()
1433 call append(line('$'), "last line")
1434endfunc
1435
1436func s:DoNothing()
1437 call append(line('$'), "nothing line")
1438endfunc
1439
1440func Test_script_local_func()
1441 set nocp viminfo+=nviminfo
1442 new
1443 nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
1444
1445 normal _x
1446 call assert_equal('nothing line', getline(2))
1447 call assert_equal('last line', getline(3))
1448 enew! | close
1449endfunc
1450
Bram Moolenaarff697e62019-02-12 22:28:33 +01001451func Test_compound_assignment_operators()
1452 " Test for number
1453 let x = 1
1454 let x += 10
1455 call assert_equal(11, x)
1456 let x -= 5
1457 call assert_equal(6, x)
1458 let x *= 4
1459 call assert_equal(24, x)
1460 let x /= 3
1461 call assert_equal(8, x)
1462 let x %= 3
1463 call assert_equal(2, x)
1464 let x .= 'n'
1465 call assert_equal('2n', x)
1466
Bram Moolenaare21c1582019-03-02 11:57:09 +01001467 " Test special cases: division or modulus with 0.
1468 let x = 1
1469 let x /= 0
1470 if has('num64')
1471 call assert_equal(0x7FFFFFFFFFFFFFFF, x)
1472 else
1473 call assert_equal(0x7fffffff, x)
1474 endif
1475
1476 let x = -1
1477 let x /= 0
1478 if has('num64')
1479 call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
1480 else
1481 call assert_equal(-0x7fffffff, x)
1482 endif
1483
1484 let x = 0
1485 let x /= 0
1486 if has('num64')
1487 call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
1488 else
1489 call assert_equal(-0x7FFFFFFF - 1, x)
1490 endif
1491
1492 let x = 1
1493 let x %= 0
1494 call assert_equal(0, x)
1495
1496 let x = -1
1497 let x %= 0
1498 call assert_equal(0, x)
1499
1500 let x = 0
1501 let x %= 0
1502 call assert_equal(0, x)
1503
Bram Moolenaarff697e62019-02-12 22:28:33 +01001504 " Test for string
1505 let x = 'str'
1506 let x .= 'ing'
1507 call assert_equal('string', x)
1508 let x += 1
1509 call assert_equal(1, x)
1510 let x -= 1.5
1511 call assert_equal(-0.5, x)
1512
1513 if has('float')
1514 " Test for float
1515 let x = 0.5
1516 let x += 4.5
1517 call assert_equal(5.0, x)
1518 let x -= 1.5
1519 call assert_equal(3.5, x)
1520 let x *= 3.0
1521 call assert_equal(10.5, x)
1522 let x /= 2.5
1523 call assert_equal(4.2, x)
1524 call assert_fails('let x %= 0.5', 'E734')
1525 call assert_fails('let x .= "f"', 'E734')
1526 endif
1527
1528 " Test for environment variable
1529 let $FOO = 1
1530 call assert_fails('let $FOO += 1', 'E734')
1531 call assert_fails('let $FOO -= 1', 'E734')
1532 call assert_fails('let $FOO *= 1', 'E734')
1533 call assert_fails('let $FOO /= 1', 'E734')
1534 call assert_fails('let $FOO %= 1', 'E734')
1535 let $FOO .= 's'
1536 call assert_equal('1s', $FOO)
1537 unlet $FOO
1538
1539 " Test for option variable (type: number)
1540 let &scrolljump = 1
1541 let &scrolljump += 5
1542 call assert_equal(6, &scrolljump)
1543 let &scrolljump -= 2
1544 call assert_equal(4, &scrolljump)
1545 let &scrolljump *= 3
1546 call assert_equal(12, &scrolljump)
1547 let &scrolljump /= 2
1548 call assert_equal(6, &scrolljump)
1549 let &scrolljump %= 5
1550 call assert_equal(1, &scrolljump)
1551 call assert_fails('let &scrolljump .= "j"', 'E734')
1552 set scrolljump&vim
1553
1554 " Test for register
1555 let @/ = 1
1556 call assert_fails('let @/ += 1', 'E734')
1557 call assert_fails('let @/ -= 1', 'E734')
1558 call assert_fails('let @/ *= 1', 'E734')
1559 call assert_fails('let @/ /= 1', 'E734')
1560 call assert_fails('let @/ %= 1', 'E734')
1561 let @/ .= 's'
1562 call assert_equal('1s', @/)
1563 let @/ = ''
1564endfunc
1565
Bram Moolenaarc3e92c12019-03-23 14:23:07 +01001566func Test_refcount()
1567 " Immediate values
1568 call assert_equal(-1, test_refcount(1))
1569 call assert_equal(-1, test_refcount('s'))
1570 call assert_equal(-1, test_refcount(v:true))
1571 call assert_equal(0, test_refcount([]))
1572 call assert_equal(0, test_refcount({}))
1573 call assert_equal(0, test_refcount(0zff))
1574 call assert_equal(0, test_refcount({-> line('.')}))
1575 if has('float')
1576 call assert_equal(-1, test_refcount(0.1))
1577 endif
1578 if has('job')
1579 call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
1580 endif
1581
1582 " No refcount types
1583 let x = 1
1584 call assert_equal(-1, test_refcount(x))
1585 let x = 's'
1586 call assert_equal(-1, test_refcount(x))
1587 let x = v:true
1588 call assert_equal(-1, test_refcount(x))
1589 if has('float')
1590 let x = 0.1
1591 call assert_equal(-1, test_refcount(x))
1592 endif
1593
1594 " Check refcount
1595 let x = []
1596 call assert_equal(1, test_refcount(x))
1597
1598 let x = {}
Bram Moolenaarce90e362019-09-08 18:58:44 +02001599 call assert_equal(1, x->test_refcount())
Bram Moolenaarc3e92c12019-03-23 14:23:07 +01001600
1601 let x = 0zff
1602 call assert_equal(1, test_refcount(x))
1603
1604 let X = {-> line('.')}
1605 call assert_equal(1, test_refcount(X))
1606 let Y = X
1607 call assert_equal(2, test_refcount(X))
1608
1609 if has('job')
1610 let job = job_start([&shell, &shellcmdflag, 'echo .'])
1611 call assert_equal(1, test_refcount(job))
1612 call assert_equal(1, test_refcount(job_getchannel(job)))
1613 call assert_equal(1, test_refcount(job))
1614 endif
1615
1616 " Function arguments, copying and unassigning
1617 func ExprCheck(x, i)
1618 let i = a:i + 1
1619 call assert_equal(i, test_refcount(a:x))
1620 let Y = a:x
1621 call assert_equal(i + 1, test_refcount(a:x))
1622 call assert_equal(test_refcount(a:x), test_refcount(Y))
1623 let Y = 0
1624 call assert_equal(i, test_refcount(a:x))
1625 endfunc
1626 call ExprCheck([], 0)
1627 call ExprCheck({}, 0)
1628 call ExprCheck(0zff, 0)
1629 call ExprCheck({-> line('.')}, 0)
1630 if has('job')
1631 call ExprCheck(job, 1)
1632 call ExprCheck(job_getchannel(job), 1)
1633 call job_stop(job)
1634 endif
1635 delfunc ExprCheck
1636
1637 " Regarding function
1638 func Func(x) abort
1639 call assert_equal(2, test_refcount(function('Func')))
1640 call assert_equal(0, test_refcount(funcref('Func')))
1641 endfunc
1642 call assert_equal(1, test_refcount(function('Func')))
1643 call assert_equal(0, test_refcount(function('Func', [1])))
1644 call assert_equal(0, test_refcount(funcref('Func')))
1645 call assert_equal(0, test_refcount(funcref('Func', [1])))
1646 let X = function('Func')
1647 let Y = X
1648 call assert_equal(1, test_refcount(X))
1649 let X = function('Func', [1])
1650 let Y = X
1651 call assert_equal(2, test_refcount(X))
1652 let X = funcref('Func')
1653 let Y = X
1654 call assert_equal(2, test_refcount(X))
1655 let X = funcref('Func', [1])
1656 let Y = X
1657 call assert_equal(2, test_refcount(X))
1658 unlet X
1659 unlet Y
1660 call Func(1)
1661 delfunc Func
1662
1663 " Function with dict
1664 func DictFunc() dict
1665 call assert_equal(3, test_refcount(self))
1666 endfunc
1667 let d = {'Func': function('DictFunc')}
1668 call assert_equal(1, test_refcount(d))
1669 call assert_equal(0, test_refcount(d.Func))
1670 call d.Func()
1671 unlet d
1672 delfunc DictFunc
1673endfunc
1674
Bram Moolenaar7d491c42019-06-25 06:28:02 +02001675func Test_funccall_garbage_collect()
Bram Moolenaar6e5000d2019-06-17 21:18:41 +02001676 func Func(x, ...)
1677 call add(a:x, a:000)
1678 endfunc
1679 call Func([], [])
1680 " Must not crash cause by invalid freeing
1681 call test_garbagecollect_now()
1682 call assert_true(v:true)
1683 delfunc Func
1684endfunc
1685
Bram Moolenaarbc2cfe42019-07-04 14:57:12 +02001686func Test_function_defined_line()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02001687 CheckNotGui
Bram Moolenaarbc2cfe42019-07-04 14:57:12 +02001688
1689 let lines =<< trim [CODE]
1690 " F1
1691 func F1()
1692 " F2
1693 func F2()
1694 "
1695 "
1696 "
1697 return
1698 endfunc
1699 " F3
1700 execute "func F3()\n\n\n\nreturn\nendfunc"
1701 " F4
1702 execute "func F4()\n
1703 \\n
1704 \\n
1705 \\n
1706 \return\n
1707 \endfunc"
1708 endfunc
1709 " F5
1710 execute "func F5()\n\n\n\nreturn\nendfunc"
1711 " F6
1712 execute "func F6()\n
1713 \\n
1714 \\n
1715 \\n
1716 \return\n
1717 \endfunc"
1718 call F1()
1719 verbose func F1
1720 verbose func F2
1721 verbose func F3
1722 verbose func F4
1723 verbose func F5
1724 verbose func F6
1725 qall!
1726 [CODE]
1727
1728 call writefile(lines, 'Xtest.vim')
Bram Moolenaar93344c22019-08-14 21:12:05 +02001729 let res = system(GetVimCommandClean() .. ' -es -X -S Xtest.vim')
Bram Moolenaarbc2cfe42019-07-04 14:57:12 +02001730 call assert_equal(0, v:shell_error)
1731
1732 let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*')
1733 call assert_match(' line 2$', m)
1734
1735 let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*')
1736 call assert_match(' line 4$', m)
1737
1738 let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*')
1739 call assert_match(' line 11$', m)
1740
1741 let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*')
1742 call assert_match(' line 13$', m)
1743
1744 let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*')
1745 call assert_match(' line 21$', m)
1746
1747 let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*')
1748 call assert_match(' line 23$', m)
1749
1750 call delete('Xtest.vim')
1751endfunc
1752
Bram Moolenaar863e80b2017-06-04 20:30:00 +02001753"-------------------------------------------------------------------------------
Bram Moolenaarf49e2402015-12-30 15:59:25 +01001754" Modelines {{{1
1755" vim: ts=8 sw=4 tw=80 fdm=marker
Bram Moolenaarf49e2402015-12-30 15:59:25 +01001756"-------------------------------------------------------------------------------