-
Notifications
You must be signed in to change notification settings - Fork 4
/
thc.c
121 lines (105 loc) · 3.47 KB
/
thc.c
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
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include "thc.h"
#define PRIVATE static
#define PUBLIC
enum {
THC_MAX_TESTS = 1024
};
PRIVATE struct timeval start, stop;
PRIVATE double time_elapsed = 0;
PRIVATE const char *RED = "\033[01;31m";
PRIVATE const char *GREEN = "\033[01;32m";
PRIVATE const char *STOPCOLOR = "\033[m";
PRIVATE char verbose_tests = 0;
PRIVATE long ntests = 0;
PRIVATE long nfailures = 0;
PRIVATE long nsegfaults = 0;
PRIVATE void (*tests[THC_MAX_TESTS])(void);
PRIVATE void thc_add_success(const char *expr, const char *func, const char *filename, const int fileno);
PRIVATE void thc_add_failure(const char *expr, const char *func, const char *filename, const int fileno);
PRIVATE void thc_report_tests(void);
PRIVATE void thc_calc_time(struct timeval start, struct timeval stop, double *time_elapsed){
*time_elapsed = stop.tv_sec - start.tv_sec + (stop.tv_usec - start.tv_usec)/1000000.0;
}
PRIVATE void thc_add_success(const char *expr, const char *func, const char *filename, const int fileno) {
if (verbose_tests) {
printf("%s%s ... OK %s[%s, %s:%d]\n", GREEN, expr, STOPCOLOR, func, filename, fileno);
} else {
printf(".");
}
}
PRIVATE void thc_add_failure(const char *expr, const char *func, const char *filename, const int fileno) {
if (verbose_tests) {
printf("%s%s ... FAIL %s[%s, %s:%d]\n", RED, expr, STOPCOLOR, func, filename, fileno);
} else {
printf("F");
}
nfailures++;
}
PRIVATE void thc_report_tests(void) {
char *color = (char *)GREEN;
if (nfailures) {
color = (char *)RED;
}
gettimeofday(&stop, NULL);
thc_calc_time(start, stop, &time_elapsed);
printf("\n%sRun %ld test%s with %ld failure%s and %ld segfault%s in %.4fs\n %s\n",
color, ntests, (ntests == 1 ? "" : "s"),
nfailures, (nfailures == 1 ? "" : "s"),
nsegfaults, (nsegfaults == 1 ? "" : "s"),
time_elapsed, STOPCOLOR);
}
PUBLIC void thc_run_check(const int result, const char *expr, const char *func, const char *fname, const int fline) {
if (result) {
thc_add_success(expr, func, fname, fline);
} else {
thc_add_failure(expr, func, fname, fline);
}
}
PUBLIC void thc_addtest(void (*f)(void)) {
tests[ntests++] = f;
}
PUBLIC int thc_run(int options) {
gettimeofday(&start, NULL);
int i;
int child_status;
int no_fork;
pid_t pid;
if ((options & THC_QUIET) && (options & THC_VERBOSE)) {
printf("Invalid Test Option\n");
printf("You can't mix THC_QUIET and THC_VERBOSE\n");
exit(-1);
}
verbose_tests = options & THC_VERBOSE;
no_fork = options & THC_NOFORK;
for (i = 0 ; i < ntests ; i++) {
if (no_fork) {
tests[i]();
} else {
pid = fork();
if (pid == 0) {
nfailures = 0;
tests[i]();
exit(nfailures);
} else {
wait(&child_status);
if (child_status > 0) {
if (WIFEXITED(child_status)) {
nfailures++;
} else{
nsegfaults++;
printf("\n%sTHC FOUND A SEGFAULT!!!\n%s", (char*)RED,
(char*)STOPCOLOR);
}
}
}
}
}
thc_report_tests();
return nfailures;
}