0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

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.ca@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Milly 2024-10-21 22:20:51 +02:00 committed by Christian Brabandt
parent bfe568d8c4
commit 6eca04e9f1
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
9 changed files with 193 additions and 74 deletions

View File

@ -1694,7 +1694,11 @@ getout(int exitval)
} }
#ifdef FEAT_VIMINFO #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 out the registers, history, marks etc, to the viminfo file
write_viminfo(NULL, FALSE); write_viminfo(NULL, FALSE);
#endif #endif

View File

@ -232,6 +232,7 @@ NEW_TESTS = \
test_normal \ test_normal \
test_number \ test_number \
test_options \ test_options \
test_options_all \
test_packadd \ test_packadd \
test_partial \ test_partial \
test_paste \ test_paste \
@ -492,6 +493,7 @@ NEW_TESTS_RES = \
test_normal.res \ test_normal.res \
test_number.res \ test_number.res \
test_options.res \ test_options.res \
test_options_all.res \
test_packadd.res \ test_packadd.res \
test_partial.res \ test_partial.res \
test_paste.res \ test_paste.res \

View File

@ -22,7 +22,7 @@ default: nongui
include Make_all.mak include Make_all.mak
# Explicit dependencies. # Explicit dependencies.
test_options.res test_alot.res: opt_test.vim test_options_all.res: opt_test.vim
TEST_OUTFILES = $(SCRIPTS_TINY_OUT) TEST_OUTFILES = $(SCRIPTS_TINY_OUT)
DOSTMP = dostmp 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 $< $(VIMPROG) -u gui_preinit.vim -U gui_init.vim $(NO_PLUGINS) -S runtest.vim $<
@$(DEL) vimcmd @$(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 $^ $(VIMPROG) -e -s -u NONE $(COMMON_ARGS) --nofork -S $^
@if test -f test.log; then \ @if test -f test.log; then \
cat test.log; \ cat test.log; \

View File

@ -16,7 +16,7 @@ default: nongui
!include Make_all.mak !include Make_all.mak
# Explicit dependencies. # Explicit dependencies.
test_options.res test_alot.res: opt_test.vim test_options_all.res: opt_test.vim
TEST_OUTFILES = $(SCRIPTS_TINY_OUT) TEST_OUTFILES = $(SCRIPTS_TINY_OUT)
DOSTMP = dostmp 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 $(VIMPROG) -u gui_preinit.vim -U gui_init.vim $(NO_PLUGINS) -S runtest.vim $*.vim
@del vimcmd @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 $** $(VIMPROG) -e -s -u NONE $(COMMON_ARGS) --nofork -S $**
@if exist test.log ( type test.log & exit /b 1 ) @if exist test.log ( type test.log & exit /b 1 )

View File

@ -30,7 +30,7 @@ default: nongui
include Make_all.mak include Make_all.mak
# Explicit dependencies. # Explicit dependencies.
test_options.res test_alot.res: opt_test.vim test_options_all.res: opt_test.vim
.SUFFIXES: .in .out .res .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 $< $(RUN_VIMTEST) -u gui_preinit.vim -U gui_init.vim $(NO_PLUGINS) -S runtest.vim $<
@rm vimcmd @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) opt_test.vim: $(GEN_OPT_DEPS)
$(VIMPROG) -e -s -u NONE $(NO_INITS) --nofork --gui-dialog-file guidialog -S $(GEN_OPT_DEPS) $(VIMPROG) -e -s -u NONE $(NO_INITS) --nofork --gui-dialog-file guidialog -S $(GEN_OPT_DEPS)

View File

