changeset 19689:da98d2ed8dc5 v8.2.0401

patch 8.2.0401: not enough test coverage for evalvars.c Commit: https://github.com/vim/vim/commit/8dfcce3a78ccb520cc9d09081f998091494c50bf Author: Bram Moolenaar <Bram@vim.org> Date: Wed Mar 18 19:32:26 2020 +0100 patch 8.2.0401: not enough test coverage for evalvars.c Problem: Not enough test coverage for evalvars.c. Solution: Add more tests. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/5804)
author Bram Moolenaar <Bram@vim.org>
date Wed, 18 Mar 2020 19:45:04 +0100
parents 8d01c76e0bc7
children 7f881865a240
files src/testdir/test_cmdline.vim src/testdir/test_const.vim src/testdir/test_diffmode.vim src/testdir/test_excmd.vim src/testdir/test_functions.vim src/testdir/test_let.vim src/testdir/test_listdict.vim src/testdir/test_spell.vim src/testdir/test_unlet.vim src/testdir/test_user_func.vim src/testdir/test_vimscript.vim src/version.c
diffstat 12 files changed, 274 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -784,6 +784,40 @@ func Test_cmdline_complete_various()
   " completion for the expression register
   call feedkeys(":\"\<C-R>=float2\t\"\<C-B>\"\<CR>", 'xt')
   call assert_equal('"float2nr("', @=)
+
+  " completion for :language command with an invalid argument
+  call feedkeys(":language dummy \t\<C-B>\"\<CR>", 'xt')
+  call assert_equal("\"language dummy \t", @:)
+
+  " completion for commands after a :global command
+  call feedkeys(":g/a\\xb/call float2\t\<C-B>\"\<CR>", 'xt')
+  call assert_equal('"g/a\xb/call float2nr(', @:)
+
+  " completion with ambiguous user defined commands
+  com TCmd1 echo 'TCmd1'
+  com TCmd2 echo 'TCmd2'
+  call feedkeys(":TCmd \t\<C-B>\"\<CR>", 'xt')
+  call assert_equal('"TCmd ', @:)
+  delcom TCmd1
+  delcom TCmd2
+
+  " completion after a range followed by a pipe (|) character
+  call feedkeys(":1,10 | chist\t\<C-B>\"\<CR>", 'xt')
+  call assert_equal('"1,10 | chistory', @:)
+
+  " completion for window local variables
+  let w:wvar1 = 10
+  let w:wvar2 = 10
+  call feedkeys(":echo w:wvar\<C-A>\<C-B>\"\<CR>", 'xt')
+  call assert_equal('"echo w:wvar1 w:wvar2', @:)
+  unlet w:wvar1 w:wvar2
+
+  " completion for tab local variables
+  let t:tvar1 = 10
+  let t:tvar2 = 10
+  call feedkeys(":echo t:tvar\<C-A>\<C-B>\"\<CR>", 'xt')
+  call assert_equal('"echo t:tvar1 t:tvar2', @:)
+  unlet t:tvar1 t:tvar2
 endfunc
 
 func Test_cmdline_write_alternatefile()
@@ -1304,16 +1338,16 @@ func Test_wildmode()
   " Test for wildmode=longest with 'fileignorecase' set
   set wildmode=longest
   set fileignorecase
-  argadd AA AAA AAAA
-  call feedkeys(":buffer \t\<C-B>\"\<CR>", 'xt')
-  call assert_equal('"buffer AA', @:)
+  argadd AAA AAAA AAAAA
+  call feedkeys(":buffer a\t\<C-B>\"\<CR>", 'xt')
+  call assert_equal('"buffer AAA', @:)
   set fileignorecase&
 
   " Test for listing files with wildmode=list
   set wildmode=list
   let g:Sline = ''
   call feedkeys(":b A\t\t\<F2>\<C-B>\"\<CR>", 'xt')
-  call assert_equal('AA    AAA   AAAA', g:Sline)
+  call assert_equal('AAA    AAAA   AAAAA', g:Sline)
   call assert_equal('"b A', @:)
 
   %argdelete
--- a/src/testdir/test_const.vim
+++ b/src/testdir/test_const.vim
@@ -251,6 +251,14 @@ func Test_const_with_special_variables()
     call assert_fails('const &filetype = "vim"', 'E996:')
     call assert_fails('const &l:filetype = "vim"', 'E996:')
     call assert_fails('const &g:encoding = "utf-8"', 'E996:')
+
+    call assert_fails('const [a, $CONST_FOO] = [369, "abc"]', 'E996:')
+    call assert_equal(369, a)
+    call assert_equal(v:null, getenv("CONST_FOO"))
+
+    call assert_fails('const [b; $CONST_FOO] = [246, 2, "abc"]', 'E996:')
+    call assert_equal(246, b)
+    call assert_equal(v:null, getenv("CONST_FOO"))
 endfunc
 
 func Test_const_with_eval_name()
