diff --git a/Cargo.toml b/Cargo.toml index 80fc095..6f6917c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,8 +35,9 @@ name = "main" harness = false [features] -default = ["task", "fs", "net"] +default = ["task", "time", "fs", "net"] task = ["lb/task"] +time = ["lb/time"] fs = ["lb/fs"] net = ["lb/net"] tokio-console = ["dep:console-subscriber"] diff --git a/crates/lb/Cargo.toml b/crates/lb/Cargo.toml index 2a0aabb..6d1837c 100644 --- a/crates/lb/Cargo.toml +++ b/crates/lb/Cargo.toml @@ -10,6 +10,7 @@ repository.workspace = true [features] runtime = ["tokio/rt"] task = ["tokio/rt", "tokio/time"] +time = [] fs = ["tokio/fs", "dep:walkdir", "dep:globset", "dep:tempfile"] net = ["tokio/net", "tokio/io-util"] diff --git a/crates/lb/src/lib.rs b/crates/lb/src/lib.rs index 975de0b..d119491 100644 --- a/crates/lb/src/lib.rs +++ b/crates/lb/src/lib.rs @@ -9,3 +9,5 @@ pub mod net; pub mod runtime; #[cfg(feature = "task")] pub mod task; +#[cfg(feature = "time")] +pub mod time; diff --git a/crates/lb/src/time.rs b/crates/lb/src/time.rs new file mode 100644 index 0000000..4f31d58 --- /dev/null +++ b/crates/lb/src/time.rs @@ -0,0 +1,30 @@ +use luaffi::{cdef, metatype}; + +#[cdef(module = "lb:time")] +pub struct lb_timelib; + +#[metatype] +impl lb_timelib { + #[new] + extern "Lua-C" fn new() -> Self { + Self + } + + pub extern "Lua-C" fn instant() -> lb_instant { + lb_instant::new(std::time::Instant::now()) + } +} + +#[cdef] +pub struct lb_instant(#[opaque] std::time::Instant); + +#[metatype] +impl lb_instant { + fn new(instant: std::time::Instant) -> Self { + Self(instant) + } + + pub extern "Lua-C" fn elapsed(&self) -> f64 { + self.0.elapsed().as_secs_f64() + } +} diff --git a/src/lib.rs b/src/lib.rs index 06eb7b9..1f7486d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ pub use lb::fs; pub use lb::net; #[cfg(feature = "task")] pub use lb::task; +#[cfg(feature = "time")] +pub use lb::time; #[doc(hidden)] pub fn open(#[allow(unused)] rt: &mut lb::runtime::Builder) { @@ -13,6 +15,8 @@ pub fn open(#[allow(unused)] rt: &mut lb::runtime::Builder) { rt.module::(); #[cfg(feature = "task")] rt.module::(); + #[cfg(feature = "time")] + rt.module::(); #[cfg(feature = "fs")] rt.module::(); #[cfg(feature = "net")] diff --git a/tests/main.lua b/tests/main.lua index 61c0ab4..8fc1db9 100644 --- a/tests/main.lua +++ b/tests/main.lua @@ -1,25 +1,27 @@ 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 +if not ok then error("lua test harness requires 'lb:task'") end +local ok, time = pcall(require, "lb:time") +if not ok then error("lua test harness requires 'lb:time'") end local ok, fs = pcall(require, "lb:fs") -if not ok then error("lua test harness requires lb:fs module") end +if not ok then error("lua test harness requires 'lb:fs'") end local global = _G -local colors = { +local color = { reset = "\x1b[0m", pass = "\x1b[32;1m", -- green fail = "\x1b[31;1m", -- red } -local icons = { +local icon = { check = "\u{2713}", cross = "\u{00d7}", chevron = "\u{203a}", } local function style(name, s) - return ("%s%s%s"):format(colors[name], s, colors.reset) + return ("%s%s%s"):format(color[name], s, color.reset) end local function create_test(name, f, group) @@ -54,7 +56,7 @@ local function name_test(test) local name = test.name local group = test.group while group ~= nil do - if group.name ~= "" then name = ("%s %s %s"):format(group.name, icons.chevron, name) end + if group.name ~= "" then name = ("%s %s %s"):format(group.name, icon.chevron, name) end group = group.parent end return name @@ -106,7 +108,7 @@ end local function main(item) local cx = { tasks = {} } - local time, pass, fail = os.clock(), 0, 0 + local time, pass, fail = time.instant(), 0, 0 start(cx, item) for _, task in ipairs(cx.tasks) do if task:await().state == "pass" then @@ -115,21 +117,25 @@ local function main(item) fail = fail + 1 end end - local time = (os.clock() - time) * 1000 + local elapsed = time:elapsed() local code = 1 if fail == 0 then - print("", style("pass", ("%s %d tests passed"):format(icons.check, pass))) + print("", style("pass", ("%s %d tests passed"):format(icon.check, pass))) code = 0 else print( "", ("%s, %s"):format( - style("pass", ("%s %d tests passed"):format(icons.check, pass)), - style("fail", ("%s %d tests failed"):format(icons.cross, fail)) + style("pass", ("%s %d tests passed"):format(icon.check, pass)), + style("fail", ("%s %d tests failed"):format(icon.cross, fail)) ) ) end - print("", ("%s completed in %d ms"):format(icons.chevron, time)) + if elapsed < 1000 then + print("", ("%s completed in %.2f ms"):format(icon.chevron, elapsed * 1000)) + else + print("", ("%s completed in %.2f s"):format(icon.chevron, elapsed)) + end cx = nil collectgarbage() check_refs()