ref: 26da0e6f98ac76f3930ed68649b5fbfe87c06ec4
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.pathjoin([b.curdir, 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
;;
}