aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/api/highlight_spec.lua21
-rw-r--r--test/functional/autocmd/autocmd_oldtest_spec.lua7
-rw-r--r--test/functional/core/startup_spec.lua30
-rw-r--r--test/functional/editor/mark_spec.lua44
-rw-r--r--test/functional/legacy/061_undo_tree_spec.lua17
-rw-r--r--test/functional/legacy/prompt_buffer_spec.lua6
-rw-r--r--test/functional/lua/loader_spec.lua36
-rw-r--r--test/functional/lua/vim_spec.lua36
-rw-r--r--test/functional/plugin/lsp_spec.lua31
-rw-r--r--test/functional/shada/merging_spec.lua2
-rw-r--r--test/functional/ui/float_spec.lua19
-rw-r--r--test/functional/ui/highlight_spec.lua21
-rw-r--r--test/functional/ui/messages_spec.lua9
-rw-r--r--test/functional/ui/statuscolumn_spec.lua36
-rw-r--r--test/functional/ui/winbar_spec.lua35
-rw-r--r--test/functional/vimscript/eval_spec.lua35
-rw-r--r--test/functional/vimscript/system_spec.lua4
-rw-r--r--test/helpers.lua18
-rw-r--r--test/old/testdir/test_alot.vim1
-rw-r--r--test/old/testdir/test_arglist.vim35
-rw-r--r--test/old/testdir/test_behave.vim29
-rw-r--r--test/old/testdir/test_cmdline.vim17
-rw-r--r--test/old/testdir/test_expr.vim32
-rw-r--r--test/old/testdir/test_help_tagjump.vim4
-rw-r--r--test/old/testdir/test_let.vim4
-rw-r--r--test/old/testdir/test_prompt_buffer.vim13
-rw-r--r--test/old/testdir/test_usercommands.vim8
-rw-r--r--test/old/testdir/test_vimscript.vim30
-rw-r--r--test/old/testdir/test_visual.vim6
-rw-r--r--test/unit/eval/helpers.lua3
-rw-r--r--test/unit/formatc.lua2
-rw-r--r--test/unit/helpers.lua314
-rw-r--r--test/unit/preprocess.lua176
-rw-r--r--test/unit/set.lua44
34 files changed, 766 insertions, 359 deletions
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua
index a4bd574a56..a6e9f9a42b 100644
--- a/test/functional/api/highlight_spec.lua
+++ b/test/functional/api/highlight_spec.lua
@@ -575,4 +575,25 @@ describe('API: get highlight', function()
meths.set_hl(0, 'Foo', hl)
eq(hl, meths.get_hl(0, { name = 'Foo', link = true }))
end)
+
+ it("doesn't contain unset groups", function()
+ local id = meths.get_hl_id_by_name "@foobar.hubbabubba"
+ ok(id > 0)
+
+ local data = meths.get_hl(0, {})
+ eq(nil, data["@foobar.hubbabubba"])
+ eq(nil, data["@foobar"])
+
+ command 'hi @foobar.hubbabubba gui=bold'
+ data = meths.get_hl(0, {})
+ eq({bold = true}, data["@foobar.hubbabubba"])
+ eq(nil, data["@foobar"])
+
+ -- @foobar.hubbabubba was explicitly cleared and thus shows up
+ -- but @foobar was never touched, and thus doesn't
+ command 'hi clear @foobar.hubbabubba'
+ data = meths.get_hl(0, {})
+ eq({}, data["@foobar.hubbabubba"])
+ eq(nil, data["@foobar"])
+ end)
end)
diff --git a/test/functional/autocmd/autocmd_oldtest_spec.lua b/test/functional/autocmd/autocmd_oldtest_spec.lua
index 29d589a296..29a6171269 100644
--- a/test/functional/autocmd/autocmd_oldtest_spec.lua
+++ b/test/functional/autocmd/autocmd_oldtest_spec.lua
@@ -50,6 +50,7 @@ describe('oldtests', function()
it('should fire on unload buf', function()
funcs.writefile({'Test file Xxx1'}, 'Xxx1')
funcs.writefile({'Test file Xxx2'}, 'Xxx2')
+ local fname = 'Xtest_functional_autocmd_unload'
local content = [[
func UnloadAllBufs()
@@ -69,15 +70,15 @@ describe('oldtests', function()
q
]]
- funcs.writefile(funcs.split(content, "\n"), 'Xtest')
+ funcs.writefile(funcs.split(content, "\n"), fname)
funcs.delete('Xout')
- funcs.system(meths.get_vvar('progpath') .. ' -u NORC -i NONE -N -S Xtest')
+ funcs.system(string.format('%s -u NORC -i NONE -N -S %s', meths.get_vvar('progpath'), fname))
eq(1, funcs.filereadable('Xout'))
funcs.delete('Xxx1')
funcs.delete('Xxx2')
- funcs.delete('Xtest')
+ funcs.delete(fname)
funcs.delete('Xout')
end)
end)
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index cc94623df3..b8a3c1dcd5 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -28,6 +28,9 @@ local meths = helpers.meths
local alter_slashes = helpers.alter_slashes
local is_os = helpers.is_os
local dedent = helpers.dedent
+local tbl_map = helpers.tbl_map
+local tbl_filter = helpers.tbl_filter
+local endswith = helpers.endswith
local testfile = 'Xtest_startuptime'
after_each(function()
@@ -202,12 +205,12 @@ describe('startup', function()
end)
it('disables swapfile/shada/config/plugins', function()
- assert_l_out('updatecount=0 shadafile=NONE loadplugins=false scriptnames=1',
+ assert_l_out('updatecount=0 shadafile=NONE loadplugins=false scripts=1',
nil,
nil,
'-',
- [[print(('updatecount=%d shadafile=%s loadplugins=%s scriptnames=%d'):format(
- vim.o.updatecount, vim.o.shadafile, tostring(vim.o.loadplugins), math.max(1, #vim.fn.split(vim.fn.execute('scriptnames'),'\n'))))]])
+ [[print(('updatecount=%d shadafile=%s loadplugins=%s scripts=%d'):format(
+ vim.o.updatecount, vim.o.shadafile, tostring(vim.o.loadplugins), math.max(1, #vim.fn.getscriptinfo())))]])
end)
end)
@@ -398,13 +401,13 @@ describe('startup', function()
for _,arg in ipairs({'-es', '-Es'}) do
local out = funcs.system({nvim_prog, arg,
'+set swapfile? updatecount? shadafile?',
- "+put =execute('scriptnames')", '+%print'})
+ "+put =map(getscriptinfo(), {-> v:val.name})", '+%print'})
local line1 = string.match(out, '^.-\n')
-- updatecount=0 means swapfile was disabled.
eq(" swapfile updatecount=0 shadafile=\n", line1)
-- Standard plugins were loaded, but not user config.
- eq('health.vim', string.match(out, 'health.vim'))
- eq(nil, string.match(out, 'init.vim'))
+ ok(string.find(out, 'man.lua') ~= nil)
+ ok(string.find(out, 'init.vim') == nil)
end
end)
@@ -865,6 +868,10 @@ describe('runtime:', function()
local plugin_file_path = table.concat({plugin_folder_path, 'plugin.lua'},
pathsep)
local profiler_file = 'test_startuptime.log'
+ finally(function()
+ os.remove(profiler_file)
+ rmdir(plugin_path)
+ end)
mkdir_p(plugin_folder_path)
write_file(plugin_file_path, [[vim.g.lua_plugin = 2]])
@@ -872,18 +879,15 @@ describe('runtime:', function()
clear{ args_rm={'-u'}, args={'--startuptime', profiler_file}, env=xenv }
eq(2, eval('g:lua_plugin'))
- -- Check if plugin_file_path is listed in :scriptname
- local scripts = exec_capture('scriptnames')
- assert(scripts:find(plugin_file_path))
+ -- Check if plugin_file_path is listed in getscriptinfo()
+ local scripts = tbl_map(function(s) return s.name end, funcs.getscriptinfo())
+ ok(#tbl_filter(function(s) return endswith(s, plugin_file_path) end, scripts) > 0)
-- Check if plugin_file_path is listed in startup profile
local profile_reader = io.open(profiler_file, 'r')
local profile_log = profile_reader:read('*a')
profile_reader:close()
- assert(profile_log:find(plugin_file_path))
-
- os.remove(profiler_file)
- rmdir(plugin_path)
+ ok(profile_log:find(plugin_file_path) ~= nil)
end)
it('loads plugin/*.lua from site packages', function()
diff --git a/test/functional/editor/mark_spec.lua b/test/functional/editor/mark_spec.lua
index 365f8527a0..a6e4b0c5eb 100644
--- a/test/functional/editor/mark_spec.lua
+++ b/test/functional/editor/mark_spec.lua
@@ -417,4 +417,48 @@ describe('named marks view', function()
|
]])
end)
+
+ it('fallback to standard behavior when mark is loaded from shada', function()
+ local screen = Screen.new(10, 6)
+ screen:attach()
+ command('edit ' .. file1)
+ feed('G')
+ feed('mA')
+ screen:expect([[
+ 26 line |
+ 27 line |
+ 28 line |
+ 29 line |
+ ^30 line |
+ |
+ ]])
+ command('set shadafile=Xtestfile-functional-editor-marks-shada')
+ finally(function()
+ command('set shadafile=NONE')
+ os.remove('Xtestfile-functional-editor-marks-shada')
+ end)
+ command('wshada!')
+ command('bwipe!')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]])
+ command('rshada!')
+ command('edit ' .. file1)
+ feed('`"')
+ screen:expect([[
+ 26 line |
+ 27 line |
+ 28 line |
+ 29 line |
+ ^30 line |
+ |
+ ]])
+ feed('`A')
+ screen:expect_unchanged()
+ end)
end)
diff --git a/test/functional/legacy/061_undo_tree_spec.lua b/test/functional/legacy/061_undo_tree_spec.lua
index 1a8ef067d0..b5af8f7d52 100644
--- a/test/functional/legacy/061_undo_tree_spec.lua
+++ b/test/functional/legacy/061_undo_tree_spec.lua
@@ -22,29 +22,30 @@ end
describe('undo tree:', function()
before_each(clear)
+ local fname = 'Xtest_functional_legacy_undotree'
teardown(function()
- os.remove('Xtest.source')
+ os.remove(fname .. '.source')
end)
describe(':earlier and :later', function()
before_each(function()
- os.remove('Xtest')
+ os.remove(fname)
end)
teardown(function()
- os.remove('Xtest')
+ os.remove(fname)
end)
it('time specifications, g- g+', function()
-- We write the test text to a file in order to prevent nvim to record
-- the inserting of the text into the undo history.
- write_file('Xtest', '\n123456789\n')
+ write_file(fname, '\n123456789\n')
-- `:earlier` and `:later` are (obviously) time-sensitive, so this test
-- sometimes fails if the system is under load. It is wrapped in a local
-- function to allow multiple attempts.
local function test_earlier_later()
clear()
- feed_command('e Xtest')
+ feed_command('e ' .. fname)
-- Assert that no undo history is present.
eq({}, eval('undotree().entries'))
-- Delete three characters and undo.
@@ -103,7 +104,7 @@ describe('undo tree:', function()
it('file-write specifications', function()
feed('ione one one<esc>')
- feed_command('w Xtest')
+ feed_command('w ' .. fname)
feed('otwo<esc>')
feed('otwo<esc>')
feed_command('w')
@@ -187,7 +188,7 @@ describe('undo tree:', function()
it('undo an expression-register', function()
local normal_commands = 'o1\027a2\018=string(123)\n\027'
- write_file('Xtest.source', normal_commands)
+ write_file(fname .. '.source', normal_commands)
feed('oa<esc>')
feed('ob<esc>')
@@ -221,7 +222,7 @@ describe('undo tree:', function()
c
12]])
feed('od<esc>')
- feed_command('so! Xtest.source')
+ feed_command('so! ' .. fname .. '.source')
expect([[
a
diff --git a/test/functional/legacy/prompt_buffer_spec.lua b/test/functional/legacy/prompt_buffer_spec.lua
index 6c72cde855..5c3f8a6f8c 100644
--- a/test/functional/legacy/prompt_buffer_spec.lua
+++ b/test/functional/legacy/prompt_buffer_spec.lua
@@ -247,6 +247,7 @@ describe('prompt buffer', function()
func DoAppend()
call appendbufline('prompt', '$', 'Test')
+ return ''
endfunc
]])
feed('asomething<CR>')
@@ -254,7 +255,12 @@ describe('prompt buffer', function()
neq(prev_win, meths.get_current_win())
feed('exit<CR>')
eq(prev_win, meths.get_current_win())
+ eq({ mode = 'n', blocking = false }, meths.get_mode())
command('call DoAppend()')
eq({ mode = 'n', blocking = false }, meths.get_mode())
+ feed('i')
+ eq({ mode = 'i', blocking = false }, meths.get_mode())
+ command('call DoAppend()')
+ eq({ mode = 'i', blocking = false }, meths.get_mode())
end)
end)
diff --git a/test/functional/lua/loader_spec.lua b/test/functional/lua/loader_spec.lua
new file mode 100644
index 0000000000..e2958d1592
--- /dev/null
+++ b/test/functional/lua/loader_spec.lua
@@ -0,0 +1,36 @@
+-- Test suite for testing interactions with API bindings
+local helpers = require('test.functional.helpers')(after_each)
+
+local exec_lua = helpers.exec_lua
+local command = helpers.command
+local eq = helpers.eq
+
+describe('vim.loader', function()
+ before_each(helpers.clear)
+
+ it('handles changing files (#23027)', function()
+ exec_lua[[
+ vim.loader.enable()
+ ]]
+
+ local tmp = helpers.tmpname()
+ command('edit ' .. tmp)
+
+ eq(1, exec_lua([[
+ vim.api.nvim_buf_set_lines(0, 0, -1, true, {'_G.TEST=1'})
+ vim.cmd.write()
+ loadfile(...)()
+ return _G.TEST
+ ]], tmp))
+
+ -- fs latency
+ helpers.sleep(10)
+
+ eq(2, exec_lua([[
+ vim.api.nvim_buf_set_lines(0, 0, -1, true, {'_G.TEST=2'})
+ vim.cmd.write()
+ loadfile(...)()
+ return _G.TEST
+ ]], tmp))
+ end)
+end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 45d9263c0c..1ee1a13fd5 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -461,6 +461,22 @@ describe('lua stdlib', function()
pcall_err(exec_lua, [[return vim.pesc(2)]]))
end)
+ it('vim.list_contains', function()
+ eq(true, exec_lua("return vim.list_contains({'a','b','c'}, 'c')"))
+ eq(false, exec_lua("return vim.list_contains({'a','b','c'}, 'd')"))
+ end)
+
+ it('vim.tbl_contains', function()
+ eq(true, exec_lua("return vim.tbl_contains({'a','b','c'}, 'c')"))
+ eq(false, exec_lua("return vim.tbl_contains({'a','b','c'}, 'd')"))
+ eq(true, exec_lua("return vim.tbl_contains({[2]='a',foo='b',[5] = 'c'}, 'c')"))
+ eq(true, exec_lua([[
+ return vim.tbl_contains({ 'a', { 'b', 'c' } }, function(v)
+ return vim.deep_equal(v, { 'b', 'c' })
+ end, { predicate = true })
+ ]]))
+ end)
+
it('vim.tbl_keys', function()
eq({}, exec_lua("return vim.tbl_keys({})"))
for _, v in pairs(exec_lua("return vim.tbl_keys({'a', 'b', 'c'})")) do
@@ -505,6 +521,19 @@ describe('lua stdlib', function()
]]))
end)
+ it('vim.tbl_isarray', function()
+ eq(true, exec_lua("return vim.tbl_isarray({})"))
+ eq(false, exec_lua("return vim.tbl_isarray(vim.empty_dict())"))
+ eq(true, exec_lua("return vim.tbl_isarray({'a', 'b', 'c'})"))
+ eq(false, exec_lua("return vim.tbl_isarray({'a', '32', a='hello', b='baz'})"))
+ eq(false, exec_lua("return vim.tbl_isarray({1, a='hello', b='baz'})"))
+ eq(false, exec_lua("return vim.tbl_isarray({a='hello', b='baz', 1})"))
+ eq(false, exec_lua("return vim.tbl_isarray({1, 2, nil, a='hello'})"))
+ eq(true, exec_lua("return vim.tbl_isarray({1, 2, nil, 4})"))
+ eq(true, exec_lua("return vim.tbl_isarray({nil, 2, 3, 4})"))
+ eq(false, exec_lua("return vim.tbl_isarray({1, [1.5]=2, [3]=3})"))
+ end)
+
it('vim.tbl_islist', function()
eq(true, exec_lua("return vim.tbl_islist({})"))
eq(false, exec_lua("return vim.tbl_islist(vim.empty_dict())"))
@@ -513,6 +542,9 @@ describe('lua stdlib', function()
eq(false, exec_lua("return vim.tbl_islist({1, a='hello', b='baz'})"))
eq(false, exec_lua("return vim.tbl_islist({a='hello', b='baz', 1})"))
eq(false, exec_lua("return vim.tbl_islist({1, 2, nil, a='hello'})"))
+ eq(false, exec_lua("return vim.tbl_islist({1, 2, nil, 4})"))
+ eq(false, exec_lua("return vim.tbl_islist({nil, 2, 3, 4})"))
+ eq(false, exec_lua("return vim.tbl_islist({1, [1.5]=2, [3]=3})"))
end)
it('vim.tbl_isempty', function()
@@ -2297,6 +2329,10 @@ describe('lua stdlib', function()
insert([[αα]])
eq({0,5}, exec_lua[[ return vim.region(0,{0,0},{0,4},'3',true)[0] ]])
end)
+ it('getpos() input', function()
+ insert('getpos')
+ eq({0,6}, exec_lua[[ return vim.region(0,{0,0},'.','v',true)[0] ]])
+ end)
end)
describe('vim.on_key', function()
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index da05b09593..5ba0706208 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -323,15 +323,13 @@ describe('LSP', function()
local client
test_rpc_server {
test_name = "set_defaults_all_capabilities";
- on_setup = function()
+ on_init = function(_client)
+ client = _client
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
+ lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
]]
end;
- on_init = function(_client)
- client = _client
- exec_lua("lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)")
- end;
on_handler = function(_, _, ctx)
if ctx.method == 'test' then
eq('v:lua.vim.lsp.tagfunc', get_buf_option("tagfunc"))
@@ -352,7 +350,8 @@ describe('LSP', function()
local client
test_rpc_server {
test_name = "set_defaults_all_capabilities";
- on_setup = function()
+ on_init = function(_client)
+ client = _client
exec_lua [[
vim.api.nvim_command('filetype plugin on')
BUFFER_1 = vim.api.nvim_create_buf(false, true)
@@ -360,14 +359,16 @@ describe('LSP', function()
vim.api.nvim_buf_set_option(BUFFER_1, 'filetype', 'man')
vim.api.nvim_buf_set_option(BUFFER_2, 'filetype', 'xml')
]]
+
+ -- Sanity check to ensure that some values are set after setting filetype.
eq('v:lua.require\'man\'.goto_tag', get_buf_option("tagfunc", "BUFFER_1"))
eq('xmlcomplete#CompleteTags', get_buf_option("omnifunc", "BUFFER_2"))
eq('xmlformat#Format()', get_buf_option("formatexpr", "BUFFER_2"))
- end;
- on_init = function(_client)
- client = _client
- exec_lua("lsp.buf_attach_client(BUFFER_1, TEST_RPC_CLIENT_ID)")
- exec_lua("lsp.buf_attach_client(BUFFER_2, TEST_RPC_CLIENT_ID)")
+
+ exec_lua [[
+ lsp.buf_attach_client(BUFFER_1, TEST_RPC_CLIENT_ID)
+ lsp.buf_attach_client(BUFFER_2, TEST_RPC_CLIENT_ID)
+ ]]
end;
on_handler = function(_, _, ctx)
if ctx.method == 'test' then
@@ -389,18 +390,16 @@ describe('LSP', function()
local client
test_rpc_server {
test_name = "set_defaults_all_capabilities";
- on_setup = function()
+ on_init = function(_client)
+ client = _client
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_option(BUFFER, 'tagfunc', 'tfu')
vim.api.nvim_buf_set_option(BUFFER, 'omnifunc', 'ofu')
vim.api.nvim_buf_set_option(BUFFER, 'formatexpr', 'fex')
+ lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
]]
end;
- on_init = function(_client)
- client = _client
- exec_lua("lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)")
- end;
on_handler = function(_, _, ctx)
if ctx.method == 'test' then
eq('tfu', get_buf_option("tagfunc"))
diff --git a/test/functional/shada/merging_spec.lua b/test/functional/shada/merging_spec.lua
index da2fbbe029..dad7aa851d 100644
--- a/test/functional/shada/merging_spec.lua
+++ b/test/functional/shada/merging_spec.lua
@@ -1115,5 +1115,3 @@ describe('ShaDa changes support code', function()
eq(found, 100)
end)
end)
-
--- vim: ts=2 sw=2
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index f88954c16b..3203b187cc 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -432,6 +432,25 @@ describe('float window', function()
assert_alive()
end)
+ it("should re-apply 'style' when present", function()
+ local float_opts = {style = 'minimal', relative = 'editor', row = 1, col = 1, width = 1, height = 1}
+ local float_win = meths.open_win(0, true, float_opts)
+ meths.win_set_option(float_win, 'number', true)
+ float_opts.row = 2
+ meths.win_set_config(float_win, float_opts)
+ eq(false, meths.win_get_option(float_win, 'number'))
+ end)
+
+ it("should not re-apply 'style' when missing", function()
+ local float_opts = {style = 'minimal', relative = 'editor', row = 1, col = 1, width = 1, height = 1}
+ local float_win = meths.open_win(0, true, float_opts)
+ meths.win_set_option(float_win, 'number', true)
+ float_opts.row = 2
+ float_opts.style = nil
+ meths.win_set_config(float_win, float_opts)
+ eq(true, meths.win_get_option(float_win, 'number'))
+ end)
+
it("'scroll' is computed correctly when opening float with splitkeep=screen #20684", function()
meths.set_option('splitkeep', 'screen')
local float_opts = {relative = 'editor', row = 1, col = 1, width = 10, height = 10}
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index fedfaca7ba..89b503141b 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -1411,10 +1411,10 @@ describe('ColorColumn highlight', function()
[3] = {foreground = Screen.colors.Brown}, -- LineNr
[4] = {foreground = Screen.colors.Brown, bold = true}, -- CursorLineNr
[5] = {foreground = Screen.colors.Blue, bold = true}, -- NonText
- -- NonText and ColorColumn
[6] = {foreground = Screen.colors.Blue, background = Screen.colors.LightRed, bold = true},
[7] = {reverse = true, bold = true}, -- StatusLine
[8] = {reverse = true}, -- StatusLineNC
+ [9] = {background = Screen.colors.Grey90, foreground = Screen.colors.Red},
})
screen:attach()
end)
@@ -1500,6 +1500,25 @@ describe('ColorColumn highlight', function()
|
]])
end)
+
+ it('is combined with low-priority CursorLine highlight #23016', function()
+ screen:try_resize(40, 2)
+ command('set colorcolumn=30 cursorline')
+ screen:expect([[
+ {2:^ }{1: }{2: }|
+ |
+ ]])
+ command('hi clear ColorColumn')
+ screen:expect([[
+ {2:^ }|
+ |
+ ]])
+ command('hi ColorColumn guifg=Red')
+ screen:expect([[
+ {2:^ }{9: }{2: }|
+ |
+ ]])
+ end)
end)
describe("MsgSeparator highlight and msgsep fillchar", function()
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index 5220f3fa89..1a7fe26d26 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -22,6 +22,7 @@ local skip = helpers.skip
describe('ui/ext_messages', function()
local screen
+ local fname = 'Xtest_functional_ui_messages_spec'
before_each(function()
clear()
@@ -41,7 +42,7 @@ describe('ui/ext_messages', function()
})
end)
after_each(function()
- os.remove('Xtest')
+ os.remove(fname)
end)
it('msg_clear follows msg_show kind of confirm', function()
@@ -126,7 +127,7 @@ describe('ui/ext_messages', function()
feed('nq')
-- kind=wmsg (editing readonly file)
- command('write Xtest')
+ command('write ' .. fname)
command('set readonly nohls')
feed('G$x')
screen:expect{grid=[[
@@ -912,9 +913,9 @@ stack traceback:
end)
it('does not truncate messages', function()
- command('write Xtest')
+ command('write '.. fname)
screen:expect({messages={
- {content = { { '"Xtest" [New] 0L, 0B written' } }, kind = "" }
+ {content = { { string.format('"%s" [New] 0L, 0B written', fname) } }, kind = "" }
}})
end)
end)
diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua
index 0a253455ad..a2fe875e65 100644
--- a/test/functional/ui/statuscolumn_spec.lua
+++ b/test/functional/ui/statuscolumn_spec.lua
@@ -397,6 +397,29 @@ describe('statuscolumn', function()
{0:~ }|
|
]])
+ -- Also test virt_lines when 'cpoptions' includes "n"
+ exec_lua([[
+ vim.opt.cpoptions:append("n")
+ local ns = vim.api.nvim_create_namespace("ns")
+ vim.api.nvim_buf_set_extmark(0, ns, 14, 0, { virt_lines = {{{"virt_line1", ""}}} })
+ vim.api.nvim_buf_set_extmark(0, ns, 14, 0, { virt_lines = {{{"virt_line2", ""}}} })
+ ]])
+ screen:expect([[
+ {1:buffer 0 13}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaa |
+ {1:buffer 0 14}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaa |
+ {1:buffer 0 15}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaa |
+ {1:virtual-2 15}virt_line1 |
+ {1:virtual-2 15}virt_line2 |
+ {1:buffer 0 16}{5:^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {5:aaaaaaaaa }|
+ {1:virtual-1 16}END |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
end)
it("works with 'statuscolumn' clicks", function()
@@ -593,4 +616,17 @@ describe('statuscolumn', function()
|
]])
end)
+
+ it("is only evaluated twice, once to estimate and once to draw", function()
+ command([[
+ let g:stcnr = 0
+ func! Stc()
+ let g:stcnr += 1
+ return '12345'
+ endfunc
+ set stc=%!Stc()
+ norm ggdG
+ ]])
+ eq(2, eval('g:stcnr'))
+ end)
end)
diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua
index ece27ec3ff..970f9c3d76 100644
--- a/test/functional/ui/winbar_spec.lua
+++ b/test/functional/ui/winbar_spec.lua
@@ -114,6 +114,41 @@ describe('winbar', function()
{2:[No Name] [No Name] }|
|
]])
+ -- 'showcmdloc' "statusline" should not interfere with winbar redrawing #23030
+ command('set showcmd showcmdloc=statusline')
+ feed('<C-W>w')
+ feed('<C-W>')
+ screen:expect([[
+ {6:Set Up The Bars }│{6:Set Up The Bars }|
+ │ |
+ {3:~ }│{3:~ }|
+ {3:~ }│{2:[No Name] }|
+ {3:~ }│{5:Set Up The Bars }|
+ {3:~ }│^ |
+ {3:~ }│{3:~ }|
+ {3:~ }│{4:[No Name] ^W }|
+ {3:~ }│{6:Set Up The Bars }|
+ {3:~ }│ |
+ {3:~ }│{3:~ }|
+ {2:[No Name] [No Name] }|
+ |
+ ]])
+ feed('w<C-W>W')
+ screen:expect([[
+ {6:Set Up The Bars }│{6:Set Up The Bars }|
+ │ |
+ {3:~ }│{3:~ }|
+ {3:~ }│{2:[No Name] }|
+ {3:~ }│{5:Set Up The Bars }|
+ {3:~ }│^ |
+ {3:~ }│{3:~ }|
+ {3:~ }│{4:[No Name] }|
+ {3:~ }│{6:Set Up The Bars }|
+ {3:~ }│ |
+ {3:~ }│{3:~ }|
+ {2:[No Name] [No Name] }|
+ |
+ ]])
end)
it('works when switching value of \'winbar\'', function()
diff --git a/test/functional/vimscript/eval_spec.lua b/test/functional/vimscript/eval_spec.lua
index b995aaa5a6..b411b1e379 100644
--- a/test/functional/vimscript/eval_spec.lua
+++ b/test/functional/vimscript/eval_spec.lua
@@ -220,3 +220,38 @@ describe('listing functions using :function', function()
assert_alive()
end)
end)
+
+it('no double-free in garbage collection #16287', function()
+ clear()
+ -- Don't use exec() here as using a named script reproduces the issue better.
+ write_file('Xgarbagecollect.vim', [[
+ func Foo() abort
+ let s:args = [a:000]
+ let foo0 = ""
+ let foo1 = ""
+ let foo2 = ""
+ let foo3 = ""
+ let foo4 = ""
+ let foo5 = ""
+ let foo6 = ""
+ let foo7 = ""
+ let foo8 = ""
+ let foo9 = ""
+ let foo10 = ""
+ let foo11 = ""
+ let foo12 = ""
+ let foo13 = ""
+ let foo14 = ""
+ endfunc
+
+ set updatetime=1
+ call Foo()
+ call Foo()
+ ]])
+ finally(function()
+ os.remove('Xgarbagecollect.vim')
+ end)
+ command('source Xgarbagecollect.vim')
+ sleep(10)
+ assert_alive()
+end)
diff --git a/test/functional/vimscript/system_spec.lua b/test/functional/vimscript/system_spec.lua
index 158dfe86d7..130d5d81fa 100644
--- a/test/functional/vimscript/system_spec.lua
+++ b/test/functional/vimscript/system_spec.lua
@@ -393,7 +393,7 @@ describe('system()', function()
end)
describe('with output containing NULs', function()
- local fname = 'Xtest'
+ local fname = 'Xtest_functional_vimscript_system_nuls'
before_each(create_file_with_nuls(fname))
after_each(delete_file(fname))
@@ -549,7 +549,7 @@ describe('systemlist()', function()
end)
describe('with output containing NULs', function()
- local fname = 'Xtest'
+ local fname = 'Xtest_functional_vimscript_systemlist_nuls'
before_each(function()
command('set ff=unix')
diff --git a/test/helpers.lua b/test/helpers.lua
index 94dcf86c4d..8f06311a3c 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -3,7 +3,6 @@ local shared = vim
local assert = require('luassert')
local busted = require('busted')
local luv = require('luv')
-local relpath = require('pl.path').relpath
local Paths = require('test.cmakeconfig.paths')
assert:set_parameter('TableFormatLevel', 100)
@@ -21,6 +20,16 @@ local module = {
REMOVE_THIS = {},
}
+--- @param p string
+--- @return string
+local function relpath(p)
+ p = vim.fs.normalize(p)
+ local cwd = luv.cwd()
+ return p:gsub("^" .. cwd)
+end
+
+--- @param path string
+--- @return boolean
function module.isdir(path)
if not path then
return false
@@ -32,6 +41,8 @@ function module.isdir(path)
return stat.type == 'directory'
end
+--- @param path string
+--- @return boolean
function module.isfile(path)
if not path then
return false
@@ -43,6 +54,7 @@ function module.isfile(path)
return stat.type == 'file'
end
+--- @return string
function module.argss_to_cmd(...)
local cmd = ''
for i = 1, select('#', ...) do
@@ -457,6 +469,7 @@ function module.check_cores(app, force) -- luacheck: ignore
end
end
+--- @return string?
function module.repeated_read_cmd(...)
for _ = 1, 10 do
local stream = module.popen_r(...)
@@ -556,6 +569,9 @@ function module.concat_tables(...)
return ret
end
+--- @param str string
+--- @param leave_indent? boolean
+--- @return string
function module.dedent(str, leave_indent)
-- find minimum common indent across lines
local indent = nil
diff --git a/test/old/testdir/test_alot.vim b/test/old/testdir/test_alot.vim
index a3d240f27e..4a22315b9f 100644
--- a/test/old/testdir/test_alot.vim
+++ b/test/old/testdir/test_alot.vim
@@ -2,7 +2,6 @@
" This makes testing go faster, since Vim doesn't need to restart.
source test_backup.vim
-source test_behave.vim
source test_compiler.vim
source test_ex_equal.vim
source test_ex_undo.vim
diff --git a/test/old/testdir/test_arglist.vim b/test/old/testdir/test_arglist.vim
index fb8b17cd16..de4e5e33d6 100644
--- a/test/old/testdir/test_arglist.vim
+++ b/test/old/testdir/test_arglist.vim
@@ -183,22 +183,25 @@ func Test_argument()
let save_columns = &columns
let &columns = 79
- exe 'args ' .. join(range(1, 81))
- call assert_equal(join([
- \ '',
- \ '[1] 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 ',
- \ '2 7 12 17 22 27 32 37 42 47 52 57 62 67 72 77 ',
- \ '3 8 13 18 23 28 33 38 43 48 53 58 63 68 73 78 ',
- \ '4 9 14 19 24 29 34 39 44 49 54 59 64 69 74 79 ',
- \ '5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 ',
- \ ], "\n"),
- \ execute('args'))
-
- " No trailing newline with one item per row.
- let long_arg = repeat('X', 81)
- exe 'args ' .. long_arg
- call assert_equal("\n[".long_arg.']', execute('args'))
- let &columns = save_columns
+ try
+ exe 'args ' .. join(range(1, 81))
+ call assert_equal(join([
+ \ '',
+ \ '[1] 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 ',
+ \ '2 7 12 17 22 27 32 37 42 47 52 57 62 67 72 77 ',
+ \ '3 8 13 18 23 28 33 38 43 48 53 58 63 68 73 78 ',
+ \ '4 9 14 19 24 29 34 39 44 49 54 59 64 69 74 79 ',
+ \ '5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 ',
+ \ ], "\n"),
+ \ execute('args'))
+
+ " No trailing newline with one item per row.
+ let long_arg = repeat('X', 81)
+ exe 'args ' .. long_arg
+ call assert_equal("\n[".long_arg.']', execute('args'))
+ finally
+ let &columns = save_columns
+ endtry
" Setting argument list should fail when the current buffer has unsaved
" changes
diff --git a/test/old/testdir/test_behave.vim b/test/old/testdir/test_behave.vim
deleted file mode 100644
index c26bfe7ce3..0000000000
--- a/test/old/testdir/test_behave.vim
+++ /dev/null
@@ -1,29 +0,0 @@
-" Test the :behave command
-
-func Test_behave()
- behave mswin
- call assert_equal('mouse,key', &selectmode)
- call assert_equal('popup', &mousemodel)
- call assert_equal('startsel,stopsel', &keymodel)
- call assert_equal('exclusive', &selection)
-
- behave xterm
- call assert_equal('', &selectmode)
- call assert_equal('extend', &mousemodel)
- call assert_equal('', &keymodel)
- call assert_equal('inclusive', &selection)
-
- set selection&
- set mousemodel&
- set keymodel&
- set selection&
-endfunc
-
-func Test_behave_completion()
- call feedkeys(":behave \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"behave mswin xterm', @:)
-endfunc
-
-func Test_behave_error()
- call assert_fails('behave x', 'E475:')
-endfunc
diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim
index 1dceb43e5d..74dd7bf3c4 100644
--- a/test/old/testdir/test_cmdline.vim
+++ b/test/old/testdir/test_cmdline.vim
@@ -453,10 +453,10 @@ func Test_getcompletion()
let l = getcompletion('blahblah', 'augroup')
call assert_equal([], l)
- let l = getcompletion('', 'behave')
- call assert_true(index(l, 'mswin') >= 0)
- let l = getcompletion('not', 'behave')
- call assert_equal([], l)
+ " let l = getcompletion('', 'behave')
+ " call assert_true(index(l, 'mswin') >= 0)
+ " let l = getcompletion('not', 'behave')
+ " call assert_equal([], l)
let l = getcompletion('', 'color')
call assert_true(index(l, 'default') >= 0)
@@ -2770,6 +2770,7 @@ endfunc
" :behave suboptions fuzzy completion
func Test_fuzzy_completion_behave()
+ throw 'Skipped: Nvim removed :behave'
set wildoptions&
call feedkeys(":behave xm\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"behave xm', @:)
@@ -3532,6 +3533,14 @@ endfunc
func Test_setcmdline()
func SetText(text, pos)
+ call assert_equal(0, setcmdline(v:_null_string))
+ call assert_equal('', getcmdline())
+ call assert_equal(1, getcmdpos())
+
+ call assert_equal(0, setcmdline(''[: -1]))
+ call assert_equal('', getcmdline())
+ call assert_equal(1, getcmdpos())
+
autocmd CmdlineChanged * let g:cmdtype = expand('<afile>')
call assert_equal(0, setcmdline(a:text))
call assert_equal(a:text, getcmdline())
diff --git a/test/old/testdir/test_expr.vim b/test/old/testdir/test_expr.vim
index 292a504df9..1810cf6741 100644
--- a/test/old/testdir/test_expr.vim
+++ b/test/old/testdir/test_expr.vim
@@ -39,6 +39,38 @@ func Test_version()
call assert_false(has('patch-9.9.1'))
endfunc
+func Test_op_trinary()
+ call assert_equal('yes', 1 ? 'yes' : 'no')
+ call assert_equal('no', 0 ? 'yes' : 'no')
+ call assert_equal('no', 'x' ? 'yes' : 'no')
+ call assert_equal('yes', '1x' ? 'yes' : 'no')
+
+ call assert_fails('echo [1] ? "yes" : "no"', 'E745:')
+ call assert_fails('echo {} ? "yes" : "no"', 'E728:')
+endfunc
+
+func Test_op_falsy()
+ call assert_equal(v:true, v:true ?? 456)
+ call assert_equal(123, 123 ?? 456)
+ call assert_equal('yes', 'yes' ?? 456)
+ call assert_equal(0z00, 0z00 ?? 456)
+ call assert_equal([1], [1] ?? 456)
+ call assert_equal(#{one: 1}, #{one: 1} ?? 456)
+ if has('float')
+ call assert_equal(0.1, 0.1 ?? 456)
+ endif
+
+ call assert_equal(456, v:false ?? 456)
+ call assert_equal(456, 0 ?? 456)
+ call assert_equal(456, '' ?? 456)
+ call assert_equal(456, 0z ?? 456)
+ call assert_equal(456, [] ?? 456)
+ call assert_equal(456, {} ?? 456)
+ if has('float')
+ call assert_equal(456, 0.0 ?? 456)
+ endif
+endfunc
+
func Test_dict()
let d = {'': 'empty', 'a': 'a', 0: 'zero'}
call assert_equal('empty', d[''])
diff --git a/test/old/testdir/test_help_tagjump.vim b/test/old/testdir/test_help_tagjump.vim
index eae1a241e3..8a58d2f13c 100644
--- a/test/old/testdir/test_help_tagjump.vim
+++ b/test/old/testdir/test_help_tagjump.vim
@@ -35,9 +35,7 @@ func Test_help_tagjump()
help ??
call assert_equal("help", &filetype)
- " *??* tag needs patch 8.2.1794
- " call assert_true(getline('.') =~ '\*??\*')
- call assert_true(getline('.') =~ '\*g??\*')
+ call assert_true(getline('.') =~ '\*??\*')
helpclose
help :?
diff --git a/test/old/testdir/test_let.vim b/test/old/testdir/test_let.vim
index 35745e9c6a..fe7633cf11 100644
--- a/test/old/testdir/test_let.vim
+++ b/test/old/testdir/test_let.vim
@@ -327,7 +327,7 @@ func Test_let_heredoc_fails()
endfunc
END
call writefile(text, 'XheredocFail')
- call assert_fails('source XheredocFail', 'E126:')
+ call assert_fails('source XheredocFail', 'E1145:')
call delete('XheredocFail')
let text =<< trim CodeEnd
@@ -336,7 +336,7 @@ func Test_let_heredoc_fails()
endfunc
CodeEnd
call writefile(text, 'XheredocWrong')
- call assert_fails('source XheredocWrong', 'E126:')
+ call assert_fails('source XheredocWrong', 'E1145:')
call delete('XheredocWrong')
let text =<< trim TEXTend
diff --git a/test/old/testdir/test_prompt_buffer.vim b/test/old/testdir/test_prompt_buffer.vim
index 43d8bb4789..3dfbbcece6 100644
--- a/test/old/testdir/test_prompt_buffer.vim
+++ b/test/old/testdir/test_prompt_buffer.vim
@@ -271,6 +271,7 @@ func Test_prompt_appending_while_hidden()
func DoAppend()
call appendbufline('prompt', '$', 'Test')
+ return ''
endfunc
END
call writefile(script, 'XpromptBuffer', 'D')
@@ -282,12 +283,18 @@ func Test_prompt_appending_while_hidden()
call TermWait(buf)
call term_sendkeys(buf, "exit\<CR>")
- call TermWait(buf)
+ call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))})
call term_sendkeys(buf, ":call DoAppend()\<CR>")
- call TermWait(buf)
- call assert_notmatch('-- INSERT --', term_getline(buf, 10))
+ call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, "i")
+ call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))})
+ call term_sendkeys(buf, "\<C-R>=DoAppend()\<CR>")
+ call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf)
endfunc
diff --git a/test/old/testdir/test_usercommands.vim b/test/old/testdir/test_usercommands.vim
index 898f7a59f1..e22f57b6f1 100644
--- a/test/old/testdir/test_usercommands.vim
+++ b/test/old/testdir/test_usercommands.vim
@@ -303,7 +303,7 @@ func Test_CmdErrors()
call assert_fails('com! -complete=xxx DoCmd :', 'E180:')
call assert_fails('com! -complete=custom DoCmd :', 'E467:')
call assert_fails('com! -complete=customlist DoCmd :', 'E467:')
- call assert_fails('com! -complete=behave,CustomComplete DoCmd :', 'E468:')
+ " call assert_fails('com! -complete=behave,CustomComplete DoCmd :', 'E468:')
call assert_fails('com! -complete=file DoCmd :', 'E1208:')
call assert_fails('com! -nargs=0 -complete=file DoCmd :', 'E1208:')
call assert_fails('com! -nargs=x DoCmd :', 'E176:')
@@ -391,9 +391,9 @@ func Test_CmdCompletion()
call feedkeys(":com DoC\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"com DoC', @:)
- com! -nargs=1 -complete=behave DoCmd :
- call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"DoCmd mswin xterm', @:)
+ " com! -nargs=1 -complete=behave DoCmd :
+ " call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
+ " call assert_equal('"DoCmd mswin xterm', @:)
" Test for file name completion
com! -nargs=1 -complete=file DoCmd :
diff --git a/test/old/testdir/test_vimscript.vim b/test/old/testdir/test_vimscript.vim
index b0c4baf7c2..5988d6ed71 100644
--- a/test/old/testdir/test_vimscript.vim
+++ b/test/old/testdir/test_vimscript.vim
@@ -6746,7 +6746,7 @@ func Test_script_lines()
\ ])
call assert_report("Shouldn't be able to define function")
catch
- call assert_exception('Vim(function):E126: Missing :endfunction')
+ call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
endtry
" :change
@@ -6766,7 +6766,7 @@ func Test_script_lines()
\ ])
call assert_report("Shouldn't be able to define function")
catch
- call assert_exception('Vim(function):E126: Missing :endfunction')
+ call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
endtry
" :insert
@@ -6786,7 +6786,7 @@ func Test_script_lines()
\ ])
call assert_report("Shouldn't be able to define function")
catch
- call assert_exception('Vim(function):E126: Missing :endfunction')
+ call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
endtry
endfunc
@@ -7258,6 +7258,30 @@ func Test_typed_script_var()
call StopVimInTerminal(buf)
endfunc
+" Test for issue6776 {{{1
+func Test_trinary_expression()
+ try
+ call eval('0 ? 0')
+ catch
+ endtry
+ " previous failure should not cause next expression to fail
+ call assert_equal(v:false, eval(string(v:false)))
+
+ try
+ call eval('0 ? "burp')
+ catch
+ endtry
+ " previous failure should not cause next expression to fail
+ call assert_equal(v:false, eval(string(v:false)))
+
+ try
+ call eval('1 ? 0 : "burp')
+ catch
+ endtry
+ " previous failure should not cause next expression to fail
+ call assert_equal(v:false, eval(string(v:false)))
+endfunction
+
func Test_for_over_string()
let res = ''
for c in 'aéc̀d'
diff --git a/test/old/testdir/test_visual.vim b/test/old/testdir/test_visual.vim
index 350c69fe4e..d10a946200 100644
--- a/test/old/testdir/test_visual.vim
+++ b/test/old/testdir/test_visual.vim
@@ -485,14 +485,16 @@ endfunc
func Test_visual_block_put_invalid()
enew!
- behave mswin
+ " behave mswin
+ set selection=exclusive
norm yy
norm v)Ps/^/
" this was causing the column to become negative
silent norm ggv)P
bwipe!
- behave xterm
+ " behave xterm
+ set selection&
endfunc
" Visual modes (v V CTRL-V) followed by an operator; count; repeating
diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/helpers.lua
index 9dd6b76de2..883f01bd84 100644
--- a/test/unit/eval/helpers.lua
+++ b/test/unit/eval/helpers.lua
@@ -512,7 +512,8 @@ end
local function eval0(expr)
local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}),
eval.tv_clear)
- if eval.eval0(to_cstr(expr), tv, nil, true) == 0 then
+ local evalarg = ffi.new('evalarg_T', {eval_flags = eval.EVAL_EVALUATE})
+ if eval.eval0(to_cstr(expr), tv, nil, evalarg) == 0 then
return nil
else
return tv
diff --git a/test/unit/formatc.lua b/test/unit/formatc.lua
index 2fd37c599a..c94f0d88f7 100644
--- a/test/unit/formatc.lua
+++ b/test/unit/formatc.lua
@@ -154,6 +154,8 @@ local C_keywords = set { -- luacheck: ignore
--
-- The first one will have a lot of false positives (the line '{' for
-- example), the second one is more unique.
+--- @param string
+--- @return string
local function formatc(str)
local toks = TokeniseC(str)
local result = {}
diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua
index 708929ad9f..10b7594a88 100644
--- a/test/unit/helpers.lua
+++ b/test/unit/helpers.lua
@@ -14,20 +14,15 @@ local map = global_helpers.tbl_map
local eq = global_helpers.eq
local trim = global_helpers.trim
--- C constants.
-local NULL = ffi.cast('void*', 0)
-
-local OK = 1
-local FAIL = 0
-
-local cimport
-
-- add some standard header locations
for _, p in ipairs(Paths.include_paths) do
Preprocess.add_to_include_path(p)
end
-local child_pid = nil
+local child_pid = nil --- @type integer
+--- @generic F: function
+--- @param func F
+--- @return F
local function only_separate(func)
return function(...)
if child_pid ~= 0 then
@@ -36,9 +31,20 @@ local function only_separate(func)
return func(...)
end
end
-local child_calls_init = {}
-local child_calls_mod = nil
-local child_calls_mod_once = nil
+
+--- @class ChildCall
+--- @field func function
+--- @field args any[]
+
+--- @class ChildCallLog
+--- @field func string
+--- @field args any[]
+--- @field ret any?
+
+local child_calls_init = {} --- @type ChildCall[]
+local child_calls_mod = nil --- @type ChildCall[]
+local child_calls_mod_once = nil --- @type ChildCall[]?
+
local function child_call(func, ret)
return function(...)
local child_calls = child_calls_mod or child_calls_init
@@ -53,16 +59,16 @@ end
-- Run some code at the start of the child process, before running the test
-- itself. Is supposed to be run in `before_each`.
+--- @param func function
local function child_call_once(func, ...)
if child_pid ~= 0 then
- child_calls_mod_once[#child_calls_mod_once + 1] = {
- func=func, args={...}}
+ child_calls_mod_once[#child_calls_mod_once + 1] = { func = func, args = {...} }
else
func(...)
end
end
-local child_cleanups_mod_once = nil
+local child_cleanups_mod_once = nil --- @type ChildCall[]?
-- Run some code at the end of the child process, before exiting. Is supposed to
-- be run in `before_each` because `after_each` is run after child has exited.
@@ -125,8 +131,9 @@ local pragma_pack_id = 1
-- some things are just too complex for the LuaJIT C parser to digest. We
-- usually don't need them anyway.
+--- @param body string
local function filter_complex_blocks(body)
- local result = {}
+ local result = {} --- @type string[]
for line in body:gmatch("[^\r\n]+") do
if not (string.find(line, "(^)", 1, true) ~= nil
@@ -153,18 +160,20 @@ typedef struct { char bytes[16]; } __attribute__((aligned(16))) __uint128_t;
typedef struct { char bytes[16]; } __attribute__((aligned(16))) __float128;
]]
-local preprocess_cache_init = {}
+local preprocess_cache_init = {} --- @type table<string,string>
local previous_defines_mod = ''
-local preprocess_cache_mod = nil
+local preprocess_cache_mod = nil --- @type table<string,string>
local function is_child_cdefs()
- return (os.getenv('NVIM_TEST_MAIN_CDEFS') ~= '1')
+ return os.getenv('NVIM_TEST_MAIN_CDEFS') ~= '1'
end
-- use this helper to import C files, you can pass multiple paths at once,
-- this helper will return the C namespace of the nvim library.
-cimport = function(...)
- local previous_defines, preprocess_cache, cdefs
+local function cimport(...)
+ local previous_defines --- @type string
+ local preprocess_cache --- @type table<string,string>
+ local cdefs
if is_child_cdefs() and preprocess_cache_mod then
preprocess_cache = preprocess_cache_mod
previous_defines = previous_defines_mod
@@ -180,7 +189,7 @@ cimport = function(...)
path = './' .. path
end
if not preprocess_cache[path] then
- local body
+ local body --- @type string
body, previous_defines = Preprocess.preprocess(previous_defines, path)
-- format it (so that the lines are "unique" statements), also filter out
-- Objective-C blocks
@@ -202,6 +211,7 @@ cimport = function(...)
-- (they are needed in the right order with the struct definitions,
-- otherwise luajit has wrong memory layouts for the sturcts)
if line:match("#pragma%s+pack") then
+ --- @type string
line = line .. " // " .. pragma_pack_id
pragma_pack_id = pragma_pack_id + 1
end
@@ -229,20 +239,21 @@ cimport = function(...)
return lib
end
-local cimport_immediate = function(...)
+local function cimport_immediate(...)
local saved_pid = child_pid
child_pid = 0
local err, emsg = pcall(cimport, ...)
child_pid = saved_pid
if not err then
- emsg = tostring(emsg)
- io.stderr:write(emsg .. '\n')
+ io.stderr:write(tostring(emsg) .. '\n')
assert(false)
else
return lib
end
end
+--- @param preprocess_cache table<string,string[]>
+--- @param path string
local function _cimportstr(preprocess_cache, path)
if imported:contains(path) then
return lib
@@ -265,12 +276,14 @@ end
local function alloc_log_new()
local log = {
- log={},
- lib=cimport('./src/nvim/memory.h'),
- original_functions={},
+ log={}, --- @type ChildCallLog[]
+ lib=cimport('./src/nvim/memory.h'), --- @type table<string,function>
+ original_functions={}, --- @type table<string,function>
null={['\0:is_null']=true},
}
+
local allocator_functions = {'malloc', 'free', 'calloc', 'realloc'}
+
function log:save_original_functions()
for _, funcname in ipairs(allocator_functions) do
if not self.original_functions[funcname] then
@@ -278,13 +291,16 @@ local function alloc_log_new()
end
end
end
+
log.save_original_functions = child_call(log.save_original_functions)
+
function log:set_mocks()
for _, k in ipairs(allocator_functions) do
do
local kk = k
self.lib['mem_' .. k] = function(...)
- local log_entry = {func=kk, args={...}}
+ --- @type ChildCallLog
+ local log_entry = { func = kk, args = {...} }
self.log[#self.log + 1] = log_entry
if kk == 'free' then
self.original_functions[kk](...)
@@ -305,17 +321,21 @@ local function alloc_log_new()
end
end
end
+
log.set_mocks = child_call(log.set_mocks)
+
function log:clear()
self.log = {}
end
+
function log:check(exp)
eq(exp, self.log)
self:clear()
end
+
function log:clear_tmp_allocs(clear_null_frees)
- local toremove = {}
- local allocs = {}
+ local toremove = {} --- @type integer[]
+ local allocs = {} --- @type table<string,integer>
for i, v in ipairs(self.log) do
if v.func == 'malloc' or v.func == 'calloc' then
allocs[tostring(v.ret)] = i
@@ -338,26 +358,20 @@ local function alloc_log_new()
table.remove(self.log, toremove[i])
end
end
- function log:restore_original_functions()
- -- Do nothing: set mocks live in a separate process
- return
- --[[
- [ for k, v in pairs(self.original_functions) do
- [ self.lib['mem_' .. k] = v
- [ end
- ]]
- end
+
function log:setup()
log:save_original_functions()
log:set_mocks()
end
+
function log:before_each()
- return
end
+
function log:after_each()
- log:restore_original_functions()
end
+
log:setup()
+
return log
end
@@ -374,98 +388,109 @@ local function to_cstr(string)
end
cimport_immediate('./test/unit/fixtures/posix.h')
-local sc = {
- fork = function()
- return tonumber(ffi.C.fork())
- end,
- pipe = function()
- local ret = ffi.new('int[2]', {-1, -1})
- ffi.errno(0)
- local res = ffi.C.pipe(ret)
- if (res ~= 0) then
+
+local sc = {}
+
+function sc.fork()
+ return tonumber(ffi.C.fork())
+end
+
+function sc.pipe()
+ local ret = ffi.new('int[2]', {-1, -1})
+ ffi.errno(0)
+ local res = ffi.C.pipe(ret)
+ if (res ~= 0) then
+ local err = ffi.errno(0)
+ assert(res == 0, ("pipe() error: %u: %s"):format(
+ err, ffi.string(ffi.C.strerror(err))))
+ end
+ assert(ret[0] ~= -1 and ret[1] ~= -1)
+ return ret[0], ret[1]
+end
+
+--- @return string
+function sc.read(rd, len)
+ local ret = ffi.new('char[?]', len, {0})
+ local total_bytes_read = 0
+ ffi.errno(0)
+ while total_bytes_read < len do
+ local bytes_read = tonumber(ffi.C.read(
+ rd,
+ ffi.cast('void*', ret + total_bytes_read),
+ len - total_bytes_read))
+ if bytes_read == -1 then
local err = ffi.errno(0)
- assert(res == 0, ("pipe() error: %u: %s"):format(
- err, ffi.string(ffi.C.strerror(err))))
- end
- assert(ret[0] ~= -1 and ret[1] ~= -1)
- return ret[0], ret[1]
- end,
- read = function(rd, len)
- local ret = ffi.new('char[?]', len, {0})
- local total_bytes_read = 0
- ffi.errno(0)
- while total_bytes_read < len do
- local bytes_read = tonumber(ffi.C.read(
- rd,
- ffi.cast('void*', ret + total_bytes_read),
- len - total_bytes_read))
- if bytes_read == -1 then
- local err = ffi.errno(0)
- if err ~= ffi.C.kPOSIXErrnoEINTR then
- assert(false, ("read() error: %u: %s"):format(
- err, ffi.string(ffi.C.strerror(err))))
- end
- elseif bytes_read == 0 then
- break
- else
- total_bytes_read = total_bytes_read + bytes_read
+ if err ~= ffi.C.kPOSIXErrnoEINTR then
+ assert(false, ("read() error: %u: %s"):format(
+ err, ffi.string(ffi.C.strerror(err))))
end
+ elseif bytes_read == 0 then
+ break
+ else
+ total_bytes_read = total_bytes_read + bytes_read
end
- return ffi.string(ret, total_bytes_read)
- end,
- write = function(wr, s)
- local wbuf = to_cstr(s)
- local total_bytes_written = 0
- ffi.errno(0)
- while total_bytes_written < #s do
- local bytes_written = tonumber(ffi.C.write(
- wr,
- ffi.cast('void*', wbuf + total_bytes_written),
- #s - total_bytes_written))
- if bytes_written == -1 then
- local err = ffi.errno(0)
- if err ~= ffi.C.kPOSIXErrnoEINTR then
- assert(false, ("write() error: %u: %s ('%s')"):format(
- err, ffi.string(ffi.C.strerror(err)), s))
- end
- elseif bytes_written == 0 then
- break
- else
- total_bytes_written = total_bytes_written + bytes_written
+ end
+ return ffi.string(ret, total_bytes_read)
+end
+
+function sc.write(wr, s)
+ local wbuf = to_cstr(s)
+ local total_bytes_written = 0
+ ffi.errno(0)
+ while total_bytes_written < #s do
+ local bytes_written = tonumber(ffi.C.write(
+ wr,
+ ffi.cast('void*', wbuf + total_bytes_written),
+ #s - total_bytes_written))
+ if bytes_written == -1 then
+ local err = ffi.errno(0)
+ if err ~= ffi.C.kPOSIXErrnoEINTR then
+ assert(false, ("write() error: %u: %s ('%s')"):format(
+ err, ffi.string(ffi.C.strerror(err)), s))
end
+ elseif bytes_written == 0 then
+ break
+ else
+ total_bytes_written = total_bytes_written + bytes_written
end
- return total_bytes_written
- end,
- close = ffi.C.close,
- wait = function(pid)
- ffi.errno(0)
- local stat_loc = ffi.new('int[1]', {0})
- while true do
- local r = ffi.C.waitpid(pid, stat_loc, ffi.C.kPOSIXWaitWUNTRACED)
- if r == -1 then
- local err = ffi.errno(0)
- if err == ffi.C.kPOSIXErrnoECHILD then
- break
- elseif err ~= ffi.C.kPOSIXErrnoEINTR then
- assert(false, ("waitpid() error: %u: %s"):format(
- err, ffi.string(ffi.C.strerror(err))))
- end
- else
- assert(r == pid)
+ end
+ return total_bytes_written
+end
+
+sc.close = ffi.C.close
+
+--- @param pid integer
+--- @return integer
+function sc.wait(pid)
+ ffi.errno(0)
+ local stat_loc = ffi.new('int[1]', {0})
+ while true do
+ local r = ffi.C.waitpid(pid, stat_loc, ffi.C.kPOSIXWaitWUNTRACED)
+ if r == -1 then
+ local err = ffi.errno(0)
+ if err == ffi.C.kPOSIXErrnoECHILD then
+ break
+ elseif err ~= ffi.C.kPOSIXErrnoEINTR then
+ assert(false, ("waitpid() error: %u: %s"):format(
+ err, ffi.string(ffi.C.strerror(err))))
end
+ else
+ assert(r == pid)
end
- return stat_loc[0]
- end,
- exit = ffi.C._exit,
-}
+ end
+ return stat_loc[0]
+end
+
+sc.exit = ffi.C._exit
+--- @param lst string[]
+--- @return string
local function format_list(lst)
- local ret = ''
+ local ret = {} --- @type string[]
for _, v in ipairs(lst) do
- if ret ~= '' then ret = ret .. ', ' end
- ret = ret .. assert:format({v, n=1})[1]
+ ret[#ret+1] = assert:format({v, n=1})[1]
end
- return ret
+ return table.concat(ret, ', ')
end
if os.getenv('NVIM_TEST_PRINT_SYSCALLS') == '1' then
@@ -513,19 +538,26 @@ local tracehelp = dedent([[
]])
local function child_sethook(wr)
- local trace_level = os.getenv('NVIM_TEST_TRACE_LEVEL')
- if not trace_level or trace_level == '' then
- trace_level = 0
- else
- trace_level = tonumber(trace_level)
+ local trace_level_str = os.getenv('NVIM_TEST_TRACE_LEVEL')
+ local trace_level = 0
+ if trace_level_str and trace_level_str ~= '' then
+ --- @type number
+ trace_level = assert(tonumber(trace_level_str))
end
+
if trace_level <= 0 then
return
end
+
local trace_only_c = trace_level <= 1
+ --- @type debuginfo?, string?, integer
local prev_info, prev_reason, prev_lnum
+
+ --- @param reason string
+ --- @param lnum integer
+ --- @param use_prev boolean
local function hook(reason, lnum, use_prev)
- local info = nil
+ local info = nil --- @type debuginfo?
if use_prev then
info = prev_info
elseif reason ~= 'tail return' then -- tail return
@@ -533,6 +565,7 @@ local function child_sethook(wr)
end
if trace_only_c and (not info or info.what ~= 'C') and not use_prev then
+ --- @cast info -nil
if info.source:sub(-9) == '_spec.lua' then
prev_info = info
prev_reason = 'saved'
@@ -573,12 +606,8 @@ local function child_sethook(wr)
end
-- assert(-1 <= lnum and lnum <= 99999)
- local lnum_s
- if lnum == -1 then
- lnum_s = 'nknwn'
- else
- lnum_s = ('%u'):format(lnum)
- end
+ local lnum_s = lnum == -1 and 'nknwn' or ('%u'):format(lnum)
+ --- @type string
local msg = ( -- lua does not support %*
''
.. msgchar
@@ -600,6 +629,7 @@ end
local trace_end_msg = ('E%s\n'):format((' '):rep(hook_msglen - 2))
+--- @type function
local _debug_log
local debug_log = only_separate(function(...)
@@ -607,6 +637,7 @@ local debug_log = only_separate(function(...)
end)
local function itp_child(wr, func)
+ --- @param s string
_debug_log = function(s)
s = s:sub(1, hook_msglen - 2)
sc.write(wr, '>' .. s .. (' '):rep(hook_msglen - 2 - #s) .. '\n')
@@ -638,7 +669,7 @@ local function itp_child(wr, func)
end
local function check_child_err(rd)
- local trace = {}
+ local trace = {} --- @type string[]
local did_traceline = false
local maxtrace = tonumber(os.getenv('NVIM_TEST_MAXTRACE')) or 1024
while true do
@@ -668,11 +699,14 @@ local function check_child_err(rd)
local len = tonumber(len_s)
neq(0, len)
if os.getenv('NVIM_TEST_TRACE_ON_ERROR') == '1' and #trace ~= 0 then
+ --- @type string
err = '\nTest failed, trace:\n' .. tracehelp
for _, traceline in ipairs(trace) do
+ --- @type string
err = err .. traceline
end
end
+ --- @type string
err = err .. sc.read(rd, len + 1)
end
local eres = sc.read(rd, 2)
@@ -686,10 +720,12 @@ local function check_child_err(rd)
end
end
if not did_traceline then
+ --- @type string
err = err .. '\nNo end of trace occurred'
end
local cc_err, cc_emsg = pcall(check_cores, Paths.test_luajit_prg, true)
if not cc_err then
+ --- @type string
err = err .. '\ncheck_cores failed: ' .. cc_emsg
end
end
@@ -822,9 +858,9 @@ local module = {
lib = lib,
cstr = cstr,
to_cstr = to_cstr,
- NULL = NULL,
- OK = OK,
- FAIL = FAIL,
+ NULL = ffi.cast('void*', 0),
+ OK = 1,
+ FAIL = 0,
alloc_log_new = alloc_log_new,
gen_itp = gen_itp,
only_separate = only_separate,
diff --git a/test/unit/preprocess.lua b/test/unit/preprocess.lua
index 88f7a14d1f..c5fb62dce5 100644
--- a/test/unit/preprocess.lua
+++ b/test/unit/preprocess.lua
@@ -7,6 +7,9 @@ local global_helpers = require('test.helpers')
local argss_to_cmd = global_helpers.argss_to_cmd
local repeated_read_cmd = global_helpers.repeated_read_cmd
+--- @alias Compiler {path: string[], type: string}
+
+--- @type Compiler[]
local ccs = {}
local env_cc = os.getenv("CC")
@@ -27,6 +30,8 @@ table.insert(ccs, {path = {"/usr/bin/env", "clang"}, type = "clang"})
table.insert(ccs, {path = {"/usr/bin/env", "icc"}, type = "gcc"})
-- parse Makefile format dependencies into a Lua table
+--- @param deps string
+--- @return string[]
local function parse_make_deps(deps)
-- remove line breaks and line concatenators
deps = deps:gsub("\n", ""):gsub("\\", "")
@@ -36,7 +41,7 @@ local function parse_make_deps(deps)
deps = deps:gsub(" +", " ")
-- split according to token (space in this case)
- local headers = {}
+ local headers = {} --- @type string[]
for token in deps:gmatch("[^%s]+") do
-- headers[token] = true
headers[#headers + 1] = token
@@ -53,57 +58,58 @@ local function parse_make_deps(deps)
return headers
end
--- will produce a string that represents a meta C header file that includes
--- all the passed in headers. I.e.:
---
--- headerize({"stdio.h", "math.h"}, true)
--- produces:
--- #include <stdio.h>
--- #include <math.h>
---
--- headerize({"vim.h", "memory.h"}, false)
--- produces:
--- #include "vim.h"
--- #include "memory.h"
+--- will produce a string that represents a meta C header file that includes
+--- all the passed in headers. I.e.:
+---
+--- headerize({"stdio.h", "math.h"}, true)
+--- produces:
+--- #include <stdio.h>
+--- #include <math.h>
+---
+--- headerize({"vim.h", "memory.h"}, false)
+--- produces:
+--- #include "vim.h"
+--- #include "memory.h"
+--- @param headers string[]
+--- @param global? boolean
+--- @return string
local function headerize(headers, global)
- local pre = '"'
- local post = pre
- if global then
- pre = "<"
- post = ">"
- end
-
- local formatted = {}
+ local fmt = global and '#include <%s>' or '#include "%s"'
+ local formatted = {} --- @type string[]
for _, hdr in ipairs(headers) do
- formatted[#formatted + 1] = "#include " ..
- tostring(pre) ..
- tostring(hdr) ..
- tostring(post)
+ formatted[#formatted + 1] = string.format(fmt, hdr)
end
return table.concat(formatted, "\n")
end
+--- @class Gcc
+--- @field path string
+--- @field preprocessor_extra_flags string[]
+--- @field get_defines_extra_flags string[]
+--- @field get_declarations_extra_flags string[]
local Gcc = {
preprocessor_extra_flags = {},
get_defines_extra_flags = {'-std=c99', '-dM', '-E'},
get_declarations_extra_flags = {'-std=c99', '-P', '-E'},
}
+--- @param name string
+--- @param args string[]?
+--- @param val string?
function Gcc:define(name, args, val)
- local define = '-D' .. name
- if args ~= nil then
- define = define .. '(' .. table.concat(args, ',') .. ')'
+ local define = string.format('-D%s', name)
+ if args then
+ define = string.format('%s(%s)', define, table.concat(args, ','))
end
- if val ~= nil then
- define = define .. '=' .. val
+ if val then
+ define = string.format('%s=%s', define, val)
end
self.preprocessor_extra_flags[#self.preprocessor_extra_flags + 1] = define
end
function Gcc:undefine(name)
- self.preprocessor_extra_flags[#self.preprocessor_extra_flags + 1] = (
- '-U' .. name)
+ self.preprocessor_extra_flags[#self.preprocessor_extra_flags + 1] = '-U' .. name
end
function Gcc:init_defines()
@@ -128,6 +134,8 @@ function Gcc:init_defines()
self:undefine('__BLOCKS__')
end
+--- @param obj? Compiler
+--- @return Gcc
function Gcc:new(obj)
obj = obj or {}
setmetatable(obj, self)
@@ -136,6 +144,7 @@ function Gcc:new(obj)
return obj
end
+--- @param ... string
function Gcc:add_to_include_path(...)
for i = 1, select('#', ...) do
local path = select(i, ...)
@@ -145,110 +154,115 @@ function Gcc:add_to_include_path(...)
end
-- returns a list of the headers files upon which this file relies
+--- @param hdr string
+--- @return string[]?
function Gcc:dependencies(hdr)
+ --- @type string
local cmd = argss_to_cmd(self.path, {'-M', hdr}) .. ' 2>&1'
- local out = io.popen(cmd)
+ local out = assert(io.popen(cmd))
local deps = out:read("*a")
out:close()
if deps then
return parse_make_deps(deps)
- else
- return nil
end
end
+--- @param defines string
+--- @return string
function Gcc:filter_standard_defines(defines)
if not self.standard_defines then
local pseudoheader_fname = 'tmp_empty_pseudoheader.h'
- local pseudoheader_file = io.open(pseudoheader_fname, 'w')
+ local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
pseudoheader_file:close()
- local standard_defines = repeated_read_cmd(self.path,
- self.preprocessor_extra_flags,
- self.get_defines_extra_flags,
- {pseudoheader_fname})
+ local standard_defines = assert(repeated_read_cmd(self.path,
+ self.preprocessor_extra_flags,
+ self.get_defines_extra_flags,
+ {pseudoheader_fname}))
os.remove(pseudoheader_fname)
- self.standard_defines = {}
+ self.standard_defines = {} --- @type table<string,true>
for line in standard_defines:gmatch('[^\n]+') do
self.standard_defines[line] = true
end
end
- local ret = {}
+
+ local ret = {} --- @type string[]
for line in defines:gmatch('[^\n]+') do
if not self.standard_defines[line] then
ret[#ret + 1] = line
end
end
+
return table.concat(ret, "\n")
end
--- returns a stream representing a preprocessed form of the passed-in headers.
--- Don't forget to close the stream by calling the close() method on it.
+--- returns a stream representing a preprocessed form of the passed-in headers.
+--- Don't forget to close the stream by calling the close() method on it.
+--- @param previous_defines string
+--- @param ... string
+--- @return string, string
function Gcc:preprocess(previous_defines, ...)
-- create pseudo-header
local pseudoheader = headerize({...}, false)
local pseudoheader_fname = 'tmp_pseudoheader.h'
- local pseudoheader_file = io.open(pseudoheader_fname, 'w')
+ local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
pseudoheader_file:write(previous_defines)
pseudoheader_file:write("\n")
pseudoheader_file:write(pseudoheader)
pseudoheader_file:flush()
pseudoheader_file:close()
- local defines = repeated_read_cmd(self.path, self.preprocessor_extra_flags,
- self.get_defines_extra_flags,
- {pseudoheader_fname})
+ local defines = assert(repeated_read_cmd(self.path, self.preprocessor_extra_flags,
+ self.get_defines_extra_flags,
+ {pseudoheader_fname}))
defines = self:filter_standard_defines(defines)
- local declarations = repeated_read_cmd(self.path,
- self.preprocessor_extra_flags,
- self.get_declarations_extra_flags,
- {pseudoheader_fname})
+ local declarations = assert(repeated_read_cmd(self.path,
+ self.preprocessor_extra_flags,
+ self.get_declarations_extra_flags,
+ {pseudoheader_fname}))
os.remove(pseudoheader_fname)
- assert(declarations and defines)
return declarations, defines
end
-local Clang = Gcc:new()
-local Msvc = Gcc:new()
-
-local type_to_class = {
- ["gcc"] = Gcc,
- ["clang"] = Clang,
- ["msvc"] = Msvc
-}
-
-- find the best cc. If os.exec causes problems on windows (like popping up
-- a console window) we might consider using something like this:
-- http://scite-ru.googlecode.com/svn/trunk/pack/tools/LuaLib/shell.html#exec
+--- @param compilers Compiler[]
+--- @return Gcc?
local function find_best_cc(compilers)
for _, meta in pairs(compilers) do
- local version = io.popen(tostring(meta.path) .. " -v 2>&1")
+ local version = assert(io.popen(tostring(meta.path) .. " -v 2>&1"))
version:close()
if version then
- return type_to_class[meta.type]:new({path = meta.path})
+ return Gcc:new({path = meta.path})
end
end
- return nil
end
-- find the best cc. If os.exec causes problems on windows (like popping up
-- a console window) we might consider using something like this:
-- http://scite-ru.googlecode.com/svn/trunk/pack/tools/LuaLib/shell.html#exec
-local cc = nil
-if cc == nil then
- cc = find_best_cc(ccs)
-end
-
-return {
- includes = function(hdr)
- return cc:dependencies(hdr)
- end,
- preprocess = function(...)
- return cc:preprocess(...)
- end,
- add_to_include_path = function(...)
- return cc:add_to_include_path(...)
- end
-}
+local cc = assert(find_best_cc(ccs))
+
+local M = {}
+
+--- @param hdr string
+--- @return string[]?
+function M.includes(hdr)
+ return cc:dependencies(hdr)
+end
+
+--- @param ... string
+--- @return string, string
+function M.preprocess(...)
+ return cc:preprocess(...)
+end
+
+--- @param ... string
+function M.add_to_include_path(...)
+ return cc:add_to_include_path(...)
+end
+
+return M
diff --git a/test/unit/set.lua b/test/unit/set.lua
index f3d68c3042..91b7e2dd70 100644
--- a/test/unit/set.lua
+++ b/test/unit/set.lua
@@ -4,10 +4,15 @@
-- other:
-- 1) index => item
-- 2) item => index
+--- @class Set
+--- @field nelem integer
+--- @field items string[]
+--- @field tbl table
local Set = {}
+--- @param items? string[]
function Set:new(items)
- local obj = {}
+ local obj = {} --- @ type Set
setmetatable(obj, self)
self.__index = self
@@ -26,8 +31,9 @@ function Set:new(items)
return obj
end
+--- @return Set
function Set:copy()
- local obj = {}
+ local obj = {} --- @ type Set
obj.nelem = self.nelem
obj.tbl = {}
obj.items = {}
@@ -43,6 +49,7 @@ function Set:copy()
end
-- adds the argument Set to this Set
+--- @param other Set
function Set:union(other)
for e in other:iterator() do
self:add(e)
@@ -57,6 +64,7 @@ function Set:union_table(t)
end
-- subtracts the argument Set from this Set
+--- @param other Set
function Set:diff(other)
if other:size() > self:size() then
-- this set is smaller than the other set
@@ -75,6 +83,7 @@ function Set:diff(other)
end
end
+--- @param it string
function Set:add(it)
if not self:contains(it) then
local idx = #self.tbl + 1
@@ -84,6 +93,7 @@ function Set:add(it)
end
end
+--- @param it string
function Set:remove(it)
if self:contains(it) then
local idx = self.items[it]
@@ -93,10 +103,13 @@ function Set:remove(it)
end
end
+--- @param it string
+--- @return boolean
function Set:contains(it)
return self.items[it] or false
end
+--- @return integer
function Set:size()
return self.nelem
end
@@ -113,29 +126,18 @@ function Set:iterator()
return pairs(self.items)
end
+--- @return string[]
function Set:to_table()
-- there might be gaps in @tbl, so we have to be careful and sort first
- local keys
- do
- local _accum_0 = { }
- local _len_0 = 1
- for idx, _ in pairs(self.tbl) do
- _accum_0[_len_0] = idx
- _len_0 = _len_0 + 1
- end
- keys = _accum_0
+ local keys = {} --- @type string[]
+ for idx, _ in pairs(self.tbl) do
+ keys[#keys+1] = idx
end
+
table.sort(keys)
- local copy
- do
- local _accum_0 = { }
- local _len_0 = 1
- for _index_0 = 1, #keys do
- local idx = keys[_index_0]
- _accum_0[_len_0] = self.tbl[idx]
- _len_0 = _len_0 + 1
- end
- copy = _accum_0
+ local copy = {} --- @type string[]
+ for _, idx in ipairs(keys) do
+ copy[#copy+1] = self.tbl[idx]
end
return copy
end