aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/ex_cmds/map_spec.lua164
-rw-r--r--test/functional/lua/thread_spec.lua386
-rw-r--r--test/functional/ui/cmdline_highlight_spec.lua13
3 files changed, 557 insertions, 6 deletions
diff --git a/test/functional/ex_cmds/map_spec.lua b/test/functional/ex_cmds/map_spec.lua
index 160c7cf126..007d68d61a 100644
--- a/test/functional/ex_cmds/map_spec.lua
+++ b/test/functional/ex_cmds/map_spec.lua
@@ -1,6 +1,8 @@
local helpers = require("test.functional.helpers")(after_each)
+local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
+local exec = helpers.exec
local feed = helpers.feed
local meths = helpers.meths
local clear = helpers.clear
@@ -61,3 +63,165 @@ describe(':*map', function()
eq('Some te', eval("getline('.')"))
end)
end)
+
+describe(':*map cursor and redrawing', function()
+ local screen
+ before_each(function()
+ clear()
+ screen = Screen.new(20, 5)
+ screen:attach()
+ end)
+
+ it('cursor is restored after :map <expr> which calls input()', function()
+ command('map <expr> x input("> ")')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]])
+ feed('x')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ > ^ |
+ ]])
+ feed('\n')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ > |
+ ]])
+ end)
+
+ it('cursor is restored after :imap <expr> which calls input()', function()
+ command('imap <expr> x input("> ")')
+ feed('i')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ -- INSERT -- |
+ ]])
+ feed('x')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ > ^ |
+ ]])
+ feed('\n')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ > |
+ ]])
+ end)
+
+ it('cursor is restored after :map <expr> which redraws statusline vim-patch:8.1.2336', function()
+ exec([[
+ call setline(1, ['one', 'two', 'three'])
+ 2
+ set ls=2
+ hi! link StatusLine ErrorMsg
+ noremap <expr> <C-B> Func()
+ func Func()
+ let g:on = !get(g:, 'on', 0)
+ redraws
+ return ''
+ endfunc
+ func Status()
+ return get(g:, 'on', 0) ? '[on]' : ''
+ endfunc
+ set stl=%{Status()}
+ ]])
+ feed('<C-B>')
+ screen:expect([[
+ one |
+ ^two |
+ three |
+ [on] |
+ |
+ ]])
+ end)
+
+ it('error in :nmap <expr> does not mess up display vim-patch:4.2.4338', function()
+ screen:try_resize(40, 5)
+ command('nmap <expr> <F2> execute("throw 42")')
+ feed('<F2>')
+ screen:expect([[
+ |
+ |
+ Error detected while processing : |
+ E605: Exception not caught: 42 |
+ Press ENTER or type command to continue^ |
+ ]])
+ feed('<CR>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]])
+ end)
+
+ it('error in :cmap <expr> handled correctly vim-patch:4.2.4338', function()
+ screen:try_resize(40, 5)
+ command('cmap <expr> <F2> execute("throw 42")')
+ feed(':echo "foo')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ :echo "foo^ |
+ ]])
+ feed('<F2>')
+ screen:expect([[
+ |
+ :echo "foo |
+ Error detected while processing : |
+ E605: Exception not caught: 42 |
+ :echo "foo^ |
+ ]])
+ feed('"')
+ screen:expect([[
+ |
+ :echo "foo |
+ Error detected while processing : |
+ E605: Exception not caught: 42 |
+ :echo "foo"^ |
+ ]])
+ feed('\n')
+ screen:expect([[
+ :echo "foo |
+ Error detected while processing : |
+ E605: Exception not caught: 42 |
+ foo |
+ Press ENTER or type command to continue^ |
+ ]])
+ end)
+
+ it('listing mappings clears command line vim-patch:8.2.4401', function()
+ screen:try_resize(40, 5)
+ command('nmap a b')
+ feed(': nmap a<CR>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ n a b |
+ ]])
+ end)
+end)
diff --git a/test/functional/lua/thread_spec.lua b/test/functional/lua/thread_spec.lua
new file mode 100644
index 0000000000..2e0ab7bdff
--- /dev/null
+++ b/test/functional/lua/thread_spec.lua
@@ -0,0 +1,386 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
+local clear = helpers.clear
+local feed = helpers.feed
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local next_msg = helpers.next_msg
+local NIL = helpers.NIL
+local pcall_err = helpers.pcall_err
+
+describe('thread', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(50, 10)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {bold = true, reverse = true},
+ [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [5] = {bold = true},
+ })
+ end)
+
+ it('entry func is executed in protected mode', function()
+ exec_lua [[
+ local thread = vim.loop.new_thread(function()
+ error('Error in thread entry func')
+ end)
+ vim.loop.thread_join(thread)
+ ]]
+
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ {3:Error in luv thread:} |
+ {3:[string "<nvim>"]:2: Error in thread entry func} |
+ {4:Press ENTER or type command to continue}^ |
+ ]])
+ feed('<cr>')
+ assert_alive()
+ end)
+
+ it('callback is executed in protected mode', function()
+ exec_lua [[
+ local thread = vim.loop.new_thread(function()
+ local timer = vim.loop.new_timer()
+ local function ontimeout()
+ timer:stop()
+ timer:close()
+ error('Error in thread callback')
+ end
+ timer:start(10, 0, ontimeout)
+ vim.loop.run()
+ end)
+ vim.loop.thread_join(thread)
+ ]]
+
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ {3:Error in luv callback, thread:} |
+ {3:[string "<nvim>"]:6: Error in thread callback} |
+ {4:Press ENTER or type command to continue}^ |
+ ]])
+ feed('<cr>')
+ assert_alive()
+ end)
+
+ describe('print', function()
+ it('works', function()
+ exec_lua [[
+ local thread = vim.loop.new_thread(function()
+ print('print in thread')
+ end)
+ vim.loop.thread_join(thread)
+ ]]
+
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ print in thread |
+ ]])
+ end)
+ end)
+
+ describe('vim.*', function()
+ before_each(function()
+ clear()
+ exec_lua [[
+ Thread_Test = {}
+
+ Thread_Test.entry_func = function(async, entry_str, args)
+ local decoded_args = vim.mpack.decode(args)
+ assert(loadstring(entry_str))(async, decoded_args)
+ end
+
+ function Thread_Test:do_test()
+ local async
+ local on_async = self.on_async
+ async = vim.loop.new_async(function(ret)
+ on_async(ret)
+ async:close()
+ end)
+ local thread =
+ vim.loop.new_thread(self.entry_func, async, self.entry_str, self.args)
+ vim.loop.thread_join(thread)
+ end
+
+ Thread_Test.new = function(entry, on_async, ...)
+ self = {}
+ setmetatable(self, {__index = Thread_Test})
+ self.args = vim.mpack.encode({...})
+ self.entry_str = string.dump(entry)
+ self.on_async = on_async
+ return self
+ end
+ ]]
+ end)
+
+ it('is_thread', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.is_thread())
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, 'result', ret)
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {true}}, next_msg())
+ end)
+
+ it('loop', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.loop.version())
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, ret)
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ local msg = next_msg()
+ eq(msg[1], 'notification')
+ assert(tonumber(msg[2]) >= 72961)
+ end)
+
+ it('mpack', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.mpack.encode({33, vim.NIL, 'text'}))
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, 'result', vim.mpack.decode(ret))
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ end)
+
+ it('json', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.json.encode({33, vim.NIL, 'text'}))
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, 'result', vim.json.decode(ret))
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ end)
+
+ it('diff', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.diff('Hello\n', 'Helli\n'))
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, 'result', ret)
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ eq({'notification', 'result',
+ {table.concat({
+ '@@ -1 +1 @@',
+ '-Hello',
+ '+Helli',
+ ''
+ }, '\n')}},
+ next_msg())
+ end)
+ end)
+end)
+
+describe('threadpool', function()
+ before_each(clear)
+
+ it('is_thread', function()
+ eq(false, exec_lua [[return vim.is_thread()]])
+
+ exec_lua [[
+ local work_fn = function()
+ return vim.is_thread()
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, 'result', ret)
+ end
+ local work = vim.loop.new_work(work_fn, after_work_fn)
+ work:queue()
+ ]]
+
+ eq({'notification', 'result', {true}}, next_msg())
+ end)
+
+ it('with invalid argument', function()
+ local status = pcall_err(exec_lua, [[
+ local work = vim.loop.new_thread(function() end, function() end)
+ work:queue({})
+ ]])
+
+ eq([[Error executing lua: [string "<nvim>"]:0: Error: thread arg not support type 'function' at 1]],
+ status)
+ end)
+
+ it('with invalid return value', function()
+ local screen = Screen.new(50, 10)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {bold = true, reverse = true},
+ [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [5] = {bold = true},
+ })
+
+ exec_lua [[
+ local work = vim.loop.new_work(function() return {} end, function() end)
+ work:queue()
+ ]]
+
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ {3:Error in luv thread:} |
+ {3:Error: thread arg not support type 'table' at 1} |
+ {4:Press ENTER or type command to continue}^ |
+ ]])
+ end)
+
+ describe('vim.*', function()
+ before_each(function()
+ clear()
+ exec_lua [[
+ Threadpool_Test = {}
+
+ Threadpool_Test.work_fn = function(work_fn_str, args)
+ local decoded_args = vim.mpack.decode(args)
+ return assert(loadstring(work_fn_str))(decoded_args)
+ end
+
+ function Threadpool_Test:do_test()
+ local work =
+ vim.loop.new_work(self.work_fn, self.after_work)
+ work:queue(self.work_fn_str, self.args)
+ end
+
+ Threadpool_Test.new = function(work_fn, after_work, ...)
+ self = {}
+ setmetatable(self, {__index = Threadpool_Test})
+ self.args = vim.mpack.encode({...})
+ self.work_fn_str = string.dump(work_fn)
+ self.after_work = after_work
+ return self
+ end
+ ]]
+ end)
+
+ it('loop', function()
+ exec_lua [[
+ local work_fn = function()
+ return vim.loop.version()
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, ret)
+ end
+ local threadpool_test = Threadpool_Test.new(work_fn, after_work_fn)
+ threadpool_test:do_test()
+ ]]
+
+ local msg = next_msg()
+ eq(msg[1], 'notification')
+ assert(tonumber(msg[2]) >= 72961)
+ end)
+
+ it('mpack', function()
+ exec_lua [[
+ local work_fn = function()
+ local var = vim.mpack.encode({33, vim.NIL, 'text'})
+ return var
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, 'result', vim.mpack.decode(ret))
+ end
+ local threadpool_test = Threadpool_Test.new(work_fn, after_work_fn)
+ threadpool_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ end)
+
+ it('json', function()
+ exec_lua [[
+ local work_fn = function()
+ local var = vim.json.encode({33, vim.NIL, 'text'})
+ return var
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, 'result', vim.json.decode(ret))
+ end
+ local threadpool_test = Threadpool_Test.new(work_fn, after_work_fn)
+ threadpool_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ end)
+
+ it('work', function()
+ exec_lua [[
+ local work_fn = function()
+ return vim.diff('Hello\n', 'Helli\n')
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, 'result', ret)
+ end
+ local threadpool_test = Threadpool_Test.new(work_fn, after_work_fn)
+ threadpool_test:do_test()
+ ]]
+
+ eq({'notification', 'result',
+ {table.concat({
+ '@@ -1 +1 @@',
+ '-Hello',
+ '+Helli',
+ ''
+ }, '\n')}},
+ next_msg())
+ end)
+ end)
+end)
diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua
index 9c746b99bd..384761ab17 100644
--- a/test/functional/ui/cmdline_highlight_spec.lua
+++ b/test/functional/ui/cmdline_highlight_spec.lua
@@ -33,7 +33,7 @@ before_each(function()
let g:NUM_LVLS = 4
function Redraw()
mode
- return ''
+ return "\<Ignore>"
endfunction
let g:id = ''
cnoremap <expr> {REDRAW} Redraw()
@@ -42,7 +42,7 @@ before_each(function()
let Cb = g:Nvim_color_input{g:id}
let out = input({'prompt': ':', 'highlight': Cb})
let g:out{id} = out
- return (a:do_return ? out : '')
+ return (a:do_return ? out : "\<Ignore>")
endfunction
nnoremap <expr> {PROMPT} DoPrompt(0)
cnoremap <expr> {PROMPT} DoPrompt(1)
@@ -410,7 +410,7 @@ describe('Command-line coloring', function()
end)
it('stops executing callback after a number of errors', function()
set_color_cb('SplittedMultibyteStart')
- start_prompt('let x = "«»«»«»«»«»"\n')
+ start_prompt('let x = "«»«»«»«»«»"')
screen:expect([[
{EOB:~ }|
{EOB:~ }|
@@ -419,7 +419,7 @@ describe('Command-line coloring', function()
:let x = " |
{ERR:E5405: Chunk 0 start 10 splits multibyte}|
{ERR: character} |
- ^:let x = "«»«»«»«»«»" |
+ :let x = "«»«»«»«»«»"^ |
]])
feed('\n')
screen:expect([[
@@ -432,6 +432,7 @@ describe('Command-line coloring', function()
{EOB:~ }|
|
]])
+ feed('\n')
eq('let x = "«»«»«»«»«»"', meths.get_var('out'))
local msg = '\nE5405: Chunk 0 start 10 splits multibyte character'
eq(msg:rep(1), funcs.execute('messages'))
@@ -474,14 +475,14 @@ describe('Command-line coloring', function()
]])
feed('\n')
screen:expect([[
- |
+ ^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
- ^:echo 42 |
+ :echo 42 |
]])
feed('\n')
eq('echo 42', meths.get_var('out'))