hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

run.ha (2492B)


      1 // License: MPL-2.0
      2 // (c) 2022 Bor Grošelj Simić <bor.groseljsimic@telemach.net>
      3 // (c) 2021 Drew DeVault <sir@cmpwn.com>
      4 // (c) 2021 Ember Sawady <ecs@d2evs.net>
      5 
      6 type test = struct {
      7 	name: str,
      8 	func: *fn() void,
      9 };
     10 
     11 type abort_reason = struct {
     12 	loc: str,
     13 	msg: str,
     14 };
     15 
     16 const @symbol("__test_array_start") test_start: [*]test;
     17 const @symbol("__test_array_end") test_end: [*]test;
     18 
     19 let jmp: jmpbuf = jmpbuf { ... };
     20 let reason: abort_reason = abort_reason { ... };
     21 
     22 export fn tests_main() size = {
     23 	const ntest = (&test_end: uintptr - &test_start: uintptr): size / size(test);
     24 	let maxname = 0z;
     25 	for (let i = 0z; i < ntest; i += 1) {
     26 		if (len(test_start[i].name) > maxname) {
     27 			maxname = len(test_start[i].name);
     28 		};
     29 	};
     30 
     31 	let failures: [](str, abort_reason) = [];
     32 	let npass = 0z, nfail = 0z;
     33 	let default_round = fegetround();
     34 	print("Running ");
     35 	print(ztos(ntest));
     36 	print(" tests:\n\n");
     37 	time_start();
     38 	for (let i = 0z; i < ntest; i += 1) {
     39 		if (!should_test(test_start[i].name)) {
     40 			continue;
     41 		};
     42 		print(test_start[i].name);
     43 		dots(maxname - len(test_start[i].name) + 3);
     44 		print(" ");
     45 
     46 		if (setjmp(&jmp) != 0) {
     47 			nfail += 1;
     48 			append(failures, (test_start[i].name, reason));
     49 			print("FAIL\n");
     50 			continue;
     51 		};
     52 
     53 		fesetround(default_round);
     54 		feclearexcept(~0u);
     55 
     56 		test_start[i].func();
     57 
     58 		npass += 1;
     59 		print("OK\n");
     60 	};
     61 	let end = time_stop();
     62 
     63 	if (nfail != 0) {
     64 		print("\n");
     65 		print(ztos(nfail));
     66 		if (nfail == 1) {
     67 			print(" test failed:\n");
     68 		} else {
     69 			print(" tests failed:\n");
     70 		};
     71 		for (let i = 0z; i < nfail; i += 1) {
     72 			print(failures[i].0);
     73 			print(": ");
     74 			if (len(failures[i].1.loc) != 0) {
     75 				print(failures[i].1.loc);
     76 				print(": ");
     77 			};
     78 			print(failures[i].1.msg);
     79 			print("\n");
     80 		};
     81 	};
     82 
     83 	print("\n");
     84 	print(ztos(npass));
     85 	print(" passed; ");
     86 	print(ztos(nfail));
     87 	print(" failed; ");
     88 	print(ztos(ntest));
     89 	print(" tests completed in ");
     90 	print(ztos(end.0));
     91 	print(".");
     92 	if (end.1 < 10) {
     93 		print("00");
     94 	} else if (end.1 < 100) {
     95 		print("0");
     96 	};
     97 	print(ztos(end.1));
     98 	print("s\n");
     99 
    100 	return nfail;
    101 };
    102 
    103 fn print(msg: str) void = {
    104 	write(STDOUT_FILENO, *(&msg: **void): *const char, len(msg))!;
    105 };
    106 
    107 fn dots(n: size) void = {
    108 	// XXX: this is slow, I guess
    109 	for (let i = 0z; i < n; i += 1) {
    110 		print(".");
    111 	};
    112 };
    113 
    114 fn should_test(name: str) bool = {
    115 	if (argc == 1) {
    116 		return true;
    117 	};
    118 	for (let i = 1z; i < argc; i += 1) {
    119 		let s = from_c_unsafe(argv[i]);
    120 		if (name == s) {
    121 			return true;
    122 		};
    123 	};
    124 	return false;
    125 };