aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rw-r--r--test/functional/api/buffer_spec.lua3
-rw-r--r--test/functional/api/server_notifications_spec.lua1
-rw-r--r--test/functional/api/tabpage_spec.lua19
-rw-r--r--test/functional/api/vim_spec.lua149
-rw-r--r--test/functional/api/window_spec.lua27
-rw-r--r--test/functional/core/job_spec.lua8
-rw-r--r--test/functional/eval/execute_spec.lua12
-rw-r--r--test/functional/eval/system_spec.lua (renamed from test/functional/shell/viml_system_spec.lua)27
-rw-r--r--test/functional/eval/timer_spec.lua68
-rw-r--r--test/functional/ex_cmds/bang_filter_spec.lua (renamed from test/functional/shell/bang_filter_spec.lua)0
-rw-r--r--test/functional/ex_cmds/dict_notifications_spec.lua (renamed from test/functional/dict_notifications_spec.lua)0
-rw-r--r--test/functional/ex_cmds/write_spec.lua41
-rw-r--r--test/functional/helpers.lua20
-rw-r--r--test/functional/legacy/assert_spec.lua15
-rw-r--r--test/functional/legacy/quickfix_spec.lua117
-rw-r--r--test/functional/terminal/api_spec.lua12
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua48
-rw-r--r--test/functional/viml/completion_spec.lua56
18 files changed, 561 insertions, 62 deletions
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index 71ec213b97..3d3a2bb046 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -1,4 +1,3 @@
--- Sanity checks for buffer_* API calls via msgpack-rpc
local helpers = require('test.functional.helpers')(after_each)
local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer
local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq
@@ -6,7 +5,7 @@ local curbufmeths, ok = helpers.curbufmeths, helpers.ok
local funcs, request = helpers.funcs, helpers.request
local NIL = helpers.NIL
-describe('buffer_* functions', function()
+describe('api/buf', function()
before_each(clear)
-- access deprecated functions
diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua
index 88e8c60560..78639d7ed7 100644
--- a/test/functional/api/server_notifications_spec.lua
+++ b/test/functional/api/server_notifications_spec.lua
@@ -1,4 +1,3 @@
--- Tests for nvim notifications
local helpers = require('test.functional.helpers')(after_each)
local eq, clear, eval, execute, nvim, next_message =
helpers.eq, helpers.clear, helpers.eval, helpers.execute, helpers.nvim,
diff --git a/test/functional/api/tabpage_spec.lua b/test/functional/api/tabpage_spec.lua
index 47dede8b44..e10f30085f 100644
--- a/test/functional/api/tabpage_spec.lua
+++ b/test/functional/api/tabpage_spec.lua
@@ -1,4 +1,3 @@
--- Sanity checks for tabpage_* API calls via msgpack-rpc
local helpers = require('test.functional.helpers')(after_each)
local clear, nvim, tabpage, curtab, eq, ok =
helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq,
@@ -8,7 +7,7 @@ local funcs = helpers.funcs
local request = helpers.request
local NIL = helpers.NIL
-describe('tabpage_* functions', function()
+describe('api/tabpage', function()
before_each(clear)
describe('list_wins and get_win', function()
@@ -51,6 +50,22 @@ describe('tabpage_* functions', function()
end)
end)
+ describe('get_number', function()
+ it('works', function()
+ local tabs = nvim('list_tabpages')
+ eq(1, tabpage('get_number', tabs[1]))
+
+ nvim('command', 'tabnew')
+ local tab1, tab2 = unpack(nvim('list_tabpages'))
+ eq(1, tabpage('get_number', tab1))
+ eq(2, tabpage('get_number', tab2))
+
+ nvim('command', '-tabmove')
+ eq(2, tabpage('get_number', tab1))
+ eq(1, tabpage('get_number', tab2))
+ end)
+ end)
+
describe('is_valid', function()
it('works', function()
nvim('command', 'tabnew')
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 6b30c0e81c..ce6c52e334 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -1,4 +1,3 @@
--- Sanity checks for vim_* API calls via msgpack-rpc
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local NIL = helpers.NIL
@@ -9,10 +8,10 @@ local meths = helpers.meths
local funcs = helpers.funcs
local request = helpers.request
-describe('vim_* functions', function()
+describe('api', function()
before_each(clear)
- describe('command', function()
+ describe('nvim_command', function()
it('works', function()
local fname = helpers.tmpname()
nvim('command', 'new')
@@ -29,9 +28,18 @@ describe('vim_* functions', function()
f:close()
os.remove(fname)
end)
+
+ it("VimL error: fails (VimL error), does NOT update v:errmsg", function()
+ -- Most API methods return generic errors (or no error) if a VimL
+ -- expression fails; nvim_command returns the VimL error details.
+ local status, rv = pcall(nvim, "command", "bogus_command")
+ eq(false, status) -- nvim_command() failed.
+ eq("E492:", string.match(rv, "E%d*:")) -- VimL error was returned.
+ eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated.
+ end)
end)
- describe('eval', function()
+ describe('nvim_eval', function()
it('works', function()
nvim('command', 'let g:v1 = "a"')
nvim('command', 'let g:v2 = [1, 2, {"v3": 3}]')
@@ -46,18 +54,41 @@ describe('vim_* functions', function()
it('works under deprecated name', function()
eq(2, request("vim_eval", "1+1"))
end)
+
+ it("VimL error: fails (generic error), does NOT update v:errmsg", function()
+ local status, rv = pcall(nvim, "eval", "bogus expression")
+ eq(false, status) -- nvim_eval() failed.
+ ok(nil ~= string.find(rv, "Failed to evaluate expression"))
+ eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated.
+ end)
end)
- describe('call_function', function()
+ describe('nvim_call_function', function()
it('works', function()
nvim('call_function', 'setqflist', {{{ filename = 'something', lnum = 17}}, 'r'})
eq(17, nvim('call_function', 'getqflist', {})[1].lnum)
eq(17, nvim('call_function', 'eval', {17}))
eq('foo', nvim('call_function', 'simplify', {'this/./is//redundant/../../../foo'}))
end)
+
+ it("VimL error: fails (generic error), does NOT update v:errmsg", function()
+ local status, rv = pcall(nvim, "call_function", "bogus function", {"arg1"})
+ eq(false, status) -- nvim_call_function() failed.
+ ok(nil ~= string.find(rv, "Error calling function"))
+ eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated.
+ end)
end)
- describe('strwidth', function()
+ describe('nvim_input', function()
+ it("VimL error: does NOT fail, updates v:errmsg", function()
+ local status, _ = pcall(nvim, "input", ":call bogus_fn()<CR>")
+ local v_errnum = string.match(nvim("eval", "v:errmsg"), "E%d*:")
+ eq(true, status) -- nvim_input() did not fail.
+ eq("E117:", v_errnum) -- v:errmsg was updated.
+ end)
+ end)
+
+ describe('nvim_strwidth', function()
it('works', function()
eq(3, nvim('strwidth', 'abc'))
-- 6 + (neovim)
@@ -70,7 +101,7 @@ describe('vim_* functions', function()
end)
end)
- describe('{get,set}_current_line', function()
+ describe('nvim_get_current_line, nvim_set_current_line', function()
it('works', function()
eq('', nvim('get_current_line'))
nvim('set_current_line', 'abc')
@@ -78,7 +109,7 @@ describe('vim_* functions', function()
end)
end)
- describe('{get,set,del}_var', function()
+ describe('nvim_get_var, nvim_set_var, nvim_del_var', function()
it('works', function()
nvim('set_var', 'lua', {1, 2, {['3'] = 1}})
eq({1, 2, {['3'] = 1}}, nvim('get_var', 'lua'))
@@ -109,7 +140,7 @@ describe('vim_* functions', function()
end)
end)
- describe('{get,set}_option', function()
+ describe('nvim_get_option, nvim_set_option', function()
it('works', function()
ok(nvim('get_option', 'equalalways'))
nvim('set_option', 'equalalways', false)
@@ -117,7 +148,7 @@ describe('vim_* functions', function()
end)
end)
- describe('{get,set}_current_buf and list_bufs', function()
+ describe('nvim_{get,set}_current_buf, nvim_list_bufs', function()
it('works', function()
eq(1, #nvim('list_bufs'))
eq(nvim('list_bufs')[1], nvim('get_current_buf'))
@@ -129,7 +160,7 @@ describe('vim_* functions', function()
end)
end)
- describe('{get,set}_current_win and list_wins', function()
+ describe('nvim_{get,set}_current_win, nvim_list_wins', function()
it('works', function()
eq(1, #nvim('list_wins'))
eq(nvim('list_wins')[1], nvim('get_current_win'))
@@ -142,7 +173,7 @@ describe('vim_* functions', function()
end)
end)
- describe('{get,set}_current_tabpage and list_tabpages', function()
+ describe('nvim_{get,set}_current_tabpage, nvim_list_tabpages', function()
it('works', function()
eq(1, #nvim('list_tabpages'))
eq(nvim('list_tabpages')[1], nvim('get_current_tabpage'))
@@ -161,7 +192,7 @@ describe('vim_* functions', function()
end)
end)
- describe('replace_termcodes', function()
+ 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))
end)
@@ -183,7 +214,7 @@ describe('vim_* functions', function()
end)
end)
- describe('feedkeys', function()
+ describe('nvim_feedkeys', function()
it('CSI escaping', function()
local function on_setup()
-- notice the special char(…) \xe2\80\xa6
@@ -210,7 +241,7 @@ describe('vim_* functions', function()
end)
end)
- describe('err_write', function()
+ describe('nvim_err_write', function()
local screen
before_each(function()
@@ -298,6 +329,94 @@ describe('vim_* functions', function()
end)
end)
+ describe('nvim_call_atomic', function()
+ it('works', function()
+ meths.buf_set_lines(0, 0, -1, true, {'first'})
+ local req = {
+ {'nvim_get_current_line', {}},
+ {'nvim_set_current_line', {'second'}},
+ }
+ eq({{'first', NIL}, NIL}, meths.call_atomic(req))
+ eq({'second'}, meths.buf_get_lines(0, 0, -1, true))
+ end)
+
+ it('allows multiple return values', function()
+ local req = {
+ {'nvim_set_var', {'avar', true}},
+ {'nvim_set_var', {'bvar', 'string'}},
+ {'nvim_get_var', {'avar'}},
+ {'nvim_get_var', {'bvar'}},
+ }
+ eq({{NIL, NIL, true, 'string'}, NIL}, meths.call_atomic(req))
+ end)
+
+ it('is aborted by errors in call', function()
+ local error_types = meths.get_api_info()[2].error_types
+ local req = {
+ {'nvim_set_var', {'one', 1}},
+ {'nvim_buf_set_lines', {}},
+ {'nvim_set_var', {'two', 2}},
+ }
+ eq({{NIL}, {1, error_types.Exception.id,
+ 'Wrong number of arguments: expecting 5 but got 0'}},
+ meths.call_atomic(req))
+ eq(1, meths.get_var('one'))
+ eq(false, pcall(meths.get_var, 'two'))
+
+ -- still returns all previous successful calls
+ req = {
+ {'nvim_set_var', {'avar', 5}},
+ {'nvim_set_var', {'bvar', 'string'}},
+ {'nvim_get_var', {'avar'}},
+ {'nvim_buf_get_lines', {0, 10, 20, true}},
+ {'nvim_get_var', {'bvar'}},
+ }
+ eq({{NIL, NIL, 5}, {3, error_types.Validation.id, 'Index out of bounds'}},
+ meths.call_atomic(req))
+
+ req = {
+ {'i_am_not_a_method', {'xx'}},
+ {'nvim_set_var', {'avar', 10}},
+ }
+ eq({{}, {0, error_types.Exception.id, 'Invalid method name'}},
+ meths.call_atomic(req))
+ eq(5, meths.get_var('avar'))
+ end)
+
+ it('throws error on malformated arguments', function()
+ local req = {
+ {'nvim_set_var', {'avar', 1}},
+ {'nvim_set_var'},
+ {'nvim_set_var', {'avar', 2}},
+ }
+ local status, err = pcall(meths.call_atomic, req)
+ eq(false, status)
+ ok(err:match(' All items in calls array must be arrays of size 2') ~= nil)
+ -- call before was done, but not after
+ eq(1, meths.get_var('avar'))
+
+ req = {
+ {'nvim_set_var', {'bvar', {2,3}}},
+ 12,
+ }
+ status, err = pcall(meths.call_atomic, req)
+ eq(false, status)
+ ok(err:match('All items in calls array must be arrays') ~= nil)
+ eq({2,3}, meths.get_var('bvar'))
+
+ req = {
+ {'nvim_set_current_line', 'little line'},
+ {'nvim_set_var', {'avar', 3}},
+ }
+ status, err = pcall(meths.call_atomic, req)
+ eq(false, status)
+ 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))
+ end)
+ end)
+
it('can throw exceptions', function()
local status, err = pcall(nvim, 'get_option', 'invalid-option')
eq(false, status)
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 2c43e4db2c..465bda6bc9 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -1,4 +1,3 @@
--- Sanity checks for window_* API calls via msgpack-rpc
local helpers = require('test.functional.helpers')(after_each)
local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq,
ok, feed, insert, eval = helpers.clear, helpers.nvim, helpers.curbuf,
@@ -29,7 +28,7 @@ local function is_visible(str)
return false
end
-describe('window_* functions', function()
+describe('api/win', function()
before_each(clear)
describe('get_buf', function()
@@ -200,6 +199,30 @@ describe('window_* functions', function()
end)
end)
+ describe('get_number', function()
+ it('works', function()
+ local wins = nvim('list_wins')
+ eq(1, window('get_number', wins[1]))
+
+ nvim('command', 'split')
+ local win1, win2 = unpack(nvim('list_wins'))
+ eq(1, window('get_number', win1))
+ eq(2, window('get_number', win2))
+
+ nvim('command', 'wincmd J')
+ eq(2, window('get_number', win1))
+ eq(1, window('get_number', win2))
+
+ nvim('command', 'tabnew')
+ local win3 = nvim('list_wins')[3]
+ -- First tab page
+ eq(2, window('get_number', win1))
+ eq(1, window('get_number', win2))
+ -- Second tab page
+ eq(1, window('get_number', win3))
+ end)
+ end)
+
describe('is_valid', function()
it('works', function()
nvim('command', 'split')
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index adbe17d4b5..5872ebe8ee 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -121,14 +121,14 @@ describe('jobs', function()
eq({'notification', 'exit', {0, 0}}, next_msg())
end)
- it('can preserve newlines', function()
+ it('preserves newlines', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, "a\\n\\nc\\n\\n\\n\\nb\\n\\n")')
eq({'notification', 'stdout',
{0, {'a', '', 'c', '', '', '', 'b', '', ''}}}, next_msg())
end)
- it('can preserve NULs', function()
+ it('preserves NULs', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, ["\n123\n", "abc\\nxyz\n", ""])')
eq({'notification', 'stdout', {0, {'\n123\n', 'abc\nxyz\n', ''}}},
@@ -137,7 +137,7 @@ describe('jobs', function()
eq({'notification', 'exit', {0, 0}}, next_msg())
end)
- it('can avoid sending final newline', function()
+ it('avoids sending final newline', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, ["some data", "without\nfinal nl"])')
eq({'notification', 'stdout', {0, {'some data', 'without\nfinal nl'}}},
@@ -146,7 +146,7 @@ describe('jobs', function()
eq({'notification', 'exit', {0, 0}}, next_msg())
end)
- it('can close the job streams with jobclose', function()
+ it('closes the job streams with jobclose', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobclose(j, "stdin")')
eq({'notification', 'exit', {0, 0}}, next_msg())
diff --git a/test/functional/eval/execute_spec.lua b/test/functional/eval/execute_spec.lua
index 10a6de6eb4..b5b481435a 100644
--- a/test/functional/eval/execute_spec.lua
+++ b/test/functional/eval/execute_spec.lua
@@ -70,16 +70,16 @@ describe('execute()', function()
end)
it('silences command run inside', function()
- local screen = Screen.new(20, 5)
+ local screen = Screen.new(40, 5)
screen:attach()
screen:set_default_attr_ids( {[0] = {bold=true, foreground=255}} )
feed(':let g:mes = execute("echon 42")<CR>')
screen:expect([[
- ^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ :let g:mes = execute("echon 42") |
]])
eq('42', eval('g:mes'))
end)
diff --git a/test/functional/shell/viml_system_spec.lua b/test/functional/eval/system_spec.lua
index b8de7cc86f..6393477260 100644
--- a/test/functional/shell/viml_system_spec.lua
+++ b/test/functional/eval/system_spec.lua
@@ -1,10 +1,7 @@
--- Specs for
--- - `system()`
--- - `systemlist()`
-
local helpers = require('test.functional.helpers')(after_each)
-local eq, clear, eval, feed, nvim =
- helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.nvim
+local eq, clear, eval, execute, feed, nvim =
+ helpers.eq, helpers.clear, helpers.eval, helpers.execute, helpers.feed,
+ helpers.nvim
local Screen = require('test.functional.ui.screen')
@@ -120,12 +117,30 @@ describe('system()', function()
it('returns the program output', function()
eq("echoed", eval('system("echo -n echoed")'))
end)
+ it('to backgrounded command does not crash', function()
+ -- This is indeterminate, just exercise the codepath. May get E5677.
+ execute('call system("echo -n echoed &")')
+ local v_errnum = string.match(eval("v:errmsg"), "^E%d*:")
+ if v_errnum then
+ eq("E5677:", v_errnum)
+ end
+ eq(2, eval("1+1")) -- Still alive?
+ end)
end)
describe('passing input', function()
it('returns the program output', function()
eq("input", eval('system("cat -", "input")'))
end)
+ it('to backgrounded command does not crash', function()
+ -- This is indeterminate, just exercise the codepath. May get E5677.
+ execute('call system("cat - &")')
+ local v_errnum = string.match(eval("v:errmsg"), "^E%d*:")
+ if v_errnum then
+ eq("E5677:", v_errnum)
+ end
+ eq(2, eval("1+1")) -- Still alive?
+ end)
end)
describe('passing a lot of input', function()
diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua
index 295c763d74..fba9466b78 100644
--- a/test/functional/eval/timer_spec.lua
+++ b/test/functional/eval/timer_spec.lua
@@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen')
local ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval
local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run
local clear, execute, funcs = helpers.clear, helpers.execute, helpers.funcs
+local curbufmeths = helpers.curbufmeths
describe('timers', function()
before_each(function()
@@ -62,19 +63,76 @@ describe('timers', function()
end)
it('are paused when event processing is disabled', function()
- -- this is not the intended behavior, but at least there will
- -- not be a burst of queued up callbacks
- execute("call timer_start(50, 'MyHandler', {'repeat': 2})")
+ execute("call timer_start(50, 'MyHandler', {'repeat': -1})")
run(nil, nil, nil, 100)
local count = eval("g:val")
+ -- shows two line error message and thus invokes the return prompt.
+ -- if we start to allow event processing here, we need to change this test.
+ execute("throw 'fatal error'")
+ run(nil, nil, nil, 300)
+ feed("<cr>")
+ local diff = eval("g:val") - count
+ ok(0 <= diff and diff <= 4)
+ end)
+
+ it('are triggered in blocking getchar() call', function()
+ execute("call timer_start(50, 'MyHandler', {'repeat': -1})")
nvim_async("command", "let g:c = getchar()")
run(nil, nil, nil, 300)
feed("c")
- local diff = eval("g:val") - count
- ok(0 <= diff and diff <= 2)
+ local count = eval("g:val")
+ ok(count >= 5)
eq(99, eval("g:c"))
end)
+ it('can invoke redraw in blocking getchar() call', function()
+ local screen = Screen.new(40, 6)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold=true, foreground=Screen.colors.Blue},
+ })
+
+ curbufmeths.set_lines(0, -1, true, {"ITEM 1", "ITEM 2"})
+ source([[
+ func! AddItem(timer)
+ call nvim_buf_set_lines(0, 2, 2, v:true, ['ITEM 3'])
+ redraw
+ endfunc
+ call timer_start(200, 'AddItem')
+ ]])
+ nvim_async("command", "let g:c2 = getchar()")
+
+ screen:expect([[
+ ITEM 1 |
+ ITEM 2 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ^ |
+ ]])
+
+ screen:sleep(200)
+ screen:expect([[
+ ITEM 1 |
+ ITEM 2 |
+ ITEM 3 |
+ {1:~ }|
+ {1:~ }|
+ ^ |
+ ]])
+
+ feed("3")
+ eq(51, eval("g:c2"))
+ screen:expect([[
+ ^ITEM 1 |
+ ITEM 2 |
+ ITEM 3 |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end)
+
it('can be stopped', function()
local t = eval("timer_start(50, 'MyHandler', {'repeat': -1})")
eq(0,eval("g:val"))
diff --git a/test/functional/shell/bang_filter_spec.lua b/test/functional/ex_cmds/bang_filter_spec.lua
index a320e6d018..a320e6d018 100644
--- a/test/functional/shell/bang_filter_spec.lua
+++ b/test/functional/ex_cmds/bang_filter_spec.lua
diff --git a/test/functional/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua
index dc87312911..dc87312911 100644
--- a/test/functional/dict_notifications_spec.lua
+++ b/test/functional/ex_cmds/dict_notifications_spec.lua
diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua
index c1bc5d3140..4ac9f312ef 100644
--- a/test/functional/ex_cmds/write_spec.lua
+++ b/test/functional/ex_cmds/write_spec.lua
@@ -1,20 +1,26 @@
--- Specs for :write
-
local helpers = require('test.functional.helpers')(after_each)
-local eq, eval, clear, write_file, execute, source =
- helpers.eq, helpers.eval, helpers.clear, helpers.write_file,
- helpers.execute, helpers.source
+local eq, eval, clear, write_file, execute, source, insert =
+ helpers.eq, helpers.eval, helpers.clear, helpers.write_file,
+ helpers.execute, helpers.source, helpers.insert
if helpers.pending_win32(pending) then return end
describe(':write', function()
- after_each(function()
+ local function cleanup()
os.remove('test_bkc_file.txt')
os.remove('test_bkc_link.txt')
+ os.remove('test_fifo')
+ end
+ before_each(function()
+ clear()
+ cleanup()
+ end)
+ after_each(function()
+ cleanup()
end)
it('&backupcopy=auto preserves symlinks', function()
- clear('--cmd', 'set backupcopy=auto')
+ execute('set backupcopy=auto')
write_file('test_bkc_file.txt', 'content0')
execute("silent !ln -s test_bkc_file.txt test_bkc_link.txt")
source([[
@@ -27,7 +33,7 @@ describe(':write', function()
end)
it('&backupcopy=no replaces symlink with new file', function()
- clear('--cmd', 'set backupcopy=no')
+ execute('set backupcopy=no')
write_file('test_bkc_file.txt', 'content0')
execute("silent !ln -s test_bkc_file.txt test_bkc_link.txt")
source([[
@@ -38,4 +44,23 @@ describe(':write', function()
eq(eval("['content0']"), eval("readfile('test_bkc_file.txt')"))
eq(eval("['content1']"), eval("readfile('test_bkc_link.txt')"))
end)
+
+ it("appends FIFO file", function()
+ if eval("executable('mkfifo')") == 0 then
+ pending('missing "mkfifo" command', function()end)
+ return
+ end
+
+ local text = "some fifo text from write_spec"
+ assert(os.execute("mkfifo test_fifo"))
+ insert(text)
+
+ -- Blocks until a consumer reads the FIFO.
+ execute("write >> test_fifo")
+
+ -- Read the FIFO, this will unblock the :write above.
+ local fifo = assert(io.open("test_fifo"))
+ eq(text.."\n", fifo:read("*all"))
+ fifo:close()
+ end)
end)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 325f41e506..ff62b4de86 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -1,11 +1,13 @@
require('coxpcall')
local lfs = require('lfs')
-local ChildProcessStream = require('nvim.child_process_stream')
-local SocketStream = require('nvim.socket_stream')
-local TcpStream = require('nvim.tcp_stream')
-local Session = require('nvim.session')
local global_helpers = require('test.helpers')
+-- nvim client: Found in .deps/usr/share/lua/<version>/nvim/ if "bundled".
+local Session = require('nvim.session')
+local TcpStream = require('nvim.tcp_stream')
+local SocketStream = require('nvim.socket_stream')
+local ChildProcessStream = require('nvim.child_process_stream')
+
local check_logs = global_helpers.check_logs
local neq = global_helpers.neq
local eq = global_helpers.eq
@@ -134,10 +136,14 @@ local function stop()
session:stop()
end
+-- Executes an ex-command. VimL errors manifest as client (lua) errors, but
+-- v:errmsg will not be updated.
local function nvim_command(cmd)
request('nvim_command', cmd)
end
+-- Evaluates a VimL expression.
+-- Fails on VimL error, but does not update v:errmsg.
local function nvim_eval(expr)
return request('nvim_eval', expr)
end
@@ -158,10 +164,14 @@ local os_name = (function()
end)
end)()
+-- Executes a VimL function.
+-- Fails on VimL error, but does not update v:errmsg.
local function nvim_call(name, ...)
return request('nvim_call_function', name, {...})
end
+-- Sends user input to Nvim.
+-- Does not fail on VimL error, but v:errmsg will be updated.
local function nvim_feed(input)
while #input > 0 do
local written = request('nvim_input', input)
@@ -279,6 +289,8 @@ local function insert(...)
nvim_feed('<ESC>')
end
+-- Executes an ex-command by user input. Because nvim_input() is used, VimL
+-- errors will not manifest as client (lua) errors. Use command() for that.
local function execute(...)
for _, v in ipairs({...}) do
if v:sub(1, 1) ~= '/' then
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index 42dd25023a..8a042be7f7 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local nvim, call = helpers.meths, helpers.call
local clear, eq = helpers.clear, helpers.eq
local source, execute = helpers.source, helpers.execute
+local exc_exec = helpers.exc_exec
local function expected_errors(errors)
eq(errors, nvim.get_vvar('errors'))
@@ -62,6 +63,20 @@ describe('assert function:', function()
call('assert_equal', 'true', 'false')
expected_errors({"Expected 'true' but got 'false'"})
end)
+
+ it('should change v:errors when expected is not equal to actual', function()
+ source([[
+ function CheckAssert()
+ let s:v = {}
+ let s:x = {"a": s:v}
+ let s:v["b"] = s:x
+ let s:w = {"c": s:x, "d": ''}
+ call assert_equal(s:w, '')
+ endfunction
+ ]])
+ eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('call CheckAssert()'))
+ end)
end)
-- assert_notequal({expected}, {actual}[, {msg}])
diff --git a/test/functional/legacy/quickfix_spec.lua b/test/functional/legacy/quickfix_spec.lua
index df8f2625db..7657b8641b 100644
--- a/test/functional/legacy/quickfix_spec.lua
+++ b/test/functional/legacy/quickfix_spec.lua
@@ -277,6 +277,118 @@ describe('helpgrep', function()
augroup! testgroup
endfunction
+
+ " This will test for problems in quickfix:
+ " A. incorrectly copying location lists which caused the location list to show
+ " a different name than the file that was actually being displayed.
+ " B. not reusing the window for which the location list window is opened but
+ " instead creating new windows.
+ " C. make sure that the location list window is not reused instead of the
+ " window it belongs to.
+ "
+ " Set up the test environment:
+ function! ReadTestProtocol(name)
+ let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
+ let word = substitute(base, '\v(.*)\..*', '\1', '')
+
+ setl modifiable
+ setl noreadonly
+ setl noswapfile
+ setl bufhidden=delete
+ %del _
+ " For problem 2:
+ " 'buftype' has to be set to reproduce the constant opening of new windows
+ setl buftype=nofile
+
+ call setline(1, word)
+
+ setl nomodified
+ setl nomodifiable
+ setl readonly
+ exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
+ endfunction
+
+ function Test_locationlist()
+ enew
+
+ augroup testgroup
+ au!
+ autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
+ augroup END
+
+ let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
+
+ let qflist = []
+ for word in words
+ call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
+ " NOTE: problem 1:
+ " intentionally not setting 'lnum' so that the quickfix entries are not
+ " valid
+ call setloclist(0, qflist, ' ')
+ endfor
+
+ " Test A
+ lrewind
+ enew
+ lopen
+ lnext
+ lnext
+ lnext
+ lnext
+ vert split
+ wincmd L
+ lopen
+ wincmd p
+ lnext
+ let fileName = expand("%")
+ wincmd p
+ let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
+ let fileName = substitute(fileName, '\\', '/', 'g')
+ let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
+ call assert_equal("test://bar.txt", fileName)
+ call assert_equal("test://bar.txt", locationListFileName)
+
+ wincmd n | only
+
+ " Test B:
+ lrewind
+ lopen
+ 2
+ exe "normal \<CR>"
+ wincmd p
+ 3
+ exe "normal \<CR>"
+ wincmd p
+ 4
+ exe "normal \<CR>"
+ call assert_equal(2, winnr('$'))
+ wincmd n | only
+
+ " Test C:
+ lrewind
+ lopen
+ " Let's move the location list window to the top to check whether it (the
+ " first window found) will be reused when we try to open new windows:
+ wincmd K
+ 2
+ exe "normal \<CR>"
+ wincmd p
+ 3
+ exe "normal \<CR>"
+ wincmd p
+ 4
+ exe "normal \<CR>"
+ 1wincmd w
+ call assert_equal('quickfix', &buftype)
+ 2wincmd w
+ let bufferName = expand("%")
+ let bufferName = substitute(bufferName, '\\', '/', 'g')
+ call assert_equal('test://quux.txt', bufferName)
+
+ wincmd n | only
+
+ augroup! testgroup
+ endfunction
]])
end)
@@ -339,4 +451,9 @@ describe('helpgrep', function()
call('Test_locationlist_curwin_was_closed')
expected_empty()
end)
+
+ it('checks locationlist protocol read', function()
+ call('Test_locationlist')
+ expected_empty()
+ end)
end)
diff --git a/test/functional/terminal/api_spec.lua b/test/functional/terminal/api_spec.lua
index 58d6c75940..045bdb0749 100644
--- a/test/functional/terminal/api_spec.lua
+++ b/test/functional/terminal/api_spec.lua
@@ -22,7 +22,7 @@ describe('api', function()
-- Start the socket from the child nvim.
child_session.feed_data(":echo serverstart('"..socket_name.."')\n")
- -- Wait for socket creation by abusing expect().
+ -- Wait for socket creation.
screen:expect([[
{1: } |
{4:~ }|
@@ -37,6 +37,16 @@ describe('api', function()
local socket_session2 = helpers.connect(socket_name)
child_session.feed_data("i[tui] insert-mode")
+ -- Wait for stdin to be processed.
+ screen:expect([[
+ [tui] insert-mode{1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
+ ]])
ok(socket_session1:request("nvim_ui_attach", 42, 6, {rgb=true}))
ok(socket_session2:request("nvim_ui_attach", 25, 30, {rgb=true}))
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 09b4eaa8d5..4247be0417 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -13,6 +13,42 @@ describe(':terminal', function()
clear()
screen = Screen.new(50, 4)
screen:attach({rgb=false})
+ end)
+
+ it("does not interrupt Press-ENTER prompt #2748", function()
+ -- Ensure that :messages shows Press-ENTER.
+ source([[
+ echomsg "msg1"
+ echomsg "msg2"
+ ]])
+ -- Invoke a command that emits frequent terminal activity.
+ execute([[terminal while true; do echo X; done]])
+ helpers.feed([[<C-\><C-N>]])
+ screen:expect([[
+ X |
+ X |
+ ^X |
+ |
+ ]])
+ helpers.sleep(10) -- Let some terminal activity happen.
+ execute("messages")
+ screen:expect([[
+ X |
+ msg1 |
+ msg2 |
+ Press ENTER or type command to continue^ |
+ ]])
+ end)
+
+end)
+
+describe(':terminal (with fake shell)', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(50, 4)
+ screen:attach({rgb=false})
-- shell-test.c is a fake shell that prints its arguments and exits.
nvim('set_option', 'shell', nvim_dir..'/shell-test')
nvim('set_option', 'shellcmdflag', 'EXE')
@@ -20,12 +56,12 @@ describe(':terminal', function()
-- Invokes `:terminal {cmd}` using a fake shell (shell-test.c) which prints
-- the {cmd} and exits immediately .
- local function terminal_run_fake_shell_cmd(cmd)
+ local function terminal_with_fake_shell(cmd)
execute("terminal "..(cmd and cmd or ""))
end
it('with no argument, acts like termopen()', function()
- terminal_run_fake_shell_cmd()
+ terminal_with_fake_shell()
wait()
screen:expect([[
ready $ |
@@ -36,7 +72,7 @@ describe(':terminal', function()
end)
it('executes a given command through the shell', function()
- terminal_run_fake_shell_cmd('echo hi')
+ terminal_with_fake_shell('echo hi')
wait()
screen:expect([[
ready $ echo hi |
@@ -47,7 +83,7 @@ describe(':terminal', function()
end)
it('allows quotes and slashes', function()
- terminal_run_fake_shell_cmd([[echo 'hello' \ "world"]])
+ terminal_with_fake_shell([[echo 'hello' \ "world"]])
wait()
screen:expect([[
ready $ echo 'hello' \ "world" |
@@ -66,14 +102,14 @@ describe(':terminal', function()
end)
it('ignores writes if the backing stream closes', function()
- terminal_run_fake_shell_cmd()
+ terminal_with_fake_shell()
helpers.feed('iiXXXXXXX')
wait()
-- Race: Though the shell exited (and streams were closed by SIGCHLD
-- handler), :terminal cleanup is pending on the main-loop.
-- This write should be ignored (not crash, #5445).
helpers.feed('iiYYYYYYY')
- wait()
+ eq(2, eval("1+1")) -- Still alive?
end)
end)
diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua
index 0897c2d836..da3400fb27 100644
--- a/test/functional/viml/completion_spec.lua
+++ b/test/functional/viml/completion_spec.lua
@@ -317,6 +317,62 @@ describe('completion', function()
end)
end)
+ describe('completeopt+=noinsert does not add blank undo items', function()
+ before_each(function()
+ source([[
+ function! TestComplete() abort
+ call complete(1, ['foo', 'bar'])
+ return ''
+ endfunction
+ ]])
+ execute('set completeopt+=noselect,noinsert')
+ execute('inoremap <right> <c-r>=TestComplete()<cr>')
+ end)
+
+ local tests = {
+ ['<up>, <down>, <cr>'] = {'<down><cr>', '<up><cr>'},
+ ['<c-n>, <c-p>, <c-y>'] = {'<c-n><c-y>', '<c-p><c-y>'},
+ }
+
+ for name, seq in pairs(tests) do
+ it('using ' .. name, function()
+ feed('iaaa<esc>')
+ feed('A<right>' .. seq[1] .. '<esc>')
+ feed('A<right><esc>A<right><esc>')
+ feed('A<cr>bbb<esc>')
+ feed('A<right>' .. seq[2] .. '<esc>')
+ feed('A<right><esc>A<right><esc>')
+ feed('A<cr>ccc<esc>')
+ feed('A<right>' .. seq[1] .. '<esc>')
+ feed('A<right><esc>A<right><esc>')
+
+ local expected = {
+ {'foo', 'bar', 'foo'},
+ {'foo', 'bar', 'ccc'},
+ {'foo', 'bar'},
+ {'foo', 'bbb'},
+ {'foo'},
+ {'aaa'},
+ {''},
+ }
+
+ for i = 1, #expected do
+ if i > 1 then
+ feed('u')
+ end
+ eq(expected[i], eval('getline(1, "$")'))
+ end
+
+ for i = #expected, 1, -1 do
+ if i < #expected then
+ feed('<c-r>')
+ end
+ eq(expected[i], eval('getline(1, "$")'))
+ end
+ end)
+ end
+ end)
+
describe("refresh:always", function()
before_each(function()
source([[