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