diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2019-04-13 02:13:29 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2019-04-13 17:07:58 +0200 |
commit | 7e1591e06ab85bf088c7482a15ad48fc58c1005d (patch) | |
tree | 5a1e8c7f87d11bd28598836c7a989186bd3e0746 | |
parent | d08692a8246039b938b5645a6c01b4ff7f51671e (diff) | |
download | rneovim-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.h | 5 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/channel.c | 16 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 12 | ||||
-rw-r--r-- | test/functional/ex_cmds/swapfile_preserve_recover_spec.lua | 10 | ||||
-rw-r--r-- | test/functional/helpers.lua | 30 | ||||
-rw-r--r-- | test/helpers.lua | 14 |
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, |