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 = v:errmsg->escape('"')
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    eval 127->and(16)->assert_equal(16)
1334    call assert_equal(0, and(127, 128))
1335    call assert_fails("call and(1.0, 1)", 'E805:')
1336    call assert_fails("call and([], 1)", 'E745:')
1337    call assert_fails("call and({}, 1)", 'E728:')
1338    call assert_fails("call and(1, 1.0)", 'E805:')
1339    call assert_fails("call and(1, [])", 'E745:')
1340    call assert_fails("call and(1, {})", 'E728:')
1341    " or
1342    call assert_equal(23, or(16, 7))
1343    call assert_equal(15, or(8, 7))
1344    eval 8->or(7)->assert_equal(15)
1345    call assert_equal(123, or(0, 123))
1346    call assert_fails("call or(1.0, 1)", 'E805:')
1347    call assert_fails("call or([], 1)", 'E745:')
1348    call assert_fails("call or({}, 1)", 'E728:')
1349    call assert_fails("call or(1, 1.0)", 'E805:')
1350    call assert_fails("call or(1, [])", 'E745:')
1351    call assert_fails("call or(1, {})", 'E728:')
1352    " xor
1353    call assert_equal(0, xor(127, 127))
1354    call assert_equal(111, xor(127, 16))
1355    eval 127->xor(16)->assert_equal(111)
1356    call assert_equal(255, xor(127, 128))
1357    call assert_fails("call xor(1.0, 1)", 'E805:')
1358    call assert_fails("call xor([], 1)", 'E745:')
1359    call assert_fails("call xor({}, 1)", 'E728:')
1360    call assert_fails("call xor(1, 1.0)", 'E805:')
1361    call assert_fails("call xor(1, [])", 'E745:')
1362    call assert_fails("call xor(1, {})", 'E728:')
1363    " invert
1364    call assert_equal(65408, and(invert(127), 65535))
1365    eval 127->invert()->and(65535)->assert_equal(65408)
1366    call assert_equal(65519, and(invert(16), 65535))
1367    call assert_equal(65407, and(invert(128), 65535))
1368    call assert_fails("call invert(1.0)", 'E805:')
1369    call assert_fails("call invert([])", 'E745:')
1370    call assert_fails("call invert({})", 'E728:')
1371endfunc
1372
1373" Test trailing text after :endfunction				    {{{1
1374func Test_endfunction_trailing()
1375    call assert_false(exists('*Xtest'))
1376
1377    exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'"
1378    call assert_true(exists('*Xtest'))
1379    call assert_equal('yes', done)
1380    delfunc Xtest
1381    unlet done
1382
1383    exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'"
1384    call assert_true(exists('*Xtest'))
1385    call assert_equal('yes', done)
1386    delfunc Xtest
1387    unlet done
1388
1389    " trailing line break
1390    exe "func Xtest()\necho 'hello'\nendfunc\n"
1391    call assert_true(exists('*Xtest'))
1392    delfunc Xtest
1393
1394    set verbose=1
1395    exe "func Xtest()\necho 'hello'\nendfunc \" garbage"
1396    call assert_notmatch('W22:', split(execute('1messages'), "\n")[0])
1397    call assert_true(exists('*Xtest'))
1398    delfunc Xtest
1399
1400    exe "func Xtest()\necho 'hello'\nendfunc garbage"
1401    call assert_match('W22:', split(execute('1messages'), "\n")[0])
1402    call assert_true(exists('*Xtest'))
1403    delfunc Xtest
1404    set verbose=0
1405
1406    function Foo()
1407	echo 'hello'
1408    endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
1409    delfunc Foo
1410endfunc
1411
1412func Test_delfunction_force()
1413    delfunc! Xtest
1414    delfunc! Xtest
1415    func Xtest()
1416	echo 'nothing'
1417    endfunc
1418    delfunc! Xtest
1419    delfunc! Xtest
1420endfunc
1421
1422" Test using bang after user command				    {{{1
1423func Test_user_command_with_bang()
1424    command -bang Nieuw let nieuw = 1
1425    Ni!
1426    call assert_equal(1, nieuw)
1427    unlet nieuw
1428    delcommand Nieuw
1429endfunc
1430
1431" Test for script-local function
1432func <SID>DoLast()
1433  call append(line('$'), "last line")
1434endfunc
1435
1436func s:DoNothing()
1437  call append(line('$'), "nothing line")
1438endfunc
1439
1440func Test_script_local_func()
1441  set nocp viminfo+=nviminfo
1442  new
1443  nnoremap <buffer> _x	:call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
1444
1445  normal _x
1446  call assert_equal('nothing line', getline(2))
1447  call assert_equal('last line', getline(3))
1448  enew! | close
1449endfunc
1450
1451func Test_compound_assignment_operators()
1452    " Test for number
1453    let x = 1
1454    let x += 10
1455    call assert_equal(11, x)
1456    let x -= 5
1457    call assert_equal(6, x)
1458    let x *= 4
1459    call assert_equal(24, x)
1460    let x /= 3
1461    call assert_equal(8, x)
1462    let x %= 3
1463    call assert_equal(2, x)
1464    let x .= 'n'
1465    call assert_equal('2n', x)
1466
1467    " Test special cases: division or modulus with 0.
1468    let x = 1
1469    let x /= 0
1470    if has('num64')
1471        call assert_equal(0x7FFFFFFFFFFFFFFF, x)
1472    else
1473        call assert_equal(0x7fffffff, x)
1474    endif
1475
1476    let x = -1
1477    let x /= 0
1478    if has('num64')
1479        call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
1480    else
1481        call assert_equal(-0x7fffffff, x)
1482    endif
1483
1484    let x = 0
1485    let x /= 0
1486    if has('num64')
1487        call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
1488    else
1489        call assert_equal(-0x7FFFFFFF - 1, x)
1490    endif
1491
1492    let x = 1
1493    let x %= 0
1494    call assert_equal(0, x)
1495
1496    let x = -1
1497    let x %= 0
1498    call assert_equal(0, x)
1499
1500    let x = 0
1501    let x %= 0
1502    call assert_equal(0, x)
1503
1504    " Test for string
1505    let x = 'str'
1506    let x .= 'ing'
1507    call assert_equal('string', x)
1508    let x += 1
1509    call assert_equal(1, x)
1510    let x -= 1.5
1511    call assert_equal(-0.5, x)
1512
1513    if has('float')
1514        " Test for float
1515        let x = 0.5
1516        let x += 4.5
1517        call assert_equal(5.0, x)
1518        let x -= 1.5
1519        call assert_equal(3.5, x)
1520        let x *= 3.0
1521        call assert_equal(10.5, x)
1522        let x /= 2.5
1523        call assert_equal(4.2, x)
1524        call assert_fails('let x %= 0.5', 'E734')
1525        call assert_fails('let x .= "f"', 'E734')
1526    endif
1527
1528    " Test for environment variable
1529    let $FOO = 1
1530    call assert_fails('let $FOO += 1', 'E734')
1531    call assert_fails('let $FOO -= 1', 'E734')
1532    call assert_fails('let $FOO *= 1', 'E734')
1533    call assert_fails('let $FOO /= 1', 'E734')
1534    call assert_fails('let $FOO %= 1', 'E734')
1535    let $FOO .= 's'
1536    call assert_equal('1s', $FOO)
1537    unlet $FOO
1538
1539    " Test for option variable (type: number)
1540    let &scrolljump = 1
1541    let &scrolljump += 5
1542    call assert_equal(6, &scrolljump)
1543    let &scrolljump -= 2
1544    call assert_equal(4, &scrolljump)
1545    let &scrolljump *= 3
1546    call assert_equal(12, &scrolljump)
1547    let &scrolljump /= 2
1548    call assert_equal(6, &scrolljump)
1549    let &scrolljump %= 5
1550    call assert_equal(1, &scrolljump)
1551    call assert_fails('let &scrolljump .= "j"', 'E734')
1552    set scrolljump&vim
1553
1554    " Test for register
1555    let @/ = 1
1556    call assert_fails('let @/ += 1', 'E734')
1557    call assert_fails('let @/ -= 1', 'E734')
1558    call assert_fails('let @/ *= 1', 'E734')
1559    call assert_fails('let @/ /= 1', 'E734')
1560    call assert_fails('let @/ %= 1', 'E734')
1561    let @/ .= 's'
1562    call assert_equal('1s', @/)
1563    let @/ = ''
1564endfunc
1565
1566func Test_refcount()
1567    " Immediate values
1568    call assert_equal(-1, test_refcount(1))
1569    call assert_equal(-1, test_refcount('s'))
1570    call assert_equal(-1, test_refcount(v:true))
1571    call assert_equal(0, test_refcount([]))
1572    call assert_equal(0, test_refcount({}))
1573    call assert_equal(0, test_refcount(0zff))
1574    call assert_equal(0, test_refcount({-> line('.')}))
1575    if has('float')
1576        call assert_equal(-1, test_refcount(0.1))
1577    endif
1578    if has('job')
1579        call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
1580    endif
1581
1582    " No refcount types
1583    let x = 1
1584    call assert_equal(-1, test_refcount(x))
1585    let x = 's'
1586    call assert_equal(-1, test_refcount(x))
1587    let x = v:true
1588    call assert_equal(-1, test_refcount(x))
1589    if has('float')
1590        let x = 0.1
1591        call assert_equal(-1, test_refcount(x))
1592    endif
1593
1594    " Check refcount
1595    let x = []
1596    call assert_equal(1, test_refcount(x))
1597
1598    let x = {}
1599    call assert_equal(1, x->test_refcount())
1600
1601    let x = 0zff
1602    call assert_equal(1, test_refcount(x))
1603
1604    let X = {-> line('.')}
1605    call assert_equal(1, test_refcount(X))
1606    let Y = X
1607    call assert_equal(2, test_refcount(X))
1608
1609    if has('job')
1610        let job = job_start([&shell, &shellcmdflag, 'echo .'])
1611        call assert_equal(1, test_refcount(job))
1612        call assert_equal(1, test_refcount(job_getchannel(job)))
1613        call assert_equal(1, test_refcount(job))
1614    endif
1615
1616    " Function arguments, copying and unassigning
1617    func ExprCheck(x, i)
1618        let i = a:i + 1
1619        call assert_equal(i, test_refcount(a:x))
1620        let Y = a:x
1621        call assert_equal(i + 1, test_refcount(a:x))
1622        call assert_equal(test_refcount(a:x), test_refcount(Y))
1623        let Y = 0
1624        call assert_equal(i, test_refcount(a:x))
1625    endfunc
1626    call ExprCheck([], 0)
1627    call ExprCheck({}, 0)
1628    call ExprCheck(0zff, 0)
1629    call ExprCheck({-> line('.')}, 0)
1630    if has('job')
1631	call ExprCheck(job, 1)
1632	call ExprCheck(job_getchannel(job), 1)
1633	call job_stop(job)
1634    endif
1635    delfunc ExprCheck
1636
1637    " Regarding function
1638    func Func(x) abort
1639        call assert_equal(2, test_refcount(function('Func')))
1640        call assert_equal(0, test_refcount(funcref('Func')))
1641    endfunc
1642    call assert_equal(1, test_refcount(function('Func')))
1643    call assert_equal(0, test_refcount(function('Func', [1])))
1644    call assert_equal(0, test_refcount(funcref('Func')))
1645    call assert_equal(0, test_refcount(funcref('Func', [1])))
1646    let X = function('Func')
1647    let Y = X
1648    call assert_equal(1, test_refcount(X))
1649    let X = function('Func', [1])
1650    let Y = X
1651    call assert_equal(2, test_refcount(X))
1652    let X = funcref('Func')
1653    let Y = X
1654    call assert_equal(2, test_refcount(X))
1655    let X = funcref('Func', [1])
1656    let Y = X
1657    call assert_equal(2, test_refcount(X))
1658    unlet X
1659    unlet Y
1660    call Func(1)
1661    delfunc Func
1662
1663    " Function with dict
1664    func DictFunc() dict
1665        call assert_equal(3, test_refcount(self))
1666    endfunc
1667    let d = {'Func': function('DictFunc')}
1668    call assert_equal(1, test_refcount(d))
1669    call assert_equal(0, test_refcount(d.Func))
1670    call d.Func()
1671    unlet d
1672    delfunc DictFunc
1673endfunc
1674
1675func Test_funccall_garbage_collect()
1676    func Func(x, ...)
1677        call add(a:x, a:000)
1678    endfunc
1679    call Func([], [])
1680    " Must not crash cause by invalid freeing
1681    call test_garbagecollect_now()
1682    call assert_true(v:true)
1683    delfunc Func
1684endfunc
1685
1686func Test_function_defined_line()
1687    CheckNotGui
1688
1689    let lines =<< trim [CODE]
1690    " F1
1691    func F1()
1692        " F2
1693        func F2()
1694            "
1695            "
1696            "
1697            return
1698        endfunc
1699        " F3
1700        execute "func F3()\n\n\n\nreturn\nendfunc"
1701        " F4
1702        execute "func F4()\n
1703                    \\n
1704                    \\n
1705                    \\n
1706                    \return\n
1707                    \endfunc"
1708    endfunc
1709    " F5
1710    execute "func F5()\n\n\n\nreturn\nendfunc"
1711    " F6
1712    execute "func F6()\n
1713                \\n
1714                \\n
1715                \\n
1716                \return\n
1717                \endfunc"
1718    call F1()
1719    verbose func F1
1720    verbose func F2
1721    verbose func F3
1722    verbose func F4
1723    verbose func F5
1724    verbose func F6
1725    qall!
1726    [CODE]
1727
1728    call writefile(lines, 'Xtest.vim')
1729    let res = system(GetVimCommandClean() .. ' -es -X -S Xtest.vim')
1730    call assert_equal(0, v:shell_error)
1731
1732    let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*')
1733    call assert_match(' line 2$', m)
1734
1735    let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*')
1736    call assert_match(' line 4$', m)
1737
1738    let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*')
1739    call assert_match(' line 11$', m)
1740
1741    let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*')
1742    call assert_match(' line 13$', m)
1743
1744    let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*')
1745    call assert_match(' line 21$', m)
1746
1747    let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*')
1748    call assert_match(' line 23$', m)
1749
1750    call delete('Xtest.vim')
1751endfunc
1752
1753"-------------------------------------------------------------------------------
1754" Modelines								    {{{1
1755" vim: ts=8 sw=4 tw=80 fdm=marker
1756"-------------------------------------------------------------------------------
1757