0
0
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:
Bram Moolenaar
2017-03-18 19:42:22 +01:00
parent 7a43cb9cb5
commit 42205551b1
9 changed files with 149 additions and 64 deletions

View File

@@ -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()*

View File

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

View File

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

View File

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

View File

@@ -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. */

View File

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

View File

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

View File

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

View File

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