174 lines
2.9 KiB
C
174 lines
2.9 KiB
C
|
#include "t-utils.h"
|
||
|
|
||
|
const char *cyan = "", *red = "", *green = "", *yellow = "", *reset = "";
|
||
|
uint passed, failed, t_verbose = 0;
|
||
|
static uint t_depth;
|
||
|
static const char *indent_str = " ";
|
||
|
|
||
|
/* can't be used when a or b has side-effects, but we don't care here */
|
||
|
#define max(a, b) (a > b ? a : b)
|
||
|
#define min(a, b) (a < b ? a : b)
|
||
|
#define delta(a, b) ((max(a, b) - (min(a, b))))
|
||
|
|
||
|
|
||
|
void t_reset(void)
|
||
|
{
|
||
|
passed = failed = 0;
|
||
|
}
|
||
|
|
||
|
void t_set_colors(int force)
|
||
|
{
|
||
|
if (force == 1 || isatty(fileno(stdout))) {
|
||
|
cyan = CLR_CYAN;
|
||
|
red = CLR_RED;
|
||
|
yellow = CLR_YELLOW;
|
||
|
green = CLR_GREEN;
|
||
|
reset = CLR_RESET;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void t_indent(uint depth)
|
||
|
{
|
||
|
uint i;
|
||
|
for (i = 0; i < depth; i++) {
|
||
|
printf("%s", indent_str);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void t_start(const char *fmt, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
t_indent(t_depth++);
|
||
|
va_start(ap, fmt);
|
||
|
printf("%s### ", cyan);
|
||
|
vfprintf(stdout, fmt, ap);
|
||
|
printf("%s\n", reset);
|
||
|
va_end(ap);
|
||
|
}
|
||
|
|
||
|
int t_end(void)
|
||
|
{
|
||
|
if (t_depth)
|
||
|
t_depth--;
|
||
|
if (!t_depth || failed) {
|
||
|
t_indent(t_depth);
|
||
|
printf("Test results: %s%u passed%s, %s%u failed%s\n",
|
||
|
green, passed, reset, failed ? red : "", failed, failed ? reset : "");
|
||
|
}
|
||
|
|
||
|
return failed ? EXIT_FAILURE : EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static int t_okv(int success, const char *fmt, va_list ap)
|
||
|
{
|
||
|
passed += !!success;
|
||
|
failed += !success;
|
||
|
|
||
|
if (fmt && (!success || t_verbose || (t_verbose = !!getenv("TEST_VERBOSE")))) {
|
||
|
t_indent(t_depth);
|
||
|
if (success) {
|
||
|
printf("%sPASS%s ", green, reset);
|
||
|
} else {
|
||
|
printf("%sFAIL%s ", red, reset);
|
||
|
}
|
||
|
vfprintf(stdout, fmt, ap);
|
||
|
putchar('\n');
|
||
|
}
|
||
|
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
int t_ok(int success, const char *fmt, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
if (fmt) {
|
||
|
va_start(ap, fmt);
|
||
|
t_okv(success, fmt, ap);
|
||
|
va_end(ap);
|
||
|
}
|
||
|
else
|
||
|
t_okv(success, NULL, NULL);
|
||
|
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
void t_pass(const char *fmt, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
va_start(ap, fmt);
|
||
|
t_okv(TEST_PASS, fmt, ap);
|
||
|
va_end(ap);
|
||
|
}
|
||
|
|
||
|
void t_fail(const char *fmt, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
va_start(ap, fmt);
|
||
|
t_okv(TEST_FAIL, fmt, ap);
|
||
|
va_end(ap);
|
||
|
}
|
||
|
|
||
|
void t_diag(const char *fmt, ...)
|
||
|
{
|
||
|
if (fmt) {
|
||
|
va_list ap;
|
||
|
t_indent(t_depth + 1);
|
||
|
va_start(ap, fmt);
|
||
|
vfprintf(stdout, fmt, ap);
|
||
|
va_end(ap);
|
||
|
putchar('\n');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int ok_int(int a, int b, const char *name)
|
||
|
{
|
||
|
if (a == b) {
|
||
|
t_pass("%s", name);
|
||
|
return TEST_PASS;
|
||
|
}
|
||
|
|
||
|
t_fail("%s", name);
|
||
|
t_diag("%d != %d. delta: %d", a, b, delta(a, b));
|
||
|
return TEST_FAIL;
|
||
|
}
|
||
|
|
||
|
int ok_uint(uint a, uint b, const char *name)
|
||
|
{
|
||
|
if (a == b) {
|
||
|
t_pass("%s", name);
|
||
|
return TEST_PASS;
|
||
|
}
|
||
|
|
||
|
t_fail("%s", name);
|
||
|
t_diag("%u != %u. delta: %u", a, b, delta(a, b));
|
||
|
return TEST_FAIL;
|
||
|
}
|
||
|
|
||
|
int ok_str(const char *a, const char *b, const char *name)
|
||
|
{
|
||
|
if ((!a && !b) || (a && b && !strcmp(a, b))) {
|
||
|
t_pass("%s", name);
|
||
|
return TEST_PASS;
|
||
|
}
|
||
|
|
||
|
t_fail("%s", name);
|
||
|
t_diag("'%s' != '%s'", a, b);
|
||
|
return TEST_FAIL;
|
||
|
}
|
||
|
|
||
|
void __attribute__((__noreturn__)) crash(const char *fmt, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
va_start(ap, fmt);
|
||
|
vfprintf(stderr, fmt, ap);
|
||
|
va_end(ap);
|
||
|
fputc('\n', stderr);
|
||
|
|
||
|
exit(1);
|
||
|
}
|