ref: d798a21d16cbd1d866752fbde81871012a789ea8
dir: /lib/testr/testr.myr/
use std pkg testr = type ctx = struct ok : bool reason : byte[:] jmpbuf : std.jmpbuf# ;; type spec = struct name : byte[:] fn : (ctx : ctx# -> void) ;; const run : (specs : spec[:] -> void) const ok : (ctx : ctx# -> void) const fail : (ctx : ctx#, msg : byte[:], args : ... -> void) const check : (ctx : ctx#, cond : bool, msg : byte[:], args : ... -> void) const softfail : (ctx : ctx#, msg : byte[:], args : ... -> void) ;; const run = {specs std.put("MTEST {}\n", specs.len) for s : specs runspec(&s) ;; } const ok = {ctx /* nothing to do here */ } const check = {ctx, cond, msg, args var ap if !cond ap = std.vastart(&args) failv(ctx, msg, &ap) ;; } const fail = {ctx, msg, args var ap ap = std.vastart(&args) failv(ctx, msg, &ap) } const failv = {ctx, msg, ap softfailv(ctx, msg, ap) std.longjmp(ctx.jmpbuf) } const softfail = {ctx, msg, args var ap ap = std.vastart(&args) softfailv(ctx, msg, &ap) } const softfailv = {ctx, msg, ap ctx.ok = false ctx.reason = std.fmtv(msg, ap) } const runspec = {ts var ctx : ctx var status, reason var jmpbuf ctx.ok = true ctx.reason = "" ctx.jmpbuf = &jmpbuf std.put("test {} <<{{!\n", ts.name) if !std.setjmp(&jmpbuf) ts.fn(&ctx) ;; if ctx.ok status = "ok" reason = "" else status = "fail" reason = ctx.reason ;; std.put("!}}>> {} {}\n", status, reason) std.slfree(reason) }