summaryrefslogtreecommitdiff
path: root/mbld/subtest.myr
blob: d8b1e60f4fcab4a4d3ef349d24cb88c17a2febaf (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
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
	;;
}