mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.0.0477: the client-server test may hang when failing
Problem: The client-server test may hang when failing. Solution: Set a timer. Add assert_report()
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
*eval.txt* For Vim version 8.0. Last change: 2017 Mar 09
|
||||
*eval.txt* For Vim version 8.0. Last change: 2017 Mar 18
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -1986,16 +1986,23 @@ argidx() Number current index in the argument list
|
||||
arglistid([{winnr} [, {tabnr}]]) Number argument list id
|
||||
argv({nr}) String {nr} entry of the argument list
|
||||
argv() List the argument list
|
||||
assert_equal({exp}, {act} [, {msg}]) none assert {exp} is equal to {act}
|
||||
assert_exception({error} [, {msg}]) none assert {error} is in v:exception
|
||||
assert_fails({cmd} [, {error}]) none assert {cmd} fails
|
||||
assert_false({actual} [, {msg}]) none assert {actual} is false
|
||||
assert_equal({exp}, {act} [, {msg}])
|
||||
none assert {exp} is equal to {act}
|
||||
assert_exception({error} [, {msg}])
|
||||
none assert {error} is in v:exception
|
||||
assert_fails({cmd} [, {error}]) none assert {cmd} fails
|
||||
assert_false({actual} [, {msg}])
|
||||
none assert {actual} is false
|
||||
assert_inrange({lower}, {upper}, {actual} [, {msg}])
|
||||
none assert {actual} is inside the range
|
||||
assert_match({pat}, {text} [, {msg}]) none assert {pat} matches {text}
|
||||
assert_notequal({exp}, {act} [, {msg}]) none assert {exp} is not equal {act}
|
||||
assert_notmatch({pat}, {text} [, {msg}]) none assert {pat} not matches {text}
|
||||
assert_true({actual} [, {msg}]) none assert {actual} is true
|
||||
assert_match({pat}, {text} [, {msg}])
|
||||
none assert {pat} matches {text}
|
||||
assert_notequal({exp}, {act} [, {msg}])
|
||||
none assert {exp} is not equal {act}
|
||||
assert_notmatch({pat}, {text} [, {msg}])
|
||||
none assert {pat} not matches {text}
|
||||
assert_report({msg}) none report a test failure
|
||||
assert_true({actual} [, {msg}]) none assert {actual} is true
|
||||
asin({expr}) Float arc sine of {expr}
|
||||
atan({expr}) Float arc tangent of {expr}
|
||||
atan2({expr1}, {expr2}) Float arc tangent of {expr1} / {expr2}
|
||||
@@ -2583,7 +2590,10 @@ assert_notmatch({pattern}, {actual} [, {msg}])
|
||||
The opposite of `assert_match()`: add an error message to
|
||||
|v:errors| when {pattern} matches {actual}.
|
||||
|
||||
assert_true({actual} [, {msg}]) *assert_true()*
|
||||
assert_report({msg}) *assert_report()*
|
||||
Report a test failure directly, using {msg}.
|
||||
|
||||
assert_true({actual} [, {msg}]) *assert_true()*
|
||||
When {actual} is not true an error message is added to
|
||||
|v:errors|, like with |assert_equal()|.
|
||||
A value is TRUE when it is a non-zero number. When {actual}
|
||||
@@ -3925,11 +3935,14 @@ foldtext() Returns a String, to be displayed for a closed fold. This is
|
||||
|v:foldstart|, |v:foldend| and |v:folddashes| variables.
|
||||
The returned string looks like this: >
|
||||
+-- 45 lines: abcdef
|
||||
< The number of dashes depends on the foldlevel. The "45" is
|
||||
the number of lines in the fold. "abcdef" is the text in the
|
||||
first non-blank line of the fold. Leading white space, "//"
|
||||
or "/*" and the text from the 'foldmarker' and 'commentstring'
|
||||
options is removed.
|
||||
< The number of leading dashes depends on the foldlevel. The
|
||||
"45" is the number of lines in the fold. "abcdef" is the text
|
||||
in the first non-blank line of the fold. Leading white space,
|
||||
"//" or "/*" and the text from the 'foldmarker' and
|
||||
'commentstring' options is removed.
|
||||
When used to draw the actual foldtext, the rest of the line
|
||||
will be filled with the fold char from the 'fillchars'
|
||||
setting.
|
||||
{not available when compiled without the |+folding| feature}
|
||||
|
||||
foldtextresult({lnum}) *foldtextresult()*
|
||||
|
11
src/eval.c
11
src/eval.c
@@ -9083,6 +9083,17 @@ assert_bool(typval_T *argvars, int isTrue)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
assert_report(typval_T *argvars)
|
||||
{
|
||||
garray_T ga;
|
||||
|
||||
prepare_assert_error(&ga);
|
||||
ga_concat(&ga, get_tv_string(&argvars[0]));
|
||||
assert_error(&ga);
|
||||
ga_clear(&ga);
|
||||
}
|
||||
|
||||
void
|
||||
assert_exception(typval_T *argvars)
|
||||
{
|
||||
|
@@ -52,6 +52,7 @@ static void f_assert_inrange(typval_T *argvars, typval_T *rettv);
|
||||
static void f_assert_match(typval_T *argvars, typval_T *rettv);
|
||||
static void f_assert_notequal(typval_T *argvars, typval_T *rettv);
|
||||
static void f_assert_notmatch(typval_T *argvars, typval_T *rettv);
|
||||
static void f_assert_report(typval_T *argvars, typval_T *rettv);
|
||||
static void f_assert_true(typval_T *argvars, typval_T *rettv);
|
||||
#ifdef FEAT_FLOAT
|
||||
static void f_asin(typval_T *argvars, typval_T *rettv);
|
||||
@@ -483,6 +484,7 @@ static struct fst
|
||||
{"assert_match", 2, 3, f_assert_match},
|
||||
{"assert_notequal", 2, 3, f_assert_notequal},
|
||||
{"assert_notmatch", 2, 3, f_assert_notmatch},
|
||||
{"assert_report", 1, 1, f_assert_report},
|
||||
{"assert_true", 1, 2, f_assert_true},
|
||||
#ifdef FEAT_FLOAT
|
||||
{"atan", 1, 1, f_atan},
|
||||
@@ -1313,6 +1315,15 @@ f_assert_notmatch(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
assert_match_common(argvars, ASSERT_NOTMATCH);
|
||||
}
|
||||
|
||||
/*
|
||||
* "assert_report(msg)" function
|
||||
*/
|
||||
static void
|
||||
f_assert_report(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
assert_report(argvars);
|
||||
}
|
||||
|
||||
/*
|
||||
* "assert_true(actual[, msg])" function
|
||||
*/
|
||||
|
@@ -596,6 +596,10 @@ ServerWait(
|
||||
if (seconds >= 0 && (now - start) >= seconds)
|
||||
break;
|
||||
|
||||
#ifdef FEAT_TIMERS
|
||||
check_due_timer();
|
||||
#endif
|
||||
|
||||
/* Just look out for the answer without calling back into Vim */
|
||||
if (localLoop)
|
||||
{
|
||||
|
@@ -2570,6 +2570,9 @@ serverGetReply(HWND server, int *expr_res, int remove, int wait)
|
||||
/* Loop until we receive a reply */
|
||||
while (reply_received == 0)
|
||||
{
|
||||
#ifdef FEAT_TIMERS
|
||||
check_due_timer();
|
||||
#endif
|
||||
/* Wait for a SendMessage() call to us. This could be the reply
|
||||
* we are waiting for. Use a timeout of a second, to catch the
|
||||
* situation that the server died unexpectedly. */
|
||||
|
@@ -123,6 +123,7 @@ void assert_equal_common(typval_T *argvars, assert_type_T atype);
|
||||
void assert_match_common(typval_T *argvars, assert_type_T atype);
|
||||
void assert_inrange(typval_T *argvars);
|
||||
void assert_bool(typval_T *argvars, int isTrue);
|
||||
void assert_report(typval_T *argvars);
|
||||
void assert_exception(typval_T *argvars);
|
||||
void assert_fails(typval_T *argvars);
|
||||
void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, typval_T *got_tv, assert_type_T atype);
|
||||
|
@@ -86,7 +86,7 @@ function GetAllocId(name)
|
||||
return lnum - top - 1
|
||||
endfunc
|
||||
|
||||
function RunTheTest(test)
|
||||
func RunTheTest(test)
|
||||
echo 'Executing ' . a:test
|
||||
|
||||
" Avoid stopping at the "hit enter" prompt
|
||||
@@ -142,6 +142,60 @@ function RunTheTest(test)
|
||||
set nomodified
|
||||
endfunc
|
||||
|
||||
func AfterTheTest()
|
||||
if len(v:errors) > 0
|
||||
let s:fail += 1
|
||||
call add(s:errors, 'Found errors in ' . s:test . ':')
|
||||
call extend(s:errors, v:errors)
|
||||
let v:errors = []
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" This function can be called by a test if it wants to abort testing.
|
||||
func FinishTesting()
|
||||
call AfterTheTest()
|
||||
|
||||
" Don't write viminfo on exit.
|
||||
set viminfo=
|
||||
|
||||
if s:fail == 0
|
||||
" Success, create the .res file so that make knows it's done.
|
||||
exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
|
||||
write
|
||||
endif
|
||||
|
||||
if len(s:errors) > 0
|
||||
" Append errors to test.log
|
||||
split test.log
|
||||
call append(line('$'), '')
|
||||
call append(line('$'), 'From ' . g:testname . ':')
|
||||
call append(line('$'), s:errors)
|
||||
write
|
||||
endif
|
||||
|
||||
let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
|
||||
echo message
|
||||
call add(s:messages, message)
|
||||
if s:fail > 0
|
||||
let message = s:fail . ' FAILED:'
|
||||
echo message
|
||||
call add(s:messages, message)
|
||||
call extend(s:messages, s:errors)
|
||||
endif
|
||||
|
||||
" Add SKIPPED messages
|
||||
call extend(s:messages, s:skipped)
|
||||
|
||||
" Append messages to the file "messages"
|
||||
split messages
|
||||
call append(line('$'), '')
|
||||
call append(line('$'), 'From ' . g:testname . ':')
|
||||
call append(line('$'), s:messages)
|
||||
write
|
||||
|
||||
qall!
|
||||
endfunc
|
||||
|
||||
" Source the test script. First grab the file name, in case the script
|
||||
" navigates away. g:testname can be used by the tests.
|
||||
let g:testname = expand('%')
|
||||
@@ -164,6 +218,7 @@ endif
|
||||
|
||||
" Names of flaky tests.
|
||||
let s:flaky = [
|
||||
\ 'Test_client_server()',
|
||||
\ 'Test_close_and_exit_cb()',
|
||||
\ 'Test_collapse_buffers()',
|
||||
\ 'Test_communicate()',
|
||||
@@ -197,52 +252,9 @@ for s:test in sort(s:tests)
|
||||
call RunTheTest(s:test)
|
||||
endif
|
||||
|
||||
if len(v:errors) > 0
|
||||
let s:fail += 1
|
||||
call add(s:errors, 'Found errors in ' . s:test . ':')
|
||||
call extend(s:errors, v:errors)
|
||||
let v:errors = []
|
||||
endif
|
||||
call AfterTheTest()
|
||||
endfor
|
||||
|
||||
" Don't write viminfo on exit.
|
||||
set viminfo=
|
||||
|
||||
if s:fail == 0
|
||||
" Success, create the .res file so that make knows it's done.
|
||||
exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
|
||||
write
|
||||
endif
|
||||
|
||||
if len(s:errors) > 0
|
||||
" Append errors to test.log
|
||||
split test.log
|
||||
call append(line('$'), '')
|
||||
call append(line('$'), 'From ' . g:testname . ':')
|
||||
call append(line('$'), s:errors)
|
||||
write
|
||||
endif
|
||||
|
||||
let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
|
||||
echo message
|
||||
call add(s:messages, message)
|
||||
if s:fail > 0
|
||||
let message = s:fail . ' FAILED:'
|
||||
echo message
|
||||
call add(s:messages, message)
|
||||
call extend(s:messages, s:errors)
|
||||
endif
|
||||
|
||||
" Add SKIPPED messages
|
||||
call extend(s:messages, s:skipped)
|
||||
|
||||
" Append messages to the file "messages"
|
||||
split messages
|
||||
call append(line('$'), '')
|
||||
call append(line('$'), 'From ' . g:testname . ':')
|
||||
call append(line('$'), s:messages)
|
||||
write
|
||||
|
||||
qall!
|
||||
call FinishTesting()
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@@ -6,29 +6,46 @@ endif
|
||||
|
||||
source shared.vim
|
||||
|
||||
let s:where = 0
|
||||
func Abort(id)
|
||||
call assert_report('Test timed out at ' . s:where)
|
||||
call FinishTesting()
|
||||
endfunc
|
||||
|
||||
func Test_client_server()
|
||||
let cmd = GetVimCommand()
|
||||
if cmd == ''
|
||||
return
|
||||
endif
|
||||
let name = 'XVIMTEXT'
|
||||
|
||||
" Some of these commands may hang when failing.
|
||||
call timer_start(10000, 'Abort')
|
||||
|
||||
let s:where = 1
|
||||
let name = 'XVIMTEST'
|
||||
let cmd .= ' --servername ' . name
|
||||
let g:job = job_start(cmd, {'stoponexit': 'kill', 'out_io': 'null'})
|
||||
call WaitFor('job_status(g:job) == "run"')
|
||||
if job_status(g:job) != 'run'
|
||||
call assert_true(0, 'Cannot run the Vim server')
|
||||
call assert_report('Cannot run the Vim server')
|
||||
return
|
||||
endif
|
||||
let s:where = 2
|
||||
|
||||
" Takes a short while for the server to be active.
|
||||
call WaitFor('serverlist() =~ "' . name . '"')
|
||||
call assert_match(name, serverlist())
|
||||
let s:where = 3
|
||||
|
||||
call remote_foreground(name)
|
||||
let s:where = 4
|
||||
|
||||
call remote_send(name, ":let testvar = 'yes'\<CR>")
|
||||
let s:where = 5
|
||||
call WaitFor('remote_expr("' . name . '", "testvar") == "yes"')
|
||||
let s:where = 6
|
||||
call assert_equal('yes', remote_expr(name, "testvar"))
|
||||
let s:where = 7
|
||||
|
||||
if has('unix') && has('gui') && !has('gui_running')
|
||||
" Running in a terminal and the GUI is avaiable: Tell the server to open
|
||||
@@ -36,29 +53,40 @@ func Test_client_server()
|
||||
" Need to wait for the GUI to start up, otherwise the send hangs in trying
|
||||
" to send to the terminal window.
|
||||
call remote_send(name, ":gui -f\<CR>")
|
||||
let s:where = 8
|
||||
sleep 500m
|
||||
call remote_send(name, ":let testvar = 'maybe'\<CR>")
|
||||
let s:where = 9
|
||||
call WaitFor('remote_expr("' . name . '", "testvar") == "maybe"')
|
||||
let s:where = 10
|
||||
call assert_equal('maybe', remote_expr(name, "testvar"))
|
||||
let s:where = 11
|
||||
endif
|
||||
|
||||
call assert_fails('call remote_send("XXX", ":let testvar = ''yes''\<CR>")', 'E241')
|
||||
let s:where = 12
|
||||
|
||||
" Expression evaluated locally.
|
||||
if v:servername == ''
|
||||
call remote_startserver('MYSELF')
|
||||
let s:where = 13
|
||||
call assert_equal('MYSELF', v:servername)
|
||||
endif
|
||||
let g:testvar = 'myself'
|
||||
call assert_equal('myself', remote_expr(v:servername, 'testvar'))
|
||||
let s:where = 14
|
||||
|
||||
call remote_send(name, ":call server2client(expand('<client>'), 'got it')\<CR>", 'g:myserverid')
|
||||
let s:where = 15
|
||||
call assert_equal('got it', remote_read(g:myserverid))
|
||||
let s:where = 16
|
||||
|
||||
call remote_send(name, ":qa!\<CR>")
|
||||
let s:where = 17
|
||||
call WaitFor('job_status(g:job) == "dead"')
|
||||
let s:where = 18
|
||||
if job_status(g:job) != 'dead'
|
||||
call assert_true(0, 'Server did not exit')
|
||||
call assert_report('Server did not exit')
|
||||
call job_stop(g:job, 'kill')
|
||||
endif
|
||||
endfunc
|
||||
|
@@ -764,6 +764,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
477,
|
||||
/**/
|
||||
476,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user