patch 9.1.0797: testing of options can be further improved Commit: https://github.com/vim/vim/commit/6eca04e9f1d446dc509ba51e32da56fa413fe2f0 Author: Milly <milly...@gmail.com> Date: Mon Oct 21 22:20:51 2024 +0200
patch 9.1.0797: testing of options can be further improved 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: #15894 Signed-off-by: Milly <milly...@gmail.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/main.c b/src/main.c index e5faaa720..ecc61f4d0 100644 --- a/src/main.c +++ b/src/main.c @@ -1694,7 +1694,11 @@ getout(int exitval) } #ifdef FEAT_VIMINFO - if (*p_viminfo != NUL) + if ( +# ifdef EXITFREE + entered_free_all_mem == FALSE && +# endif + *p_viminfo != NUL) // Write out the registers, history, marks etc, to the viminfo file write_viminfo(NULL, FALSE); #endif diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 67ef64100..750c1940a 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -232,6 +232,7 @@ NEW_TESTS = \ test_normal \ test_number \ test_options \ + test_options_all \ test_packadd \ test_partial \ test_paste \ @@ -492,6 +493,7 @@ NEW_TESTS_RES = \ test_normal.res \ test_number.res \ test_options.res \ + test_options_all.res \ test_packadd.res \ test_partial.res \ test_paste.res \ diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak index 16632b350..2ffe4025e 100644 --- a/src/testdir/Make_ming.mak +++ b/src/testdir/Make_ming.mak @@ -22,7 +22,7 @@ default: nongui include Make_all.mak # Explicit dependencies. -test_options.res test_alot.res: opt_test.vim +test_options_all.res: opt_test.vim TEST_OUTFILES = $(SCRIPTS_TINY_OUT) DOSTMP = dostmp @@ -157,7 +157,7 @@ test_gui_init.res: test_gui_init.vim $(VIMPROG) -u gui_preinit.vim -U gui_init.vim $(NO_PLUGINS) -S runtest.vim $< @$(DEL) vimcmd -opt_test.vim: gen_opt_test.vim ../optiondefs.h +opt_test.vim: gen_opt_test.vim ../optiondefs.h ../../runtime/doc/options.txt $(VIMPROG) -e -s -u NONE $(COMMON_ARGS) --nofork -S $^ @if test -f test.log; then \ cat test.log; \ diff --git a/src/testdir/Make_mvc.mak b/src/testdir/Make_mvc.mak index bbfd8f09e..1a54823e5 100644 --- a/src/testdir/Make_mvc.mak +++ b/src/testdir/Make_mvc.mak @@ -16,7 +16,7 @@ default: nongui !include Make_all.mak # Explicit dependencies. -test_options.res test_alot.res: opt_test.vim +test_options_all.res: opt_test.vim TEST_OUTFILES = $(SCRIPTS_TINY_OUT) DOSTMP = dostmp @@ -151,7 +151,7 @@ test_gui_init.res: test_gui_init.vim $(VIMPROG) -u gui_preinit.vim -U gui_init.vim $(NO_PLUGINS) -S runtest.vim $*.vim @del vimcmd -opt_test.vim: gen_opt_test.vim ../optiondefs.h +opt_test.vim: gen_opt_test.vim ../optiondefs.h ../../runtime/doc/options.txt $(VIMPROG) -e -s -u NONE $(COMMON_ARGS) --nofork -S $** @if exist test.log ( type test.log & exit /b 1 ) diff --git a/src/testdir/Makefile b/src/testdir/Makefile index 66b8f1b74..3b665e707 100644 --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -30,7 +30,7 @@ default: nongui include Make_all.mak # Explicit dependencies. -test_options.res test_alot.res: opt_test.vim +test_options_all.res: opt_test.vim .SUFFIXES: .in .out .res .vim @@ -160,7 +160,7 @@ test_gui_init.res: test_gui_init.vim $(RUN_VIMTEST) -u gui_preinit.vim -U gui_init.vim $(NO_PLUGINS) -S runtest.vim $< @rm vimcmd -GEN_OPT_DEPS = gen_opt_test.vim ../optiondefs.h +GEN_OPT_DEPS = gen_opt_test.vim ../optiondefs.h ../../runtime/doc/options.txt opt_test.vim: $(GEN_OPT_DEPS) $(VIMPROG) -e -s -u NONE $(NO_INITS) --nofork --gui-dialog-file guidialog -S $(GEN_OPT_DEPS) diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim index f308e0ec1..e85560252 100644 --- a/src/testdir/gen_opt_test.vim +++ b/src/testdir/gen_opt_test.vim @@ -1,4 +1,5 @@ -" Script to generate testdir/opt_test.vim from optiondefs.h +" Script to generate src/testdir/opt_test.vim from src/optiondefs.h and +" runtime/doc/options.txt set cpo=&vim @@ -11,19 +12,65 @@ 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', + \ 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', + \} + " The terminal size is restored at the end. -" Clear out t_WS, we don't want to resize the actual terminal. 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', - \ 'set t_WS=', + \ 'scriptencoding utf-8', \ ] -/#define p_term -let end = line('.') +b optiondefs.h +const end = search('#define p_term', 'nw') " font name that works everywhere (hopefully) let fontname = has('win32') ? 'fixedsys' : 'fixed' @@ -295,6 +342,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) @@ -302,69 +370,104 @@ if !empty(invalid_options) endif 1 -/struct vimoption options +call search('struct vimoption options') while 1 - /{" - if line('.') > end + if search('{"', 'W') > end break endif let line = getline('.') - let name = substitute(line, '.*{"\([^"]*\)".*', ' ', '') + let fullname = substitute(line, '.*{"\([^"]*\)".*', ' ', '') let shortname = substitute(line, '.*"\([^"]*\)".*', ' ', '') - if has_key(test_values, name) - let a = test_values[name] - elseif line =~ 'P_NUM' - let a = test_values['othernum'] - else - let a = test_values['otherstring'] + let [valid_values, invalid_values] = test_values[ + \ has_key(test_values, fullname) ? fullname + \ : line =~ 'P_NUM' ? '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 line =~ 'P_BOOL' - 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 line =~ 'P_BOOL' + 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 - call add(script, "endif") - endif + 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 + " 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 == '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 -endwhile -call add(script, 'let &columns = save_columns') -call add(script, 'let &lines = save_lines') + let script += post_processing + call add(script, 'endfunc') +endwhile call writefile(script, 'opt_test.vim') @@ -381,3 +484,5 @@ endtry endif qa! + +" vim:sw=2:ts=8:noet:nolist:nosta: diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index eec71efeb..cbc84a471 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -4,6 +4,8 @@ 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) @@ -1037,15 +1039,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() " Only do this for Windows Vista and later, fails on Windows XP and earlier. " Doesn't hurt to do this on a non-Windows system. diff --git a/src/testdir/test_options_all.vim b/src/testdir/test_options_all.vim new file mode 100644 index 000000000..a2330ecb9 --- /dev/null +++ b/src/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 diff --git a/src/version.c b/src/version.c index e979c0456..cd49f58fd 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 797, /**/ 796, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/E1t2z2R-00Fa4D-9t%40256bit.org.