949fe00f6a
- Reject archive members that are absolute, escape via .., are special files or link outside the destination, before anything is written - Stage under the pack root so the swap is a same-filesystem rename, with an EXDEV copy fallback; propagate auth errors, validate dir_name
113 lines
3.1 KiB
Lua
113 lines
3.1 KiB
Lua
-- Minimal busted-flavoured harness: no rocks, no vendored plugins.
|
|
-- Run with: nvim --headless --clean -l tests/minimal.lua tests/*_spec.lua
|
|
local root = vim.fn.fnamemodify(debug.getinfo(1, 'S').source:sub(2), ':p:h:h')
|
|
vim.opt.runtimepath:prepend(root)
|
|
package.path = table.concat({ root .. '/lua/?.lua', root .. '/lua/?/init.lua', package.path }, ';')
|
|
|
|
local M = { passed = 0, failed = 0, failures = {} }
|
|
local stack = {}
|
|
|
|
local function describe(name, fn)
|
|
stack[#stack + 1] = name
|
|
fn()
|
|
stack[#stack] = nil
|
|
end
|
|
|
|
local function it(name, fn)
|
|
local label = table.concat(stack, ' ') .. ' ' .. name
|
|
local ok, err = pcall(fn)
|
|
if ok then
|
|
M.passed = M.passed + 1
|
|
io.write('ok ' .. label .. '\n')
|
|
else
|
|
M.failed = M.failed + 1
|
|
M.failures[#M.failures + 1] = label .. '\n ' .. tostring(err)
|
|
io.write('FAIL ' .. label .. '\n ' .. tostring(err) .. '\n')
|
|
end
|
|
end
|
|
|
|
local assert_eq = function(expected, got, msg)
|
|
if not vim.deep_equal(expected, got) then
|
|
error(
|
|
string.format('%sexpected %s, got %s', msg and (msg .. ': ') or '', vim.inspect(expected), vim.inspect(got)),
|
|
2
|
|
)
|
|
end
|
|
end
|
|
|
|
local assert_true = function(value, msg)
|
|
if not value then
|
|
error(msg or ('expected truthy, got ' .. vim.inspect(value)), 2)
|
|
end
|
|
end
|
|
|
|
local assert_nil = function(value, msg)
|
|
if value ~= nil then
|
|
error(msg or ('expected nil, got ' .. vim.inspect(value)), 2)
|
|
end
|
|
end
|
|
|
|
local assert_match = function(pattern, str, msg)
|
|
if type(str) ~= 'string' or not str:find(pattern, 1, true) then
|
|
error(string.format('%sexpected %s to contain %q', msg and (msg .. ': ') or '', vim.inspect(str), pattern), 2)
|
|
end
|
|
end
|
|
|
|
_G.describe = describe
|
|
_G.it = it
|
|
_G.assert_eq = assert_eq
|
|
_G.assert_true = assert_true
|
|
_G.assert_nil = assert_nil
|
|
_G.assert_match = assert_match
|
|
_G.tmpdir = function()
|
|
local dir = vim.fs.joinpath(vim.fn.tempname(), 'vimpack-test')
|
|
vim.fn.mkdir(dir, 'p')
|
|
return dir
|
|
end
|
|
|
|
-- A writable directory on a filesystem other than `reference`, so the EXDEV
|
|
-- paths can be exercised for real. nil when the box has no second mount.
|
|
_G.otherfs_dir = function(reference)
|
|
local uv = vim.uv or vim.loop
|
|
local ref = uv.fs_stat(reference)
|
|
if not ref then
|
|
return nil
|
|
end
|
|
for _, base in ipairs({ '/dev/shm', '/run/user/' .. tostring(uv.getuid and uv.getuid() or 0), '/var/tmp', '/tmp' }) do
|
|
local stat = uv.fs_stat(base)
|
|
if stat and stat.dev ~= ref.dev then
|
|
local dir = vim.fs.joinpath(base, 'vimpack-xdev-' .. tostring(uv.hrtime()))
|
|
if vim.fn.mkdir(dir, 'p') == 1 then
|
|
return dir
|
|
end
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local files = {}
|
|
for i = 1, #_G.arg do
|
|
files[#files + 1] = _G.arg[i]
|
|
end
|
|
if #files == 0 then
|
|
for name, kind in vim.fs.dir(root .. '/tests') do
|
|
if kind == 'file' and name:match('_spec%.lua$') then
|
|
files[#files + 1] = root .. '/tests/' .. name
|
|
end
|
|
end
|
|
table.sort(files)
|
|
end
|
|
|
|
for _, file in ipairs(files) do
|
|
dofile(file)
|
|
end
|
|
|
|
io.write(string.format('\n%d passed, %d failed\n', M.passed, M.failed))
|
|
if M.failed > 0 then
|
|
for _, failure in ipairs(M.failures) do
|
|
io.write('\n' .. failure .. '\n')
|
|
end
|
|
vim.cmd('cquit 1')
|
|
end
|
|
vim.cmd('quit')
|