From ba2f615cd40d5d809d1a141c7b098e3bd22ff7bb Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 16 Jul 2016 02:26:04 +0300 Subject: functests: Test for error conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During testing found the following bugs: 1. msgpack-gen.lua script is completely unprepared for Float values either in return type or in arguments. Specifically: 1. At the time of writing relevant code FLOAT_OBJ did not exist as well as FLOATING_OBJ, but it would be used by msgpack-gen.lua should return type be Float. I added FLOATING_OBJ macros later because did not know that msgpack-gen.lua uses these _OBJ macros, otherwise it would be FLOAT_OBJ. 2. msgpack-gen.lua should use .data.floating in place of .data.float. But it did not expect that .data subattribute may have name different from lowercased type name. 2. vim_replace_termcodes returned its argument as-is if it receives an empty string (as well as _vim_id*() functions did). But if something in returned argument lives in an allocated memory such action will cause double free: once when freeing arguments, then when freeing return value. It did not cause problems yet because msgpack bindings return empty string as {NULL, 0} and nothing was actually allocated. 3. New code in msgpack-gen.lua popped arguments in reversed order, making lua bindings’ signatures be different from API ones. --- test/functional/api/vim_spec.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 3348368a36..24ed0afe67 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -219,6 +219,17 @@ describe('api', function() eq('\128\253\44', helpers.nvim('replace_termcodes', '', true, true, true)) end) + + it('does not crash when transforming an empty string', function() + -- Actually does not test anything, because current code will use NULL for + -- an empty string. + -- + -- Problem here is that if String argument has .data in allocated memory + -- then `return str` in vim_replace_termcodes body will make Neovim free + -- `str.data` twice: once when freeing arguments, then when freeing return + -- value. + eq('', meths.replace_termcodes('', true, true, true)) + end) end) describe('nvim_feedkeys', function() -- cgit From eb0e94f71b1f44cebf7ae5c1bcff348264af6cef Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Thu, 30 Mar 2017 22:03:52 +0200 Subject: api: {get,set}_option should {get,set} global value of local options (#6405) - nvim_get_option should return the global default of a local option. - nvim_set_option should set the global default of a local option. --- test/functional/api/vim_spec.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 3348368a36..8f9f155110 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -153,6 +153,28 @@ describe('api', function() nvim('set_option', 'equalalways', false) ok(not nvim('get_option', 'equalalways')) end) + + it('works to get global value of local options', function() + eq(false, nvim('get_option', 'lisp')) + eq(8, nvim('get_option', 'shiftwidth')) + end) + + it('works to set global value of local options', function() + nvim('set_option', 'lisp', true) + eq(true, nvim('get_option', 'lisp')) + eq(false, helpers.curbuf('get_option', 'lisp')) + eq(nil, nvim('command_output', 'setglobal lisp?'):match('nolisp')) + eq('nolisp', nvim('command_output', 'setlocal lisp?'):match('nolisp')) + nvim('set_option', 'shiftwidth', 20) + eq('20', nvim('command_output', 'setglobal shiftwidth?'):match('%d+')) + eq('8', nvim('command_output', 'setlocal shiftwidth?'):match('%d+')) + end) + + it('most window-local options have no global value', function() + local status, err = pcall(nvim, 'get_option', 'foldcolumn') + eq(false, status) + ok(err:match('Invalid option name') ~= nil) + end) end) describe('nvim_{get,set}_current_buf, nvim_list_bufs', function() -- cgit From 45240538742d6276ab25abe0d8b02550e1c68179 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 21 Apr 2017 14:58:52 +0200 Subject: test: api: Do not truncate errors <1 MB. --- test/functional/api/vim_spec.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 8f9f155110..60f30dcfe6 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -412,7 +412,7 @@ describe('api', function() eq(5, meths.get_var('avar')) end) - it('throws error on malformated arguments', function() + it('throws error on malformed arguments', function() local req = { {'nvim_set_var', {'avar', 1}}, {'nvim_set_var'}, @@ -452,6 +452,13 @@ describe('api', function() ok(err:match('Invalid option name') ~= nil) end) + it('does not truncate error message <1 MB #5984', function() + local very_long_name = 'A'..('x'):rep(10000)..'Z' + local status, err = pcall(nvim, 'get_option', very_long_name) + eq(false, status) + eq(very_long_name, err:match('Ax+Z?')) + end) + it("doesn't leak memory on incorrect argument types", function() local status, err = pcall(nvim, 'set_current_dir',{'not', 'a', 'dir'}) eq(false, status) -- cgit From 086c354a0aad2769042dc91bf5bad021109f56e4 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 23 Apr 2017 22:30:08 +0200 Subject: api: Do not translate error messages. Also re-word some error messages: - "Key does not exist: %s" - "Invalid channel: %" - "Request array size must be 4 (request) or 3 (notification)" - "String cannot contain newlines" References #6150 --- test/functional/api/vim_spec.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 60f30dcfe6..5b173f3196 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -119,7 +119,7 @@ describe('api', function() eq(1, funcs.exists('g:lua')) meths.del_var('lua') eq(0, funcs.exists('g:lua')) - eq({false, 'Key "lua" doesn\'t exist'}, meth_pcall(meths.del_var, 'lua')) + eq({false, 'Key does not exist: lua'}, meth_pcall(meths.del_var, 'lua')) meths.set_var('lua', 1) command('lockvar lua') eq({false, 'Key is locked: lua'}, meth_pcall(meths.del_var, 'lua')) @@ -439,7 +439,7 @@ describe('api', function() } status, err = pcall(meths.call_atomic, req) eq(false, status) - ok(err:match('args must be Array') ~= nil) + ok(err:match('Args must be Array') ~= nil) -- call before was done, but not after eq(1, meths.get_var('avar')) eq({''}, meths.buf_get_lines(0, 0, -1, true)) -- cgit From 3ea10077534cb1dcb1597ffcf85e601fa0c0e27b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 13 Mar 2017 15:02:37 +0100 Subject: api: nvim_get_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Asynchronous API functions are served immediately, which means pending input could change the state of Nvim shortly after an async API function result is returned. nvim_get_mode() is different: - If RPCs are known to be blocked, it responds immediately (without flushing the input/event queue) - else it is handled just-in-time before waiting for input, after pending input was processed. This makes the result more reliable (but not perfect). Internally this is handled as a special case, but _semantically_ nothing has changed: API users never know when input flushes, so this internal special-case doesn't violate that. As far as API users are concerned, nvim_get_mode() is just another asynchronous API function. In all cases nvim_get_mode() never blocks for more than the time it takes to flush the input/event queue (~µs). Note: This doesn't address #6166; nvim_get_mode() will provoke #6166 if e.g. `d` is operator-pending. Closes #6159 --- test/functional/api/vim_spec.lua | 106 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 5b173f3196..d06dd4c487 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -9,6 +9,7 @@ local funcs = helpers.funcs local request = helpers.request local meth_pcall = helpers.meth_pcall local command = helpers.command +local wait = helpers.wait describe('api', function() before_each(clear) @@ -221,6 +222,109 @@ describe('api', function() end) end) + local function appendfile(fname, text) + local file = io.open(fname, 'a') + file:write(text) + file:flush() + file:close() + end + + describe('nvim_get_mode', function() + it("during normal-mode `g` returns blocking=true", function() + nvim("input", "o") -- add a line + eq({mode='i', blocking=false}, nvim("get_mode")) + nvim("input", [[]]) + eq(2, nvim("eval", "line('.')")) + eq({mode='n', blocking=false}, nvim("get_mode")) + + nvim("input", "g") + eq({mode='n', blocking=true}, nvim("get_mode")) + + nvim("input", "k") -- complete the operator + eq(1, nvim("eval", "line('.')")) -- verify the completed operator + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + it("returns the correct result multiple consecutive times", function() + for _ = 1,5 do + eq({mode='n', blocking=false}, nvim("get_mode")) + end + nvim("input", "g") + for _ = 1,4 do + eq({mode='n', blocking=true}, nvim("get_mode")) + end + nvim("input", "g") + for _ = 1,7 do + eq({mode='n', blocking=false}, nvim("get_mode")) + end + end) + + it("during normal-mode CTRL-W, returns blocking=true", function() + nvim("input", "") + eq({mode='n', blocking=true}, nvim("get_mode")) + + nvim("input", "s") -- complete the operator + eq(2, nvim("eval", "winnr('$')")) -- verify the completed operator + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + it("during press-enter prompt returns blocking=true", function() + eq({mode='n', blocking=false}, nvim("get_mode")) + command("echom 'msg1'") + command("echom 'msg2'") + command("echom 'msg3'") + command("echom 'msg4'") + command("echom 'msg5'") + eq({mode='n', blocking=false}, nvim("get_mode")) + nvim("input", ":messages") + eq({mode='r', blocking=true}, nvim("get_mode")) + end) + + it("during getchar() returns blocking=false", function() + nvim("input", ":let g:test_input = nr2char(getchar())") + -- Events are enabled during getchar(), RPC calls are *not* blocked. #5384 + eq({mode='n', blocking=false}, nvim("get_mode")) + eq(0, nvim("eval", "exists('g:test_input')")) + nvim("input", "J") + eq("J", nvim("eval", "g:test_input")) + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + -- TODO: bug #6247#issuecomment-286403810 + it("batched with input", function() + eq({mode='n', blocking=false}, nvim("get_mode")) + command("echom 'msg1'") + command("echom 'msg2'") + command("echom 'msg3'") + command("echom 'msg4'") + command("echom 'msg5'") + + local req = { + {'nvim_get_mode', {}}, + {'nvim_input', {':messages'}}, + {'nvim_get_mode', {}}, + {'nvim_eval', {'1'}}, + } + eq({{{mode='n', blocking=false}, + 13, + {mode='n', blocking=false}, -- TODO: should be blocked=true + 1}, + NIL}, meths.call_atomic(req)) + eq({mode='r', blocking=true}, nvim("get_mode")) + end) + -- TODO: bug #6166 + it("during insert-mode map-pending, returns blocking=true #6166", function() + command("inoremap xx foo") + nvim("input", "ix") + eq({mode='i', blocking=true}, nvim("get_mode")) + end) + -- TODO: bug #6166 + it("during normal-mode gU, returns blocking=false #6166", function() + nvim("input", "gu") + eq({mode='no', blocking=false}, nvim("get_mode")) + end) + end) + describe('nvim_replace_termcodes', function() it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function() eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true)) @@ -459,7 +563,7 @@ describe('api', function() eq(very_long_name, err:match('Ax+Z?')) end) - it("doesn't leak memory on incorrect argument types", function() + it("does not leak memory on incorrect argument types", function() local status, err = pcall(nvim, 'set_current_dir',{'not', 'a', 'dir'}) eq(false, status) ok(err:match(': Wrong type for argument 1, expecting String') ~= nil) -- cgit From acfd2a2a29ae852ecc965ca888eb5049400bf39d Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Mar 2017 00:44:03 +0100 Subject: input.c: Process only safe events before blocking. Introduce multiqueue_process_priority() to process only events at or above a certain priority. --- test/functional/api/vim_spec.lua | 8 -------- 1 file changed, 8 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index d06dd4c487..7c79d8832f 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -9,7 +9,6 @@ local funcs = helpers.funcs local request = helpers.request local meth_pcall = helpers.meth_pcall local command = helpers.command -local wait = helpers.wait describe('api', function() before_each(clear) @@ -222,13 +221,6 @@ describe('api', function() end) end) - local function appendfile(fname, text) - local file = io.open(fname, 'a') - file:write(text) - file:flush() - file:close() - end - describe('nvim_get_mode', function() it("during normal-mode `g` returns blocking=true", function() nvim("input", "o") -- add a line -- cgit From f424189093ab23fb727a996d317ff19d4d3f0b63 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 9 May 2017 08:55:04 +0200 Subject: api: execute lua directly from the remote api --- test/functional/api/vim_spec.lua | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 282ecbfd87..61ec6ea829 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -81,6 +81,36 @@ describe('api', function() end) end) + describe('nvim_execute_lua', function() + it('works', function() + meths.execute_lua('vim.api.nvim_set_var("test", 3)', {}) + eq(3, meths.get_var('test')) + + eq(17, meths.execute_lua('a, b = ...\nreturn a + b', {10,7})) + + eq(NIL, meths.execute_lua('function xx(a,b)\nreturn a..b\nend',{})) + eq("xy", meths.execute_lua('return xx(...)', {'x','y'})) + end) + + it('reports errors', function() + eq({false, 'Error loading lua: [string ""]:1: '.. + "'=' expected near '+'"}, + meth_pcall(meths.execute_lua, 'a+*b', {})) + + eq({false, 'Error loading lua: [string ""]:1: '.. + "unexpected symbol near '1'"}, + meth_pcall(meths.execute_lua, '1+2', {})) + + eq({false, 'Error loading lua: [string ""]:1: '.. + "unexpected symbol"}, + meth_pcall(meths.execute_lua, 'aa=bb\0', {})) + + eq({false, 'Error executing lua: [string ""]:1: '.. + "attempt to call global 'bork' (a nil value)"}, + meth_pcall(meths.execute_lua, 'bork()', {})) + end) + end) + describe('nvim_input', function() it("VimL error: does NOT fail, updates v:errmsg", function() local status, _ = pcall(nvim, "input", ":call bogus_fn()") -- cgit From bdd73fc07ff8bcf9502f9c6a980a278b9e7b8f27 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 20 May 2017 22:20:21 +0200 Subject: api/nvim_replace_termcodes: Document keycodes behavior --- test/functional/api/vim_spec.lua | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 61ec6ea829..161682b973 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -368,6 +368,11 @@ describe('api', function() '', true, true, true)) end) + it('converts keycodes', function() + eq('\nx\27x\rxxxxx', true, true, true)) + end) + it('does not crash when transforming an empty string', function() -- Actually does not test anything, because current code will use NULL for -- an empty string. -- cgit From a5a5c83608e6d4455ac40e8786fd16eaf817c608 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 23 May 2017 00:16:23 +0300 Subject: api/vim: Fix nvim_list_runtimepaths It used to 1. Always omit last component in runtimepath. 2. Always omit trailing empty item and leave uninitialized memory in place of it. --- test/functional/api/vim_spec.lua | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 161682b973..c531d4af46 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -327,11 +327,11 @@ describe('api', function() {'nvim_get_mode', {}}, {'nvim_eval', {'1'}}, } - eq({{{mode='n', blocking=false}, - 13, - {mode='n', blocking=false}, -- TODO: should be blocked=true - 1}, - NIL}, meths.call_atomic(req)) + eq({ { {mode='n', blocking=false}, + 13, + {mode='n', blocking=false}, -- TODO: should be blocked=true + 1 }, + NIL}, meths.call_atomic(req)) eq({mode='r', blocking=true}, nvim("get_mode")) end) -- TODO: bug #6166 @@ -588,6 +588,36 @@ describe('api', function() end) end) + describe('list_runtime_paths', function() + it('returns nothing with empty &runtimepath', function() + meths.set_option('runtimepath', '') + eq({}, meths.list_runtime_paths()) + end) + it('returns single runtimepath', function() + meths.set_option('runtimepath', 'a') + eq({'a'}, meths.list_runtime_paths()) + end) + it('returns two runtimepaths', function() + meths.set_option('runtimepath', 'a,b') + eq({'a', 'b'}, meths.list_runtime_paths()) + end) + it('returns empty strings when appropriate', function() + meths.set_option('runtimepath', 'a,,b') + eq({'a', '', 'b'}, meths.list_runtime_paths()) + meths.set_option('runtimepath', ',a,b') + eq({'', 'a', 'b'}, meths.list_runtime_paths()) + meths.set_option('runtimepath', 'a,b,') + eq({'a', 'b', ''}, meths.list_runtime_paths()) + end) + it('truncates too long paths', function() + local long_path = ('/a'):rep(8192) + meths.set_option('runtimepath', long_path) + local paths_list = meths.list_runtime_paths() + neq({long_path}, paths_list) + eq({long_path:sub(1, #(paths_list[1]))}, paths_list) + end) + end) + it('can throw exceptions', function() local status, err = pcall(nvim, 'get_option', 'invalid-option') eq(false, status) -- cgit From 0ea7e45bc1d1881f505da2b77e0b3e4eb56f12fe Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 2 Jul 2017 13:21:38 +0200 Subject: 'cpoptions': remove "<" flag; ignore Closes #6937 "nvim_get_keymap output is unreliable" --- test/functional/api/vim_spec.lua | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index c531d4af46..e59b5d712d 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -373,6 +373,11 @@ describe('api', function() 'xxxx', true, true, true)) end) + it('does not convert keycodes if special=false', function() + eq('xxxx', helpers.nvim('replace_termcodes', + 'xxxx', true, true, false)) + end) + it('does not crash when transforming an empty string', function() -- Actually does not test anything, because current code will use NULL for -- an empty string. @@ -391,13 +396,13 @@ describe('api', function() -- notice the special char(…) \xe2\80\xa6 nvim('feedkeys', ':let x1="…"\n', '', true) - -- Both replace_termcodes and feedkeys escape \x80 + -- Both nvim_replace_termcodes and nvim_feedkeys escape \x80 local inp = helpers.nvim('replace_termcodes', ':let x2="…"', true, true, true) - nvim('feedkeys', inp, '', true) + nvim('feedkeys', inp, '', true) -- escape_csi=true - -- Disabling CSI escaping in feedkeys + -- nvim_feedkeys with CSI escaping disabled inp = helpers.nvim('replace_termcodes', ':let x3="…"', true, true, true) - nvim('feedkeys', inp, '', false) + nvim('feedkeys', inp, '', false) -- escape_csi=false helpers.stop() end -- cgit From 541dde36e3302314e2646415dbfd2b79a6c2a1fc Mon Sep 17 00:00:00 2001 From: Matthew Malcomson Date: Sat, 2 Sep 2017 14:12:32 +0100 Subject: eventloop: K_EVENT should not finish operator normal_finish_command() and normal_prepare() assume that any pending operator needs to be finished after any subsequent key. Set `finish_op = false` in nv_event() to indicate that the pending operator shouldn't be finished in normal_execute(). This is how nv_visual() indicates that 'v' or 'V' in operator-pending mode should not finish the current pending operator. fixes #5398 fixes #6166 (partially; mappings are still interrupted) --- test/functional/api/vim_spec.lua | 62 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index e59b5d712d..5566c6d8e4 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -329,24 +329,80 @@ describe('api', function() } eq({ { {mode='n', blocking=false}, 13, - {mode='n', blocking=false}, -- TODO: should be blocked=true + {mode='n', blocking=false}, -- TODO: should be blocked=true ? 1 }, NIL}, meths.call_atomic(req)) eq({mode='r', blocking=true}, nvim("get_mode")) end) - -- TODO: bug #6166 it("during insert-mode map-pending, returns blocking=true #6166", function() command("inoremap xx foo") nvim("input", "ix") eq({mode='i', blocking=true}, nvim("get_mode")) end) - -- TODO: bug #6166 it("during normal-mode gU, returns blocking=false #6166", function() nvim("input", "gu") eq({mode='no', blocking=false}, nvim("get_mode")) end) end) + describe('RPC (K_EVENT) #6166', function() + it('does not complete/interrupt normal-mode operator', function() + helpers.insert([[ + FIRST LINE + SECOND LINE]]) + nvim('input', 'gg') + nvim('input', 'gu') + -- Make any non-async RPC request. + nvim('get_current_buf') + -- Buffer should not change. + helpers.expect([[ + FIRST LINE + SECOND LINE]]) + -- Now send input to complete the operator. + nvim("input", "j") + helpers.expect([[ + first line + second line]]) + end) + -- TODO: bug #6166 + pending('does not complete/interrupt normal-mode mapping', function() + command("nnoremap dd :let g:foo='it worked...'") + helpers.insert([[ + FIRST LINE + SECOND LINE]]) + nvim('input', 'gg') + nvim('input', 'd') + helpers.expect([[ + FIRST LINE + SECOND LINE]]) + -- Make any non-async RPC request. (expect() does RPC, but be explicit) + nvim('get_current_buf') + -- Send input to complete the mapping. + nvim('input', 'd') + helpers.expect([[ + FIRST LINE + SECOND LINE]]) + eq('it worked...', eval('g:foo')) + end) + it('does not complete/interrupt insert-mode mapping', function() + command("inoremap xx foo") + helpers.insert([[ + FIRST LINE + SECOND LINE]]) + nvim('input', 'ix') + helpers.expect([[ + FIRST LINE + SECOND LINxE]]) + -- Make any non-async RPC request. (expect() does RPC, but be explicit) + nvim('get_current_buf') + -- Send input to complete the mapping. + nvim('input', 'x') + helpers.expect([[ + FIRST LINE + SECOND LINxxE]]) -- TODO: should be "SECOND LINfooE" #6166 + end) + end) + describe('nvim_replace_termcodes', function() it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function() eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true)) -- cgit From 3922237b1442deed48d1be32a7967e9eb6a19151 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 4 Sep 2017 08:46:10 +0200 Subject: test: lint --- test/functional/api/vim_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 5566c6d8e4..252a380378 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -382,7 +382,7 @@ describe('api', function() helpers.expect([[ FIRST LINE SECOND LINE]]) - eq('it worked...', eval('g:foo')) + eq('it worked...', helpers.eval('g:foo')) end) it('does not complete/interrupt insert-mode mapping', function() command("inoremap xx foo") -- cgit From ce852bab04c63262ce8545c01a4ff4fc827148a1 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 4 Sep 2017 22:45:14 +0200 Subject: eventloop: K_EVENT does not finish mapping The "mapping" tests added in 541dde36e330 were flawed: - Unlike op-pending mode, RPCs are _blocked_ during map-pending. So a synchronous RPC like nvim_get_current_buf() waits until 'timeoutlen', then the mapping is canceled. - helpers.expect() also performs a blocking RPC, so again that must not intervene the two nvim_input() calls. closes #6166 --- test/functional/api/vim_spec.lua | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 252a380378..a4b643589a 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -346,37 +346,33 @@ describe('api', function() end) describe('RPC (K_EVENT) #6166', function() - it('does not complete/interrupt normal-mode operator', function() + it('does not complete ("interrupt") normal-mode operator-pending', function() helpers.insert([[ FIRST LINE SECOND LINE]]) nvim('input', 'gg') nvim('input', 'gu') - -- Make any non-async RPC request. + -- Make any RPC request (can be non-async: op-pending does not block). nvim('get_current_buf') -- Buffer should not change. helpers.expect([[ FIRST LINE SECOND LINE]]) -- Now send input to complete the operator. - nvim("input", "j") + nvim('input', 'j') helpers.expect([[ - first line - second line]]) + first line + second line]]) end) - -- TODO: bug #6166 - pending('does not complete/interrupt normal-mode mapping', function() + it('does not complete ("interrupt") normal-mode map-pending', function() command("nnoremap dd :let g:foo='it worked...'") helpers.insert([[ FIRST LINE SECOND LINE]]) nvim('input', 'gg') nvim('input', 'd') - helpers.expect([[ - FIRST LINE - SECOND LINE]]) - -- Make any non-async RPC request. (expect() does RPC, but be explicit) - nvim('get_current_buf') + -- Make any RPC request (must be async, because map-pending blocks). + nvim('get_api_info') -- Send input to complete the mapping. nvim('input', 'd') helpers.expect([[ @@ -384,22 +380,20 @@ describe('api', function() SECOND LINE]]) eq('it worked...', helpers.eval('g:foo')) end) - it('does not complete/interrupt insert-mode mapping', function() - command("inoremap xx foo") + it('does not complete ("interrupt") insert-mode map-pending', function() + command('inoremap xx foo') + command('set timeoutlen=9999') helpers.insert([[ FIRST LINE SECOND LINE]]) nvim('input', 'ix') - helpers.expect([[ - FIRST LINE - SECOND LINxE]]) - -- Make any non-async RPC request. (expect() does RPC, but be explicit) - nvim('get_current_buf') + -- Make any RPC request (must be async, because map-pending blocks). + nvim('get_api_info') -- Send input to complete the mapping. nvim('input', 'x') helpers.expect([[ FIRST LINE - SECOND LINxxE]]) -- TODO: should be "SECOND LINfooE" #6166 + SECOND LINfooE]]) end) end) -- cgit From 9d6bac3219a0cc1647b560b0d28b0a3fce9dc96a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 16 Sep 2017 12:17:59 +0200 Subject: test: more coverage for RPC + op-pending #3732 --- test/functional/api/vim_spec.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index a4b643589a..b849304d45 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -364,6 +364,24 @@ describe('api', function() first line second line]]) end) + + it('does not complete ("interrupt") `d` #3732', function() + local screen = Screen.new(20, 4) + screen:attach() + command('set listchars=eol:$') + command('set list') + feed('iabckkk') + feed('d') + -- Make any RPC request (can be non-async: op-pending does not block). + nvim('get_current_buf') + screen:expect([[ + ^a$ | + b$ | + c$ | + | + ]]) + end) + it('does not complete ("interrupt") normal-mode map-pending', function() command("nnoremap dd :let g:foo='it worked...'") helpers.insert([[ -- cgit