summaryrefslogtreecommitdiff
path: root/mbld/test.myr
blob: f74c5cf881f909e81bc70d256cedc91038afb1f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use std

use "build"
use "opts"
use "types"
use "util"
use "subtest"

use "config"

pkg bld =
	const test	: (b : build#, targs : byte[:][:] -> bool)
	const bench	: (b : build#, targs : byte[:][:] -> bool)
;;

const test = {b, targs
	-> go(b, targs, "test", false)
}

const bench = {b, targs
	-> go(b, targs, "bench", true)
}

const go = {b, targs, kind, isbench
	var logdir, failed, ok
	var tests

	if !buildtarg(b, kind)
		std.exit(1)
	;;
	tests = std.htgetv(b.deps.targs, kind, [][:])
	ok = true
	failed = [][:]
	for t : tests
		logdir = std.fmt("{}/{}/{}", b.basedir, opt_objdir, t.wdir)
		std.mkpath(logdir)
		if !runtest(b, t, targs, logdir, isbench, &failed)
			ok = false
		;;
		std.slfree(logdir)
	;;
	std.chdir(b.basedir)

	if tests.len == 0
		-> true
	;;

	printfailed(failed)
	if ok
		mbldput("TESTS PASSED\n")
	else
		mbldput("TESTS FAILED\n")
	;;
	std.slfree(failed)
	-> ok
}

const printfailed = {failed
	if failed.len > 0
		mbldput("FAILURES: {}\n", failed.len)
		for t : failed
			mbldput("\t{}\n", t)
		;;
	;;
}

const runtest = {b, n, targs, logdir, isbench, failed
	var dir, res, log, logfd
	var sub, found

	if targs.len > 0
		found = false
		for t : targs
			found = found || matchtest(n.lbl, t)
		;;
		if !found
			-> true
		;;
	;;
	mbldput("run {}: ", n.lbl)
	dir = std.pathcat(b.basedir, n.wdir)
	std.chdir(dir)
	std.slfree(dir)

	if targs.len > 0
		match std.strfind(targs[0], ":")
		| `std.Some i:	std.setenv("MTEST_SUBSET", targs[0][i+1:])
		| `std.None:	/* ok */
		;;
	;;
	match std.spork(n.cmd)
	| `std.Err m:
		std.fatal("\nunable to run test: {}\n", m)
	| `std.Ok (pid, infd, outfd):
		if opt_verbosity >= 1
			log = ""
			logfd = std.try(std.dup(std.Out))
		else
			log = std.fmt("{}/{}.log", logdir, std.basename(n.lbl))
			logfd = std.try(std.openmode(log, std.Owrite | std.Ocreat, 0o644))
		;;
		sub = showsub(b, n.lbl, outfd, logfd, failed)
		std.slfree(log)
		std.close(infd)
		std.close(outfd)

		res = false
		match std.wait(pid)
		| `std.Waiterror:	mbldput("FUCK pid {}\n", pid)
		| `std.Wfailure:	mbldput("FAIL\n")
		| `std.Wsignalled:	mbldput("CRASH\n")
		| `std.Wsuccess:
			res = true
			/* if we have subtests, we've already printed the output */
			match sub
			| `std.Some r:	res = r
			| `std.None:
				if isbench
					mbldput("MISSING TIMING\n")
					res = false
				else
					mbldput("PASS\n")
				;;
			;;
		;;
		if !res
			std.slpush(failed, std.fmt("{j= }", n.cmd))
		;;
		std.close(logfd)
	;;
	-> res
}

const matchtest = {name, pat
	match std.strfind(pat, ":")
	| `std.Some i:	-> std.strhas(name, pat[:i])
	| `std.None:	-> std.strhas(name, pat)
	;;
}