blob: c09e2343b6b00110593cb849e61d2d8a3f12f1a8 [file] [log] [blame]
Bram Moolenaarf49e2402015-12-30 15:59:25 +01001" Test various aspects of the Vim language.
Bram Moolenaar4119cf82016-01-17 14:59:01 +01002" Most of this was formerly in test49.
Bram Moolenaarf49e2402015-12-30 15:59:25 +01003
4"-------------------------------------------------------------------------------
5" Test environment {{{1
6"-------------------------------------------------------------------------------
7
8com! XpathINIT let g:Xpath = ''
9com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . <args>
10
11" Append a message to the "messages" file
12func! Xout(text)
13 split messages
14 $put =a:text
15 wq
16endfunc
17
18com! -nargs=1 Xout call Xout(<args>)
19
20" MakeScript() - Make a script file from a function. {{{2
21"
22" Create a script that consists of the body of the function a:funcname.
23" Replace any ":return" by a ":finish", any argument variable by a global
24" variable, and and every ":call" by a ":source" for the next following argument
25" in the variable argument list. This function is useful if similar tests are
26" to be made for a ":return" from a function call or a ":finish" in a script
27" file.
28function! MakeScript(funcname, ...)
29 let script = tempname()
30 execute "redir! >" . script
31 execute "function" a:funcname
32 redir END
33 execute "edit" script
34 " Delete the "function" and the "endfunction" lines. Do not include the
35 " word "function" in the pattern since it might be translated if LANG is
36 " set. When MakeScript() is being debugged, this deletes also the debugging
37 " output of its line 3 and 4.
38 exec '1,/.*' . a:funcname . '(.*)/d'
39 /^\d*\s*endfunction\>/,$d
40 %s/^\d*//e
41 %s/return/finish/e
42 %s/\<a:\(\h\w*\)/g:\1/ge
43 normal gg0
44 let cnt = 0
45 while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
46 let cnt = cnt + 1
47 s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
48 endwhile
49 g/^\s*$/d
50 write
51 bwipeout
52 return script
53endfunction
54
55" ExecAsScript - Source a temporary script made from a function. {{{2
56"
57" Make a temporary script file from the function a:funcname, ":source" it, and
Bram Moolenaarf4f79b82016-01-25 20:38:30 +010058" delete it afterwards. However, if an exception is thrown the file may remain,
59" the caller should call DeleteTheScript() afterwards.
60let s:script_name = ''
Bram Moolenaarf49e2402015-12-30 15:59:25 +010061function! ExecAsScript(funcname)
62 " Make a script from the function passed as argument.
Bram Moolenaarf4f79b82016-01-25 20:38:30 +010063 let s:script_name = MakeScript(a:funcname)
Bram Moolenaarf49e2402015-12-30 15:59:25 +010064
65 " Source and delete the script.
Bram Moolenaarf4f79b82016-01-25 20:38:30 +010066 exec "source" s:script_name
67 call delete(s:script_name)
68 let s:script_name = ''
Bram Moolenaarf49e2402015-12-30 15:59:25 +010069endfunction
70
Bram Moolenaarf4f79b82016-01-25 20:38:30 +010071function! DeleteTheScript()
72 if s:script_name
73 call delete(s:script_name)
74 let s:script_name = ''
75 endif
76endfunc
77
Bram Moolenaarf49e2402015-12-30 15:59:25 +010078com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
79
80
81"-------------------------------------------------------------------------------
82" Test 1: :endwhile in function {{{1
83"
84" Detect if a broken loop is (incorrectly) reactivated by the
85" :endwhile. Use a :return to prevent an endless loop, and make
86" this test first to get a meaningful result on an error before other
87" tests will hang.
88"-------------------------------------------------------------------------------
89
90function! T1_F()
91 Xpath 'a'
92 let first = 1
93 while 1
94 Xpath 'b'
95 if first
96 Xpath 'c'
97 let first = 0
98 break
99 else
100 Xpath 'd'
101 return
102 endif
103 endwhile
104endfunction
105
106function! T1_G()
107 Xpath 'h'
108 let first = 1
109 while 1
110 Xpath 'i'
111 if first
112 Xpath 'j'
113 let first = 0
114 break
115 else
116 Xpath 'k'
117 return
118 endif
119 if 1 " unmatched :if
120 endwhile
121endfunction
122
123func Test_endwhile_function()
124 XpathINIT
125 call T1_F()
126 Xpath 'F'
127
128 try
129 call T1_G()
130 catch
131 " Catch missing :endif
132 call assert_true(v:exception =~ 'E171')
133 Xpath 'x'
134 endtry
135 Xpath 'G'
136
137 call assert_equal('abcFhijxG', g:Xpath)
138endfunc
139
140"-------------------------------------------------------------------------------
141" Test 2: :endwhile in script {{{1
142"
143" Detect if a broken loop is (incorrectly) reactivated by the
144" :endwhile. Use a :finish to prevent an endless loop, and place
145" this test before others that might hang to get a meaningful result
146" on an error.
147"
148" This test executes the bodies of the functions T1_F and T1_G from
149" the previous test as script files (:return replaced by :finish).
150"-------------------------------------------------------------------------------
151
152func Test_endwhile_script()
153 XpathINIT
154 ExecAsScript T1_F
155 Xpath 'F'
Bram Moolenaarf4f79b82016-01-25 20:38:30 +0100156 call DeleteTheScript()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100157
158 try
159 ExecAsScript T1_G
160 catch
161 " Catch missing :endif
162 call assert_true(v:exception =~ 'E171')
163 Xpath 'x'
164 endtry
165 Xpath 'G'
Bram Moolenaarf4f79b82016-01-25 20:38:30 +0100166 call DeleteTheScript()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100167
168 call assert_equal('abcFhijxG', g:Xpath)
169endfunc
170
171"-------------------------------------------------------------------------------
172" Test 3: :if, :elseif, :while, :continue, :break {{{1
173"-------------------------------------------------------------------------------
174
175function Test_if_while()
176 XpathINIT
177 if 1
178 Xpath 'a'
179 let loops = 3
180 while loops > -1 " main loop: loops == 3, 2, 1 (which breaks)
181 if loops <= 0
182 let break_err = 1
183 let loops = -1
184 else
185 Xpath 'b' . loops
186 endif
187 if (loops == 2)
188 while loops == 2 " dummy loop
189 Xpath 'c' . loops
190 let loops = loops - 1
191 continue " stop dummy loop
192 Xpath 'd' . loops
193 endwhile
194 continue " continue main loop
195 Xpath 'e' . loops
196 elseif (loops == 1)
197 let p = 1
198 while p " dummy loop
199 Xpath 'f' . loops
200 let p = 0
201 break " break dummy loop
202 Xpath 'g' . loops
203 endwhile
204 Xpath 'h' . loops
205 unlet p
206 break " break main loop
207 Xpath 'i' . loops
208 endif
209 if (loops > 0)
210 Xpath 'j' . loops
211 endif
212 while loops == 3 " dummy loop
213 let loops = loops - 1
214 endwhile " end dummy loop
215 endwhile " end main loop
216 Xpath 'k'
217 else
218 Xpath 'l'
219 endif
220 Xpath 'm'
221 if exists("break_err")
222 Xpath 'm'
223 unlet break_err
224 endif
225
226 unlet loops
227
228 call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
229endfunc
230
231"-------------------------------------------------------------------------------
232" Test 4: :return {{{1
233"-------------------------------------------------------------------------------
234
235function! T4_F()
236 if 1
237 Xpath 'a'
238 let loops = 3
239 while loops > 0 " 3: 2: 1:
240 Xpath 'b' . loops
241 if (loops == 2)
242 Xpath 'c' . loops
243 return
244 Xpath 'd' . loops
245 endif
246 Xpath 'e' . loops
247 let loops = loops - 1
248 endwhile
249 Xpath 'f'
250 else
251 Xpath 'g'
252 endif
253endfunction
254
255function Test_return()
256 XpathINIT
257 call T4_F()
258 Xpath '4'
259
260 call assert_equal('ab3e3b2c24', g:Xpath)
261endfunction
262
263
264"-------------------------------------------------------------------------------
265" Test 5: :finish {{{1
266"
267" This test executes the body of the function T4_F from the previous
268" test as a script file (:return replaced by :finish).
269"-------------------------------------------------------------------------------
270
271function Test_finish()
272 XpathINIT
273 ExecAsScript T4_F
274 Xpath '5'
Bram Moolenaarf4f79b82016-01-25 20:38:30 +0100275 call DeleteTheScript()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100276
277 call assert_equal('ab3e3b2c25', g:Xpath)
278endfunction
279
280
281
282"-------------------------------------------------------------------------------
283" Test 6: Defining functions in :while loops {{{1
284"
285" Functions can be defined inside other functions. An inner function
286" gets defined when the outer function is executed. Functions may
287" also be defined inside while loops. Expressions in braces for
288" defining the function name are allowed.
289"
290" The functions are defined when sourcing the script, only the
291" resulting path is checked in the test function.
292"-------------------------------------------------------------------------------
293
294XpathINIT
295
296" The command CALL collects the argument of all its invocations in "calls"
297" when used from a function (that is, when the global variable "calls" needs
298" the "g:" prefix). This is to check that the function code is skipped when
299" the function is defined. For inner functions, do so only if the outer
300" function is not being executed.
301"
302let calls = ""
303com! -nargs=1 CALL
304 \ if !exists("calls") && !exists("outer") |
305 \ let g:calls = g:calls . <args> |
306 \ endif
307
308let i = 0
309while i < 3
310 let i = i + 1
311 if i == 1
312 Xpath 'a'
313 function! F1(arg)
314 CALL a:arg
315 let outer = 1
316
317 let j = 0
318 while j < 1
319 Xpath 'b'
320 let j = j + 1
321 function! G1(arg)
322 CALL a:arg
323 endfunction
324 Xpath 'c'
325 endwhile
326 endfunction
327 Xpath 'd'
328
329 continue
330 endif
331
332 Xpath 'e' . i
333 function! F{i}(i, arg)
334 CALL a:arg
335 let outer = 1
336
337 if a:i == 3
338 Xpath 'f'
339 endif
340 let k = 0
341 while k < 3
342 Xpath 'g' . k
343 let k = k + 1
344 function! G{a:i}{k}(arg)
345 CALL a:arg
346 endfunction
347 Xpath 'h' . k
348 endwhile
349 endfunction
350 Xpath 'i'
351
352endwhile
353
354if exists("*G1")
355 Xpath 'j'
356endif
357if exists("*F1")
358 call F1("F1")
359 if exists("*G1")
360 call G1("G1")
361 endif
362endif
363
364if exists("G21") || exists("G22") || exists("G23")
365 Xpath 'k'
366endif
367if exists("*F2")
368 call F2(2, "F2")
369 if exists("*G21")
370 call G21("G21")
371 endif
372 if exists("*G22")
373 call G22("G22")
374 endif
375 if exists("*G23")
376 call G23("G23")
377 endif
378endif
379
380if exists("G31") || exists("G32") || exists("G33")
381 Xpath 'l'
382endif
383if exists("*F3")
384 call F3(3, "F3")
385 if exists("*G31")
386 call G31("G31")
387 endif
388 if exists("*G32")
389 call G32("G32")
390 endif
391 if exists("*G33")
392 call G33("G33")
393 endif
394endif
395
396Xpath 'm'
397
398let g:test6_result = g:Xpath
399let g:test6_calls = calls
400
401unlet calls
402delfunction F1
403delfunction G1
404delfunction F2
405delfunction G21
406delfunction G22
407delfunction G23
408delfunction G31
409delfunction G32
410delfunction G33
411
412function Test_defining_functions()
413 call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
414 call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
415endfunc
416
417"-------------------------------------------------------------------------------
Bram Moolenaara2cce862016-01-02 19:50:04 +0100418" Test 7: Continuing on errors outside functions {{{1
419"
420" On an error outside a function, the script processing continues
421" at the line following the outermost :endif or :endwhile. When not
422" inside an :if or :while, the script processing continues at the next
423" line.
424"-------------------------------------------------------------------------------
425
426XpathINIT
427
428if 1
429 Xpath 'a'
430 while 1
431 Xpath 'b'
432 asdf
433 Xpath 'c'
434 break
435 endwhile | Xpath 'd'
436 Xpath 'e'
437endif | Xpath 'f'
438Xpath 'g'
439
440while 1
441 Xpath 'h'
442 if 1
443 Xpath 'i'
444 asdf
445 Xpath 'j'
446 endif | Xpath 'k'
447 Xpath 'l'
448 break
449endwhile | Xpath 'm'
450Xpath 'n'
451
452asdf
453Xpath 'o'
454
455asdf | Xpath 'p'
456Xpath 'q'
457
458let g:test7_result = g:Xpath
459
460func Test_error_in_script()
461 call assert_equal('abghinoq', g:test7_result)
462endfunc
463
464"-------------------------------------------------------------------------------
465" Test 8: Aborting and continuing on errors inside functions {{{1
466"
467" On an error inside a function without the "abort" attribute, the
468" script processing continues at the next line (unless the error was
469" in a :return command). On an error inside a function with the
470" "abort" attribute, the function is aborted and the script processing
471" continues after the function call; the value -1 is returned then.
472"-------------------------------------------------------------------------------
473
474XpathINIT
475
476function! T8_F()
477 if 1
478 Xpath 'a'
479 while 1
480 Xpath 'b'
481 asdf
482 Xpath 'c'
483 asdf | Xpath 'd'
484 Xpath 'e'
485 break
486 endwhile
487 Xpath 'f'
488 endif | Xpath 'g'
489 Xpath 'h'
490
491 while 1
492 Xpath 'i'
493 if 1
494 Xpath 'j'
495 asdf
496 Xpath 'k'
497 asdf | Xpath 'l'
498 Xpath 'm'
499 endif
500 Xpath 'n'
501 break
502 endwhile | Xpath 'o'
503 Xpath 'p'
504
505 return novar " returns (default return value 0)
506 Xpath 'q'
507 return 1 " not reached
508endfunction
509
510function! T8_G() abort
511 if 1
512 Xpath 'r'
513 while 1
514 Xpath 's'
515 asdf " returns -1
516 Xpath 't'
517 break
518 endwhile
519 Xpath 'v'
520 endif | Xpath 'w'
521 Xpath 'x'
522
523 return -4 " not reached
524endfunction
525
526function! T8_H() abort
527 while 1
528 Xpath 'A'
529 if 1
530 Xpath 'B'
531 asdf " returns -1
532 Xpath 'C'
533 endif
534 Xpath 'D'
535 break
536 endwhile | Xpath 'E'
537 Xpath 'F'
538
539 return -4 " not reached
540endfunction
541
542" Aborted functions (T8_G and T8_H) return -1.
543let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
544Xpath 'X'
545let g:test8_result = g:Xpath
546
547func Test_error_in_function()
548 call assert_equal(13, g:test8_sum)
549 call assert_equal('abcefghijkmnoprsABX', g:test8_result)
550
551 delfunction T8_F
552 delfunction T8_G
553 delfunction T8_H
554endfunc
555
556
557"-------------------------------------------------------------------------------
558" Test 9: Continuing after aborted functions {{{1
559"
560" When a function with the "abort" attribute is aborted due to an
561" error, the next function back in the call hierarchy without an
562" "abort" attribute continues; the value -1 is returned then.
563"-------------------------------------------------------------------------------
564
565XpathINIT
566
567function! F() abort
568 Xpath 'a'
569 let result = G() " not aborted
570 Xpath 'b'
571 if result != 2
572 Xpath 'c'
573 endif
574 return 1
575endfunction
576
577function! G() " no abort attribute
578 Xpath 'd'
579 if H() != -1 " aborted
580 Xpath 'e'
581 endif
582 Xpath 'f'
583 return 2
584endfunction
585
586function! H() abort
587 Xpath 'g'
588 call I() " aborted
589 Xpath 'h'
590 return 4
591endfunction
592
593function! I() abort
594 Xpath 'i'
595 asdf " error
596 Xpath 'j'
597 return 8
598endfunction
599
600if F() != 1
601 Xpath 'k'
602endif
603
604let g:test9_result = g:Xpath
605
606delfunction F
607delfunction G
608delfunction H
609delfunction I
610
611func Test_func_abort()
612 call assert_equal('adgifb', g:test9_result)
613endfunc
614
615
616"-------------------------------------------------------------------------------
617" Test 10: :if, :elseif, :while argument parsing {{{1
618"
619" A '"' or '|' in an argument expression must not be mixed up with
620" a comment or a next command after a bar. Parsing errors should
621" be recognized.
622"-------------------------------------------------------------------------------
623
624XpathINIT
625
626function! MSG(enr, emsg)
627 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
628 if a:enr == ""
629 Xout "TODO: Add message number for:" a:emsg
630 let v:errmsg = ":" . v:errmsg
631 endif
632 let match = 1
633 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
634 let match = 0
635 if v:errmsg == ""
636 Xout "Message missing."
637 else
638 let v:errmsg = escape(v:errmsg, '"')
639 Xout "Unexpected message:" v:errmsg
640 endif
641 endif
642 return match
643endfunction
644
645if 1 || strlen("\"") | Xpath 'a'
646 Xpath 'b'
647endif
648Xpath 'c'
649
650if 0
651elseif 1 || strlen("\"") | Xpath 'd'
652 Xpath 'e'
653endif
654Xpath 'f'
655
656while 1 || strlen("\"") | Xpath 'g'
657 Xpath 'h'
658 break
659endwhile
660Xpath 'i'
661
662let v:errmsg = ""
663if 1 ||| strlen("\"") | Xpath 'j'
664 Xpath 'k'
665endif
666Xpath 'l'
667if !MSG('E15', "Invalid expression")
668 Xpath 'm'
669endif
670
671let v:errmsg = ""
672if 0
673elseif 1 ||| strlen("\"") | Xpath 'n'
674 Xpath 'o'
675endif
676Xpath 'p'
677if !MSG('E15', "Invalid expression")
678 Xpath 'q'
679endif
680
681let v:errmsg = ""
682while 1 ||| strlen("\"") | Xpath 'r'
683 Xpath 's'
684 break
685endwhile
686Xpath 't'
687if !MSG('E15', "Invalid expression")
688 Xpath 'u'
689endif
690
691let g:test10_result = g:Xpath
692delfunction MSG
693
694func Test_expr_parsing()
695 call assert_equal('abcdefghilpt', g:test10_result)
696endfunc
697
698
699"-------------------------------------------------------------------------------
700" Test 11: :if, :elseif, :while argument evaluation after abort {{{1
701"
702" When code is skipped over due to an error, the boolean argument to
703" an :if, :elseif, or :while must not be evaluated.
704"-------------------------------------------------------------------------------
705
706XpathINIT
707
708let calls = 0
709
710function! P(num)
711 let g:calls = g:calls + a:num " side effect on call
712 return 0
713endfunction
714
715if 1
716 Xpath 'a'
717 asdf " error
718 Xpath 'b'
719 if P(1) " should not be called
720 Xpath 'c'
721 elseif !P(2) " should not be called
722 Xpath 'd'
723 else
724 Xpath 'e'
725 endif
726 Xpath 'f'
727 while P(4) " should not be called
728 Xpath 'g'
729 endwhile
730 Xpath 'h'
731endif
732Xpath 'x'
733
734let g:test11_calls = calls
735let g:test11_result = g:Xpath
736
737unlet calls
738delfunction P
739
740func Test_arg_abort()
741 call assert_equal(0, g:test11_calls)
742 call assert_equal('ax', g:test11_result)
743endfunc
744
745
746"-------------------------------------------------------------------------------
747" Test 12: Expressions in braces in skipped code {{{1
748"
749" In code skipped over due to an error or inactive conditional,
750" an expression in braces as part of a variable or function name
751" should not be evaluated.
752"-------------------------------------------------------------------------------
753
754XpathINIT
755
756function! NULL()
757 Xpath 'a'
758 return 0
759endfunction
760
761function! ZERO()
762 Xpath 'b'
763 return 0
764endfunction
765
766function! F0()
767 Xpath 'c'
768endfunction
769
770function! F1(arg)
771 Xpath 'e'
772endfunction
773
774let V0 = 1
775
776Xpath 'f'
777echo 0 ? F{NULL() + V{ZERO()}}() : 1
778
779Xpath 'g'
780if 0
781 Xpath 'h'
782 call F{NULL() + V{ZERO()}}()
783endif
784
785Xpath 'i'
786if 1
787 asdf " error
788 Xpath 'j'
789 call F1(F{NULL() + V{ZERO()}}())
790endif
791
792Xpath 'k'
793if 1
794 asdf " error
795 Xpath 'l'
796 call F{NULL() + V{ZERO()}}()
797endif
798
799let g:test12_result = g:Xpath
800
801func Test_braces_skipped()
802 call assert_equal('fgik', g:test12_result)
803endfunc
804
805
806"-------------------------------------------------------------------------------
807" Test 13: Failure in argument evaluation for :while {{{1
808"
809" A failure in the expression evaluation for the condition of a :while
810" causes the whole :while loop until the matching :endwhile being
811" ignored. Continuation is at the next following line.
812"-------------------------------------------------------------------------------
813
814XpathINIT
815
816Xpath 'a'
817while asdf
818 Xpath 'b'
819 while 1
820 Xpath 'c'
821 break
822 endwhile
823 Xpath 'd'
824 break
825endwhile
826Xpath 'e'
827
828while asdf | Xpath 'f' | endwhile | Xpath 'g'
829Xpath 'h'
830let g:test13_result = g:Xpath
831
832func Test_while_fail()
833 call assert_equal('aeh', g:test13_result)
834endfunc
835
836
837"-------------------------------------------------------------------------------
838" Test 14: Failure in argument evaluation for :if {{{1
839"
840" A failure in the expression evaluation for the condition of an :if
841" does not cause the corresponding :else or :endif being matched to
842" a previous :if/:elseif. Neither of both branches of the failed :if
843" are executed.
844"-------------------------------------------------------------------------------
845
846XpathINIT
847
848function! F()
849 Xpath 'a'
850 let x = 0
851 if x " false
852 Xpath 'b'
853 elseif !x " always true
854 Xpath 'c'
855 let x = 1
856 if g:boolvar " possibly undefined
857 Xpath 'd'
858 else
859 Xpath 'e'
860 endif
861 Xpath 'f'
862 elseif x " never executed
863 Xpath 'g'
864 endif
865 Xpath 'h'
866endfunction
867
868let boolvar = 1
869call F()
870Xpath '-'
871
872unlet boolvar
873call F()
874let g:test14_result = g:Xpath
875
876delfunction F
877
878func Test_if_fail()
879 call assert_equal('acdfh-acfh', g:test14_result)
880endfunc
881
882
883"-------------------------------------------------------------------------------
884" Test 15: Failure in argument evaluation for :if (bar) {{{1
885"
886" Like previous test, except that the failing :if ... | ... | :endif
887" is in a single line.
888"-------------------------------------------------------------------------------
889
890XpathINIT
891
892function! F()
893 Xpath 'a'
894 let x = 0
895 if x " false
896 Xpath 'b'
897 elseif !x " always true
898 Xpath 'c'
899 let x = 1
900 if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
901 Xpath 'f'
902 elseif x " never executed
903 Xpath 'g'
904 endif
905 Xpath 'h'
906endfunction
907
908let boolvar = 1
909call F()
910Xpath '-'
911
912unlet boolvar
913call F()
914let g:test15_result = g:Xpath
915
916delfunction F
917
918func Test_if_bar_fail()
919 call assert_equal('acdfh-acfh', g:test15_result)
920endfunc
921
Bram Moolenaar4119cf82016-01-17 14:59:01 +0100922"-------------------------------------------------------------------------------
923" Test 90: Recognizing {} in variable name. {{{1
924"-------------------------------------------------------------------------------
925
926func Test_curlies()
927 let s:var = 66
928 let ns = 's'
929 call assert_equal(66, {ns}:var)
930
931 let g:a = {}
932 let g:b = 't'
933 let g:a[g:b] = 77
934 call assert_equal(77, g:a['t'])
935endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100936
937"-------------------------------------------------------------------------------
Bram Moolenaarf95534c2016-01-23 21:59:52 +0100938" Test 91: using type(). {{{1
939"-------------------------------------------------------------------------------
940
941func Test_type()
942 call assert_equal(0, type(0))
943 call assert_equal(1, type(""))
944 call assert_equal(2, type(function("tr")))
Bram Moolenaar953cc7f2016-03-19 18:52:29 +0100945 call assert_equal(2, type(function("tr", [8])))
Bram Moolenaarf95534c2016-01-23 21:59:52 +0100946 call assert_equal(3, type([]))
947 call assert_equal(4, type({}))
948 call assert_equal(5, type(0.0))
949 call assert_equal(6, type(v:false))
950 call assert_equal(6, type(v:true))
951 call assert_equal(7, type(v:none))
952 call assert_equal(7, type(v:null))
Bram Moolenaarf562e722016-07-19 17:25:25 +0200953 call assert_equal(8, v:t_job)
954 call assert_equal(9, v:t_channel)
955 call assert_equal(v:t_number, type(0))
956 call assert_equal(v:t_string, type(""))
957 call assert_equal(v:t_func, type(function("tr")))
958 call assert_equal(v:t_func, type(function("tr", [8])))
959 call assert_equal(v:t_list, type([]))
960 call assert_equal(v:t_dict, type({}))
961 call assert_equal(v:t_float, type(0.0))
962 call assert_equal(v:t_bool, type(v:false))
963 call assert_equal(v:t_bool, type(v:true))
964 call assert_equal(v:t_none, type(v:none))
965 call assert_equal(v:t_none, type(v:null))
966
Bram Moolenaar17a13432016-01-24 14:22:10 +0100967
968 call assert_equal(0, 0 + v:false)
969 call assert_equal(1, 0 + v:true)
970 call assert_equal(0, 0 + v:none)
971 call assert_equal(0, 0 + v:null)
972
Bram Moolenaarf48aa162016-01-24 17:54:24 +0100973 call assert_equal('v:false', '' . v:false)
974 call assert_equal('v:true', '' . v:true)
975 call assert_equal('v:none', '' . v:none)
976 call assert_equal('v:null', '' . v:null)
Bram Moolenaar6039c7f2016-01-24 15:05:32 +0100977
978 call assert_true(v:false == 0)
979 call assert_false(v:false != 0)
980 call assert_true(v:true == 1)
981 call assert_false(v:true != 1)
982 call assert_false(v:true == v:false)
983 call assert_true(v:true != v:false)
984
985 call assert_true(v:null == 0)
986 call assert_false(v:null != 0)
987 call assert_true(v:none == 0)
988 call assert_false(v:none != 0)
Bram Moolenaar04369222016-01-24 17:21:29 +0100989
990 call assert_true(v:false is v:false)
991 call assert_true(v:true is v:true)
992 call assert_true(v:none is v:none)
993 call assert_true(v:null is v:null)
994
995 call assert_false(v:false isnot v:false)
996 call assert_false(v:true isnot v:true)
997 call assert_false(v:none isnot v:none)
998 call assert_false(v:null isnot v:null)
999
1000 call assert_false(v:false is 0)
1001 call assert_false(v:true is 1)
1002 call assert_false(v:true is v:false)
1003 call assert_false(v:none is 0)
1004 call assert_false(v:null is 0)
1005 call assert_false(v:null is v:none)
1006
1007 call assert_true(v:false isnot 0)
1008 call assert_true(v:true isnot 1)
1009 call assert_true(v:true isnot v:false)
1010 call assert_true(v:none isnot 0)
1011 call assert_true(v:null isnot 0)
1012 call assert_true(v:null isnot v:none)
Bram Moolenaar65591002016-01-24 21:51:57 +01001013
1014 call assert_equal(v:false, eval(string(v:false)))
1015 call assert_equal(v:true, eval(string(v:true)))
1016 call assert_equal(v:none, eval(string(v:none)))
1017 call assert_equal(v:null, eval(string(v:null)))
Bram Moolenaar767d8c12016-01-25 20:22:54 +01001018
Bram Moolenaar15550002016-01-31 18:45:24 +01001019 call assert_equal(v:false, copy(v:false))
1020 call assert_equal(v:true, copy(v:true))
1021 call assert_equal(v:none, copy(v:none))
1022 call assert_equal(v:null, copy(v:null))
1023
1024 call assert_equal([v:false], deepcopy([v:false]))
1025 call assert_equal([v:true], deepcopy([v:true]))
1026 call assert_equal([v:none], deepcopy([v:none]))
1027 call assert_equal([v:null], deepcopy([v:null]))
1028
Bram Moolenaar767d8c12016-01-25 20:22:54 +01001029 call assert_true(empty(v:false))
1030 call assert_false(empty(v:true))
1031 call assert_true(empty(v:null))
1032 call assert_true(empty(v:none))
Bram Moolenaar6650a692016-01-26 19:59:10 +01001033
1034 func ChangeYourMind()
1035 try
1036 return v:true
1037 finally
1038 return 'something else'
1039 endtry
1040 endfunc
1041
1042 call ChangeYourMind()
Bram Moolenaarf95534c2016-01-23 21:59:52 +01001043endfunc
1044
1045"-------------------------------------------------------------------------------
Bram Moolenaarea8c2192016-02-07 19:27:53 +01001046" Test 92: skipping code {{{1
1047"-------------------------------------------------------------------------------
1048
1049func Test_skip()
1050 let Fn = function('Test_type')
1051 call assert_false(0 && Fn[1])
1052 call assert_false(0 && string(Fn))
1053 call assert_false(0 && len(Fn))
1054 let l = []
1055 call assert_false(0 && l[1])
1056 call assert_false(0 && string(l))
1057 call assert_false(0 && len(l))
1058 let f = 1.0
1059 call assert_false(0 && f[1])
1060 call assert_false(0 && string(f))
1061 call assert_false(0 && len(f))
1062 let sp = v:null
1063 call assert_false(0 && sp[1])
1064 call assert_false(0 && string(sp))
1065 call assert_false(0 && len(sp))
1066
1067endfunc
1068
1069"-------------------------------------------------------------------------------
Bram Moolenaar18dfb442016-05-31 22:31:23 +02001070" Test 93: :echo and string() {{{1
1071"-------------------------------------------------------------------------------
1072
1073func Test_echo_and_string()
1074 " String
1075 let a = 'foo bar'
1076 redir => result
1077 echo a
1078 echo string(a)
1079 redir END
1080 let l = split(result, "\n")
1081 call assert_equal(["foo bar",
1082 \ "'foo bar'"], l)
1083
1084 " Float
1085 if has('float')
1086 let a = -1.2e0
1087 redir => result
1088 echo a
1089 echo string(a)
1090 redir END
1091 let l = split(result, "\n")
1092 call assert_equal(["-1.2",
1093 \ "-1.2"], l)
1094 endif
1095
1096 " Funcref
1097 redir => result
1098 echo function('string')
1099 echo string(function('string'))
1100 redir END
1101 let l = split(result, "\n")
1102 call assert_equal(["string",
1103 \ "function('string')"], l)
1104
1105 " Recursive dictionary
1106 let a = {}
1107 let a["a"] = a
1108 redir => result
1109 echo a
1110 echo string(a)
1111 redir END
1112 let l = split(result, "\n")
1113 call assert_equal(["{'a': {...}}",
1114 \ "{'a': {...}}"], l)
1115
1116 " Recursive list
1117 let a = [0]
1118 let a[0] = a
1119 redir => result
1120 echo a
1121 echo string(a)
1122 redir END
1123 let l = split(result, "\n")
1124 call assert_equal(["[[...]]",
1125 \ "[[...]]"], l)
1126
1127 " Empty dictionaries in a list
1128 let a = {}
1129 redir => result
1130 echo [a, a, a]
1131 echo string([a, a, a])
1132 redir END
1133 let l = split(result, "\n")
1134 call assert_equal(["[{}, {}, {}]",
1135 \ "[{}, {}, {}]"], l)
1136
1137 " Empty dictionaries in a dictionary
1138 let a = {}
1139 let b = {"a": a, "b": a}
1140 redir => result
1141 echo b
1142 echo string(b)
1143 redir END
1144 let l = split(result, "\n")
1145 call assert_equal(["{'a': {}, 'b': {}}",
1146 \ "{'a': {}, 'b': {}}"], l)
1147
1148 " Empty lists in a list
1149 let a = []
1150 redir => result
1151 echo [a, a, a]
1152 echo string([a, a, a])
1153 redir END
1154 let l = split(result, "\n")
1155 call assert_equal(["[[], [], []]",
1156 \ "[[], [], []]"], l)
1157
1158 " Empty lists in a dictionary
1159 let a = []
1160 let b = {"a": a, "b": a}
1161 redir => result
1162 echo b
1163 echo string(b)
1164 redir END
1165 let l = split(result, "\n")
1166 call assert_equal(["{'a': [], 'b': []}",
1167 \ "{'a': [], 'b': []}"], l)
1168
1169 " Dictionaries in a list
1170 let a = {"one": "yes", "two": "yes", "three": "yes"}
1171 redir => result
1172 echo [a, a, a]
1173 echo string([a, a, a])
1174 redir END
1175 let l = split(result, "\n")
1176 call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
1177 \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
1178
1179 " Dictionaries in a dictionary
1180 let a = {"one": "yes", "two": "yes", "three": "yes"}
1181 let b = {"a": a, "b": a}
1182 redir => result
1183 echo b
1184 echo string(b)
1185 redir END
1186 let l = split(result, "\n")
1187 call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
1188 \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
1189
1190 " Lists in a list
1191 let a = [1, 2, 3]
1192 redir => result
1193 echo [a, a, a]
1194 echo string([a, a, a])
1195 redir END
1196 let l = split(result, "\n")
1197 call assert_equal(["[[1, 2, 3], [...], [...]]",
1198 \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
1199
1200 " Lists in a dictionary
1201 let a = [1, 2, 3]
1202 let b = {"a": a, "b": a}
1203 redir => result
1204 echo b
1205 echo string(b)
1206 redir END
1207 let l = split(result, "\n")
1208 call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
1209 \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
1210
1211endfunc
1212
1213"-------------------------------------------------------------------------------
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001214" Test 94: 64-bit Numbers {{{1
1215"-------------------------------------------------------------------------------
1216
1217func Test_num64()
1218 if !has('num64')
1219 return
1220 endif
1221
1222 call assert_notequal( 4294967296, 0)
1223 call assert_notequal(-4294967296, 0)
1224 call assert_equal( 4294967296, 0xFFFFffff + 1)
1225 call assert_equal(-4294967296, -0xFFFFffff - 1)
1226
1227 call assert_equal( 9223372036854775807, 1 / 0)
1228 call assert_equal(-9223372036854775807, -1 / 0)
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001229 call assert_equal(-9223372036854775807 - 1, 0 / 0)
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001230
1231 call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
1232 call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
1233
1234 let rng = range(0xFFFFffff, 0x100000001)
1235 call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
1236 call assert_equal(0x100000001, max(rng))
1237 call assert_equal(0xFFFFffff, min(rng))
1238 call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
1239endfunc
1240
1241"-------------------------------------------------------------------------------
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001242" Test 95: lines of :append, :change, :insert {{{1
1243"-------------------------------------------------------------------------------
1244
1245function! DefineFunction(name, body)
1246 let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
1247 exec func
1248endfunction
1249
1250func Test_script_lines()
1251 " :append
1252 try
1253 call DefineFunction('T_Append', [
1254 \ 'append',
1255 \ 'py <<EOS',
1256 \ '.',
1257 \ ])
1258 catch
Bram Moolenaar37175402017-03-18 20:18:45 +01001259 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001260 endtry
1261 try
1262 call DefineFunction('T_Append', [
1263 \ 'append',
1264 \ 'abc',
1265 \ ])
Bram Moolenaar37175402017-03-18 20:18:45 +01001266 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001267 catch
1268 call assert_exception('Vim(function):E126: Missing :endfunction')
1269 endtry
1270
1271 " :change
1272 try
1273 call DefineFunction('T_Change', [
1274 \ 'change',
1275 \ 'py <<EOS',
1276 \ '.',
1277 \ ])
1278 catch
Bram Moolenaar37175402017-03-18 20:18:45 +01001279 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001280 endtry
1281 try
1282 call DefineFunction('T_Change', [
1283 \ 'change',
1284 \ 'abc',
1285 \ ])
Bram Moolenaar37175402017-03-18 20:18:45 +01001286 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001287 catch
1288 call assert_exception('Vim(function):E126: Missing :endfunction')
1289 endtry
1290
1291 " :insert
1292 try
1293 call DefineFunction('T_Insert', [
1294 \ 'insert',
1295 \ 'py <<EOS',
1296 \ '.',
1297 \ ])
1298 catch
Bram Moolenaar37175402017-03-18 20:18:45 +01001299 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001300 endtry
1301 try
1302 call DefineFunction('T_Insert', [
1303 \ 'insert',
1304 \ 'abc',
1305 \ ])
Bram Moolenaar37175402017-03-18 20:18:45 +01001306 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01001307 catch
1308 call assert_exception('Vim(function):E126: Missing :endfunction')
1309 endtry
1310endfunc
1311
1312"-------------------------------------------------------------------------------
Bram Moolenaar478af672017-04-10 22:22:42 +02001313" Test 96: line continuation {{{1
1314"
1315" Undefined behavior was detected by ubsan with line continuation
1316" after an empty line.
1317"-------------------------------------------------------------------------------
1318func Test_script_emty_line_continuation()
1319
1320 \
1321endfunc
1322
1323"-------------------------------------------------------------------------------
Bram Moolenaar863e80b2017-06-04 20:30:00 +02001324" Test 97: bitwise functions {{{1
1325"-------------------------------------------------------------------------------
1326func Test_bitwise_functions()
1327 " and
1328 call assert_equal(127, and(127, 127))
1329 call assert_equal(16, and(127, 16))
1330 call assert_equal(0, and(127, 128))
1331 call assert_fails("call and(1.0, 1)", 'E805:')
1332 call assert_fails("call and([], 1)", 'E745:')
1333 call assert_fails("call and({}, 1)", 'E728:')
1334 call assert_fails("call and(1, 1.0)", 'E805:')
1335 call assert_fails("call and(1, [])", 'E745:')
1336 call assert_fails("call and(1, {})", 'E728:')
1337 " or
1338 call assert_equal(23, or(16, 7))
1339 call assert_equal(15, or(8, 7))
1340 call assert_equal(123, or(0, 123))
1341 call assert_fails("call or(1.0, 1)", 'E805:')
1342 call assert_fails("call or([], 1)", 'E745:')
1343 call assert_fails("call or({}, 1)", 'E728:')
1344 call assert_fails("call or(1, 1.0)", 'E805:')
1345 call assert_fails("call or(1, [])", 'E745:')
1346 call assert_fails("call or(1, {})", 'E728:')
1347 " xor
1348 call assert_equal(0, xor(127, 127))
1349 call assert_equal(111, xor(127, 16))
1350 call assert_equal(255, xor(127, 128))
1351 call assert_fails("call xor(1.0, 1)", 'E805:')
1352 call assert_fails("call xor([], 1)", 'E745:')
1353 call assert_fails("call xor({}, 1)", 'E728:')
1354 call assert_fails("call xor(1, 1.0)", 'E805:')
1355 call assert_fails("call xor(1, [])", 'E745:')
1356 call assert_fails("call xor(1, {})", 'E728:')
1357 " invert
1358 call assert_equal(65408, and(invert(127), 65535))
1359 call assert_equal(65519, and(invert(16), 65535))
1360 call assert_equal(65407, and(invert(128), 65535))
1361 call assert_fails("call invert(1.0)", 'E805:')
1362 call assert_fails("call invert([])", 'E745:')
1363 call assert_fails("call invert({})", 'E728:')
1364endfunc
1365
Bram Moolenaar663bb232017-06-22 19:12:10 +02001366" Test trailing text after :endfunction {{{1
1367func Test_endfunction_trailing()
1368 call assert_false(exists('*Xtest'))
1369
1370 exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'"
1371 call assert_true(exists('*Xtest'))
1372 call assert_equal('yes', done)
1373 delfunc Xtest
1374 unlet done
1375
1376 exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'"
1377 call assert_true(exists('*Xtest'))
1378 call assert_equal('yes', done)
1379 delfunc Xtest
1380 unlet done
1381
1382 set verbose=1
1383 exe "func Xtest()\necho 'hello'\nendfunc \" garbage"
1384 call assert_true(exists('*Xtest'))
1385 delfunc Xtest
1386
1387 call assert_fails("func Xtest()\necho 'hello'\nendfunc garbage", 'E946')
1388 call assert_true(exists('*Xtest'))
1389 delfunc Xtest
1390 set verbose=0
1391endfunc
1392
Bram Moolenaard6abcd12017-06-22 19:15:24 +02001393func Test_delfunction_force()
1394 delfunc! Xtest
1395 delfunc! Xtest
1396 func Xtest()
1397 echo 'nothing'
1398 endfunc
1399 delfunc! Xtest
1400 delfunc! Xtest
1401endfunc
1402
Bram Moolenaar863e80b2017-06-04 20:30:00 +02001403"-------------------------------------------------------------------------------
Bram Moolenaarf49e2402015-12-30 15:59:25 +01001404" Modelines {{{1
1405" vim: ts=8 sw=4 tw=80 fdm=marker
1406" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
1407"-------------------------------------------------------------------------------