diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-10-22 09:05:14 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-22 09:05:14 +0800 |
commit | f663243e95f488b8f4224bdae2697ddac21d0ffb (patch) | |
tree | 944b6e4c5e0593605060ce96861d5f3ddf94a100 | |
parent | c8e47f648052f8001d8a493cf7ca6c4867a36bc3 (diff) | |
download | rneovim-f663243e95f488b8f4224bdae2697ddac21d0ffb.tar.gz rneovim-f663243e95f488b8f4224bdae2697ddac21d0ffb.tar.bz2 rneovim-f663243e95f488b8f4224bdae2697ddac21d0ffb.zip |
vim-patch:9.1.0797: testing of options can be further improved (#30893)
Problem: testing of options can be further improved
Solution: split the generated option test into test_options_all.vim,
add more test cases, save and restore values, fix use-after-free
closes: vim/vim#15894
https://github.com/vim/vim/commit/6eca04e9f1d446dc509ba51e32da56fa413fe2f0
Co-authored-by: Milly <milly.ca@gmail.com>
-rw-r--r-- | runtime/doc/options.txt | 2 | ||||
-rwxr-xr-x | scripts/gen_eval_files.lua | 2 | ||||
-rw-r--r-- | src/nvim/main.c | 6 | ||||
-rw-r--r-- | test/old/testdir/Makefile | 4 | ||||
-rw-r--r-- | test/old/testdir/gen_opt_test.vim | 223 | ||||
-rw-r--r-- | test/old/testdir/test_options.vim | 12 | ||||
-rw-r--r-- | test/old/testdir/test_options_all.vim | 13 |
7 files changed, 194 insertions, 68 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index e6065acb5e..44c5934233 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1417,7 +1417,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'cmdheight'* *'ch'* 'cmdheight' 'ch' number (default 1) - global or local to tab page |global-local| + global or local to tab page Number of screen lines to use for the command-line. Helps avoiding |hit-enter| prompts. The value of this option is stored with the tab page, so that each tab diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index b9ea4e73f0..eb92e10401 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -670,7 +670,7 @@ local function scope_to_doc(s) return m[s[1]] end assert(s[1] == 'global') - return 'global or ' .. m[s[2]] .. ' |global-local|' + return 'global or ' .. m[s[2]] .. (s[2] ~= 'tab' and ' |global-local|' or '') end -- @param o vim.option_meta diff --git a/src/nvim/main.c b/src/nvim/main.c index 436c3ccc7a..695bd4c95a 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -777,7 +777,11 @@ void getout(int exitval) } } - if (p_shada && *p_shada != NUL) { + if ( +#ifdef EXITFREE + !entered_free_all_mem && +#endif + p_shada && *p_shada != NUL) { // Write out the registers, history, marks etc, to the ShaDa file shada_write_file(NULL, false); } diff --git a/test/old/testdir/Makefile b/test/old/testdir/Makefile index 6f6c90fda1..d73571f463 100644 --- a/test/old/testdir/Makefile +++ b/test/old/testdir/Makefile @@ -154,7 +154,7 @@ newtests: newtestssilent newtestssilent: $(NEW_TESTS_RES) -GEN_OPT_DEPS = gen_opt_test.vim ../../../src/nvim/options.lua +GEN_OPT_DEPS = gen_opt_test.vim ../../../src/nvim/options.lua ../../../runtime/doc/options.txt opt_test.vim: $(GEN_OPT_DEPS) $(NVIM_PRG) -e -s -u NONE $(NO_INITS) -S $(GEN_OPT_DEPS) @@ -164,7 +164,7 @@ opt_test.vim: $(GEN_OPT_DEPS) fi # Explicit dependencies. -test_options.res test_alot.res: opt_test.vim +test_options_all.res: opt_test.vim %.res: %.vim .gdbinit @echo "[OLDTEST] Running" $* diff --git a/test/old/testdir/gen_opt_test.vim b/test/old/testdir/gen_opt_test.vim index e2002cd5a0..85f5e33dcf 100644 --- a/test/old/testdir/gen_opt_test.vim +++ b/test/old/testdir/gen_opt_test.vim @@ -1,4 +1,10 @@ -" Script to generate testdir/opt_test.vim from options.lua +" Script to generate test/old/testdir/opt_test.vim from src/nvim/options.lua +" and runtime/doc/options.txt + +set cpo&vim + +" Only do this when build with the +eval feature. +if 1 try @@ -6,13 +12,64 @@ set nomore const K_KENTER = -16715 +" Get global-local options. +" "key" is full-name of the option. +" "value" is the local value to switch back to the global value. +b options.txt +call cursor(1, 1) +let global_locals = {} +while search("^'[^']*'.*\\n.*|global-local", 'W') + let fullname = getline('.')->matchstr("^'\\zs[^']*") + let global_locals[fullname] = '' +endwhile +call extend(global_locals, #{ + \ scrolloff: -1, + \ sidescrolloff: -1, + \ undolevels: -12345, + \}) + +" Get local-noglobal options. +" "key" is full-name of the option. +" "value" is no used. +b options.txt +call cursor(1, 1) +let local_noglobals = {} +while search("^'[^']*'.*\\n.*|local-noglobal", 'W') + let fullname = getline('.')->matchstr("^'\\zs[^']*") + let local_noglobals[fullname] = v:true +endwhile + +" Options to skip `setglobal` tests. +" "key" is full-name of the option. +" "value" is the reason. +let skip_setglobal_reasons = #{ + \ iminsert: 'The global value is always overwritten by the local value', + \ imsearch: 'The global value is always overwritten by the local value', + \ breakindentopt: 'TODO: fix missing error handling for setglobal', + \ colorcolumn: 'TODO: fix missing error handling for setglobal', + \ conceallevel: 'TODO: fix missing error handling for setglobal', + \ foldcolumn: 'TODO: fix missing error handling for setglobal', + \ foldmethod: 'TODO: fix `setglobal fdm=` not given an error', + \ iskeyword: 'TODO: fix missing error handling for setglobal', + \ numberwidth: 'TODO: fix missing error handling for setglobal', + \ scrolloff: 'TODO: fix missing error handling for setglobal', + \ shiftwidth: 'TODO: fix missing error handling for setglobal', + \ sidescrolloff: 'TODO: fix missing error handling for setglobal', + \ signcolumn: 'TODO(nvim): fix missing error handling for setglobal', + \ spelloptions: 'TODO(nvim): fix missing error handling for setglobal', + \ tabstop: 'TODO: fix missing error handling for setglobal', + \ termwinkey: 'TODO: fix missing error handling for setglobal', + \ termwinsize: 'TODO: fix missing error handling for setglobal', + \ textwidth: 'TODO: fix missing error handling for setglobal', + \ winhighlight: 'TODO(nvim): fix missing error handling for setglobal', + \} + " The terminal size is restored at the end. let script = [ \ '" DO NOT EDIT: Generated with gen_opt_test.vim', - \ '" Used by test_options.vim.', + \ '" Used by test_options_all.vim.', \ '', - \ 'let save_columns = &columns', - \ 'let save_lines = &lines', + \ 'scriptencoding utf-8', \ ] let options = luaeval('loadfile("../../../src/nvim/options.lua")().options') @@ -314,6 +371,27 @@ let test_values = { \ 'otherstring': [['', 'xxx'], []], \} +" Two lists with values: values that pre- and post-processing in test. +" Clear out t_WS: we don't want to resize the actual terminal. +let test_prepost = { + \ 'browsedir': [["call mkdir('Xdir with space', 'D')"], []], + \ 'columns': [[ + \ 'set t_WS=', + \ 'let save_columns = &columns' + \ ], [ + \ 'let &columns = save_columns', + \ 'set t_WS&' + \ ]], + \ 'lines': [[ + \ 'set t_WS=', + \ 'let save_lines = &lines' + \ ], [ + \ 'let &lines = save_lines', + \ 'set t_WS&' + \ ]], + \ 'verbosefile': [[], ['call delete("Xfile")']], + \} + const invalid_options = test_values->keys() \->filter({-> v:val !~# '^other' && !exists($"&{v:val}")}) if !empty(invalid_options) @@ -321,69 +399,102 @@ if !empty(invalid_options) endif for option in options - let name = option.full_name - let shortname = get(option, 'abbreviation', name) + let fullname = option.full_name + let shortname = get(option, 'abbreviation', fullname) if get(option, 'immutable', v:false) continue endif - if has_key(test_values, name) - let a = test_values[name] - elseif option.type == 'number' - let a = test_values['othernum'] - else - let a = test_values['otherstring'] + let [valid_values, invalid_values] = test_values[ + \ has_key(test_values, fullname) ? fullname + \ : option.type == 'number' ? 'othernum' + \ : 'otherstring'] + + if empty(valid_values) && empty(invalid_values) + continue endif - if len(a[0]) > 0 || len(a[1]) > 0 - if name == 'browsedir' - call add(script, 'call mkdir("Xdir with space")') - endif - if option.type == 'boolean' - call add(script, 'set ' . name) - call add(script, 'set ' . shortname) - call add(script, 'set no' . name) - call add(script, 'set no' . shortname) - else - for val in a[0] - call add(script, 'set ' . name . '=' . val) - call add(script, 'set ' . shortname . '=' . val) - endfor + call add(script, $"func Test_opt_set_{fullname}()") + call add(script, $"if exists('+{fullname}') && execute('set!') =~# '\\n..{fullname}\\([=\\n]\\|$\\)'") + call add(script, $"let l:saved = [&g:{fullname}, &l:{fullname}]") + call add(script, 'endif') + + let [pre_processing, post_processing] = get(test_prepost, fullname, [[], []]) + let script += pre_processing - " setting an option can only fail when it's implemented. - call add(script, "if exists('+" . name . "')") - for val in a[1] - call add(script, "silent! call assert_fails('set " . name . "=" . val . "')") - call add(script, "silent! call assert_fails('set " . shortname . "=" . val . "')") + if option.type == 'boolean' + for opt in [fullname, shortname] + for cmd in ['set', 'setlocal', 'setglobal'] + call add(script, $'{cmd} {opt}') + call add(script, $'{cmd} no{opt}') + call add(script, $'{cmd} inv{opt}') + call add(script, $'{cmd} {opt}!') + endfor + endfor + else " P_NUM || P_STRING + " Normal tests + for opt in [fullname, shortname] + for cmd in ['set', 'setlocal', 'setglobal'] + for val in valid_values + if local_noglobals->has_key(fullname) && cmd ==# 'setglobal' + " Skip `:setglobal {option}={val}` for local-noglobal option. + " It has no effect. + let pre = '" Skip local-noglobal: ' + else + let pre = '' + endif + call add(script, $'{pre}{cmd} {opt}={val}') + endfor endfor - call add(script, "endif") - endif + " Testing to clear the local value and switch back to the global value. + if global_locals->has_key(fullname) + let swichback_val = global_locals[fullname] + call add(script, $'setlocal {opt}={swichback_val}') + endif + endfor - " cannot change 'termencoding' in GTK - if name != 'termencoding' || !has('gui_gtk') - call add(script, 'set ' . name . '&') - call add(script, 'set ' . shortname . '&') - endif - if name == 'browsedir' - call add(script, 'call delete("Xdir with space", "d")') - elseif name == 'verbosefile' - call add(script, 'call delete("Xfile")') - endif + " Failure tests + " Setting an option can only fail when it's implemented. + call add(script, $"if exists('+{fullname}')") + for opt in [fullname, shortname] + for cmd in ['set', 'setlocal', 'setglobal'] + for val in invalid_values + if val is# global_locals->get(fullname, {}) && cmd ==# 'setlocal' + " Skip setlocal switchback-value to global-local option. It will + " not result in failure. + let pre = '" Skip global-local: ' + elseif local_noglobals->has_key(fullname) && cmd ==# 'setglobal' + " Skip setglobal to local-noglobal option. It will not result in + " failure. + let pre = '" Skip local-noglobal: ' + elseif skip_setglobal_reasons->has_key(fullname) && cmd ==# 'setglobal' + " Skip setglobal to reasoned option. It will not result in failure. + let reason = skip_setglobal_reasons[fullname] + let pre = $'" Skip {reason}: ' + else + let pre = '' + endif + let cmdline = $'{cmd} {opt}={val}' + call add(script, $"{pre}silent! call assert_fails({string(cmdline)})") + endfor + endfor + endfor + call add(script, "endif") + endif - if name == 'more' - call add(script, 'set nomore') - elseif name == 'laststatus' - call add(script, 'set laststatus=1') - elseif name == 'lines' - call add(script, 'let &lines = save_lines') - endif + " Cannot change 'termencoding' in GTK + if fullname != 'termencoding' || !has('gui_gtk') + call add(script, $'set {fullname}&') + call add(script, $'set {shortname}&') + call add(script, $"if exists('l:saved')") + call add(script, $"let [&g:{fullname}, &l:{fullname}] = l:saved") + call add(script, 'endif') endif -endfor -call add(script, 'let &columns = save_columns') -call add(script, 'let &lines = save_lines') -call add(script, 'source unix.vim') + let script += post_processing + call add(script, 'endfunc') +endfor call writefile(script, 'opt_test.vim') @@ -397,4 +508,8 @@ catch write endtry +endif + qa! + +" vim:sw=2:ts=8:noet:nolist:nosta: diff --git a/test/old/testdir/test_options.vim b/test/old/testdir/test_options.vim index 4d750a4160..ccc7abe2d8 100644 --- a/test/old/testdir/test_options.vim +++ b/test/old/testdir/test_options.vim @@ -1,8 +1,11 @@ " Test for options +source shared.vim source check.vim source view_util.vim +scriptencoding utf-8 + func Test_whichwrap() set whichwrap=b,s call assert_equal('b,s', &whichwrap) @@ -1024,15 +1027,6 @@ func Test_set_all_one_column() call assert_equal(sort(copy(options)), options) endfunc -func Test_set_values() - " opt_test.vim is generated from ../optiondefs.h using gen_opt_test.vim - if filereadable('opt_test.vim') - source opt_test.vim - else - throw 'Skipped: opt_test.vim does not exist' - endif -endfunc - func Test_renderoptions() throw 'skipped: Nvim does not support renderoptions' " Only do this for Windows Vista and later, fails on Windows XP and earlier. diff --git a/test/old/testdir/test_options_all.vim b/test/old/testdir/test_options_all.vim new file mode 100644 index 0000000000..a2330ecb90 --- /dev/null +++ b/test/old/testdir/test_options_all.vim @@ -0,0 +1,13 @@ +" Test for options + +" opt_test.vim is generated from src/optiondefs.h and runtime/doc/options.txt +" using gen_opt_test.vim +if filereadable('opt_test.vim') + source opt_test.vim +else + func Test_set_values() + throw 'Skipped: opt_test.vim does not exist' + endfunc +endif + +" vim: shiftwidth=2 sts=2 expandtab |