// timetest — exercises lib/time. Run with `out/bin/ww run // lib/time/timetest.ww`. A failing row aborts via the assert/abort // builtin (task #5 @test conversion). package time_test; import time; // ---- constants: load-bearing names + values ---------------------------- // // Without these multipliers every caller would re-derive 1e9 in // place. The values themselves are nailed down by Hare's // ref/hare/time/duration.ha:9-18. @test fn constants() void = { assert(!((time.nanosecond: i64) != 1i64)); assert(!((time.microsecond: i64) != 1000i64)); assert(!((time.millisecond: i64) != 1000000i64)); assert(!((time.second: i64) != 1000000000i64)); // "Roundtrip" check: derived multiples land on the canonical // nanosecond count. Catches a future re-derivation drift. assert(!(5i64 * (time.second: i64) != 5000000000i64)); assert(!(3i64 * (time.millisecond: i64) != 3000000i64)); assert(!(7i64 * (time.microsecond: i64) != 7000i64)); }; // ---- now(monotonic) is monotonic across two calls ---------------------- @test fn nowmonotonic() void = { let a = time.now(time.clock.monotonic); let b = time.now(time.clock.monotonic); // Two back-to-back calls — b can equal a (same ns tick) but // must never precede it. assert(!(time.compare(a, b) > 0i8)); }; // ---- now(realtime) returns a post-2020 epoch --------------------------- // // Sanity check that the syscall plumbing actually lands real bytes // in the instant. 2020-01-01 UTC = 1577836800 unix seconds; any // past-2020 wall clock satisfies this. (CI / test machines running // pre-2020 would fail here; acceptable trade for catching a // zero-init / wrong-slot regression.) @test fn nowrealtime() void = { let t = time.now(time.clock.realtime); assert(!(t.sec < 1577836800i64)); assert(!(t.nsec < 0i64)); assert(!(t.nsec >= 1000000000i64)); }; // ---- add: zero duration is identity ------------------------------------ @test fn addzero() void = { let a: time.instant; a.sec = 100i64; a.nsec = 500i64; let r = time.add(a, 0i64); assert(!(r.sec != 100i64)); assert(!(r.nsec != 500i64)); }; // ---- add: positive duration, no carry ---------------------------------- @test fn addpos_nocarry() void = { let a: time.instant; a.sec = 10i64; a.nsec = 100i64; let r = time.add(a, 200i64); assert(!(r.sec != 10i64)); assert(!(r.nsec != 300i64)); }; // ---- add: positive duration, carries into next second ------------------ @test fn addpos_carry() void = { let a: time.instant; a.sec = 10i64; a.nsec = 999999900i64; let r = time.add(a, 200i64); assert(!(r.sec != 11i64)); assert(!(r.nsec != 100i64)); }; // ---- add: full-second duration ----------------------------------------- @test fn addpos_fullsecond() void = { let a: time.instant; a.sec = 5i64; a.nsec = 0i64; let r = time.add(a, (time.second: i64) * 3i64); assert(!(r.sec != 8i64)); assert(!(r.nsec != 0i64)); }; // ---- add: negative duration, no borrow --------------------------------- @test fn addneg_noborrow() void = { let a: time.instant; a.sec = 10i64; a.nsec = 500i64; let r = time.add(a, -100i64); assert(!(r.sec != 10i64)); assert(!(r.nsec != 400i64)); }; // ---- add: negative duration, borrows from previous second -------------- @test fn addneg_borrow() void = { let a: time.instant; a.sec = 10i64; a.nsec = 100i64; let r = time.add(a, -200i64); assert(!(r.sec != 9i64)); assert(!(r.nsec != 999999900i64)); }; // ---- diff: simple subtraction ------------------------------------------ @test fn diffsimple() void = { let a: time.instant; a.sec = 10i64; a.nsec = 100i64; let b: time.instant; b.sec = 12i64; b.nsec = 300i64; let d: i64 = time.diff(a, b): i64; // b - a = 2.0000002 sec = 2_000_000_200 ns assert(!(d != 2000000200i64)); }; // ---- diff: reversed sign ----------------------------------------------- @test fn diffneg() void = { let a: time.instant; a.sec = 12i64; a.nsec = 300i64; let b: time.instant; b.sec = 10i64; b.nsec = 100i64; let d: i64 = time.diff(a, b): i64; assert(!(d != -2000000200i64)); }; // ---- compare: -1 / 0 / +1 ladder --------------------------------------- @test fn comparelt() void = { let a: time.instant; a.sec = 1i64; a.nsec = 0i64; let b: time.instant; b.sec = 2i64; b.nsec = 0i64; assert(!(time.compare(a, b) != -1i8)); }; @test fn comparegt() void = { let a: time.instant; a.sec = 2i64; a.nsec = 0i64; let b: time.instant; b.sec = 1i64; b.nsec = 0i64; assert(!(time.compare(a, b) != 1i8)); }; @test fn compareeq() void = { let a: time.instant; a.sec = 5i64; a.nsec = 42i64; let b: time.instant; b.sec = 5i64; b.nsec = 42i64; assert(!(time.compare(a, b) != 0i8)); }; @test fn comparensec_only() void = { let a: time.instant; a.sec = 5i64; a.nsec = 100i64; let b: time.instant; b.sec = 5i64; b.nsec = 200i64; assert(!(time.compare(a, b) != -1i8)); assert(!(time.compare(b, a) != 1i8)); };