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