aboutsummaryrefslogtreecommitdiff
path: root/test/functional/eval
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/eval')
-rw-r--r--test/functional/eval/api_functions_spec.lua2
-rw-r--r--test/functional/eval/function_spec.lua29
-rw-r--r--test/functional/eval/input_spec.lua354
-rw-r--r--test/functional/eval/map_functions_spec.lua120
-rw-r--r--test/functional/eval/msgpack_functions_spec.lua8
-rw-r--r--test/functional/eval/server_spec.lua47
6 files changed, 537 insertions, 23 deletions
diff --git a/test/functional/eval/api_functions_spec.lua b/test/functional/eval/api_functions_spec.lua
index 7f6f53d226..fea4a87a26 100644
--- a/test/functional/eval/api_functions_spec.lua
+++ b/test/functional/eval/api_functions_spec.lua
@@ -106,7 +106,7 @@ describe('api functions', function()
it('have metadata accessible with api_info()', function()
local api_keys = eval("sort(keys(api_info()))")
- eq({'error_types', 'functions', 'types', 'version'}, api_keys)
+ eq({'error_types', 'functions', 'types', 'ui_events', 'version'}, api_keys)
end)
it('are highlighted by vim.vim syntax file', function()
diff --git a/test/functional/eval/function_spec.lua b/test/functional/eval/function_spec.lua
new file mode 100644
index 0000000000..776e760aaf
--- /dev/null
+++ b/test/functional/eval/function_spec.lua
@@ -0,0 +1,29 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local eq = helpers.eq
+local exc_exec = helpers.exc_exec
+
+describe('Up to MAX_FUNC_ARGS arguments are handled by', function()
+ local max_func_args = 20 -- from eval.h
+ local range = helpers.funcs.range
+
+ before_each(clear)
+
+ it('printf()', function()
+ local printf = helpers.funcs.printf
+ local rep = helpers.funcs['repeat']
+ local expected = '2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,'
+ eq(expected, printf(rep('%d,', max_func_args-1), unpack(range(2, max_func_args))))
+ local ret = exc_exec('call printf("", 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
+ eq('Vim(call):E740: Too many arguments for function printf', ret)
+ end)
+
+ it('rpcnotify()', function()
+ local rpcnotify = helpers.funcs.rpcnotify
+ local ret = rpcnotify(0, 'foo', unpack(range(3, max_func_args)))
+ eq(1, ret)
+ ret = exc_exec('call rpcnotify(0, "foo", 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
+ eq('Vim(call):E740: Too many arguments for function rpcnotify', ret)
+ end)
+end)
diff --git a/test/functional/eval/input_spec.lua b/test/functional/eval/input_spec.lua
index 393fc10175..74ad32bc6c 100644
--- a/test/functional/eval/input_spec.lua
+++ b/test/functional/eval/input_spec.lua
@@ -1,9 +1,13 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local eq = helpers.eq
local feed = helpers.feed
+local meths = helpers.meths
local clear = helpers.clear
+local source = helpers.source
local command = helpers.command
+local exc_exec = helpers.exc_exec
local screen
@@ -11,28 +15,352 @@ before_each(function()
clear()
screen = Screen.new(25, 5)
screen:attach()
+ source([[
+ hi Test ctermfg=Red guifg=Red term=bold
+ function CustomCompl(...)
+ return 'TEST'
+ endfunction
+ function CustomListCompl(...)
+ return ['FOO']
+ endfunction
+ ]])
+ screen:set_default_attr_ids({
+ EOB={bold = true, foreground = Screen.colors.Blue1},
+ T={foreground=Screen.colors.Red},
+ })
end)
describe('input()', function()
- it('works correctly with multiline prompts', function()
+ it('works with multiline prompts', function()
feed([[:call input("Test\nFoo")<CR>]])
screen:expect([[
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
Test |
Foo^ |
- ]], {{bold=true, foreground=Screen.colors.Blue}})
+ ]])
end)
- it('works correctly with multiline prompts and :echohl', function()
- command('hi Test ctermfg=Red guifg=Red term=bold')
+ it('works with multiline prompts and :echohl', function()
feed([[:echohl Test | call input("Test\nFoo")<CR>]])
screen:expect([[
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {2:Test} |
- {2:Foo}^ |
- ]], {{bold=true, foreground=Screen.colors.Blue}, {foreground=Screen.colors.Red}})
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Test} |
+ {T:Foo}^ |
+ ]])
+ command('redraw!')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo}^ |
+ ]])
+ end)
+ it('allows unequal numeric arguments when using multiple args', function()
+ command('echohl Test')
+ feed([[:call input(1, 2)<CR>]])
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:1}2^ |
+ ]])
+ feed('<BS>')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:1}^ |
+ ]])
+ end)
+ it('allows unequal numeric values when using {opts} dictionary', function()
+ command('echohl Test')
+ meths.set_var('opts', {prompt=1, default=2, cancelreturn=3})
+ feed([[:echo input(opts)<CR>]])
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:1}2^ |
+ ]])
+ feed('<BS>')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:1}^ |
+ ]])
+ feed('<Esc>')
+ screen:expect([[
+ ^ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:3} |
+ ]])
+ end)
+ it('works with redraw', function()
+ command('echohl Test')
+ meths.set_var('opts', {prompt='Foo>', default='Bar'})
+ feed([[:echo inputdialog(opts)<CR>]])
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo>}Bar^ |
+ ]])
+ command('redraw!')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo>}Bar^ |
+ ]])
+ feed('<BS>')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo>}Ba^ |
+ ]])
+ command('redraw!')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo>}Ba^ |
+ ]])
+ end)
+ it('allows omitting everything with dictionary argument', function()
+ command('echohl Test')
+ feed([[:call input({})<CR>]])
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ ^ |
+ ]])
+ end)
+ it('supports completion', function()
+ feed(':let var = input("", "", "custom,CustomCompl")<CR>')
+ feed('<Tab><CR>')
+ eq('TEST', meths.get_var('var'))
+
+ feed(':let var = input({"completion": "customlist,CustomListCompl"})<CR>')
+ feed('<Tab><CR>')
+ eq('FOO', meths.get_var('var'))
+ end)
+ it('supports cancelreturn', function()
+ feed(':let var = input({"cancelreturn": "BAR"})<CR>')
+ feed('<Esc>')
+ eq('BAR', meths.get_var('var'))
+ end)
+ it('supports default string', function()
+ feed(':let var = input("", "DEF1")<CR>')
+ feed('<CR>')
+ eq('DEF1', meths.get_var('var'))
+
+ feed(':let var = input({"default": "DEF2"})<CR>')
+ feed('<CR>')
+ eq('DEF2', meths.get_var('var'))
+ end)
+ it('errors out on invalid inputs', function()
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call input([])'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call input("", [])'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call input("", "", [])'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call input({"prompt": []})'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call input({"cancelreturn": []})'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call input({"default": []})'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call input({"completion": []})'))
+ eq('Vim(call):E5050: {opts} must be the only argument',
+ exc_exec('call input({}, "default")'))
+ eq('Vim(call):E118: Too many arguments for function: input',
+ exc_exec('call input("prompt> ", "default", "file", "extra")'))
+ end)
+end)
+describe('inputdialog()', function()
+ it('works with multiline prompts', function()
+ feed([[:call inputdialog("Test\nFoo")<CR>]])
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ Test |
+ Foo^ |
+ ]])
+ end)
+ it('works with multiline prompts and :echohl', function()
+ feed([[:echohl Test | call inputdialog("Test\nFoo")<CR>]])
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Test} |
+ {T:Foo}^ |
+ ]])
+ command('redraw!')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo}^ |
+ ]])
+ end)
+ it('allows unequal numeric arguments when using multiple args', function()
+ command('echohl Test')
+ feed([[:call inputdialog(1, 2)<CR>]])
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:1}2^ |
+ ]])
+ feed('<BS>')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:1}^ |
+ ]])
+ end)
+ it('allows unequal numeric values when using {opts} dictionary', function()
+ command('echohl Test')
+ meths.set_var('opts', {prompt=1, default=2, cancelreturn=3})
+ feed([[:echo input(opts)<CR>]])
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:1}2^ |
+ ]])
+ feed('<BS>')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:1}^ |
+ ]])
+ feed('<Esc>')
+ screen:expect([[
+ ^ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:3} |
+ ]])
+ end)
+ it('works with redraw', function()
+ command('echohl Test')
+ meths.set_var('opts', {prompt='Foo>', default='Bar'})
+ feed([[:echo input(opts)<CR>]])
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo>}Bar^ |
+ ]])
+ command('redraw!')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo>}Bar^ |
+ ]])
+ feed('<BS>')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo>}Ba^ |
+ ]])
+ command('redraw!')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {T:Foo>}Ba^ |
+ ]])
+ end)
+ it('allows omitting everything with dictionary argument', function()
+ command('echohl Test')
+ feed(':echo inputdialog({})<CR>')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ ^ |
+ ]])
+ end)
+ it('supports completion', function()
+ feed(':let var = inputdialog({"completion": "customlist,CustomListCompl"})<CR>')
+ feed('<Tab><CR>')
+ eq('FOO', meths.get_var('var'))
+ end)
+ it('supports cancelreturn', function()
+ feed(':let var = inputdialog("", "", "CR1")<CR>')
+ feed('<Esc>')
+ eq('CR1', meths.get_var('var'))
+
+ feed(':let var = inputdialog({"cancelreturn": "BAR"})<CR>')
+ feed('<Esc>')
+ eq('BAR', meths.get_var('var'))
+ end)
+ it('supports default string', function()
+ feed(':let var = inputdialog("", "DEF1")<CR>')
+ feed('<CR>')
+ eq('DEF1', meths.get_var('var'))
+
+ feed(':let var = inputdialog({"default": "DEF2"})<CR>')
+ feed('<CR>')
+ eq('DEF2', meths.get_var('var'))
+ end)
+ it('errors out on invalid inputs', function()
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call inputdialog([])'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call inputdialog("", [])'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call inputdialog("", "", [])'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call inputdialog({"prompt": []})'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call inputdialog({"cancelreturn": []})'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call inputdialog({"default": []})'))
+ eq('Vim(call):E730: using List as a String',
+ exc_exec('call inputdialog({"completion": []})'))
+ eq('Vim(call):E5050: {opts} must be the only argument',
+ exc_exec('call inputdialog({}, "default")'))
+ eq('Vim(call):E118: Too many arguments for function: inputdialog',
+ exc_exec('call inputdialog("prompt> ", "default", "file", "extra")'))
end)
end)
diff --git a/test/functional/eval/map_functions_spec.lua b/test/functional/eval/map_functions_spec.lua
new file mode 100644
index 0000000000..a260522aa3
--- /dev/null
+++ b/test/functional/eval/map_functions_spec.lua
@@ -0,0 +1,120 @@
+
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local eq = helpers.eq
+local eval = helpers.eval
+local funcs = helpers.funcs
+local nvim = helpers.nvim
+local source = helpers.source
+
+describe('maparg()', function()
+ before_each(clear)
+
+ local foo_bar_map_table = {
+ lhs='foo',
+ silent=0,
+ rhs='bar',
+ expr=0,
+ sid=0,
+ buffer=0,
+ nowait=0,
+ mode='n',
+ noremap=1,
+ }
+
+ it('returns a dictionary', function()
+ nvim('command', 'nnoremap foo bar')
+ eq('bar', funcs.maparg('foo'))
+ eq(foo_bar_map_table, funcs.maparg('foo', 'n', false, true))
+ end)
+
+ it('returns 1 for silent when <silent> is used', function()
+ nvim('command', 'nnoremap <silent> foo bar')
+ eq(1, funcs.maparg('foo', 'n', false, true)['silent'])
+
+ nvim('command', 'nnoremap baz bat')
+ eq(0, funcs.maparg('baz', 'n', false, true)['silent'])
+ end)
+
+ it('returns an empty string when no map is present', function()
+ eq('', funcs.maparg('not a mapping'))
+ end)
+
+ it('returns an empty dictionary when no map is present and dict is requested', function()
+ eq({}, funcs.maparg('not a mapping', 'n', false, true))
+ end)
+
+ it('returns the same value for noremap and <script>', function()
+ nvim('command', 'inoremap <script> hello world')
+ nvim('command', 'inoremap this that')
+ eq(
+ funcs.maparg('hello', 'i', false, true)['noremap'],
+ funcs.maparg('this', 'i', false, true)['noremap']
+ )
+ end)
+
+ it('returns a boolean for buffer', function()
+ -- Open enough windows to know we aren't on buffer number 1
+ nvim('command', 'new')
+ nvim('command', 'new')
+ nvim('command', 'new')
+ nvim('command', 'cnoremap <buffer> this that')
+ eq(1, funcs.maparg('this', 'c', false, true)['buffer'])
+
+ -- Global will return 0 always
+ nvim('command', 'nnoremap other another')
+ eq(0, funcs.maparg('other', 'n', false, true)['buffer'])
+ end)
+
+ it('returns script numbers', function()
+ source([[
+ function! s:maparg_test_function() abort
+ return 'testing'
+ endfunction
+
+ nnoremap fizz :call <SID>maparg_test_function()<CR>
+ ]])
+ eq(1, funcs.maparg('fizz', 'n', false, true)['sid'])
+ eq('testing', nvim('call_function', '<SNR>1_maparg_test_function', {}))
+ end)
+
+ it('works with <F12> and others', function()
+ source([[
+ let g:maparg_test_var = 0
+
+ nnoremap <F12> :let g:maparg_test_var = 1<CR>
+ ]])
+ eq(0, eval('g:maparg_test_var'))
+ source([[
+ call feedkeys("\<F12>")
+ ]])
+ eq(1, eval('g:maparg_test_var'))
+
+ eq(':let g:maparg_test_var = 1<CR>', funcs.maparg('<F12>', 'n', false, true)['rhs'])
+ end)
+
+ it('works with <expr>', function()
+ source([[
+ let counter = 0
+ inoremap <expr> <C-L> ListItem()
+ inoremap <expr> <C-R> ListReset()
+
+ func ListItem()
+ let g:counter += 1
+ return g:counter . '. '
+ endfunc
+
+ func ListReset()
+ let g:counter = 0
+ return ''
+ endfunc
+
+ call feedkeys("i\<C-L>")
+ ]])
+ eq(1, eval('g:counter'))
+
+ local map_dict = funcs.maparg('<C-L>', 'i', false, true)
+ eq(1, map_dict['expr'])
+ eq('i', map_dict['mode'])
+ end)
+end)
diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/eval/msgpack_functions_spec.lua
index c5520deb73..b241635dfe 100644
--- a/test/functional/eval/msgpack_functions_spec.lua
+++ b/test/functional/eval/msgpack_functions_spec.lua
@@ -337,7 +337,8 @@ describe('msgpack*() functions', function()
eq(1, eval('type(parsed[0]) == type(0) ' ..
'|| parsed[0]._TYPE is v:msgpack_types.integer'))
if eval('type(parsed[0]) == type(0)') == 1 then
- eq(1, eval('0xFFFFFFFFFFFFFFFF == parsed[0]'))
+ command('call assert_equal(0xFFFFFFFFFFFFFFFF, parsed[0])')
+ eq({}, eval('v:errors'))
else
eq({_TYPE={}, _VAL={1, 3, 0x7FFFFFFF, 0x7FFFFFFF}}, eval('parsed[0]'))
end
@@ -351,7 +352,8 @@ describe('msgpack*() functions', function()
eq(1, eval('type(parsed[0]) == type(0) ' ..
'|| parsed[0]._TYPE is v:msgpack_types.integer'))
if eval('type(parsed[0]) == type(0)') == 1 then
- eq(1, eval('-0x8000000000000000 == parsed[0]'))
+ command('call assert_equal(-0x7fffffffffffffff - 1, parsed[0])')
+ eq({}, eval('v:errors'))
else
eq({_TYPE={}, _VAL={-1, 2, 0, 0}}, eval('parsed[0]'))
end
@@ -461,7 +463,7 @@ describe('msgpackparse() function', function()
eval(cmd)
eval(cmd) -- do it again (try to force segfault)
local api_info = eval(cmd) -- do it again
- eq({'error_types', 'functions', 'types', 'version'}, api_info)
+ eq({'error_types', 'functions', 'types', 'ui_events', 'version'}, api_info)
end)
it('fails when called with no arguments', function()
diff --git a/test/functional/eval/server_spec.lua b/test/functional/eval/server_spec.lua
index 420aea04aa..115114c3c3 100644
--- a/test/functional/eval/server_spec.lua
+++ b/test/functional/eval/server_spec.lua
@@ -1,20 +1,27 @@
local helpers = require('test.functional.helpers')(after_each)
-local nvim, eq, neq, eval = helpers.nvim, helpers.eq, helpers.neq, helpers.eval
+local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval
+local command = helpers.command
local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths
local os_name = helpers.os_name
+local function clear_serverlist()
+ for _, server in pairs(funcs.serverlist()) do
+ funcs.serverstop(server)
+ end
+end
+
describe('serverstart(), serverstop()', function()
before_each(clear)
it('sets $NVIM_LISTEN_ADDRESS on first invocation', function()
-- Unset $NVIM_LISTEN_ADDRESS
- nvim('command', 'let $NVIM_LISTEN_ADDRESS = ""')
+ command('let $NVIM_LISTEN_ADDRESS = ""')
local s = eval('serverstart()')
assert(s ~= nil and s:len() > 0, "serverstart() returned empty")
eq(s, eval('$NVIM_LISTEN_ADDRESS'))
- nvim('command', "call serverstop('"..s.."')")
+ command("call serverstop('"..s.."')")
eq('', eval('$NVIM_LISTEN_ADDRESS'))
end)
@@ -47,10 +54,38 @@ describe('serverstart(), serverstop()', function()
end)
it('serverstop() ignores invalid input', function()
- nvim('command', "call serverstop('')")
- nvim('command', "call serverstop('bogus-socket-name')")
+ command("call serverstop('')")
+ command("call serverstop('bogus-socket-name')")
end)
+ it('parses endpoints correctly', function()
+ clear_serverlist()
+ eq({}, funcs.serverlist())
+
+ local s = funcs.serverstart('127.0.0.1:0') -- assign random port
+ assert(string.match(s, '127.0.0.1:%d+'))
+ eq(s, funcs.serverlist()[1])
+ clear_serverlist()
+
+ s = funcs.serverstart('127.0.0.1:') -- assign random port
+ assert(string.match(s, '127.0.0.1:%d+'))
+ eq(s, funcs.serverlist()[1])
+ clear_serverlist()
+
+ funcs.serverstart('127.0.0.1:12345')
+ funcs.serverstart('127.0.0.1:12345') -- exists already; ignore
+ funcs.serverstart('::1:12345')
+ funcs.serverstart('::1:12345') -- exists already; ignore
+ local expected = {
+ '127.0.0.1:12345',
+ '::1:12345',
+ }
+ eq(expected, funcs.serverlist())
+ clear_serverlist()
+
+ funcs.serverstart('127.0.0.1:65536') -- invalid port
+ eq({}, funcs.serverlist())
+ end)
end)
describe('serverlist()', function()
@@ -75,7 +110,7 @@ describe('serverlist()', function()
-- The new servers should be at the end of the list.
for i = 1, #servs do
eq(servs[i], new_servs[i + n])
- nvim('command', "call serverstop('"..servs[i].."')")
+ command("call serverstop('"..servs[i].."')")
end
-- After serverstop() the servers should NOT be in the list.
eq(n, eval('len(serverlist())'))