diff options
author | Ori Bernstein <ori@eigenstate.org> | 2016-05-23 23:23:09 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2016-05-24 00:03:00 -0700 |
commit | 6d7c80f8d5efcba00ebd44d34fd7b613f4672829 (patch) | |
tree | 5c93dec897f29d26fac7689e59890865ede0f48f /mbld | |
parent | ec5f2d23637dadf6d2893bf6f2f829b070ec3b34 (diff) | |
download | mc-6d7c80f8d5efcba00ebd44d34fd7b613f4672829.tar.gz |
Add support for running subtests.
Diffstat (limited to 'mbld')
-rw-r--r-- | mbld/bld.sub | 1 | ||||
-rw-r--r-- | mbld/subtest.myr | 128 | ||||
-rw-r--r-- | mbld/test.myr | 24 |
3 files changed, 142 insertions, 11 deletions
diff --git a/mbld/bld.sub b/mbld/bld.sub index 6379627..4a2d66c 100644 --- a/mbld/bld.sub +++ b/mbld/bld.sub @@ -9,6 +9,7 @@ bin mbld = main.myr opts.myr parse.myr + subtest.myr syssel.myr test.myr types.myr diff --git a/mbld/subtest.myr b/mbld/subtest.myr new file mode 100644 index 0000000..d8b1e60 --- /dev/null +++ b/mbld/subtest.myr @@ -0,0 +1,128 @@ +use std +use bio +use regex + +pkg bld = + const showsub : (f : std.fd, logfd : std.fd -> 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+(.*)<<{!")) + footpat = std.try(regex.compile("!}>>\\s*(ok|fail\\s*(.*))")) +} + +const showsub = {fd, logfd + var f, log + var ntests + 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 regex.exec(planpat, ln) + | `std.None: + bio.write(log, ln) + showraw(fd, logfd) + | `std.Some m: + ntests = std.get(std.intparse(m[1])) + regex.matchfree(m) + res = `std.Some showtests(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.Fail e: std.fatal("error writing log: {}\n", e) + ;; + ;; + std.slfree(buf) +} + +const showtests = {f, log, ntests + var nresults + var ok + + if ntests == 0 + std.put("FAIL: missing tests\n") + -> false + ;; + ok = true + nresults = 0 + for ln in bio.byline(f) + ln = std.strstrip(ln) + match testhead(ln) + | `std.None: + | `std.Some t: + std.put("\trun {}:\t", std.strstrip(t)) + bio.put(log, "RUN {}\n", t) + continue + ;; + + match testfoot(ln) + | `std.None: + | `std.Some `std.Ok _: + std.put("PASS\n") + nresults++ + continue + | `std.Some `std.Fail m: + std.put("FAIL\n") + ok = false + nresults++ + continue + ;; + + bio.put(log, "\t{}\n", ln) + ;; + if ntests > 0 && ntests != nresults + std.put("mismatched test count: expected {}, got {}\n", ntests, nresults) + -> false + ;; + -> ok +} + +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.Fail std.sldup(m[2]) + ;; + | `std.None: + -> `std.None + ;; +} + diff --git a/mbld/test.myr b/mbld/test.myr index d8be1dc..bb2735b 100644 --- a/mbld/test.myr +++ b/mbld/test.myr @@ -8,6 +8,7 @@ use "parse" use "types" use "util" use "syssel" +use "subtest" use "config" @@ -149,7 +150,8 @@ const buildtests = {b, targ } const runtest = {b, cmd - var r, log, p + var res, log, logfd, p + var sub std.put("run") for c in cmd @@ -163,27 +165,27 @@ const runtest = {b, cmd std.fatal("\nunable to run test: {}\n", m) | `std.Ok (pid, infd, outfd): log = std.strcat(cmd[0], ".log") - match std.fslurp(outfd) - | `std.Ok "": /* empty output; nothing to log */ - | `std.Ok buf: - std.blat(log, buf, 0o644) - | `std.Fail m: - ;; + logfd = std.try(std.open(log, std.Owronly | std.Ocreat)) + sub = showsub(outfd, logfd) std.slfree(log) std.close(infd) std.close(outfd) - r = false + res = false match std.wait(pid) | `std.Wfailure: std.put("FAIL\n") | `std.Wsignalled: std.put("CRASH\n") | `std.Wsuccess: - std.put("PASS\n") - r = true + res = true + /* if we have subtests, we've already printed the output */ + match sub + | `std.Some r: res = r + | `std.None: std.put("PASS\n") + ;; | `std.Waiterror: std.put("failed waiting for pid {}\n", pid) ;; ;; - -> r + -> res } const testpath = {s |