aboutsummaryrefslogtreecommitdiff
path: root/test/functional/vimscript/ctx_functions_spec.lua
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2021-09-17 09:16:40 -0700
committerGitHub <noreply@github.com>2021-09-17 09:16:40 -0700
commitd8de4eb685e35646c7d541e9a75bdc296127b7e2 (patch)
tree4bb05ec713856715ac9ba57e5d116eed344511b9 /test/functional/vimscript/ctx_functions_spec.lua
parentd56002f7b722facd97b0958e141c8ed2d01495f7 (diff)
downloadrneovim-d8de4eb685e35646c7d541e9a75bdc296127b7e2.tar.gz
rneovim-d8de4eb685e35646c7d541e9a75bdc296127b7e2.tar.bz2
rneovim-d8de4eb685e35646c7d541e9a75bdc296127b7e2.zip
test: reorg #15698
Problem: Subdirectories like "visual", "insert", "normal" encourage people to separate *related* tests for no good reason. Typically the _mode_ is not the relevant topic of a test (and when it is, _then_ create an appropriate describe() or it()). Solution: - Delete the various `test/functional/<mode>/` subdirectories, move their tests to more meaningful topics. - Rename `…/normal/` to `…/editor/`. - Move or merge `…/visual/*` and `…/insert/*` tests into here where appropriate. - Rename `…/eval/` to `…/vimscript/`. - Move `…/viml/*` into here also. * test(reorg): insert/* => editor/mode_insert_spec.lua * test(reorg): cmdline/* => editor/mode_cmdline_spec.lua * test(reorg): eval core tests => eval_spec.lua
Diffstat (limited to 'test/functional/vimscript/ctx_functions_spec.lua')
-rw-r--r--test/functional/vimscript/ctx_functions_spec.lua406
1 files changed, 406 insertions, 0 deletions
diff --git a/test/functional/vimscript/ctx_functions_spec.lua b/test/functional/vimscript/ctx_functions_spec.lua
new file mode 100644
index 0000000000..f23adbc556
--- /dev/null
+++ b/test/functional/vimscript/ctx_functions_spec.lua
@@ -0,0 +1,406 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local call = helpers.call
+local clear = helpers.clear
+local command = helpers.command
+local eq = helpers.eq
+local eval = helpers.eval
+local feed = helpers.feed
+local map = helpers.tbl_map
+local nvim = helpers.nvim
+local parse_context = helpers.parse_context
+local redir_exec = helpers.redir_exec
+local source = helpers.source
+local trim = helpers.trim
+local write_file = helpers.write_file
+local pcall_err = helpers.pcall_err
+
+describe('context functions', function()
+ local fname1 = 'Xtest-functional-eval-ctx1'
+ local fname2 = 'Xtest-functional-eval-ctx2'
+ local outofbounds =
+ 'Vim:E475: Invalid value for argument index: out of bounds'
+
+ before_each(function()
+ clear()
+ write_file(fname1, "1\n2\n3")
+ write_file(fname2, "a\nb\nc")
+ end)
+
+ after_each(function()
+ os.remove(fname1)
+ os.remove(fname2)
+ end)
+
+ describe('ctxpush/ctxpop', function()
+ it('saves and restores registers properly', function()
+ local regs = {'1', '2', '3', 'a'}
+ local vals = {'1', '2', '3', 'hjkl'}
+ feed('i1<cr>2<cr>3<c-[>ddddddqahjklq')
+ eq(vals, map(function(r) return trim(call('getreg', r)) end, regs))
+ call('ctxpush')
+ call('ctxpush', {'regs'})
+
+ map(function(r) call('setreg', r, {}) end, regs)
+ eq({'', '', '', ''},
+ map(function(r) return trim(call('getreg', r)) end, regs))
+
+ call('ctxpop')
+ eq(vals, map(function(r) return trim(call('getreg', r)) end, regs))
+
+ map(function(r) call('setreg', r, {}) end, regs)
+ eq({'', '', '', ''},
+ map(function(r) return trim(call('getreg', r)) end, regs))
+
+ call('ctxpop')
+ eq(vals, map(function(r) return trim(call('getreg', r)) end, regs))
+ end)
+
+ it('saves and restores jumplist properly', function()
+ command('edit '..fname1)
+ feed('G')
+ feed('gg')
+ command('edit '..fname2)
+ local jumplist = call('getjumplist')
+ call('ctxpush')
+ call('ctxpush', {'jumps'})
+
+ command('clearjumps')
+ eq({{}, 0}, call('getjumplist'))
+
+ call('ctxpop')
+ eq(jumplist, call('getjumplist'))
+
+ command('clearjumps')
+ eq({{}, 0}, call('getjumplist'))
+
+ call('ctxpop')
+ eq(jumplist, call('getjumplist'))
+ end)
+
+ it('saves and restores buffer list properly', function()
+ command('edit '..fname1)
+ command('edit '..fname2)
+ command('edit TEST')
+ local bufs = call('map', call('getbufinfo'), 'v:val.name')
+ call('ctxpush')
+ call('ctxpush', {'bufs'})
+
+ command('%bwipeout')
+ eq({''}, call('map', call('getbufinfo'), 'v:val.name'))
+
+ call('ctxpop')
+ eq({'', unpack(bufs)}, call('map', call('getbufinfo'), 'v:val.name'))
+
+ command('%bwipeout')
+ eq({''}, call('map', call('getbufinfo'), 'v:val.name'))
+
+ call('ctxpop')
+ eq({'', unpack(bufs)}, call('map', call('getbufinfo'), 'v:val.name'))
+ end)
+
+ it('saves and restores global variables properly', function()
+ nvim('set_var', 'one', 1)
+ nvim('set_var', 'Two', 2)
+ nvim('set_var', 'THREE', 3)
+ eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]'))
+ call('ctxpush')
+ call('ctxpush', {'gvars'})
+
+ nvim('del_var', 'one')
+ nvim('del_var', 'Two')
+ nvim('del_var', 'THREE')
+ eq('Vim:E121: Undefined variable: g:one', pcall_err(eval, 'g:one'))
+ eq('Vim:E121: Undefined variable: g:Two', pcall_err(eval, 'g:Two'))
+ eq('Vim:E121: Undefined variable: g:THREE', pcall_err(eval, 'g:THREE'))
+
+ call('ctxpop')
+ eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]'))
+
+ nvim('del_var', 'one')
+ nvim('del_var', 'Two')
+ nvim('del_var', 'THREE')
+ eq('Vim:E121: Undefined variable: g:one', pcall_err(eval, 'g:one'))
+ eq('Vim:E121: Undefined variable: g:Two', pcall_err(eval, 'g:Two'))
+ eq('Vim:E121: Undefined variable: g:THREE', pcall_err(eval, 'g:THREE'))
+
+ call('ctxpop')
+ eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]'))
+ end)
+
+ it('saves and restores script functions properly', function()
+ source([[
+ function s:greet(name)
+ echom 'Hello, '.a:name.'!'
+ endfunction
+
+ function s:greet_all(name, ...)
+ echom 'Hello, '.a:name.'!'
+ for more in a:000
+ echom 'Hello, '.more.'!'
+ endfor
+ endfunction
+
+ function Greet(name)
+ call call('s:greet', [a:name])
+ endfunction
+
+ function GreetAll(name, ...)
+ call call('s:greet_all', extend([a:name], a:000))
+ endfunction
+
+ function SaveSFuncs()
+ call ctxpush(['sfuncs'])
+ endfunction
+
+ function DeleteSFuncs()
+ delfunction s:greet
+ delfunction s:greet_all
+ endfunction
+
+ function RestoreFuncs()
+ call ctxpop()
+ endfunction
+ ]])
+
+ eq('\nHello, World!', redir_exec([[call Greet('World')]]))
+ eq('\nHello, World!'..
+ '\nHello, One!'..
+ '\nHello, Two!'..
+ '\nHello, Three!',
+ redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+
+ call('SaveSFuncs')
+ call('DeleteSFuncs')
+
+ eq('\nError detected while processing function Greet:'..
+ '\nline 1:'..
+ '\nE117: Unknown function: s:greet',
+ redir_exec([[call Greet('World')]]))
+ eq('\nError detected while processing function GreetAll:'..
+ '\nline 1:'..
+ '\nE117: Unknown function: s:greet_all',
+ redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+
+ call('RestoreFuncs')
+
+ eq('\nHello, World!', redir_exec([[call Greet('World')]]))
+ eq('\nHello, World!'..
+ '\nHello, One!'..
+ '\nHello, Two!'..
+ '\nHello, Three!',
+ redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ end)
+
+ it('saves and restores functions properly', function()
+ source([[
+ function Greet(name)
+ echom 'Hello, '.a:name.'!'
+ endfunction
+
+ function GreetAll(name, ...)
+ echom 'Hello, '.a:name.'!'
+ for more in a:000
+ echom 'Hello, '.more.'!'
+ endfor
+ endfunction
+ ]])
+
+ eq('\nHello, World!', redir_exec([[call Greet('World')]]))
+ eq('\nHello, World!'..
+ '\nHello, One!'..
+ '\nHello, Two!'..
+ '\nHello, Three!',
+ redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+
+ call('ctxpush', {'funcs'})
+ command('delfunction Greet')
+ command('delfunction GreetAll')
+
+ eq('Vim:E117: Unknown function: Greet', pcall_err(call, 'Greet', 'World'))
+ eq('Vim:E117: Unknown function: GreetAll',
+ pcall_err(call, 'GreetAll', 'World', 'One', 'Two', 'Three'))
+
+ call('ctxpop')
+
+ eq('\nHello, World!', redir_exec([[call Greet('World')]]))
+ eq('\nHello, World!'..
+ '\nHello, One!'..
+ '\nHello, Two!'..
+ '\nHello, Three!',
+ redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ end)
+
+ it('errors out when context stack is empty', function()
+ local err = 'Vim:Context stack is empty'
+ eq(err, pcall_err(call, 'ctxpop'))
+ eq(err, pcall_err(call, 'ctxpop'))
+ call('ctxpush')
+ call('ctxpush')
+ call('ctxpop')
+ call('ctxpop')
+ eq(err, pcall_err(call, 'ctxpop'))
+ end)
+ end)
+
+ describe('ctxsize()', function()
+ it('returns context stack size', function()
+ eq(0, call('ctxsize'))
+ call('ctxpush')
+ eq(1, call('ctxsize'))
+ call('ctxpush')
+ eq(2, call('ctxsize'))
+ call('ctxpush')
+ eq(3, call('ctxsize'))
+ call('ctxpop')
+ eq(2, call('ctxsize'))
+ call('ctxpop')
+ eq(1, call('ctxsize'))
+ call('ctxpop')
+ eq(0, call('ctxsize'))
+ end)
+ end)
+
+ describe('ctxget()', function()
+ it('errors out when index is out of bounds', function()
+ eq(outofbounds, pcall_err(call, 'ctxget'))
+ call('ctxpush')
+ eq(outofbounds, pcall_err(call, 'ctxget', 1))
+ call('ctxpop')
+ eq(outofbounds, pcall_err(call, 'ctxget', 0))
+ end)
+
+ it('returns context dictionary at index in context stack', function()
+ feed('i1<cr>2<cr>3<c-[>ddddddqahjklq')
+ command('edit! '..fname1)
+ feed('G')
+ feed('gg')
+ command('edit '..fname2)
+ nvim('set_var', 'one', 1)
+ nvim('set_var', 'Two', 2)
+ nvim('set_var', 'THREE', 3)
+
+ local with_regs = {
+ ['regs'] = {
+ {['rt'] = 1, ['rc'] = {'1'}, ['n'] = 49, ['ru'] = true},
+ {['rt'] = 1, ['rc'] = {'2'}, ['n'] = 50},
+ {['rt'] = 1, ['rc'] = {'3'}, ['n'] = 51},
+ {['rc'] = {'hjkl'}, ['n'] = 97},
+ }
+ }
+
+ local with_jumps = {
+ ['jumps'] = eval(([[
+ filter(map(getjumplist()[0], 'filter(
+ { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
+ { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
+ ]]):gsub('\n', ''))
+ }
+
+ local with_bufs = {
+ ['bufs'] = eval([[
+ filter(map(getbufinfo(), '{ "f": v:val.name }'), '!empty(v:val.f)')
+ ]])
+ }
+
+ local with_gvars = {
+ ['gvars'] = {{'one', 1}, {'Two', 2}, {'THREE', 3}}
+ }
+
+ local with_all = {
+ ['regs'] = with_regs['regs'],
+ ['jumps'] = with_jumps['jumps'],
+ ['bufs'] = with_bufs['bufs'],
+ ['gvars'] = with_gvars['gvars'],
+ }
+
+ call('ctxpush')
+ eq(with_all, parse_context(call('ctxget')))
+ eq(with_all, parse_context(call('ctxget', 0)))
+
+ call('ctxpush', {'gvars'})
+ eq(with_gvars, parse_context(call('ctxget')))
+ eq(with_gvars, parse_context(call('ctxget', 0)))
+ eq(with_all, parse_context(call('ctxget', 1)))
+
+ call('ctxpush', {'bufs'})
+ eq(with_bufs, parse_context(call('ctxget')))
+ eq(with_bufs, parse_context(call('ctxget', 0)))
+ eq(with_gvars, parse_context(call('ctxget', 1)))
+ eq(with_all, parse_context(call('ctxget', 2)))
+
+ call('ctxpush', {'jumps'})
+ eq(with_jumps, parse_context(call('ctxget')))
+ eq(with_jumps, parse_context(call('ctxget', 0)))
+ eq(with_bufs, parse_context(call('ctxget', 1)))
+ eq(with_gvars, parse_context(call('ctxget', 2)))
+ eq(with_all, parse_context(call('ctxget', 3)))
+
+ call('ctxpush', {'regs'})
+ eq(with_regs, parse_context(call('ctxget')))
+ eq(with_regs, parse_context(call('ctxget', 0)))
+ eq(with_jumps, parse_context(call('ctxget', 1)))
+ eq(with_bufs, parse_context(call('ctxget', 2)))
+ eq(with_gvars, parse_context(call('ctxget', 3)))
+ eq(with_all, parse_context(call('ctxget', 4)))
+
+ call('ctxpop')
+ eq(with_jumps, parse_context(call('ctxget')))
+ eq(with_jumps, parse_context(call('ctxget', 0)))
+ eq(with_bufs, parse_context(call('ctxget', 1)))
+ eq(with_gvars, parse_context(call('ctxget', 2)))
+ eq(with_all, parse_context(call('ctxget', 3)))
+
+ call('ctxpop')
+ eq(with_bufs, parse_context(call('ctxget')))
+ eq(with_bufs, parse_context(call('ctxget', 0)))
+ eq(with_gvars, parse_context(call('ctxget', 1)))
+ eq(with_all, parse_context(call('ctxget', 2)))
+
+ call('ctxpop')
+ eq(with_gvars, parse_context(call('ctxget')))
+ eq(with_gvars, parse_context(call('ctxget', 0)))
+ eq(with_all, parse_context(call('ctxget', 1)))
+
+ call('ctxpop')
+ eq(with_all, parse_context(call('ctxget')))
+ eq(with_all, parse_context(call('ctxget', 0)))
+ end)
+ end)
+
+ describe('ctxset()', function()
+ it('errors out when index is out of bounds', function()
+ eq(outofbounds, pcall_err(call, 'ctxset', {dummy = 1}))
+ call('ctxpush')
+ eq(outofbounds, pcall_err(call, 'ctxset', {dummy = 1}, 1))
+ call('ctxpop')
+ eq(outofbounds, pcall_err(call, 'ctxset', {dummy = 1}, 0))
+ end)
+
+ it('sets context dictionary at index in context stack', function()
+ nvim('set_var', 'one', 1)
+ nvim('set_var', 'Two', 2)
+ nvim('set_var', 'THREE', 3)
+ call('ctxpush')
+ local ctx1 = call('ctxget')
+ nvim('set_var', 'one', 'a')
+ nvim('set_var', 'Two', 'b')
+ nvim('set_var', 'THREE', 'c')
+ call('ctxpush')
+ call('ctxpush')
+ local ctx2 = call('ctxget')
+
+ eq({'a', 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]'))
+ call('ctxset', ctx1)
+ call('ctxset', ctx2, 2)
+ call('ctxpop')
+ eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]'))
+ call('ctxpop')
+ eq({'a', 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]'))
+ nvim('set_var', 'one', 1.5)
+ eq({1.5, 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]'))
+ call('ctxpop')
+ eq({'a', 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]'))
+ end)
+ end)
+end)