@@ -276,3 +284,5 @@ func Test_lock_depth_is_1()
     let d['bar'] = 'hello'
     let d.foo = 44
 endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
--- a/src/testdir/test_diffmode.vim
+++ b/src/testdir/test_diffmode.vim
@@ -1065,3 +1065,32 @@ func Test_diff_maintains_change_mark()
   bwipe!
   bwipe!
 endfunc
+
+" Test for 'patchexpr'
+func Test_patchexpr()
+  let g:patch_args = []
+  func TPatch()
+    call add(g:patch_args, readfile(v:fname_in))
+    call add(g:patch_args, readfile(v:fname_diff))
+    call writefile(['output file'], v:fname_out)
+  endfunc
+  set patchexpr=TPatch()
+
+  call writefile(['input file'], 'Xinput')
+  call writefile(['diff file'], 'Xdiff')
+  %bwipe!
+  edit Xinput
+  diffpatch Xdiff
+  call assert_equal('output file', getline(1))
+  call assert_equal('Xinput.new', bufname())
+  call assert_equal(2, winnr('$'))
+  call assert_true(&diff)
+
+  call delete('Xinput')
+  call delete('Xdiff')
+  set patchexpr&
+  delfunc TPatch
+  %bwipe!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
--- a/src/testdir/test_excmd.vim
+++ b/src/testdir/test_excmd.vim
@@ -276,12 +276,21 @@ endfunc
 func Test_redir_cmd()
   call assert_fails('redir @@', 'E475:')
   call assert_fails('redir abc', 'E475:')
+  call assert_fails('redir => 1abc', 'E474:')
+  call assert_fails('redir => a b', 'E488:')
+  call assert_fails('redir => abc[1]', 'E474:')
+  let b=0zFF
+  call assert_fails('redir =>> b', 'E734:')
+  unlet b
+
   if has('unix')
+    " Redirecting to a directory name
     call mkdir('Xdir')
     call assert_fails('redir > Xdir', 'E17:')
     call delete('Xdir', 'd')
   endif
   if !has('bsd')
+    " Redirecting to a read-only file
     call writefile([], 'Xfile')
     call setfperm('Xfile', 'r--r--r--')
     call assert_fails('redir! > Xfile', 'E190:')
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -800,6 +800,10 @@ func Test_getbufvar()
   call assert_equal(0, getbufvar(bnr, '&autoindent'))
   call assert_equal(0, getbufvar(bnr, '&autoindent', 1))
 
+  " Set and get a buffer-local variable
+  call setbufvar(bnr, 'bufvar_test', ['one', 'two'])
+  call assert_equal(['one', 'two'], getbufvar(bnr, 'bufvar_test'))
+
   " Open new window with forced option values
   set fileformats=unix,dos
   new ++ff=dos ++bin ++enc=iso-8859-2
@@ -1498,6 +1502,10 @@ func Test_func_sandbox()
 
   call assert_fails('call Fsandbox()', 'E48:')
   delfunc Fsandbox
+
+  " From a sandbox try to set a predefined variable (which cannot be modified
+  " from a sandbox)
+  call assert_fails('sandbox let v:lnum = 10', 'E794:')
 endfunc
 
 func EditAnotherFile()
@@ -2030,14 +2038,6 @@ func Test_range()
   " sort()
   call assert_equal([0, 1, 2, 3, 4, 5], sort(range(5, 0, -1)))
 
-  " 'spellsuggest'
-  func MySuggest()
-    return range(3)
-  endfunc
-  set spell spellsuggest=expr:MySuggest()
-  call assert_equal([], spellsuggest('baord', 3))
-  set nospell spellsuggest&
-
   " string()
   call assert_equal('[0, 1, 2, 3, 4]', string(range(5)))
 
--- a/src/testdir/test_let.vim
+++ b/src/testdir/test_let.vim
@@ -25,9 +25,62 @@ func Test_let()
   let s = "\na                     #1\nb                     #2"
   call assert_equal(s, out)
 
+  " Test for displaying a string variable
+  let s = 'vim'
+  let out = execute('let s')
+  let s = "\ns                      vim"
+  call assert_equal(s, out)
+
+  " Test for displaying a list variable
+  let l = [1, 2]
+  let out = execute('let l')
+  let s = "\nl                     [1, 2]"
+  call assert_equal(s, out)
+
+  " Test for displaying a dict variable
+  let d = {'k' : 'v'}
+  let out = execute('let d')
+  let s = "\nd                     {'k': 'v'}"
+  call assert_equal(s, out)
+
+  " Test for displaying a function reference variable
+  let F = function('min')
+  let out = execute('let F')
+  let s = "\nF                     *min()"
+  call assert_equal(s, out)
+
   let x = 0
   if 0 | let x = 1 | endif
   call assert_equal(0, x)
