Implement basic lua test harness
This commit is contained in:
parent
db4faea821
commit
40829cdfc6
@ -1,5 +1,9 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
||||||
"runtime.version": "LuaJIT",
|
"runtime.version": "LuaJIT",
|
||||||
"diagnostics.disable": ["redefined-local", "lowercase-global"]
|
"diagnostics.disable": [
|
||||||
|
"undefined-global",
|
||||||
|
"redefined-local",
|
||||||
|
"lowercase-global"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,10 @@ repository.workspace = true
|
|||||||
dev.panic = "abort"
|
dev.panic = "abort"
|
||||||
release.panic = "abort"
|
release.panic = "abort"
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "main"
|
||||||
|
harness = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["task", "fs", "net"]
|
default = ["task", "fs", "net"]
|
||||||
task = ["lb/task"]
|
task = ["lb/task"]
|
||||||
|
17
src/main.rs
17
src/main.rs
@ -219,17 +219,14 @@ fn init_tokio(args: &Args) -> tokio::runtime::Runtime {
|
|||||||
fn init_lua(args: &Args) -> lb::runtime::Runtime {
|
fn init_lua(args: &Args) -> lb::runtime::Runtime {
|
||||||
let mut rt = {
|
let mut rt = {
|
||||||
let mut rt = lb::runtime::Builder::new();
|
let mut rt = lb::runtime::Builder::new();
|
||||||
rt.unhandled_error(error_cb);
|
|
||||||
luby::open(&mut rt);
|
luby::open(&mut rt);
|
||||||
|
|
||||||
if args.dump.iter().find(|s| *s == "cdef").is_some() {
|
if args.dump.iter().find(|s| *s == "cdef").is_some() {
|
||||||
print!("{}", rt.registry()); // for debugging
|
print!("{}", rt.registry()); // for cdef debugging
|
||||||
}
|
}
|
||||||
|
|
||||||
rt
|
rt.unhandled_error(error_cb).build().unwrap()
|
||||||
}
|
};
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for arg in args.jit.iter() {
|
for arg in args.jit.iter() {
|
||||||
let mut s = rt.guard();
|
let mut s = rt.guard();
|
||||||
@ -281,10 +278,10 @@ async fn main_async(args: Args, cx: &mut lb::runtime::Context) -> Result<(), Exi
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) = cx.load(&luajit::Chunk::new(chunk).path(path)) {
|
if let Err(ref err) = cx.load(&luajit::Chunk::new(chunk).path(path)) {
|
||||||
cx.report_error(&err);
|
cx.report_error(err);
|
||||||
} else if let Err(err) = cx.call_async(0, 0).await {
|
} else if let Err(ref err) = cx.call_async(0, 0).await {
|
||||||
cx.report_error(&err);
|
cx.report_error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
97
tests/main.lua
Normal file
97
tests/main.lua
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
if (...) ~= nil and (...).type == "group" then return end -- prevent recursive main call
|
||||||
|
local fs = require("lb:fs")
|
||||||
|
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()
|
||||||
|
for entry in fs:glob("{tests,crates/*/tests}/**/*.lua") do
|
||||||
|
local path = entry:path():sub(3)
|
||||||
|
local f, err = loadfile(path)
|
||||||
|
if not f then error(err) end
|
||||||
|
describe(path, f)
|
||||||
|
end
|
||||||
|
end))
|
44
tests/main.rs
Normal file
44
tests/main.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
use luajit::Chunk;
|
||||||
|
use owo_colors::OwoColorize;
|
||||||
|
use std::{
|
||||||
|
fs,
|
||||||
|
process::{self, ExitCode},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() -> ExitCode {
|
||||||
|
let tokio = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
let lua = {
|
||||||
|
let mut rt = lb::runtime::Builder::new();
|
||||||
|
luby::open(&mut rt);
|
||||||
|
rt.unhandled_error(error_cb).build().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let path = "tests/main.lua";
|
||||||
|
let main = lua.spawn(async move |s| {
|
||||||
|
if let Err(ref err) = s.load(Chunk::new(fs::read(path).unwrap()).path(path)) {
|
||||||
|
s.report_error(err);
|
||||||
|
} else if let Err(ref err) = s.call_async(0, 1).await {
|
||||||
|
s.report_error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.slot(1).integer().unwrap_or(1) == 0 {
|
||||||
|
ExitCode::SUCCESS
|
||||||
|
} else {
|
||||||
|
ExitCode::FAILURE
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tokio.block_on(async move {
|
||||||
|
lua.await;
|
||||||
|
main.await.unwrap()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn error_cb(err: &luajit::Error) {
|
||||||
|
match err.trace() {
|
||||||
|
Some(trace) => eprintln!("{}\n{trace}", err.red().bold()),
|
||||||
|
None => eprintln!("{}", err.red().bold()),
|
||||||
|
}
|
||||||
|
|
||||||
|
process::exit(1);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user