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
|
#include "test_harness.h"
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <setjmp.h>
static jmp_buf jmpbuf;
volatile test_t dummy
__attribute((__section__("tests")))
__attribute((__used__)) = {
"dummy",
"dummy",
NULL
};
extern test_t __start_tests;
extern test_t __stop_tests;
test_t* iter = &__start_tests;
static int execute_test(test_t* test);
int main() {
for( ; iter < &__stop_tests; ++ iter) {
if (iter->fn_ptr != NULL) {
execute_test(iter);
}
}
}
void test_harness_abort(int ec)
{
longjmp(jmpbuf, ec);
assert("Long jump failed.\n");
}
static int execute_test(test_t* test)
{
char fullname[512];
int status;
int ec;
pid_t pid;
const char* note = "";
snprintf(
fullname, sizeof(fullname), "%s::%s", iter->test_suite, iter->test_name);
if (!(pid = fork())) {
// child
if ((ec = setjmp(jmpbuf))) {
exit(ec);
} else {
test->fn_ptr();
exit(0);
}
} else {
if (waitpid(pid, &status, 0) == -1) {
fprintf(stderr, "waitpid() failed\n");
return 1;
}
ec = WEXITSTATUS(status);
switch (ec) {
case 0:
printf("%s " GREEN "[PASS]" RESET "\n", fullname);
return 0;
case 11:
note = " (SIGSEGV)";
break;
}
printf("%s " RED "[FAIL] %d%s" RESET "\n", fullname, ec, note);
return ec;
}
}
|