luby/tests/test.lua

108 lines
2.7 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

if (...) ~= nil and (...).type == "group" then return end -- prevent recursive harness call
local ok = pcall(require, "lb:task")
if not ok then error("lua test harness requires lb:task module") end
local ok, fs = pcall(require, "lb:fs")
if not ok then error("lua test harness requires lb:fs module") end
local global = _G
local colors = {
reset = "\x1b[0m",
pass = "\x1b[32;1m",
fail = "\x1b[31;1m",
}
local function color(name, s)
return colors[name] .. s .. colors.reset
end
local function create_test(name, f, group)
local test = { type = "test", name = name or "", group = group, state = "pending", f = f }
local fenv = setmetatable({}, { __index = global })
setfenv(f, fenv)
return test
end
local function create_group(name, f, parent)
local group = { type = "group", name = name or "", parent = parent, items = {} }
local fenv = setmetatable({
describe = function(name, f)
local item = create_group(name, f, group)
table.insert(group.items, item)
return item
end,
test = function(name, f)
local item = create_test(name, f, group)
table.insert(group.items, item)
return item
end,
}, { __index = global })
setfenv(f, fenv)
f(group)
return group
end
local function name_test(test)
local name = test.name
local group = test.group
while group ~= nil do
if group.name ~= "" then name = group.name .. " " .. name end
group = group.parent
end
return name
end
local function trace(msg)
return color("fail", msg) .. debug.traceback("", 2):sub(("\nstack traceback:"):len() + 1)
end
local function run_test(test)
local ok, res = xpcall(test.f, trace, test)
if ok then
test.state = "pass"
print("", color("pass", "PASS") .. " " .. name_test(test))
else
test.state = "fail"
print("", color("fail", "FAIL") .. " " .. name_test(test) .. "\n")
print(res .. "\n")
end
return test
end
local function start(cx, item)
if item.type == "test" then
table.insert(cx.tasks, spawn(run_test, item))
elseif item.type == "group" then
for _, item in ipairs(item.items) do
start(cx, item)
end
end
end
local function run(item)
local cx = { tasks = {} }
local pass = true
start(cx, item)
for _, task in ipairs(cx.tasks) do
if task:await().state ~= "pass" then pass = false end
end
if pass then return 0 end -- report status to cargo
return 1
end
return run(create_group("", function()
local function glob(path, pat)
for entry in fs:glob_dir(path, pat) do
local path = entry:path()
local f, err = loadfile(path)
if not f then error(err) end
describe(path, f)
end
end
glob("tests", "**/*.lua")
glob("crates", "*/tests/**/*.lua")
end))