@ -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 set cpo=&vim
@ -11,19 +12,65 @@ set nomore
const K_KENTER = -16715 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. " The terminal size is restored at the end.
" Clear out t_WS, we don't want to resize the actual terminal.
let script = [ let script = [
\ '" DO NOT EDIT: Generated with gen_opt_test.vim', \ '" DO NOT EDIT: Generated with gen_opt_test.vim',
\ '" Used by test_options.vim.', \ '" Used by test_options_all.vim.',
\ '', \ '',
\ 'let save_columns = &columns', \ 'scriptencoding utf-8',
\ 'let save_lines = &lines',
\ 'set t_WS=',
\ ] \ ]
/#define p_term b optiondefs.h
let end = line('.') const end = search('#define p_term', 'nw')
" font name that works everywhere (hopefully) " font name that works everywhere (hopefully)
let fontname = has('win32') ? 'fixedsys' : 'fixed' let fontname = has('win32') ? 'fixedsys' : 'fixed'
@ -295,6 +342,27 @@ let test_values = {
\ 'otherstring': [['', 'xxx'], []], \ '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() const invalid_options = test_values->keys()
\->filter({-> v:val !~# '^other' && !exists($"&{v:val}")}) \->filter({-> v:val !~# '^other' && !exists($"&{v:val}")})
if !empty(invalid_options) if !empty(invalid_options)
@ -302,70 +370,105 @@ if !empty(invalid_options)
endif endif
1 1
/struct vimoption options call search('struct vimoption options')
while 1 while 1
/{" if search('{"', 'W') > end
if line('.') > end
break break
endif endif
let line = getline('.') let line = getline('.')
let name = substitute(line, '.*{"\([^"]*\)".*', '\1', '') let fullname = substitute(line, '.*{"\([^"]*\)".*', '\1', '')
let shortname = substitute(line, '.*"\([^"]*\)".*', '\1', '') let shortname = substitute(line, '.*"\([^"]*\)".*', '\1', '')
if has_key(test_values, name) let [valid_values, invalid_values] = test_values[
let a = test_values[name] \ has_key(test_values, fullname) ? fullname
elseif line =~ 'P_NUM' \ : line =~ 'P_NUM' ? 'othernum'
let a = test_values['othernum'] \ : 'otherstring']
else
let a = test_values['otherstring'] if empty(valid_values) && empty(invalid_values)
continue
endif 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, $"func Test_opt_set_{fullname}()")
call add(script, 'set ' . name) call add(script, $"if exists('+{fullname}') && execute('set!') =~# '\\n..{fullname}\\([=\\n]\\|$\\)'")
call add(script, 'set ' . shortname) call add(script, $"let l:saved = [&g:{fullname}, &l:{fullname}]")
call add(script, 'set no' . name) call add(script, 'endif')
call add(script, 'set no' . shortname)
else let [pre_processing, post_processing] = get(test_prepost, fullname, [[], []])
for val in a[0] let script += pre_processing
call add(script, 'set ' . name . '=' . val)
call add(script, '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 endfor
endfor
" setting an option can only fail when it's implemented. else " P_NUM || P_STRING
call add(script, "if exists('+" . name . "')") " Normal tests
for val in a[1] for opt in [fullname, shortname]
call add(script, "silent! call assert_fails('set " . name . "=" . val . "')") for cmd in ['set', 'setlocal', 'setglobal']
call add(script, "silent! call assert_fails('set " . shortname . "=" . val . "')") 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 endfor
call add(script, "endif") " Testing to clear the local value and switch back to the global value.
endif 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 " Failure tests
if name != 'termencoding' || !has('gui_gtk') " Setting an option can only fail when it's implemented.
call add(script, 'set ' . name . '&') call add(script, $"if exists('+{fullname}')")
call add(script, 'set ' . shortname . '&') for opt in [fullname, shortname]
endif for cmd in ['set', 'setlocal', 'setglobal']
if name == 'browsedir' for val in invalid_values
call add(script, 'call delete("Xdir with space", "d")') if val is# global_locals->get(fullname, {}) && cmd ==# 'setlocal'
elseif name == 'verbosefile' " Skip setlocal switchback-value to global-local option. It will
call add(script, 'call delete("Xfile")') " not result in failure.
endif let pre = '" Skip global-local: '
elseif local_noglobals->has_key(fullname) && cmd ==# 'setglobal'
if name == 'more' " Skip setglobal to local-noglobal option. It will not result in
call add(script, 'set nomore') " failure.
elseif name == 'lines' let pre = '" Skip local-noglobal: '
call add(script, 'let &lines = save_lines') elseif skip_setglobal_reasons->has_key(fullname) && cmd ==# 'setglobal'
endif " 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 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
let script += post_processing
call add(script, 'endfunc')
endwhile endwhile
call add(script, 'let &columns = save_columns')
call add(script, 'let &lines = save_lines')
call writefile(script, 'opt_test.vim') call writefile(script, 'opt_test.vim')
" Write error messages if error occurs. " Write error messages if error occurs.
@ -381,3 +484,5 @@ endtry
endif endif
qa! qa!
" vim:sw=2:ts=8:noet:nolist:nosta:

View File

@ -4,6 +4,8 @@ source shared.vim
source check.vim source check.vim
source view_util.vim source view_util.vim
scriptencoding utf-8
func Test_whichwrap() func Test_whichwrap()
set whichwrap=b,s set whichwrap=b,s
call assert_equal('b,s', &whichwrap) call assert_equal('b,s', &whichwrap)
@ -1037,15 +1039,6 @@ func Test_set_all_one_column()
call assert_equal(sort(copy(options)), options) call assert_equal(sort(copy(options)), options)
endfunc 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() func Test_renderoptions()
" Only do this for Windows Vista and later, fails on Windows XP and earlier. " 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. " Doesn't hurt to do this on a non-Windows system.

View File

@ -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

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
797,
/**/ /**/
796, 796,
/**/ /**/