ref: 12b66049f3881fa6b36ed803358c659a96071e16
dir: /mbld/subtest.myr/
use std use bio use regex use "types" use "util" pkg bld = const showsub : (b : build#, cmd : byte[:], \ f : std.fd, logfd : std.fd, \ failed : byte[:][:]# -> std.option(bool)) ;; var planpat var headpat var footpat const __init__ = { planpat = std.try(regex.compile("MTEST\\s+(-?\\d+)\\s*")) headpat = std.try(regex.compile("test\\s+(.*)<<{!\\s*")) footpat = std.try(regex.compile("!}>>\\s*(ok|fail\\s*(.*))\\s*")) } const showsub = {b, cmd, fd, logfd, failed var f, log var res f = bio.mkfile(fd, bio.Rd) log = bio.mkfile(logfd, bio.Wr) res = `std.None match bio.readln(f) | `bio.Err e: std.fatal("error reading subfile: {}\n", e) | `bio.Eof: -> `std.None | `bio.Ok ln: match testplan(ln) | `std.None: bio.write(log, ln) showraw(fd, logfd) | `std.Some ntests: res = `std.Some showtests(b, cmd, failed, \ f, log, ntests) ;; std.slfree(ln) ;; bio.close(f) bio.close(log) -> res } const showraw = {f, log var buf : byte[:] buf = std.slalloc(64*std.KiB) while true match std.read(f, buf[:]) | `std.Ok 0: break | `std.Ok n: std.write(log, buf[:n]) | `std.Err e: std.fatal("error writing log: {}\n", e) ;; ;; std.slfree(buf) } const showtests = {b, cmd, failed, f, log, ntests var curtest var nresults var ok if ntests == 0 mbldput("FAIL: missing tests\n") -> false ;; ok = true curtest = "" nresults = 0 mbldput("\n") for ln in bio.byline(f) ln = std.strstrip(ln) match testhead(ln) | `std.None: | `std.Some t: starttest(&curtest, t) bio.put(log, "RUN {}\n", t) continue ;; match testfoot(ln) | `std.None: | `std.Some `std.Ok _: endtest(b, cmd, &curtest, failed, &nresults, true, "") continue | `std.Some `std.Err m: endtest(b, cmd, &curtest, failed, &nresults, false, m) ok = false continue ;; match testplan(ln) | `std.None: | `std.Some n: if curtest.len == 0 if !checktests(ntests, nresults) ok = false ;; ntests = n nresults = 0 continue ;; ;; bio.put(log, "\t{}\n", ln) ;; if !checktests(ntests, nresults) ok = false ;; -> ok } const checktests = {ntests, nresults if ntests > 0 && ntests != nresults mbldput("mismatched test count: expected {}, got {}\n", ntests, nresults) -> false ;; -> true } const starttest = {curtest, t if curtest#.len != 0 std.fatal("malformed input: test {} nested in {}\n", t, curtest) ;; mbldput("\trun {}:\t", std.strstrip(t)) curtest# = t } const endtest = {b, cmd, curtest, failed, nresults, pass, msg var p if curtest#.len == 0 std.fatal("malformed input: test ended without start\n") ;; if pass mbldput("PASS\n") else if msg.len > 0 mbldput("FAIL {}\n", msg) else mbldput("FAIL\n") ;; p = std.pathcat(cmd, curtest#) std.slpush(failed, p) ;; std.slfree(curtest#) curtest# = "" nresults#++ } const testplan = {ln var ntests match regex.exec(planpat, ln) | `std.None: -> `std.None | `std.Some m: ntests = std.get(std.intparse(m[1])) regex.matchfree(m) -> `std.Some ntests ;; } const testhead = {ln var t match regex.exec(headpat, ln) | `std.Some m: t = std.sldup(m[1]) regex.matchfree(m) -> `std.Some t | `std.None: -> `std.None ;; } const testfoot : (ln : byte[:] -> std.option(std.result(void, byte[:]))) = {ln match regex.exec(footpat, ln) | `std.Some m: if std.sleq(m[1], "ok") -> `std.Some `std.Ok void else -> `std.Some `std.Err std.sldup(m[2]) ;; | `std.None: -> `std.None ;; }