1" Test various aspects of the Vim script language.
2" Most of this was formerly in test49.
3
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.
28func 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
53endfunc
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
58" delete it afterwards.  However, if an exception is thrown the file may remain,
59" the caller should call DeleteTheScript() afterwards.
60let s:script_name = ''
61function! ExecAsScript(funcname)
62    " Make a script from the function passed as argument.
63    let s:script_name = MakeScript(a:funcname)
64
65    " Source and delete the script.
66    exec "source" s:script_name
67    call delete(s:script_name)
68    let s:script_name = ''
69endfunction
70
71function! DeleteTheScript()
72    if s:script_name
73	call delete(s:script_name)
74	let s:script_name = ''
75    endif
76endfunc
77
78com! -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'
156  call DeleteTheScript()
157
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'
166  call DeleteTheScript()
167
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'
275    call DeleteTheScript()
276
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"-------------------------------------------------------------------------------
418" 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
643endfunc
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
922"-------------------------------------------------------------------------------
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
936
937"-------------------------------------------------------------------------------
938" 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")))
945    call assert_equal(2, type(function("tr", [8])))
946    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))
953    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
967
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
973    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)
977
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)
989
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)
1013
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)))
1018
1019    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
1029    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))
1033
1034    func ChangeYourMind()
1035	try
1036	    return v:true
1037	finally
1038	    return 'something else'
1039	endtry
1040    endfunc
1041
1042    call ChangeYourMind()
1043endfunc
1044
1045"-------------------------------------------------------------------------------
1046" 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"-------------------------------------------------------------------------------
1070" 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"-------------------------------------------------------------------------------
1214" 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)
1229    call assert_equal(-9223372036854775807 - 1,  0 / 0)
1230
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"-------------------------------------------------------------------------------
1242" 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
1259	call assert_report("Can't define function")
1260    endtry
1261    try
1262	call DefineFunction('T_Append', [
1263		    \ 'append',
1264		    \ 'abc',
1265		    \ ])
1266	call assert_report("Shouldn't be able to define function")
1267    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
1279	call assert_report("Can't define function")
1280    endtry
1281    try
1282	call DefineFunction('T_Change', [
1283		    \ 'change',
1284		    \ 'abc',
1285		    \ ])
1286	call assert_report("Shouldn't be able to define function")
1287    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
1299	call assert_report("Can't define function")
1300    endtry
1301    try
1302	call DefineFunction('T_Insert', [
1303		    \ 'insert',
1304		    \ 'abc',
1305		    \ ])
1306	call assert_report("Shouldn't be able to define function")
1307    catch
1308	call assert_exception('Vim(function):E126: Missing :endfunction')
1309    endtry
1310endfunc
1311
1312"-------------------------------------------------------------------------------
1313" 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"-------------------------------------------------------------------------------
1324" 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
1366" 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    " trailing line break
1383    exe "func Xtest()\necho 'hello'\nendfunc\n"
1384    call assert_true(exists('*Xtest'))
1385    delfunc Xtest
1386
1387    set verbose=1
1388    exe "func Xtest()\necho 'hello'\nendfunc \" garbage"
1389    call assert_notmatch('W22:', split(execute('1messages'), "\n")[0])
1390    call assert_true(exists('*Xtest'))
1391    delfunc Xtest
1392
1393    exe "func Xtest()\necho 'hello'\nendfunc garbage"
1394    call assert_match('W22:', split(execute('1messages'), "\n")[0])
1395    call assert_true(exists('*Xtest'))
1396    delfunc Xtest
1397    set verbose=0
1398
1399    function Foo()
1400	echo 'hello'
1401    endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
1402    delfunc Foo
1403endfunc
1404
1405func Test_delfunction_force()
1406    delfunc! Xtest
1407    delfunc! Xtest
1408    func Xtest()
1409	echo 'nothing'
1410    endfunc
1411    delfunc! Xtest
1412    delfunc! Xtest
1413endfunc
1414
1415" Test using bang after user command				    {{{1
1416func Test_user_command_with_bang()
1417    command -bang Nieuw let nieuw = 1
1418    Ni!
1419    call assert_equal(1, nieuw)
1420    unlet nieuw
1421    delcommand Nieuw
1422endfunc
1423
1424" Test for script-local function
1425func <SID>DoLast()
1426  call append(line('$'), "last line")
1427endfunc
1428
1429func s:DoNothing()
1430  call append(line('$'), "nothing line")
1431endfunc
1432
1433func Test_script_local_func()
1434  set nocp viminfo+=nviminfo
1435  new
1436  nnoremap <buffer> _x	:call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
1437
1438  normal _x
1439  call assert_equal('nothing line', getline(2))
1440  call assert_equal('last line', getline(3))
1441  enew! | close
1442endfunc
1443
1444"-------------------------------------------------------------------------------
1445" Modelines								    {{{1
1446" vim: ts=8 sw=4 tw=80 fdm=marker
1447" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
1448"-------------------------------------------------------------------------------
1449