diff src/testdir/test_vimscript.vim @ 10942:e05695e59f6d v8.0.0360

patch 8.0.0360: sometimes VimL is used instead of "Vim script" commit https://github.com/vim/vim/commit/b544f3c81f1e6a50322855681ac266ffaa8e313c Author: Bram Moolenaar <Bram@vim.org> Date: Thu Feb 23 19:03:28 2017 +0100 patch 8.0.0360: sometimes VimL is used instead of "Vim script" Problem: Sometimes VimL is used, which is confusing. Solution: Consistently use "Vim script". (Hirohito Higashi)
author Christian Brabandt <cb@256bit.org>
date Thu, 23 Feb 2017 19:15:05 +0100
parents
children 1c4ebbae41d2
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_vimscript.vim
@@ -0,0 +1,1316 @@
+" Test various aspects of the Vim language.
+" Most of this was formerly in test49.
+
+"-------------------------------------------------------------------------------
+" Test environment							    {{{1
+"-------------------------------------------------------------------------------
+
+com!               XpathINIT  let g:Xpath = ''
+com! -nargs=1 -bar Xpath      let g:Xpath = g:Xpath . <args>
+
+" Append a message to the "messages" file
+func! Xout(text)
+    split messages
+    $put =a:text
+    wq
+endfunc
+
+com! -nargs=1	     Xout     call Xout(<args>)
+
+" MakeScript() - Make a script file from a function.			    {{{2
+"
+" Create a script that consists of the body of the function a:funcname.
+" Replace any ":return" by a ":finish", any argument variable by a global
+" variable, and and every ":call" by a ":source" for the next following argument
+" in the variable argument list.  This function is useful if similar tests are
+" to be made for a ":return" from a function call or a ":finish" in a script
+" file.
+function! MakeScript(funcname, ...)
+    let script = tempname()
+    execute "redir! >" . script
+    execute "function" a:funcname
+    redir END
+    execute "edit" script
+    " Delete the "function" and the "endfunction" lines.  Do not include the
+    " word "function" in the pattern since it might be translated if LANG is
+    " set.  When MakeScript() is being debugged, this deletes also the debugging
+    " output of its line 3 and 4.
+    exec '1,/.*' . a:funcname . '(.*)/d'
+    /^\d*\s*endfunction\>/,$d
+    %s/^\d*//e
+    %s/return/finish/e
+    %s/\<a:\(\h\w*\)/g:\1/ge
+    normal gg0
+    let cnt = 0
+    while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
+	let cnt = cnt + 1
+	s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
+    endwhile
+    g/^\s*$/d
+    write
+    bwipeout
+    return script
+endfunction
+
+" ExecAsScript - Source a temporary script made from a function.	    {{{2
+"
+" Make a temporary script file from the function a:funcname, ":source" it, and
+" delete it afterwards.  However, if an exception is thrown the file may remain,
+" the caller should call DeleteTheScript() afterwards.
+let s:script_name = ''
+function! ExecAsScript(funcname)
+    " Make a script from the function passed as argument.
+    let s:script_name = MakeScript(a:funcname)
+
+    " Source and delete the script.
+    exec "source" s:script_name
+    call delete(s:script_name)
+    let s:script_name = ''
+endfunction
+
+function! DeleteTheScript()
+    if s:script_name
+	call delete(s:script_name)
+	let s:script_name = ''
+    endif
+endfunc
+
+com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
+
+
+"-------------------------------------------------------------------------------
+" Test 1:   :endwhile in function					    {{{1
+"
+"	    Detect if a broken loop is (incorrectly) reactivated by the
+"	    :endwhile.  Use a :return to prevent an endless loop, and make
+"	    this test first to get a meaningful result on an error before other
+"	    tests will hang.
+"-------------------------------------------------------------------------------
+
+function! T1_F()
+    Xpath 'a'
+    let first = 1
+    while 1
+	Xpath 'b'
+	if first
+	    Xpath 'c'
+	    let first = 0
+	    break
+	else
+	    Xpath 'd'
+	    return
+	endif
+    endwhile
+endfunction
+
+function! T1_G()
+    Xpath 'h'
+    let first = 1
+    while 1
+	Xpath 'i'
+	if first
+	    Xpath 'j'
+	    let first = 0
+	    break
+	else
+	    Xpath 'k'
+	    return
+	endif
+	if 1	" unmatched :if
+    endwhile
+endfunction
+
+func Test_endwhile_function()
+  XpathINIT
+  call T1_F()
+  Xpath 'F'
+
+  try
+    call T1_G()
+  catch
+    " Catch missing :endif
+    call assert_true(v:exception =~ 'E171')
+    Xpath 'x'
+  endtry
+  Xpath 'G'
+
+  call assert_equal('abcFhijxG', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 2:   :endwhile in script						    {{{1
+"
+"	    Detect if a broken loop is (incorrectly) reactivated by the
+"	    :endwhile.  Use a :finish to prevent an endless loop, and place
+"	    this test before others that might hang to get a meaningful result
+"	    on an error.
+"
+"	    This test executes the bodies of the functions T1_F and T1_G from
+"	    the previous test as script files (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+func Test_endwhile_script()
+  XpathINIT
+  ExecAsScript T1_F
+  Xpath 'F'
+  call DeleteTheScript()
+
+  try
+    ExecAsScript T1_G
+  catch
+    " Catch missing :endif
+    call assert_true(v:exception =~ 'E171')
+    Xpath 'x'
+  endtry
+  Xpath 'G'
+  call DeleteTheScript()
+
+  call assert_equal('abcFhijxG', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 3:   :if, :elseif, :while, :continue, :break			    {{{1
+"-------------------------------------------------------------------------------
+
+function Test_if_while()
+    XpathINIT
+    if 1
+	Xpath 'a'
+	let loops = 3
+	while loops > -1	    " main loop: loops == 3, 2, 1 (which breaks)
+	    if loops <= 0
+		let break_err = 1
+		let loops = -1
+	    else
+		Xpath 'b' . loops
+	    endif
+	    if (loops == 2)
+		while loops == 2 " dummy loop
+		    Xpath 'c' . loops
+		    let loops = loops - 1
+		    continue    " stop dummy loop
+		    Xpath 'd' . loops
+		endwhile
+		continue	    " continue main loop
+		Xpath 'e' . loops
+	    elseif (loops == 1)
+		let p = 1
+		while p	    " dummy loop
+		    Xpath 'f' . loops
+		    let p = 0
+		    break	    " break dummy loop
+		    Xpath 'g' . loops
+		endwhile
+		Xpath 'h' . loops
+		unlet p
+		break	    " break main loop
+		Xpath 'i' . loops
+	    endif
+	    if (loops > 0)
+		Xpath 'j' . loops
+	    endif
+	    while loops == 3    " dummy loop
+		let loops = loops - 1
+	    endwhile	    " end dummy loop
+	endwhile		    " end main loop
+	Xpath 'k'
+    else
+	Xpath 'l'
+    endif
+    Xpath 'm'
+    if exists("break_err")
+	Xpath 'm'
+	unlet break_err
+    endif
+
+    unlet loops
+
+    call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 4:   :return							    {{{1
+"-------------------------------------------------------------------------------
+
+function! T4_F()
+    if 1
+	Xpath 'a'
+	let loops = 3
+	while loops > 0				"    3:  2:     1:
+	    Xpath 'b' . loops
+	    if (loops == 2)
+		Xpath 'c' . loops
+		return
+		Xpath 'd' . loops
+	    endif
+	    Xpath 'e' . loops
+	    let loops = loops - 1
+	endwhile
+	Xpath 'f'
+    else
+	Xpath 'g'
+    endif
+endfunction
+
+function Test_return()
+    XpathINIT
+    call T4_F()
+    Xpath '4'
+
+    call assert_equal('ab3e3b2c24', g:Xpath)
+endfunction
+
+
+"-------------------------------------------------------------------------------
+" Test 5:   :finish							    {{{1
+"
+"	    This test executes the body of the function T4_F from the previous
+"	    test as a script file (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+function Test_finish()
+    XpathINIT
+    ExecAsScript T4_F
+    Xpath '5'
+    call DeleteTheScript()
+
+    call assert_equal('ab3e3b2c25', g:Xpath)
+endfunction
+
+
+
+"-------------------------------------------------------------------------------
+" Test 6:   Defining functions in :while loops				    {{{1
+"
+"	     Functions can be defined inside other functions.  An inner function
+"	     gets defined when the outer function is executed.  Functions may
+"	     also be defined inside while loops.  Expressions in braces for
+"	     defining the function name are allowed.
+"
+"	     The functions are defined when sourcing the script, only the
+"	     resulting path is checked in the test function.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+" The command CALL collects the argument of all its invocations in "calls"
+" when used from a function (that is, when the global variable "calls" needs
+" the "g:" prefix).  This is to check that the function code is skipped when
+" the function is defined.  For inner functions, do so only if the outer
+" function is not being executed.
+"
+let calls = ""
+com! -nargs=1 CALL
+    	\ if !exists("calls") && !exists("outer") |
+    	\ let g:calls = g:calls . <args> |
+    	\ endif
+
+let i = 0
+while i < 3
+    let i = i + 1
+    if i == 1
+	Xpath 'a'
+	function! F1(arg)
+	    CALL a:arg
+	    let outer = 1
+
+	    let j = 0
+	    while j < 1
+		Xpath 'b'
+		let j = j + 1
+		function! G1(arg)
+		    CALL a:arg
+		endfunction
+		Xpath 'c'
+	    endwhile
+	endfunction
+	Xpath 'd'
+
+	continue
+    endif
+
+    Xpath 'e' . i
+    function! F{i}(i, arg)
+	CALL a:arg
+	let outer = 1
+
+	if a:i == 3
+	    Xpath 'f'
+	endif
+	let k = 0
+	while k < 3
+	    Xpath 'g' . k
+	    let k = k + 1
+	    function! G{a:i}{k}(arg)
+		CALL a:arg
+	    endfunction
+	    Xpath 'h' . k
+	endwhile
+    endfunction
+    Xpath 'i'
+
+endwhile
+
+if exists("*G1")
+    Xpath 'j'
+endif
+if exists("*F1")
+    call F1("F1")
+    if exists("*G1")
+        call G1("G1")
+    endif
+endif
+
+if exists("G21") || exists("G22") || exists("G23")
+    Xpath 'k'
+endif
+if exists("*F2")
+    call F2(2, "F2")
+    if exists("*G21")
+        call G21("G21")
+    endif
+    if exists("*G22")
+        call G22("G22")
+    endif
+    if exists("*G23")
+        call G23("G23")
+    endif
+endif
+
+if exists("G31") || exists("G32") || exists("G33")
+    Xpath 'l'
+endif
+if exists("*F3")
+    call F3(3, "F3")
+    if exists("*G31")
+        call G31("G31")
+    endif
+    if exists("*G32")
+        call G32("G32")
+    endif
+    if exists("*G33")
+        call G33("G33")
+    endif
+endif
+
+Xpath 'm'
+
+let g:test6_result = g:Xpath
+let g:test6_calls = calls
+
+unlet calls
+delfunction F1
+delfunction G1
+delfunction F2
+delfunction G21
+delfunction G22
+delfunction G23
+delfunction G31
+delfunction G32
+delfunction G33
+
+function Test_defining_functions()
+    call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
+    call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 7:   Continuing on errors outside functions			    {{{1
+"
+"	    On an error outside a function, the script processing continues
+"	    at the line following the outermost :endif or :endwhile.  When not
+"	    inside an :if or :while, the script processing continues at the next
+"	    line.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if 1
+    Xpath 'a'
+    while 1
+	Xpath 'b'
+	asdf
+	Xpath 'c'
+	break
+    endwhile | Xpath 'd'
+    Xpath 'e'
+endif | Xpath 'f'
+Xpath 'g'
+
+while 1
+    Xpath 'h'
+    if 1
+	Xpath 'i'
+	asdf
+	Xpath 'j'
+    endif | Xpath 'k'
+    Xpath 'l'
+    break
+endwhile | Xpath 'm'
+Xpath 'n'
+
+asdf
+Xpath 'o'
+
+asdf | Xpath 'p'
+Xpath 'q'
+
+let g:test7_result = g:Xpath
+
+func Test_error_in_script()
+    call assert_equal('abghinoq', g:test7_result)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 8:   Aborting and continuing on errors inside functions		    {{{1
+"
+"	    On an error inside a function without the "abort" attribute, the
+"	    script processing continues at the next line (unless the error was
+"	    in a :return command).  On an error inside a function with the
+"	    "abort" attribute, the function is aborted and the script processing
+"	    continues after the function call; the value -1 is returned then.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! T8_F()
+    if 1
+	Xpath 'a'
+	while 1
+	    Xpath 'b'
+	    asdf
+	    Xpath 'c'
+	    asdf | Xpath 'd'
+	    Xpath 'e'
+	    break
+	endwhile
+	Xpath 'f'
+    endif | Xpath 'g'
+    Xpath 'h'
+
+    while 1
+	Xpath 'i'
+	if 1
+	    Xpath 'j'
+	    asdf
+	    Xpath 'k'
+	    asdf | Xpath 'l'
+	    Xpath 'm'
+	endif
+	Xpath 'n'
+	break
+    endwhile | Xpath 'o'
+    Xpath 'p'
+
+    return novar		" returns (default return value 0)
+    Xpath 'q'
+    return 1			" not reached
+endfunction
+
+function! T8_G() abort
+    if 1
+	Xpath 'r'
+	while 1
+	    Xpath 's'
+	    asdf		" returns -1
+	    Xpath 't'
+	    break
+	endwhile
+	Xpath 'v'
+    endif | Xpath 'w'
+    Xpath 'x'
+
+    return -4			" not reached
+endfunction
+
+function! T8_H() abort
+    while 1
+	Xpath 'A'
+	if 1
+	    Xpath 'B'
+	    asdf		" returns -1
+	    Xpath 'C'
+	endif
+	Xpath 'D'
+	break
+    endwhile | Xpath 'E'
+    Xpath 'F'
+
+    return -4			" not reached
+endfunction
+
+" Aborted functions (T8_G and T8_H) return -1.
+let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
+Xpath 'X'
+let g:test8_result = g:Xpath
+
+func Test_error_in_function()
+    call assert_equal(13, g:test8_sum)
+    call assert_equal('abcefghijkmnoprsABX', g:test8_result)
+
+    delfunction T8_F
+    delfunction T8_G
+    delfunction T8_H
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 9:   Continuing after aborted functions				    {{{1
+"
+"	    When a function with the "abort" attribute is aborted due to an
+"	    error, the next function back in the call hierarchy without an
+"	    "abort" attribute continues; the value -1 is returned then.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F() abort
+    Xpath 'a'
+    let result = G()	" not aborted
+    Xpath 'b'
+    if result != 2
+	Xpath 'c'
+    endif
+    return 1
+endfunction
+
+function! G()		" no abort attribute
+    Xpath 'd'
+    if H() != -1	" aborted
+	Xpath 'e'
+    endif
+    Xpath 'f'
+    return 2
+endfunction
+
+function! H() abort
+    Xpath 'g'
+    call I()		" aborted
+    Xpath 'h'
+    return 4
+endfunction
+
+function! I() abort
+    Xpath 'i'
+    asdf		" error
+    Xpath 'j'
+    return 8
+endfunction
+
+if F() != 1
+    Xpath 'k'
+endif
+
+let g:test9_result = g:Xpath
+
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+
+func Test_func_abort()
+    call assert_equal('adgifb', g:test9_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 10:  :if, :elseif, :while argument parsing			    {{{1
+"
+"	    A '"' or '|' in an argument expression must not be mixed up with
+"	    a comment or a next command after a bar.  Parsing errors should
+"	    be recognized.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+    if a:enr == ""
+	Xout "TODO: Add message number for:" a:emsg
+	let v:errmsg = ":" . v:errmsg
+    endif
+    let match = 1
+    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+	let match = 0
+	if v:errmsg == ""
+	    Xout "Message missing."
+	else
+	    let v:errmsg = escape(v:errmsg, '"')
+	    Xout "Unexpected message:" v:errmsg
+	endif
+    endif
+    return match
+endfunction
+
+if 1 || strlen("\"") | Xpath 'a'
+    Xpath 'b'
+endif
+Xpath 'c'
+
+if 0
+elseif 1 || strlen("\"") | Xpath 'd'
+    Xpath 'e'
+endif
+Xpath 'f'
+
+while 1 || strlen("\"") | Xpath 'g'
+    Xpath 'h'
+    break
+endwhile
+Xpath 'i'
+
+let v:errmsg = ""
+if 1 ||| strlen("\"") | Xpath 'j'
+    Xpath 'k'
+endif
+Xpath 'l'
+if !MSG('E15', "Invalid expression")
+    Xpath 'm'
+endif
+
+let v:errmsg = ""
+if 0
+elseif 1 ||| strlen("\"") | Xpath 'n'
+    Xpath 'o'
+endif
+Xpath 'p'
+if !MSG('E15', "Invalid expression")
+    Xpath 'q'
+endif
+
+let v:errmsg = ""
+while 1 ||| strlen("\"") | Xpath 'r'
+    Xpath 's'
+    break
+endwhile
+Xpath 't'
+if !MSG('E15', "Invalid expression")
+    Xpath 'u'
+endif
+
+let g:test10_result = g:Xpath
+delfunction MSG
+
+func Test_expr_parsing()
+    call assert_equal('abcdefghilpt', g:test10_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 11:  :if, :elseif, :while argument evaluation after abort	    {{{1
+"
+"	    When code is skipped over due to an error, the boolean argument to
+"	    an :if, :elseif, or :while must not be evaluated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let calls = 0
+
+function! P(num)
+    let g:calls = g:calls + a:num   " side effect on call
+    return 0
+endfunction
+
+if 1
+    Xpath 'a'
+    asdf		" error
+    Xpath 'b'
+    if P(1)		" should not be called
+	Xpath 'c'
+    elseif !P(2)	" should not be called
+	Xpath 'd'
+    else
+	Xpath 'e'
+    endif
+    Xpath 'f'
+    while P(4)		" should not be called
+	Xpath 'g'
+    endwhile
+    Xpath 'h'
+endif
+Xpath 'x'
+
+let g:test11_calls = calls
+let g:test11_result = g:Xpath
+
+unlet calls
+delfunction P
+
+func Test_arg_abort()
+    call assert_equal(0, g:test11_calls)
+    call assert_equal('ax', g:test11_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 12:  Expressions in braces in skipped code			    {{{1
+"
+"	    In code skipped over due to an error or inactive conditional,
+"	    an expression in braces as part of a variable or function name
+"	    should not be evaluated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! NULL()
+    Xpath 'a'
+    return 0
+endfunction
+
+function! ZERO()
+    Xpath 'b'
+    return 0
+endfunction
+
+function! F0()
+    Xpath 'c'
+endfunction
+
+function! F1(arg)
+    Xpath 'e'
+endfunction
+
+let V0 = 1
+
+Xpath 'f'
+echo 0 ? F{NULL() + V{ZERO()}}() : 1
+
+Xpath 'g'
+if 0
+    Xpath 'h'
+    call F{NULL() + V{ZERO()}}()
+endif
+
+Xpath 'i'
+if 1
+    asdf		" error
+    Xpath 'j'
+    call F1(F{NULL() + V{ZERO()}}())
+endif
+
+Xpath 'k'
+if 1
+    asdf		" error
+    Xpath 'l'
+    call F{NULL() + V{ZERO()}}()
+endif
+
+let g:test12_result = g:Xpath
+
+func Test_braces_skipped()
+    call assert_equal('fgik', g:test12_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 13:  Failure in argument evaluation for :while			    {{{1
+"
+"	    A failure in the expression evaluation for the condition of a :while
+"	    causes the whole :while loop until the matching :endwhile being
+"	    ignored.  Continuation is at the next following line.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+Xpath 'a'
+while asdf
+    Xpath 'b'
+    while 1
+	Xpath 'c'
+	break
+    endwhile
+    Xpath 'd'
+    break
+endwhile
+Xpath 'e'
+
+while asdf | Xpath 'f' | endwhile | Xpath 'g'
+Xpath 'h'
+let g:test13_result = g:Xpath
+
+func Test_while_fail()
+    call assert_equal('aeh', g:test13_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 14:  Failure in argument evaluation for :if			    {{{1
+"
+"	    A failure in the expression evaluation for the condition of an :if
+"	    does not cause the corresponding :else or :endif being matched to
+"	    a previous :if/:elseif.  Neither of both branches of the failed :if
+"	    are executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+    Xpath 'a'
+    let x = 0
+    if x		" false
+	Xpath 'b'
+    elseif !x		" always true
+	Xpath 'c'
+	let x = 1
+	if g:boolvar	" possibly undefined
+	    Xpath 'd'
+	else
+	    Xpath 'e'
+	endif
+	Xpath 'f'
+    elseif x		" never executed
+	Xpath 'g'
+    endif
+    Xpath 'h'
+endfunction
+
+let boolvar = 1
+call F()
+Xpath '-'
+
+unlet boolvar
+call F()
+let g:test14_result = g:Xpath
+
+delfunction F
+
+func Test_if_fail()
+    call assert_equal('acdfh-acfh', g:test14_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 15:  Failure in argument evaluation for :if (bar)		    {{{1
+"
+"	    Like previous test, except that the failing :if ... | ... | :endif
+"	    is in a single line.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+    Xpath 'a'
+    let x = 0
+    if x		" false
+	Xpath 'b'
+    elseif !x		" always true
+	Xpath 'c'
+	let x = 1
+	if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
+	Xpath 'f'
+    elseif x		" never executed
+	Xpath 'g'
+    endif
+    Xpath 'h'
+endfunction
+
+let boolvar = 1
+call F()
+Xpath '-'
+
+unlet boolvar
+call F()
+let g:test15_result = g:Xpath
+
+delfunction F
+
+func Test_if_bar_fail()
+    call assert_equal('acdfh-acfh', g:test15_result)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 90:  Recognizing {} in variable name.			    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_curlies()
+    let s:var = 66
+    let ns = 's'
+    call assert_equal(66, {ns}:var)
+
+    let g:a = {}
+    let g:b = 't'
+    let g:a[g:b] = 77
+    call assert_equal(77, g:a['t'])
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 91:  using type().					    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_type()
+    call assert_equal(0, type(0))
+    call assert_equal(1, type(""))
+    call assert_equal(2, type(function("tr")))
+    call assert_equal(2, type(function("tr", [8])))
+    call assert_equal(3, type([]))
+    call assert_equal(4, type({}))
+    call assert_equal(5, type(0.0))
+    call assert_equal(6, type(v:false))
+    call assert_equal(6, type(v:true))
+    call assert_equal(7, type(v:none))
+    call assert_equal(7, type(v:null))
+    call assert_equal(8, v:t_job)
+    call assert_equal(9, v:t_channel)
+    call assert_equal(v:t_number, type(0))
+    call assert_equal(v:t_string, type(""))
+    call assert_equal(v:t_func, type(function("tr")))
+    call assert_equal(v:t_func, type(function("tr", [8])))
+    call assert_equal(v:t_list, type([]))
+    call assert_equal(v:t_dict, type({}))
+    call assert_equal(v:t_float, type(0.0))
+    call assert_equal(v:t_bool, type(v:false))
+    call assert_equal(v:t_bool, type(v:true))
+    call assert_equal(v:t_none, type(v:none))
+    call assert_equal(v:t_none, type(v:null))
+
+
+    call assert_equal(0, 0 + v:false)
+    call assert_equal(1, 0 + v:true)
+    call assert_equal(0, 0 + v:none)
+    call assert_equal(0, 0 + v:null)
+
+    call assert_equal('v:false', '' . v:false)
+    call assert_equal('v:true', '' . v:true)
+    call assert_equal('v:none', '' . v:none)
+    call assert_equal('v:null', '' . v:null)
+
+    call assert_true(v:false == 0)
+    call assert_false(v:false != 0)
+    call assert_true(v:true == 1)
+    call assert_false(v:true != 1)
+    call assert_false(v:true == v:false)
+    call assert_true(v:true != v:false)
+
+    call assert_true(v:null == 0)
+    call assert_false(v:null != 0)
+    call assert_true(v:none == 0)
+    call assert_false(v:none != 0)
+
+    call assert_true(v:false is v:false)
+    call assert_true(v:true is v:true)
+    call assert_true(v:none is v:none)
+    call assert_true(v:null is v:null)
+
+    call assert_false(v:false isnot v:false)
+    call assert_false(v:true isnot v:true)
+    call assert_false(v:none isnot v:none)
+    call assert_false(v:null isnot v:null)
+
+    call assert_false(v:false is 0)
+    call assert_false(v:true is 1)
+    call assert_false(v:true is v:false)
+    call assert_false(v:none is 0)
+    call assert_false(v:null is 0)
+    call assert_false(v:null is v:none)
+
+    call assert_true(v:false isnot 0)
+    call assert_true(v:true isnot 1)
+    call assert_true(v:true isnot v:false)
+    call assert_true(v:none isnot 0)
+    call assert_true(v:null isnot 0)
+    call assert_true(v:null isnot v:none)
+
+    call assert_equal(v:false, eval(string(v:false)))
+    call assert_equal(v:true, eval(string(v:true)))
+    call assert_equal(v:none, eval(string(v:none)))
+    call assert_equal(v:null, eval(string(v:null)))
+
+    call assert_equal(v:false, copy(v:false))
+    call assert_equal(v:true, copy(v:true))
+    call assert_equal(v:none, copy(v:none))
+    call assert_equal(v:null, copy(v:null))
+
+    call assert_equal([v:false], deepcopy([v:false]))
+    call assert_equal([v:true], deepcopy([v:true]))
+    call assert_equal([v:none], deepcopy([v:none]))
+    call assert_equal([v:null], deepcopy([v:null]))
+
+    call assert_true(empty(v:false))
+    call assert_false(empty(v:true))
+    call assert_true(empty(v:null))
+    call assert_true(empty(v:none))
+
+    func ChangeYourMind()
+      try
+	return v:true
+      finally
+        return 'something else'
+      endtry
+    endfunc
+
+    call ChangeYourMind()
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 92:  skipping code					    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_skip()
+    let Fn = function('Test_type')
+    call assert_false(0 && Fn[1])
+    call assert_false(0 && string(Fn))
+    call assert_false(0 && len(Fn))
+    let l = []
+    call assert_false(0 && l[1])
+    call assert_false(0 && string(l))
+    call assert_false(0 && len(l))
+    let f = 1.0
+    call assert_false(0 && f[1])
+    call assert_false(0 && string(f))
+    call assert_false(0 && len(f))
+    let sp = v:null
+    call assert_false(0 && sp[1])
+    call assert_false(0 && string(sp))
+    call assert_false(0 && len(sp))
+
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 93:  :echo and string()					    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_echo_and_string()
+    " String
+    let a = 'foo bar'
+    redir => result
+    echo a
+    echo string(a)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["foo bar",
+		     \ "'foo bar'"], l)
+
+    " Float
+    if has('float')
+	let a = -1.2e0
+	redir => result
+	echo a
+	echo string(a)
+	redir END
+	let l = split(result, "\n")
+	call assert_equal(["-1.2",
+			 \ "-1.2"], l)
+    endif
+
+    " Funcref
+    redir => result
+    echo function('string')
+    echo string(function('string'))
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["string",
+		     \ "function('string')"], l)
+
+    " Recursive dictionary
+    let a = {}
+    let a["a"] = a
+    redir => result
+    echo a
+    echo string(a)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': {...}}",
+		     \ "{'a': {...}}"], l)
+
+    " Recursive list
+    let a = [0]
+    let a[0] = a
+    redir => result
+    echo a
+    echo string(a)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[[...]]",
+		     \ "[[...]]"], l)
+
+    " Empty dictionaries in a list
+    let a = {}
+    redir => result
+    echo [a, a, a]
+    echo string([a, a, a])
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[{}, {}, {}]",
+		     \ "[{}, {}, {}]"], l)
+
+    " Empty dictionaries in a dictionary
+    let a = {}
+    let b = {"a": a, "b": a}
+    redir => result
+    echo b
+    echo string(b)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': {}, 'b': {}}",
+		     \ "{'a': {}, 'b': {}}"], l)
+
+    " Empty lists in a list
+    let a = []
+    redir => result
+    echo [a, a, a]
+    echo string([a, a, a])
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[[], [], []]",
+		     \ "[[], [], []]"], l)
+
+    " Empty lists in a dictionary
+    let a = []
+    let b = {"a": a, "b": a}
+    redir => result
+    echo b
+    echo string(b)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': [], 'b': []}",
+		     \ "{'a': [], 'b': []}"], l)
+
+    " Dictionaries in a list
+    let a = {"one": "yes", "two": "yes", "three": "yes"}
+    redir => result
+    echo [a, a, a]
+    echo string([a, a, a])
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
+		     \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
+
+    " Dictionaries in a dictionary
+    let a = {"one": "yes", "two": "yes", "three": "yes"}
+    let b = {"a": a, "b": a}
+    redir => result
+    echo b
+    echo string(b)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
+		     \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
+
+    " Lists in a list
+    let a = [1, 2, 3]
+    redir => result
+    echo [a, a, a]
+    echo string([a, a, a])
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[[1, 2, 3], [...], [...]]",
+		     \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
+
+    " Lists in a dictionary
+    let a = [1, 2, 3]
+    let b = {"a": a, "b": a}
+    redir => result
+    echo b
+    echo string(b)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
+		     \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
+
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 94:  64-bit Numbers					    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_num64()
+    if !has('num64')
+	return
+    endif
+
+    call assert_notequal( 4294967296, 0)
+    call assert_notequal(-4294967296, 0)
+    call assert_equal( 4294967296,  0xFFFFffff + 1)
+    call assert_equal(-4294967296, -0xFFFFffff - 1)
+
+    call assert_equal( 9223372036854775807,  1 / 0)
+    call assert_equal(-9223372036854775807, -1 / 0)
+    call assert_equal(-9223372036854775807 - 1,  0 / 0)
+
+    call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
+    call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
+
+    let rng = range(0xFFFFffff, 0x100000001)
+    call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
+    call assert_equal(0x100000001, max(rng))
+    call assert_equal(0xFFFFffff, min(rng))
+    call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 95:  lines of :append, :change, :insert			    {{{1
+"-------------------------------------------------------------------------------
+
+function! DefineFunction(name, body)
+    let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
+    exec func
+endfunction
+
+func Test_script_lines()
+    " :append
+    try
+        call DefineFunction('T_Append', [
+                    \ 'append',
+                    \ 'py <<EOS',
+                    \ '.',
+                    \ ])
+    catch
+        call assert_false(1, "Can't define function")
+    endtry
+    try
+        call DefineFunction('T_Append', [
+                    \ 'append',
+                    \ 'abc',
+                    \ ])
+        call assert_false(1, "Shouldn't be able to define function")
+    catch
+        call assert_exception('Vim(function):E126: Missing :endfunction')
+    endtry
+
+    " :change
+    try
+        call DefineFunction('T_Change', [
+                    \ 'change',
+                    \ 'py <<EOS',
+                    \ '.',
+                    \ ])
+    catch
+        call assert_false(1, "Can't define function")
+    endtry
+    try
+        call DefineFunction('T_Change', [
+                    \ 'change',
+                    \ 'abc',
+                    \ ])
+        call assert_false(1, "Shouldn't be able to define function")
+    catch
+        call assert_exception('Vim(function):E126: Missing :endfunction')
+    endtry
+
+    " :insert
+    try
+        call DefineFunction('T_Insert', [
+                    \ 'insert',
+                    \ 'py <<EOS',
+                    \ '.',
+                    \ ])
+    catch
+        call assert_false(1, "Can't define function")
+    endtry
+    try
+        call DefineFunction('T_Insert', [
+                    \ 'insert',
+                    \ 'abc',
+                    \ ])
+        call assert_false(1, "Shouldn't be able to define function")
+    catch
+        call assert_exception('Vim(function):E126: Missing :endfunction')
+    endtry
+endfunc
+
+"-------------------------------------------------------------------------------
+" Modelines								    {{{1
+" vim: ts=8 sw=4 tw=80 fdm=marker
+" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
+"-------------------------------------------------------------------------------