+
+  " Display a list item using an out of range index
+  let l = [10]
+  call assert_fails('let l[1]', 'E684:')
+
+  " List special variable dictionaries
+  let g:Test_Global_Var = 5
+  call assert_match("\nTest_Global_Var       #5", execute('let g:'))
+  unlet g:Test_Global_Var
+
+  let b:Test_Buf_Var = 8
+  call assert_match("\nb:Test_Buf_Var        #8", execute('let b:'))
+  unlet b:Test_Buf_Var
+
+  let w:Test_Win_Var = 'foo'
+  call assert_equal("\nw:Test_Win_Var         foo", execute('let w:'))
+  unlet w:Test_Win_Var
+
+  let t:Test_Tab_Var = 'bar'
+  call assert_equal("\nt:Test_Tab_Var         bar", execute('let t:'))
+  unlet t:Test_Tab_Var
+
+  let s:Test_Script_Var = [7]
+  call assert_match("\ns:Test_Script_Var     \\[7]", execute('let s:'))
+  unlet s:Test_Script_Var
+
+  let l:Test_Local_Var = {'k' : 5}
+  call assert_match("\nl:Test_Local_Var      {'k': 5}", execute('let l:'))
+  call assert_match("v:errors              []", execute('let v:'))
 endfunc
 
 func s:set_arg1(a) abort
@@ -200,16 +253,45 @@ func Test_let_option_error()
   let &fillchars = _w
 endfunc
 
+" Errors with the :let statement
 func Test_let_errors()
   let s = 'abcd'
   call assert_fails('let s[1] = 5', 'E689:')
 
   let l = [1, 2, 3]
   call assert_fails('let l[:] = 5', 'E709:')
+
+  call assert_fails('let x:lnum=5', 'E488:')
+  call assert_fails('let v:=5', 'E461:')
+  call assert_fails('let [a]', 'E474:')
+  call assert_fails('let [a, b] = [', 'E697:')
+  call assert_fails('let [a, b] = [10, 20', 'E696:')
+  call assert_fails('let [a, b] = 10', 'E714:')
+  call assert_fails('let [a, , b] = [10, 20]', 'E475:')
+  call assert_fails('let [a, b&] = [10, 20]', 'E475:')
+  call assert_fails('let $ = 10', 'E475:')
+  call assert_fails('let $FOO[1] = "abc"', 'E18:')
+  call assert_fails('let &buftype[1] = "nofile"', 'E18:')
+  let s = "var"
+  let var = 1
+  call assert_fails('let {s}.1 = 2', 'E18:')
+
+  " This test works only when the language is English
+  if v:lang == "C" || v:lang =~ '^[Ee]n'
+    call assert_fails('let [a ; b;] = [10, 20]',
+          \ 'Double ; in list of variables')
+  endif
 endfunc
 
 func Test_let_heredoc_fails()
   call assert_fails('let v =<< marker', 'E991:')
+  try
+    exe "let v =<< TEXT | abc | TEXT"
+    call assert_report('No exception thrown')
+  catch /E488:/
+  catch
+    call assert_report("Caught exception: " .. v:exception)
+  endtry
 
   let text =<< trim END
   func WrongSyntax()
@@ -242,6 +324,10 @@ func Test_let_heredoc_fails()
   call writefile(text, 'XheredocBadMarker')
   call assert_fails('source XheredocBadMarker', 'E221:')
   call delete('XheredocBadMarker')
+
+  call writefile(['let v =<< TEXT', 'abc'], 'XheredocMissingMarker')
+  call assert_fails('source XheredocMissingMarker', 'E990:')
+  call delete('XheredocMissingMarker')
 endfunc
 
 func Test_let_heredoc_trim_no_indent_marker()
@@ -368,3 +454,5 @@ E
 END
   call assert_equal(['     x', '     \y', '     z'], [a, b, c])
 endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
--- a/src/testdir/test_listdict.vim
+++ b/src/testdir/test_listdict.vim
@@ -559,6 +559,18 @@ func Test_let_lock_list()
   unlet l
 endfunc
 
+" Locking part of the list
+func Test_let_lock_list_items()
+  let l = [1, 2, 3, 4]
+  lockvar l[2:]
+  call assert_equal(0, islocked('l[0]'))
+  call assert_equal(1, islocked('l[2]'))
+  call assert_equal(1, islocked('l[3]'))
+  call assert_fails('let l[2] = 10', 'E741:')
+  call assert_fails('let l[3] = 20', 'E741:')
+  unlet l
+endfunc
+
 " lockvar/islocked() triggering script autoloading
 func Test_lockvar_script_autoload()
   let old_rtp = &rtp
