// globaltest — exercises the global-logger wiring (default / global / // setlogger) per ref/hare/log/global.ha ownership. Each scenario // constructs stdloggers over memio.streams and asserts the bytes the // global dispatch produced. defaultwiredtoglobal must stay the first // @test row: it pins the pristine global == default wiring that every // later setlogger caller mutates. Composed dir-mode execution is // declaration order per file, files in byte-lexicographic order // (funcs_test < global_test < silent_test), and no funcs/silent row // calls setlogger. package log_test; import log; import memio; fn gstreq(a: str, b: str) bool = { if (a.len != b.len) { return false; }; let i: i32 = 0; for (i < a.len) { if (a[i] != b[i]) { return false; }; i += 1; }; return true; }; // log.default writes to stderr through the private stderrsink — we // can't easily capture stderr from inside the test, so this scenario // verifies the initial wiring only: after lazy [[ensureinit]] runs, // [[log.default]] / [[log.silent]] are non-nil and [[log.global]] // equals [[log.default]]. The check is order-sensitive: any later // scenario that calls [[log.setlogger]] mutates the global, so this // scenario must run before [[setloggerswap]]. @test fn defaultwiredtoglobal() void = { let buf: [4]u8; let mem = memio.fixed(buf[0:4]); let s = &mem.vt; let sl = log.new(s); // triggers ensureinit assert(!(log.silent == nil)); assert(!(log.default == nil)); assert(!(log.global == nil)); assert(!(log.global != log.default)); }; // Three-phase: install sl1 as global, println writes there; swap to // sl2, println writes there only; swap to silent, println discards. // Each memio sink starts empty and is asserted at each phase to pin // the swap semantics. @test fn setloggerswap() void = { let buf1: [32]u8; let mem1 = memio.fixed(buf1[0:32]); let s1 = &mem1.vt; let sl1 = log.new(s1); let buf2: [32]u8; let mem2 = memio.fixed(buf2[0:32]); let s2 = &mem2.vt; let sl2 = log.new(s2); log.setlogger(&sl1.logger); log.println("first"); assert(!(!gstreq(memio.string(&mem1), "first\n"))); assert(!(mem2.pos != 0)); log.setlogger(&sl2.logger); log.println("second"); assert(!(!gstreq(memio.string(&mem2), "second\n"))); // mem1 must be unchanged. assert(!(!gstreq(memio.string(&mem1), "first\n"))); log.setlogger(log.silent); log.println("dropped"); // Both sinks unchanged. assert(!(!gstreq(memio.string(&mem1), "first\n"))); assert(!(!gstreq(memio.string(&mem2), "second\n"))); }; // Mirrors [[setloggerswap]] but exercises the format-string path: // install sl1 as global, printfln writes there; mem2 stays empty. @test fn printflnglobal() void = { let buf1: [32]u8; let mem1 = memio.fixed(buf1[0:32]); let s1 = &mem1.vt; let sl1 = log.new(s1); let buf2: [32]u8; let mem2 = memio.fixed(buf2[0:32]); let s2 = &mem2.vt; let sl2 = log.new(s2); log.setlogger(&sl1.logger); log.printfln("v={}", 7i64); assert(!(!gstreq(memio.string(&mem1), "v=7\n"))); assert(!(mem2.pos != 0)); };