~sircmpwn/hare

hare/rt/+test/run.ha -rw-r--r-- 2.1 KiB
e663fb3eThomas Bracht Laumann Jespersen crypto/math: Add constant-time byte slice comparison 3 hours ago
                                                                                
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
type test = struct {
	name: str,
	func: *fn() void,
};

type abort_reason = struct {
	loc: str,
	msg: str,
};

const @symbol("__test_array_start") test_start: [*]test;
const @symbol("__test_array_end") test_end: [*]test;

let jmp: jmpbuf = jmpbuf { ... };
let reason: abort_reason = abort_reason { ... };

export fn tests_main() size = {
	const ntest = (&test_end: uintptr - &test_start: uintptr): size / size(test);
	let maxname = 0z;
	for (let i = 0z; i < ntest; i += 1) {
		if (len(test_start[i].name) > maxname) {
			maxname = len(test_start[i].name);
		};
	};

	let failures: [](str, abort_reason) = [];
	let npass = 0z, nfail = 0z;
	print("Running ");
	print(ztos(ntest));
	print(" tests:\n\n");
	time_start();
	for (let i = 0z; i < ntest; i += 1) {
		if (!should_test(test_start[i].name)) {
			continue;
		};
		print(test_start[i].name);
		dots(maxname - len(test_start[i].name) + 3);
		print(" ");

		if (setjmp(&jmp) != 0) {
			nfail += 1;
			append(failures, (test_start[i].name, reason));
			print("FAIL\n");
			continue;
		};
		test_start[i].func();

		npass += 1;
		print("OK\n");
	};
	let end = time_stop();

	if (nfail != 0) {
		print("\n");
		print(ztos(nfail));
		if (nfail == 1) {
			print(" test failed:\n");
		} else {
			print(" tests failed:\n");
		};
		for (let i = 0z; i < nfail; i += 1) {
			print(failures[i].0);
			print(": ");
			if (len(failures[i].1.loc) != 0) {
				print(failures[i].1.loc);
				print(": ");
			};
			print(failures[i].1.msg);
			print("\n");
		};
	};

	print("\n");
	print(ztos(npass));
	print(" passed; ");
	print(ztos(nfail));
	print(" failed; ");
	print(ztos(ntest));
	print(" tests completed in ");
	print(ztos(end.0));
	print(".");
	print(ztos(end.1));
	print("s\n");

	return nfail;
};

fn print(msg: str) void = write(1, *(&msg: **void): *const char, len(msg))!;

fn dots(n: size) void = {
	// XXX: this is slow, I guess
	for (let i = 0z; i < n; i += 1) {
		print(".");
	};
};

fn should_test(name: str) bool = {
	if (argc == 1) {
		return true;
	};
	for (let i = 1z; i < argc; i += 1) {
		let s = from_c_unsafe(argv[i]);
		if (name == s) {
			return true;
		};
	};
	return false;
};