ref: 8aa9e0ab5cb8c9e99253842f1d29422d154c3a65
dir: /mbld/test.myr/
use std use "build.use" use "clean.use" use "deps.use" use "opts.use" use "parse.use" use "types.use" use "util.use" use "config.use" pkg bld = const test : (b : build# -> void) ;; const test = {b var ok var tests : (byte[:], byte[:])[:] /* no implicit tests to run */ tests = [][:] if std.fexists("test") for tn in b.all match gettarg(b.targs, tn) | `Bin bt: tests = std.sljoin(tests, buildtests(b, bt)) | `Lib lt: tests = std.sljoin(tests, buildtests(b, lt)) | _: /* nothing */ ;; ;; ;; for tn in b.all match gettarg(b.targs, tn) | `Test t: if t.incpath.len == 0 || !std.sleq(t.incpath[0], ".") t.incpath = std.slput(t.incpath, 0, std.sldup(".")) ;; buildbin(b, t, false) tests = std.slpush(tests, (std.strcat("./", t.name), std.sldup(t.dir))) | _: /* skip */ ;; ;; ok = true for (bin, dir) in tests setdir(b, dir) if !runtest(bin) ok = false ;; ;; for (bin, dir) in tests std.slfree(bin) std.slfree(dir) ;; std.slfree(tests) if tests.len == 0 -> ;; if ok std.put("TESTS PASSED\n") else std.put("TESTS FAILED\n") ;; } const buildtests = {b, targ var tt, bin ,path, tests tests = [][:] setdir(b, targ.dir) for s in targ.inputs path = std.pathcat("./test", s) if std.fexists(path) bin = srcswapsuffix(path, "") tt = [ .name = bin, .dir = targ.dir, .inputs = [path][:], .install = false, .libdeps = std.sldup(targ.libdeps), .incpath = std.slput(std.sldup(targ.incpath), 0, "."), ] cleantest(b, path) buildbin(b, &tt, true) tests = std.slpush(tests, (std.strcat("./", bin), std.sldup(targ.dir))) std.slfree(tt.libdeps) std.slfree(tt.incpath) ;; std.slfree(path) ;; -> tests } const cleantest = {b, src var obj, bin, log, usef obj = srcswapsuffix(src, config.Objsuffix) log = srcswapsuffix(src, ".log") usef = srcswapsuffix(src, ".use") bin = srcswapsuffix(src, "") std.remove(obj) std.remove(usef) std.remove(log) std.remove(bin) std.slfree(obj) std.slfree(usef) std.slfree(log) std.slfree(bin) } const runtest = {bin var r, log std.put("run {}:\t", bin) log = std.strcat(bin, ".log") match std.spork([bin][:]) | `std.Fail m: std.fatal("unable to run test: {}\n", m) | `std.Ok (pid, infd, outfd): match std.fslurp(outfd) | `std.Ok "": /* empty output; nothing to log */ | `std.Ok buf: std.blat(log, buf, 0o644) | `std.Fail m: ;; std.slfree(log) r = 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 | _: std.put("???\n") ;; ;; -> r }