aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-04-13 02:13:29 +0200
committerJustin M. Keyes <justinkz@gmail.com>2019-04-13 17:07:58 +0200
commit7e1591e06ab85bf088c7482a15ad48fc58c1005d (patch)
tree5a1e8c7f87d11bd28598836c7a989186bd3e0746
parentd08692a8246039b938b5645a6c01b4ff7f51671e (diff)
downloadrneovim-7e1591e06ab85bf088c7482a15ad48fc58c1005d.tar.gz
rneovim-7e1591e06ab85bf088c7482a15ad48fc58c1005d.tar.bz2
rneovim-7e1591e06ab85bf088c7482a15ad48fc58c1005d.zip
API: emit nvim_error_event on failed async request
We already do this for _invalid_ async requests #9300. Now we also do it for failed invocation of valid requests.
-rw-r--r--src/nvim/func_attr.h5
-rw-r--r--src/nvim/msgpack_rpc/channel.c16
-rw-r--r--test/functional/api/vim_spec.lua12
-rw-r--r--test/functional/ex_cmds/swapfile_preserve_recover_spec.lua10
-rw-r--r--test/functional/helpers.lua30
-rw-r--r--test/helpers.lua14
6 files changed, 73 insertions, 14 deletions
diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h
index 6e5e47c060..d3b600a40c 100644
--- a/src/nvim/func_attr.h
+++ b/src/nvim/func_attr.h
@@ -205,10 +205,15 @@
#endif
#ifdef DEFINE_FUNC_ATTRIBUTES
+/// Non-deferred API function.
# define FUNC_API_ASYNC
+/// Internal C function not exposed in the RPC API.
# define FUNC_API_NOEXPORT
+/// API function not exposed in VimL/eval.
# define FUNC_API_REMOTE_ONLY
+/// API function introduced at the given API level.
# define FUNC_API_SINCE(X)
+/// API function deprecated since the given API level.
# define FUNC_API_DEPRECATED_SINCE(X)
# define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC
# define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x)
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 4cde9d22a1..3438949e2d 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -348,28 +348,28 @@ static void handle_request(Channel *channel, msgpack_object *request)
if (is_get_mode && !input_blocking()) {
// Defer the event to a special queue used by os/input.c. #6247
- multiqueue_put(ch_before_blocking_events, response_event, 1, evdata);
+ multiqueue_put(ch_before_blocking_events, request_event, 1, evdata);
} else {
// Invoke immediately.
- response_event((void **)&evdata);
+ request_event((void **)&evdata);
}
} else {
- multiqueue_put(channel->events, response_event, 1, evdata);
+ multiqueue_put(channel->events, request_event, 1, evdata);
DLOG("RPC: scheduled %.*s", method->via.bin.size, method->via.bin.ptr);
}
}
-/// Responds to a message, depending on the type:
-/// - Request: writes the response.
-/// - Notification: does nothing.
-static void response_event(void **argv)
+/// Handles a message, depending on the type:
+/// - Request: invokes method and writes the response (or error).
+/// - Notification: invokes method (emits `nvim_error_event` on error).
+static void request_event(void **argv)
{
RequestEvent *e = argv[0];
Channel *channel = e->channel;
MsgpackRpcRequestHandler handler = e->handler;
Error error = ERROR_INIT;
Object result = handler.fn(channel->id, e->args, &error);
- if (e->type == kMessageTypeRequest) {
+ if (e->type == kMessageTypeRequest || ERROR_SET(&error)) {
// Send the response.
msgpack_packer response;
msgpack_packer_init(&response, &out_buffer, msgpack_sbuffer_write);
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 068d4973af..c508ca37db 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -49,13 +49,23 @@ describe('API', function()
it('handles errors in async requests', function()
local error_types = meths.get_api_info()[2].error_types
- nvim_async("bogus")
+ nvim_async('bogus')
eq({'notification', 'nvim_error_event',
{error_types.Exception.id, 'Invalid method: nvim_bogus'}}, next_msg())
-- error didn't close channel.
eq(2, eval('1+1'))
end)
+ it('failed async request emits nvim_error_event', function()
+ local error_types = meths.get_api_info()[2].error_types
+ nvim_async('command', 'bogus')
+ eq({'notification', 'nvim_error_event',
+ {error_types.Exception.id, 'Vim:E492: Not an editor command: bogus'}},
+ next_msg())
+ -- error didn't close channel.
+ eq(2, eval('1+1'))
+ end)
+
it('does not set CA_COMMAND_BUSY #7254', function()
nvim('command', 'split')
nvim('command', 'autocmd WinEnter * startinsert')
diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
index bbab1471f6..73cbb1d54e 100644
--- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
+++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
@@ -13,6 +13,7 @@ local rmdir = helpers.rmdir
local set_session = helpers.set_session
local spawn = helpers.spawn
local nvim_async = helpers.nvim_async
+local expect_msg_seq = helpers.expect_msg_seq
describe(':recover', function()
before_each(clear)
@@ -163,6 +164,13 @@ describe('swapfile detection', function()
screen2:expect{any=[[Found a swap file by the name ".*]]
..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]}
feed('e') -- Chose "Edit" at the swap dialog.
- feed('<c-c>')
+ expect_msg_seq({
+ ignore={'redraw'},
+ seqs={
+ { {'notification', 'nvim_error_event', {0, 'Vim(edit):E325: ATTENTION'}},
+ }
+ }
+ })
+ feed('<cr>')
end)
end)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 3e72ba6f98..7f9b5fe5fc 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -23,6 +23,7 @@ local neq = global_helpers.neq
local ok = global_helpers.ok
local read_file = global_helpers.read_file
local sleep = global_helpers.sleep
+local table_contains = global_helpers.table_contains
local table_flatten = global_helpers.table_flatten
local write_file = global_helpers.write_file
@@ -129,16 +130,33 @@ end
-- Expects a sequence of next_msg() results. If multiple sequences are
-- passed they are tried until one succeeds, in order of shortest to longest.
+--
+-- Can be called with positional args (list of sequences only):
+-- expect_msg_seq(seq1, seq2, ...)
+-- or keyword args:
+-- expect_msg_seq{ignore={...}, seqs={seq1, seq2, ...}}
+--
+-- ignore: List of ignored event names.
+-- seqs: List of one or more potential event sequences.
local function expect_msg_seq(...)
if select('#', ...) < 1 then
error('need at least 1 argument')
end
- local seqs = {...}
+ local arg1 = select(1, ...)
+ if (arg1['seqs'] and select('#', ...) > 1) or type(arg1) ~= 'table' then
+ error('invalid args')
+ end
+ local ignore = arg1['ignore'] and arg1['ignore'] or {}
+ local seqs = arg1['seqs'] and arg1['seqs'] or {...}
+ if type(ignore) ~= 'table' then
+ error("'ignore' arg must be a list of strings")
+ end
table.sort(seqs, function(a, b) -- Sort ascending, by (shallow) length.
return #a < #b
end)
local actual_seq = {}
+ local nr_ignored = 0
local final_error = ''
local function cat_err(err1, err2)
if err1 == nil then
@@ -151,12 +169,16 @@ local function expect_msg_seq(...)
-- Collect enough messages to compare the next expected sequence.
while #actual_seq < #expected_seq do
local msg = next_msg(10000) -- Big timeout for ASAN/valgrind.
+ local msg_type = msg and msg[2] or nil
if msg == nil then
error(cat_err(final_error,
- string.format('got %d messages, expected %d',
- #actual_seq, #expected_seq)))
+ string.format('got %d messages (ignored %d), expected %d',
+ #actual_seq, nr_ignored, #expected_seq)))
+ elseif table_contains(ignore, msg_type) then
+ nr_ignored = nr_ignored + 1
+ else
+ table.insert(actual_seq, msg)
end
- table.insert(actual_seq, msg)
end
local status, result = pcall(eq, expected_seq, actual_seq)
if status then
diff --git a/test/helpers.lua b/test/helpers.lua
index 795808005d..89cf13f917 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -627,6 +627,19 @@ local function table_flatten(arr)
return result
end
+-- Checks if a list-like (vector) table contains `value`.
+local function table_contains(t, value)
+ if type(t) ~= 'table' then
+ error('t must be a table')
+ end
+ for _,v in ipairs(t) do
+ if v == value then
+ return true
+ end
+ end
+ return false
+end
+
local function hexdump(str)
local len = string.len(str)
local dump = ""
@@ -771,6 +784,7 @@ local module = {
repeated_read_cmd = repeated_read_cmd,
shallowcopy = shallowcopy,
sleep = sleep,
+ table_contains = table_contains,
table_flatten = table_flatten,
tmpname = tmpname,
uname = uname,