diff --git a/test/functional/ex_cmds/trust_spec.lua b/test/functional/ex_cmds/trust_spec.lua index 5e4c428356..627d19b115 100644 --- a/test/functional/ex_cmds/trust_spec.lua +++ b/test/functional/ex_cmds/trust_spec.lua @@ -6,7 +6,6 @@ local clear = n.clear local command = n.command local exec_capture = n.exec_capture local matches = t.matches -local pathsep = n.get_pathsep() local is_os = t.is_os local fn = n.fn @@ -16,7 +15,7 @@ describe(':trust', function() local empty_file = 'Xtest_functional_ex_cmds_trust_empty' before_each(function() - n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim')) + n.mkdir_p(vim.fs.joinpath(xstate, is_os('win') and 'nvim-data' or 'nvim')) t.write_file(test_file, 'test') t.write_file(empty_file, '') clear { env = { XDG_STATE_HOME = xstate } } @@ -33,10 +32,22 @@ describe(':trust', function() return s:format(test_file) end + --- Joins path components using the OS-native separator. + --- Unlike vim.fs.joinpath (which normalizes to "/"), this preserves "\" on Windows + --- to match paths stored in the trust database. + local function osjoin(...) + return (table.concat({ ... }, n.get_pathsep())) + end + + local function assert_trust_entry(expected) + local trust = t.read_file(vim.fs.joinpath(fn.stdpath('state'), 'trust')) + eq(expected, vim.trim(trust)) + end + it('is not executed when inside false condition', function() command(fmt('edit %s')) eq('', exec_capture('if 0 | trust | endif')) - eq(nil, vim.uv.fs_stat(fn.stdpath('state') .. pathsep .. 'trust')) + eq(nil, vim.uv.fs_stat(vim.fs.joinpath(fn.stdpath('state'), 'trust'))) end) it('trust then deny then remove a file using current buffer', function() @@ -45,16 +56,13 @@ describe(':trust', function() command(fmt('edit %s')) matches(fmt('^Allowed in trust database%%: ".*%s"$'), exec_capture('trust')) - local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') - eq(string.format('%s %s', hash, cwd .. pathsep .. test_file), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, osjoin(cwd, test_file))) matches(fmt('^Denied in trust database%%: ".*%s"$'), exec_capture('trust ++deny')) - trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') - eq(string.format('! %s', cwd .. pathsep .. test_file), vim.trim(trust)) + assert_trust_entry(('! %s'):format(osjoin(cwd, test_file))) matches(fmt('^Removed from trust database%%: ".*%s"$'), exec_capture('trust ++remove')) - trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') - eq(string.format(''), vim.trim(trust)) + assert_trust_entry('') end) it('trust an empty file using current buffer', function() @@ -63,8 +71,7 @@ describe(':trust', function() command('edit ' .. empty_file) matches('^Allowed in trust database%: ".*' .. empty_file .. '"$', exec_capture('trust')) - local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') - eq(string.format('%s %s', hash, cwd .. pathsep .. empty_file), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, osjoin(cwd, empty_file))) end) it('deny then trust then remove a file using current buffer', function() @@ -73,27 +80,22 @@ describe(':trust', function() command(fmt('edit %s')) matches(fmt('^Denied in trust database%%: ".*%s"$'), exec_capture('trust ++deny')) - local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') - eq(string.format('! %s', cwd .. pathsep .. test_file), vim.trim(trust)) + assert_trust_entry(('! %s'):format(osjoin(cwd, test_file))) matches(fmt('^Allowed in trust database%%: ".*%s"$'), exec_capture('trust')) - trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') - eq(string.format('%s %s', hash, cwd .. pathsep .. test_file), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, osjoin(cwd, test_file))) matches(fmt('^Removed from trust database%%: ".*%s"$'), exec_capture('trust ++remove')) - trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') - eq(string.format(''), vim.trim(trust)) + assert_trust_entry('') end) it('deny then remove a file using file path', function() local cwd = fn.getcwd() matches(fmt('^Denied in trust database%%: ".*%s"$'), exec_capture(fmt('trust ++deny %s'))) - local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') - eq(string.format('! %s', cwd .. pathsep .. test_file), vim.trim(trust)) + assert_trust_entry(('! %s'):format(osjoin(cwd, test_file))) matches(fmt('^Removed from trust database%%: ".*%s"$'), exec_capture(fmt('trust ++remove %s'))) - trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') - eq(string.format(''), vim.trim(trust)) + assert_trust_entry('') end) end) diff --git a/test/functional/lua/secure_spec.lua b/test/functional/lua/secure_spec.lua index 94df31bf27..b8580d77a5 100644 --- a/test/functional/lua/secure_spec.lua +++ b/test/functional/lua/secure_spec.lua @@ -5,7 +5,6 @@ local Screen = require('test.functional.ui.screen') local eq = t.eq local clear = n.clear local command = n.command -local pathsep = n.get_pathsep() local is_os = t.is_os local api = n.api local exec_lua = n.exec_lua @@ -18,13 +17,25 @@ local matches = t.matches local read_file = t.read_file describe('vim.secure', function() + --- Joins path components using the OS-native separator. + --- Unlike vim.fs.joinpath (which normalizes to "/"), this preserves "\" on Windows + --- to match paths stored in the trust database. + local function osjoin(...) + return (table.concat({ ... }, n.get_pathsep())) + end + + local function assert_trust_entry(expected) + local trust = assert(read_file(vim.fs.joinpath(stdpath('state'), 'trust'))) + eq(expected, vim.trim(trust)) + end + describe('read()', function() local xstate = 'Xstate_lua_secure' local screen ---@type test.functional.ui.screen before_each(function() clear { env = { XDG_STATE_HOME = xstate } } - n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim')) + n.mkdir_p(vim.fs.joinpath(xstate, is_os('win') and 'nvim-data' or 'nvim')) t.mkdir('Xdir') t.mkdir('Xdir/Xsubdir') @@ -56,7 +67,7 @@ describe('vim.secure', function() local cwd = fn.getcwd() local msg = 'exrc: Found untrusted code. To enable it, choose (v)iew then run `:trust`:' - local path = ('%s%sXfile'):format(cwd, pathsep) + local path = osjoin(cwd, 'Xfile') -- Need to use feed_command instead of exec_lua because of the confirmation prompt feed_command([[lua vim.secure.read('Xfile')]]) @@ -76,11 +87,10 @@ describe('vim.secure', function() {MATCH: +}| ]]) - local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('! %s', cwd .. pathsep .. 'Xfile'), vim.trim(trust)) + assert_trust_entry(('! %s'):format(osjoin(cwd, 'Xfile'))) eq(vim.NIL, exec_lua([[return vim.secure.read('Xfile')]])) - os.remove(stdpath('state') .. pathsep .. 'trust') + os.remove(vim.fs.joinpath(stdpath('state'), 'trust')) feed_command([[lua vim.secure.read('Xfile')]]) screen:expect([[ @@ -97,21 +107,20 @@ describe('vim.secure', function() screen:expect([[ ^let g:foobar = 42{MATCH: +}| {1:~{MATCH: +}}|*2 - {2:]] .. fn.fnamemodify(cwd, ':~') .. pathsep .. [[Xfile [RO]{MATCH: +}}| + {2:]] .. osjoin(fn.fnamemodify(cwd, ':~'), 'Xfile') .. [[ [RO]{MATCH: +}}| {MATCH: +}| {1:~{MATCH: +}}| {4:[No Name]{MATCH: +}}| - Allowed in trust database: "]] .. cwd .. pathsep .. [[Xfile"{MATCH: +}| + Allowed in trust database: "]] .. osjoin(cwd, 'Xfile') .. [["{MATCH: +}| ]]) -- close the split for the next test below. feed(':q') local hash = fn.sha256(assert(read_file('Xfile'))) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('%s %s', hash, cwd .. pathsep .. 'Xfile'), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, osjoin(cwd, 'Xfile'))) eq('let g:foobar = 42\n', exec_lua([[return vim.secure.read('Xfile')]])) - os.remove(stdpath('state') .. pathsep .. 'trust') + os.remove(vim.fs.joinpath(stdpath('state'), 'trust')) feed_command([[lua vim.secure.read('Xfile')]]) screen:expect([[ @@ -131,7 +140,7 @@ describe('vim.secure', function() ]]) -- Trust database is not updated - eq(nil, read_file(stdpath('state') .. pathsep .. 'trust')) + eq(nil, read_file(vim.fs.joinpath(stdpath('state'), 'trust'))) feed_command([[lua vim.secure.read('Xfile')]]) screen:expect([[ @@ -147,7 +156,7 @@ describe('vim.secure', function() screen:expect([[ ^let g:foobar = 42{MATCH: +}| {1:~{MATCH: +}}|*2 - {2:]] .. fn.fnamemodify(cwd, ':~') .. pathsep .. [[Xfile [RO]{MATCH: +}}| + {2:]] .. osjoin(fn.fnamemodify(cwd, ':~'), 'Xfile') .. [[ [RO]{MATCH: +}}| {MATCH: +}| {1:~{MATCH: +}}| {4:[No Name]{MATCH: +}}| @@ -155,7 +164,7 @@ describe('vim.secure', function() ]]) -- Trust database is not updated - eq(nil, read_file(stdpath('state') .. pathsep .. 'trust')) + eq(nil, read_file(vim.fs.joinpath(stdpath('state'), 'trust'))) -- Cannot write file pcall_err(command, 'write') @@ -173,7 +182,7 @@ describe('vim.secure', function() local cwd = fn.getcwd() local msg = 'exrc: Found untrusted code. DIRECTORY trust is decided only by name, not contents:' - local path = ('%s%sXdir'):format(cwd, pathsep) + local path = osjoin(cwd, 'Xdir') -- Need to use feed_command instead of exec_lua because of the confirmation prompt feed_command([[lua vim.secure.read('Xdir')]]) @@ -193,11 +202,10 @@ describe('vim.secure', function() {MATCH: +}| ]]) - local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('! %s', cwd .. pathsep .. 'Xdir'), vim.trim(trust)) + assert_trust_entry(('! %s'):format(osjoin(cwd, 'Xdir'))) eq(vim.NIL, exec_lua([[return vim.secure.read('Xdir')]])) - os.remove(stdpath('state') .. pathsep .. 'trust') + os.remove(vim.fs.joinpath(stdpath('state'), 'trust')) feed_command([[lua vim.secure.read('Xdir')]]) screen:expect([[ @@ -218,12 +226,10 @@ describe('vim.secure', function() -- Directories aren't hashed in the trust database, instead a slug ("directory") is stored -- instead. - local expected_hash = 'directory' - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('%s %s', expected_hash, cwd .. pathsep .. 'Xdir'), vim.trim(trust)) + assert_trust_entry(('directory %s'):format(osjoin(cwd, 'Xdir'))) eq(true, exec_lua([[return vim.secure.read('Xdir')]])) - os.remove(stdpath('state') .. pathsep .. 'trust') + os.remove(vim.fs.joinpath(stdpath('state'), 'trust')) feed_command([[lua vim.secure.read('Xdir')]]) screen:expect([[ @@ -243,7 +249,7 @@ describe('vim.secure', function() ]]) -- Trust database is not updated - eq(nil, read_file(stdpath('state') .. pathsep .. 'trust')) + eq(nil, read_file(vim.fs.joinpath(stdpath('state'), 'trust'))) feed_command([[lua vim.secure.read('Xdir')]]) screen:expect([[ @@ -259,7 +265,7 @@ describe('vim.secure', function() screen:expect([[ ^{MATCH: +}| {1:~{MATCH: +}}|*2 - {2:]] .. fn.fnamemodify(cwd, ':~') .. pathsep .. [[Xdir [RO]{MATCH: +}}| + {2:]] .. osjoin(fn.fnamemodify(cwd, ':~'), 'Xdir') .. [[ [RO]{MATCH: +}}| {MATCH: +}| {1:~{MATCH: +}}| {4:[No Name]{MATCH: +}}| @@ -267,7 +273,7 @@ describe('vim.secure', function() ]]) -- Trust database is not updated - eq(nil, read_file(stdpath('state') .. pathsep .. 'trust')) + eq(nil, read_file(vim.fs.joinpath(stdpath('state'), 'trust'))) end) end) @@ -282,7 +288,7 @@ describe('vim.secure', function() end) before_each(function() - n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim')) + n.mkdir_p(vim.fs.joinpath(xstate, is_os('win') and 'nvim-data' or 'nvim')) t.write_file(test_file, 'test') t.write_file(empty_file, '') t.mkdir(test_dir) @@ -312,127 +318,111 @@ describe('vim.secure', function() it('trust then deny then remove a file using bufnr', function() local cwd = fn.getcwd() local hash = fn.sha256(assert(read_file(test_file))) - local full_path = cwd .. pathsep .. test_file + local full_path = osjoin(cwd, test_file) command('edit ' .. test_file) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('%s %s', hash, full_path), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, full_path)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]])) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('! %s', full_path), vim.trim(trust)) + assert_trust_entry(('! %s'):format(full_path)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]])) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq('', vim.trim(trust)) + assert_trust_entry('') end) it('trust an empty file using bufnr', function() local cwd = fn.getcwd() local hash = fn.sha256(assert(read_file(empty_file))) - local full_path = cwd .. pathsep .. empty_file + local full_path = osjoin(cwd, empty_file) command('edit ' .. empty_file) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('%s %s', hash, full_path), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, full_path)) end) it('deny then trust then remove a file using bufnr', function() local cwd = fn.getcwd() local hash = fn.sha256(assert(read_file(test_file))) - local full_path = cwd .. pathsep .. test_file + local full_path = osjoin(cwd, test_file) command('edit ' .. test_file) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]])) - local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('! %s', full_path), vim.trim(trust)) + assert_trust_entry(('! %s'):format(full_path)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('%s %s', hash, full_path), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, full_path)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]])) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq('', vim.trim(trust)) + assert_trust_entry('') end) it('trust using bufnr then deny then remove a file using path', function() local cwd = fn.getcwd() local hash = fn.sha256(assert(read_file(test_file))) - local full_path = cwd .. pathsep .. test_file + local full_path = osjoin(cwd, test_file) command('edit ' .. test_file) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('%s %s', hash, full_path), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, full_path)) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', path=...})}]], test_file) ) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('! %s', full_path), vim.trim(trust)) + assert_trust_entry(('! %s'):format(full_path)) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', path=...})}]], test_file) ) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq('', vim.trim(trust)) + assert_trust_entry('') end) it('trust then deny then remove a file using path', function() local cwd = fn.getcwd() local hash = fn.sha256(assert(read_file(test_file))) - local full_path = cwd .. pathsep .. test_file + local full_path = osjoin(cwd, test_file) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', path=...})}]], test_file) ) - local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('%s %s', hash, full_path), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, full_path)) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', path=...})}]], test_file) ) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('! %s', full_path), vim.trim(trust)) + assert_trust_entry(('! %s'):format(full_path)) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', path=...})}]], test_file) ) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq('', vim.trim(trust)) + assert_trust_entry('') end) it('deny then trust then remove a file using bufnr', function() local cwd = fn.getcwd() local hash = fn.sha256(assert(read_file(test_file))) - local full_path = cwd .. pathsep .. test_file + local full_path = osjoin(cwd, test_file) command('edit ' .. test_file) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', path=...})}]], test_file) ) - local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('! %s', full_path), vim.trim(trust)) + assert_trust_entry(('! %s'):format(full_path)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('%s %s', hash, full_path), vim.trim(trust)) + assert_trust_entry(('%s %s'):format(hash, full_path)) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', path=...})}]], test_file) ) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq('', vim.trim(trust)) + assert_trust_entry('') end) it('trust returns error when buffer not associated to file', function() @@ -445,20 +435,17 @@ describe('vim.secure', function() it('trust then deny then remove a directory using bufnr', function() local cwd = fn.getcwd() - local full_path = cwd .. pathsep .. test_dir + local full_path = osjoin(cwd, test_dir) command('edit ' .. test_dir) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('directory %s', full_path), vim.trim(trust)) + assert_trust_entry(('directory %s'):format(full_path)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]])) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq(string.format('! %s', full_path), vim.trim(trust)) + assert_trust_entry(('! %s'):format(full_path)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]])) - trust = assert(read_file(stdpath('state') .. pathsep .. 'trust')) - eq('', vim.trim(trust)) + assert_trust_entry('') end) end) end)