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
140
141
142
143
144
145
146
147
|
#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);
void test_printll(size_t sz, long long v1, long long v2)
{
fprintf(stderr, "%lld == %lld\n", v1, v2);
}
void test_printul(size_t sz, unsigned long v1, unsigned long v2)
{
fprintf(stderr, "%lu == %lu\n", v1, v2);
}
void test_printd(size_t sz, int v1, int v2)
{
fprintf(stderr, "%d == %d\n", v1, v2);
}
void test_printl(size_t sz, long v1, long v2)
{
fprintf(stderr, "%lu == %lu\n", v1, v2);
}
void test_printui(size_t sz, unsigned int v1, unsigned int v2)
{
fprintf(stderr, "%u == %u\n", v1, v2);
}
void test_prints(size_t sz, short v1, short v2)
{
fprintf(stderr, "%hu == %hu\n", v1, v2);
}
void test_printus(size_t sz, unsigned short v1, unsigned short v2)
{
fprintf(stderr, "%hu == %hu\n", v1, v2);
}
void test_printc(size_t sz, char v1, char v2)
{
fprintf(stderr, "'%c' == '%c'\n", v1, v2);
}
void test_printf(size_t sz, double v1, double v2)
{
fprintf(stderr, "%f == %f\n", v1, v2);
}
void test_printp(size_t sz, void* v1, void* v2)
{
fprintf(stderr, "%p == %p\n", v1, v2);
}
void test_printuc(
size_t sz, unsigned char v1, unsigned char v2)
{
fprintf(stderr, "%02x == %02x\n", (int) v1, (int) v2);
}
int do_fork = 1;
int main(int argc, char** argv) {
if (argc > 1 && strcmp(argv[1], "--nofork") == 0) {
do_fork = 0;
}
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 = 0;
pid_t pid;
snprintf(
fullname, sizeof(fullname), "%s::%s", iter->test_suite, iter->test_name);
if (!do_fork) {
if ((ec = setjmp(jmpbuf)) == 0) {
test->fn_ptr();
printf("%s " GREEN "[PASS]" RESET "\n", fullname);
return 0;
} else {
printf("%s " RED "[FAIL] %d" RESET "\n", fullname, ec);
return ec;
}
}
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;
}
if (WIFEXITED(status)) {
switch ((ec = WEXITSTATUS(status))) {
case 0:
printf("%s " GREEN "[PASS]" RESET "\n", fullname);
return 0;
default:
printf("%s " RED "[FAIL] %d" RESET "\n", fullname, ec);
return ec;
}
} else if (WIFSIGNALED(status)) {
int ec = WTERMSIG(status);
printf("%s " RED "[FAIL] signaled %d" RESET "\n", fullname, ec);
return ec;
}
return ec;
}
}
|