diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/functional/api/keymap_spec.lua | 246 | ||||
-rw-r--r-- | test/functional/api/server_requests_spec.lua | 73 | ||||
-rw-r--r-- | test/functional/eval/map_functions_spec.lua | 120 | ||||
-rw-r--r-- | test/functional/eval/server_spec.lua | 47 | ||||
-rw-r--r-- | test/functional/helpers.lua | 5 | ||||
-rw-r--r-- | test/functional/options/pastetoggle_spec.lua | 35 |
6 files changed, 502 insertions, 24 deletions
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua new file mode 100644 index 0000000000..833e0d2f3c --- /dev/null +++ b/test/functional/api/keymap_spec.lua @@ -0,0 +1,246 @@ + +local helpers = require('test.functional.helpers')(after_each) +local clear = helpers.clear +local command = helpers.command +local curbufmeths = helpers.curbufmeths +local eq = helpers.eq +local funcs = helpers.funcs +local meths = helpers.meths +local source = helpers.source + +local function local_copy(t) + local copy = {} + for k,v in pairs(t) do + copy[k] = v + end + return copy +end + +describe('get_keymap', function() + before_each(clear) + + -- Basic mapping and table to be used to describe results + local foo_bar_string = 'nnoremap foo bar' + 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 empty list when no map', function() + eq({}, meths.get_keymap('n')) + end) + + it('returns list of all applicable mappings', function() + command(foo_bar_string) + -- Only one mapping available + -- Should be the same as the dictionary we supplied earlier + -- and the dictionary you would get from maparg + -- since this is a global map, and not script local + eq({foo_bar_map_table}, meths.get_keymap('n')) + eq({funcs.maparg('foo', 'n', false, true)}, + meths.get_keymap('n') + ) + + -- Add another mapping + command('nnoremap foo_longer bar_longer') + local foolong_bar_map_table = local_copy(foo_bar_map_table) + foolong_bar_map_table['lhs'] = 'foo_longer' + foolong_bar_map_table['rhs'] = 'bar_longer' + + eq({foolong_bar_map_table, foo_bar_map_table}, + meths.get_keymap('n') + ) + + -- Remove a mapping + command('unmap foo_longer') + eq({foo_bar_map_table}, + meths.get_keymap('n') + ) + end) + + it('works for other modes', function() + -- Add two mappings, one in insert and one normal + -- We'll only check the insert mode one + command('nnoremap not_going to_check') + + command('inoremap foo bar') + -- The table will be the same except for the mode + local insert_table = local_copy(foo_bar_map_table) + insert_table['mode'] = 'i' + + eq({insert_table}, meths.get_keymap('i')) + end) + + it('considers scope', function() + -- change the map slightly + command('nnoremap foo_longer bar_longer') + local foolong_bar_map_table = local_copy(foo_bar_map_table) + foolong_bar_map_table['lhs'] = 'foo_longer' + foolong_bar_map_table['rhs'] = 'bar_longer' + + local buffer_table = local_copy(foo_bar_map_table) + buffer_table['buffer'] = 1 + + command('nnoremap <buffer> foo bar') + + -- The buffer mapping should not show up + eq({foolong_bar_map_table}, meths.get_keymap('n')) + eq({buffer_table}, curbufmeths.get_keymap('n')) + end) + + it('considers scope for overlapping maps', function() + command('nnoremap foo bar') + + local buffer_table = local_copy(foo_bar_map_table) + buffer_table['buffer'] = 1 + + command('nnoremap <buffer> foo bar') + + eq({foo_bar_map_table}, meths.get_keymap('n')) + eq({buffer_table}, curbufmeths.get_keymap('n')) + end) + + it('can retrieve mapping for different buffers', function() + local original_buffer = curbufmeths.get_number() + -- Place something in each of the buffers to make sure they stick around + -- and set hidden so we can leave them + command('set hidden') + command('new') + command('normal! ihello 2') + command('new') + command('normal! ihello 3') + + local final_buffer = curbufmeths.get_number() + + command('nnoremap <buffer> foo bar') + -- Final buffer will have buffer mappings + local buffer_table = local_copy(foo_bar_map_table) + buffer_table['buffer'] = final_buffer + eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n')) + eq({buffer_table}, meths.buf_get_keymap(0, 'n')) + + command('buffer ' .. original_buffer) + eq(original_buffer, curbufmeths.get_number()) + -- Original buffer won't have any mappings + eq({}, meths.get_keymap('n')) + eq({}, curbufmeths.get_keymap('n')) + eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n')) + end) + + -- Test toggle switches for basic options + -- @param option The key represented in the `maparg()` result dict + local function global_and_buffer_test(map, + option, + option_token, + global_on_result, + buffer_on_result, + global_off_result, + buffer_off_result, + new_windows) + + local function make_new_windows(number_of_windows) + if new_windows == nil then + return nil + end + + for _=1,number_of_windows do + command('new') + end + end + + local mode = string.sub(map, 1,1) + -- Don't run this for the <buffer> mapping, since it doesn't make sense + if option_token ~= '<buffer>' then + it(string.format( 'returns %d for the key "%s" when %s is used globally with %s (%s)', + global_on_result, option, option_token, map, mode), function() + make_new_windows(new_windows) + command(map .. ' ' .. option_token .. ' foo bar') + local result = meths.get_keymap(mode)[1][option] + eq(global_on_result, result) + end) + end + + it(string.format('returns %d for the key "%s" when %s is used for buffers with %s (%s)', + buffer_on_result, option, option_token, map, mode), function() + make_new_windows(new_windows) + command(map .. ' <buffer> ' .. option_token .. ' foo bar') + local result = curbufmeths.get_keymap(mode)[1][option] + eq(buffer_on_result, result) + end) + + -- Don't run these for the <buffer> mapping, since it doesn't make sense + if option_token ~= '<buffer>' then + it(string.format('returns %d for the key "%s" when %s is not used globally with %s (%s)', + global_off_result, option, option_token, map, mode), function() + make_new_windows(new_windows) + command(map .. ' baz bat') + local result = meths.get_keymap(mode)[1][option] + eq(global_off_result, result) + end) + + it(string.format('returns %d for the key "%s" when %s is not used for buffers with %s (%s)', + buffer_off_result, option, option_token, map, mode), function() + make_new_windows(new_windows) + command(map .. ' <buffer> foo bar') + + local result = curbufmeths.get_keymap(mode)[1][option] + eq(buffer_off_result, result) + end) + end + end + + -- Standard modes and returns the same values in the dictionary as maparg() + local mode_list = {'nnoremap', 'nmap', 'imap', 'inoremap', 'cnoremap'} + for mode in pairs(mode_list) do + global_and_buffer_test(mode_list[mode], 'silent', '<silent>', 1, 1, 0, 0) + global_and_buffer_test(mode_list[mode], 'nowait', '<nowait>', 1, 1, 0, 0) + global_and_buffer_test(mode_list[mode], 'expr', '<expr>', 1, 1, 0, 0) + end + + -- noremap will now be 2 if script was used, which is not the same as maparg() + global_and_buffer_test('nmap', 'noremap', '<script>', 2, 2, 0, 0) + global_and_buffer_test('nnoremap', 'noremap', '<script>', 2, 2, 1, 1) + + -- buffer will return the buffer ID, which is not the same as maparg() + -- Three of these tests won't run + global_and_buffer_test('nnoremap', 'buffer', '<buffer>', nil, 3, nil, nil, 2) + + it('returns script numbers for global maps', function() + source([[ + function! s:maparg_test_function() abort + return 'testing' + endfunction + + nnoremap fizz :call <SID>maparg_test_function()<CR> + ]]) + local sid_result = meths.get_keymap('n')[1]['sid'] + eq(1, sid_result) + eq('testing', meths.call_function('<SNR>' .. sid_result .. '_maparg_test_function', {})) + end) + + it('returns script numbers for buffer maps', function() + source([[ + function! s:maparg_test_function() abort + return 'testing' + endfunction + + nnoremap <buffer> fizz :call <SID>maparg_test_function()<CR> + ]]) + local sid_result = curbufmeths.get_keymap('n')[1]['sid'] + eq(1, sid_result) + eq('testing', meths.call_function('<SNR>' .. sid_result .. '_maparg_test_function', {})) + end) + + it('works with <F12> and others', function() + command('nnoremap <F12> :let g:maparg_test_var = 1<CR>') + eq('<F12>', meths.get_keymap('n')[1]['lhs']) + eq(':let g:maparg_test_var = 1<CR>', meths.get_keymap('n')[1]['rhs']) + end) +end) diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua index 658077b112..cf15062325 100644 --- a/test/functional/api/server_requests_spec.lua +++ b/test/functional/api/server_requests_spec.lua @@ -9,6 +9,8 @@ local nvim_prog, command, funcs = helpers.nvim_prog, helpers.command, helpers.fu local source, next_message = helpers.source, helpers.next_message local ok = helpers.ok local meths = helpers.meths +local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv +local set_session = helpers.set_session describe('server -> client', function() local cid @@ -225,4 +227,75 @@ describe('server -> client', function() end) end) + describe('when connecting to another nvim instance', function() + local function connect_test(server, mode, address) + local serverpid = funcs.getpid() + local client = spawn(nvim_argv) + set_session(client, true) + local clientpid = funcs.getpid() + neq(serverpid, clientpid) + local id = funcs.sockconnect(mode, address, {rpc=true}) + ok(id > 0) + + funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') + local client_id = funcs.rpcrequest(id, 'nvim_get_api_info')[1] + + set_session(server, true) + eq(serverpid, funcs.getpid()) + eq('hello', meths.get_current_line()) + + -- method calls work both ways + funcs.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!') + eq(id, funcs.rpcrequest(client_id, 'nvim_get_api_info')[1]) + + set_session(client, true) + eq(clientpid, funcs.getpid()) + eq('howdy!', meths.get_current_line()) + + server:close() + client:close() + end + + it('over a named pipe', function() + local server = spawn(nvim_argv) + set_session(server) + local address = funcs.serverlist()[1] + local first = string.sub(address,1,1) + ok(first == '/' or first == '\\') + connect_test(server, 'pipe', address) + end) + + it('to an ip adress', function() + local server = spawn(nvim_argv) + set_session(server) + local address = funcs.serverstart("127.0.0.1:") + eq('127.0.0.1:', string.sub(address,1,10)) + connect_test(server, 'tcp', address) + end) + + it('to a hostname', function() + local server = spawn(nvim_argv) + set_session(server) + local address = funcs.serverstart("localhost:") + eq('localhost:', string.sub(address,1,10)) + connect_test(server, 'tcp', address) + end) + end) + + describe('when connecting to its own pipe adress', function() + it('it does not deadlock', function() + local address = funcs.serverlist()[1] + local first = string.sub(address,1,1) + ok(first == '/' or first == '\\') + local serverpid = funcs.getpid() + + local id = funcs.sockconnect('pipe', address, {rpc=true}) + + funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') + eq('hello', meths.get_current_line()) + eq(serverpid, funcs.rpcrequest(id, "nvim_eval", "getpid()")) + + eq(id, funcs.rpcrequest(id, 'nvim_get_api_info')[1]) + end) + 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/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())')) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index b03840b3fe..62b0ce1200 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -76,8 +76,8 @@ end local session, loop_running, last_error -local function set_session(s) - if session then +local function set_session(s, keep) + if session and not keep then session:close() end session = s @@ -609,6 +609,7 @@ local module = { nvim = nvim, nvim_async = nvim_async, nvim_prog = nvim_prog, + nvim_argv = nvim_argv, nvim_set = nvim_set, nvim_dir = nvim_dir, buffer = buffer, diff --git a/test/functional/options/pastetoggle_spec.lua b/test/functional/options/pastetoggle_spec.lua index ec3c60fe37..a1f86f73ff 100644 --- a/test/functional/options/pastetoggle_spec.lua +++ b/test/functional/options/pastetoggle_spec.lua @@ -6,32 +6,35 @@ local command = helpers.command local eq = helpers.eq local eval = helpers.eval local sleep = helpers.sleep +local expect = helpers.expect describe("'pastetoggle' option", function() before_each(function() clear() command('set nopaste') - command('set pastetoggle=a') end) + it("toggles 'paste'", function() - eq(eval('&paste'), 0) + command('set pastetoggle=a') + eq(0, eval('&paste')) feed('a') -- Need another key so that the vgetorpeek() function returns. feed('j') - eq(eval('&paste'), 1) + eq(1, eval('&paste')) end) - it("multiple key 'pastetoggle' is waited for", function() - eq(eval('&paste'), 0) - local pastetoggle = 'lllll' - command('set pastetoggle=' .. pastetoggle) - command('set timeoutlen=1 ttimeoutlen=10000') - feed(pastetoggle:sub(0, 2)) - -- sleep() for long enough that vgetorpeek() is gotten into, but short - -- enough that ttimeoutlen is not reached. - sleep(200) - feed(pastetoggle:sub(3, -1)) - -- Need another key so that the vgetorpeek() function returns. - feed('j') - eq(eval('&paste'), 1) + + + it('does not wait for timeout', function() + command('set pastetoggle=abc') + command('set ttimeoutlen=9999999') + eq(0, eval('&paste')) + -- n.b. need <esc> to return from vgetorpeek() + feed('abc<esc>') + eq(1, eval('&paste')) + feed('ab') + sleep(10) + feed('c<esc>') + expect('bc') + eq(1, eval('&paste')) end) end) |