@@ -791,3 +803,43 @@ func Test_scope_dict()
   " Test for v:
   call s:check_scope_dict('v', v:true)
 endfunc
+
+" Test for deep nesting of lists (> 100)
+func Test_deep_nested_list()
+  let deep_list = []
+  let l = deep_list
+  for i in range(102)
+    let newlist = []
+    call add(l, newlist)
+    let l = newlist
+  endfor
+  call add(l, 102)
+
+  call assert_fails('let m = deepcopy(deep_list)', 'E698:')
+  call assert_fails('lockvar 110 deep_list', 'E743:')
+  call assert_fails('unlockvar 110 deep_list', 'E743:')
+  call assert_fails('let x = execute("echo deep_list")', 'E724:')
+  call test_garbagecollect_now()
+  unlet deep_list
+endfunc
+
+" Test for deep nesting of dicts (> 100)
+func Test_deep_nested_dict()
+  let deep_dict = {}
+  let d = deep_dict
+  for i in range(102)
+    let newdict = {}
+    let d.k = newdict
+    let d = newdict
+  endfor
+  let d.k = 'v'
+
+  call assert_fails('let m = deepcopy(deep_dict)', 'E698:')
+  call assert_fails('lockvar 110 deep_dict', 'E743:')
+  call assert_fails('unlockvar 110 deep_dict', 'E743:')
+  call assert_fails('let x = execute("echo deep_dict")', 'E724:')
+  call test_garbagecollect_now()
+  unlet deep_dict
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
--- a/src/testdir/test_spell.vim
+++ b/src/testdir/test_spell.vim
@@ -298,6 +298,35 @@ func Test_spellsuggest_option_expr()
   bwipe!
 endfunc
 
+" Test for 'spellsuggest' expr errrors
+func Test_spellsuggest_expr_errors()
+  " 'spellsuggest'
+  func MySuggest()
+    return range(3)
+  endfunc
+  set spell spellsuggest=expr:MySuggest()
+  call assert_equal([], spellsuggest('baord', 3))
+
+  " Test for 'spellsuggest' expression returning a non-list value
+  func! MySuggest2()
+    return 'good'
+  endfunc
+  set spellsuggest=expr:MySuggest2()
+  call assert_equal([], spellsuggest('baord'))
+
+  " Test for 'spellsuggest' expression returning a list with dict values
+  func! MySuggest3()
+    return [[{}, {}]]
+  endfunc
+  set spellsuggest=expr:MySuggest3()
+  call assert_fails("call spellsuggest('baord')", 'E728:')
+
+  set nospell spellsuggest&
+  delfunc MySuggest
+  delfunc MySuggest2
+  delfunc MySuggest3
+endfunc
+
 func Test_spellinfo()
   new
   let runtime = substitute($VIMRUNTIME, '\\', '/', 'g')
--- a/src/testdir/test_unlet.vim
+++ b/src/testdir/test_unlet.vim
@@ -20,6 +20,7 @@ endfunc
 
 func Test_unlet_fails()
   call assert_fails('unlet v:["count"]', 'E46:')
+  call assert_fails('unlet $', 'E475:')
 endfunc
 
 func Test_unlet_env()
@@ -55,3 +56,5 @@ func Test_unlet_complete()
   call feedkeys(":unlet $FOO\t\n", 'tx')
   call assert_true(!exists('$FOOBAR') || empty($FOOBAR))
 endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
--- a/src/testdir/test_user_func.vim
+++ b/src/testdir/test_user_func.vim
@@ -87,6 +87,9 @@ func Test_user_func()
   call assert_fails("call extend(g:, {'max': function('min')})", 'E704')
   call assert_equal(3, max([1, 2, 3]))
 
+  " Try to overwrite an user defined function with a function reference
+  call assert_fails("let Expr1 = function('min')", 'E705:')
+
   " Regression: the first line below used to throw ?E110: Missing ')'?
   " Second is here just to prove that this line is correct when not skipping
   " rhs of &&.
--- a/src/testdir/test_vimscript.vim
+++ b/src/testdir/test_vimscript.vim
@@ -1623,6 +1623,9 @@ func Test_delfunction_force()
     endfunc
     delfunc! Xtest
     delfunc! Xtest
+
+    " Try deleting the current function
+    call assert_fails('delfunc Test_delfunction_force', 'E131:')
 endfunc
 
 " Test using bang after user command				    {{{1
--- a/src/version.c
+++ b/src/version.c
@@ -739,6 +739,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    401,
+/**/
     400,
 /**/
     399,