Files
mpc/tests/ptest.c

357 lines
7.2 KiB
C
Raw Permalink Normal View History

2013-09-23 22:41:58 +01:00
#include "ptest.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
/* Globals */
2013-09-30 20:55:57 +01:00
enum {
MAX_NAME = 512
};
enum {
MAX_ERROR = 2048
};
enum {
MAX_TESTS = 2048
};
2013-09-23 22:41:58 +01:00
2013-09-30 20:55:57 +01:00
static int test_passing = 0;
static int suite_passing = 0;
2013-09-23 22:41:58 +01:00
/* Colors */
enum {
2015-02-22 17:22:34 +00:00
BLACK = 0,
BLUE = 1,
GREEN = 2,
AQUA = 3,
RED = 4,
PURPLE = 5,
YELLOW = 6,
WHITE = 7,
GRAY = 8,
2020-01-08 22:07:32 -08:00
2015-02-22 17:22:34 +00:00
LIGHT_BLUE = 9,
LIGHT_GREEN = 10,
LIGHT_AQUA = 11,
LIGHT_RED = 12,
LIGHT_PURPLE = 13,
LIGHT_YELLOW = 14,
LIGHT_WHITE = 15,
2020-01-08 22:07:32 -08:00
2015-03-10 10:50:29 +00:00
DEFAULT = 16
2013-09-23 22:41:58 +01:00
};
#ifdef _WIN32
2015-02-22 17:22:34 +00:00
#include <windows.h>
2013-09-23 22:41:58 +01:00
2015-02-22 17:22:34 +00:00
static WORD defaults;
static int defaults_loaded = 0;
static void pt_color(int color) {
2020-01-08 22:07:32 -08:00
2015-02-22 17:22:34 +00:00
HANDLE cnsl = GetStdHandle(STD_OUTPUT_HANDLE);
2020-01-08 22:07:32 -08:00
2015-02-22 17:22:34 +00:00
if (!defaults_loaded) {
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(cnsl, &info);
defaults = info.wAttributes;
defaults_loaded = 1;
2013-09-23 22:41:58 +01:00
}
2020-01-08 22:07:32 -08:00
2015-02-22 17:22:34 +00:00
SetConsoleTextAttribute(cnsl, color == DEFAULT ? defaults : color);
}
2013-09-23 22:41:58 +01:00
#else
static const char* colors[] = {
"\x1B[0m",
"\x1B[34m",
"\x1B[32m",
"\x1B[36m",
"\x1B[31m",
"\x1B[35m",
"\x1B[33m",
"\x1B[37m",
"",
"\x1B[34m",
"\x1B[32m",
"\x1B[36m",
"\x1B[31m",
"\x1B[35m",
"\x1B[33m",
2015-02-22 17:22:34 +00:00
"\x1B[37m",
"\x1B[39m",
2013-09-23 22:41:58 +01:00
};
2020-01-08 22:07:32 -08:00
static void pt_color(int color) {
2015-02-22 17:22:34 +00:00
printf("%s", colors[color]);
}
2013-09-23 22:41:58 +01:00
#endif
/* Asserts */
static int num_asserts = 0;
static int num_assert_passes = 0;
static int num_assert_fails = 0;
static char assert_err[MAX_ERROR];
static char assert_err_buff[MAX_ERROR];
static int assert_err_num = 0;
2015-03-10 10:50:29 +00:00
void pt_assert_run(int result, const char* expr, const char* file, int line) {
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
num_asserts++;
test_passing = test_passing && result;
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
if (result) {
num_assert_passes++;
} else {
2020-01-08 22:07:32 -08:00
sprintf(assert_err_buff,
" %i. Assert [ %s ] (%s:%i)\n",
2015-02-22 17:22:34 +00:00
assert_err_num+1, expr, file, line );
2013-09-23 22:41:58 +01:00
strcat(assert_err, assert_err_buff);
assert_err_num++;
num_assert_fails++;
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
}
static void ptest_signal(int sig) {
2015-02-22 17:22:34 +00:00
2013-09-30 20:55:57 +01:00
test_passing = 0;
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
switch( sig ) {
2015-02-22 17:22:34 +00:00
case SIGFPE: sprintf(assert_err_buff,
" %i. Division by Zero\n", assert_err_num+1);
break;
case SIGILL: sprintf(assert_err_buff,
" %i. Illegal Instruction\n", assert_err_num+1);
break;
case SIGSEGV: sprintf(assert_err_buff,
" %i. Segmentation Fault\n", assert_err_num+1);
break;
2015-03-10 10:50:29 +00:00
default: break;
2013-09-23 22:41:58 +01:00
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
assert_err_num++;
strcat(assert_err, assert_err_buff);
2020-01-08 22:07:32 -08:00
pt_color(RED);
2015-02-22 17:22:34 +00:00
printf("Failed! \n\n%s\n", assert_err);
pt_color(DEFAULT);
2020-01-08 22:07:32 -08:00
2015-02-22 17:22:34 +00:00
puts(" | Stopping Execution.");
2013-09-23 22:41:58 +01:00
fflush(stdout);
exit(0);
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
}
/* Tests */
static void pt_title_case(char* output, const char* input) {
2015-02-22 17:22:34 +00:00
2013-09-30 20:55:57 +01:00
int space = 1;
2015-02-22 17:22:34 +00:00
unsigned int i;
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
strcpy(output, input);
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
for(i = 0; i < strlen(output); i++) {
2015-02-22 17:22:34 +00:00
2013-09-23 22:41:58 +01:00
if (output[i] == '_' || output[i] == ' ') {
2013-09-30 20:55:57 +01:00
space = 1;
2013-09-23 22:41:58 +01:00
output[i] = ' ';
continue;
2020-01-08 22:07:32 -08:00
}
2013-09-23 22:41:58 +01:00
if (space && output[i] >= 'a' && output[i] <= 'z') {
2013-10-04 17:58:27 +01:00
space = 0;
2013-09-23 22:41:58 +01:00
output[i] = output[i] - 32;
continue;
}
2020-01-08 22:07:32 -08:00
2013-09-30 20:55:57 +01:00
space = 0;
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
}
typedef struct {
void (*func)(void);
char name[MAX_NAME];
char suite[MAX_NAME];
} test_t;
static test_t tests[MAX_TESTS];
static int num_tests = 0;
static int num_tests_passes = 0;
static int num_tests_fails = 0;
void pt_add_test(void (*func)(void), const char* name, const char* suite) {
2015-02-22 17:22:34 +00:00
2013-09-30 20:55:57 +01:00
test_t test;
2013-09-23 22:41:58 +01:00
if (num_tests == MAX_TESTS) {
2020-01-08 22:07:32 -08:00
printf("ERROR: Exceeded maximum test count of %i!\n",
2015-02-22 17:22:34 +00:00
MAX_TESTS); abort();
2013-09-23 22:41:58 +01:00
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
if (strlen(name) >= MAX_NAME) {
2020-01-08 22:07:32 -08:00
printf("ERROR: Test name '%s' too long (Maximum is %i characters)\n",
2015-02-22 17:22:34 +00:00
name, MAX_NAME); abort();
2013-09-23 22:41:58 +01:00
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
if (strlen(suite) >= MAX_NAME) {
2020-01-08 22:07:32 -08:00
printf("ERROR: Test suite '%s' too long (Maximum is %i characters)\n",
2015-02-22 17:22:34 +00:00
suite, MAX_NAME); abort();
2013-09-23 22:41:58 +01:00
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
test.func = func;
pt_title_case(test.name, name);
pt_title_case(test.suite, suite);
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
tests[num_tests] = test;
num_tests++;
}
/* Suites */
static int num_suites = 0;
static int num_suites_passes = 0;
static int num_suites_fails = 0;
void pt_add_suite(void (*func)(void)) {
num_suites++;
func();
}
/* Running */
static clock_t start, end;
static char current_suite[MAX_NAME];
int pt_run(void) {
2020-01-08 22:07:32 -08:00
2015-03-10 10:50:29 +00:00
int i;
2013-09-30 20:55:57 +01:00
double total;
2015-02-22 17:22:34 +00:00
test_t test;
2013-09-30 20:55:57 +01:00
2015-02-22 17:22:34 +00:00
puts("");
puts(" +-------------------------------------------+");
puts(" | ptest MicroTesting Magic for C |");
puts(" | |");
puts(" | http://github.com/orangeduck/ptest |");
puts(" | |");
puts(" | Daniel Holden (contact@theorangeduck.com) |");
puts(" +-------------------------------------------+");
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
signal(SIGFPE, ptest_signal);
signal(SIGILL, ptest_signal);
signal(SIGSEGV, ptest_signal);
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
start = clock();
strcpy(current_suite, "");
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
for(i = 0; i < num_tests; i++) {
2015-02-22 17:22:34 +00:00
test = tests[i];
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
/* Check for transition to a new suite */
if (strcmp(test.suite, current_suite)) {
2015-02-22 17:22:34 +00:00
2013-09-23 22:41:58 +01:00
/* Don't increment any counter for first entrance */
if (strcmp(current_suite, "")) {
if (suite_passing) {
num_suites_passes++;
} else {
num_suites_fails++;
}
}
2020-01-08 22:07:32 -08:00
2013-09-30 20:55:57 +01:00
suite_passing = 1;
2013-09-23 22:41:58 +01:00
strcpy(current_suite, test.suite);
printf("\n\n ===== %s =====\n\n", current_suite);
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
/* Run Test */
2020-01-08 22:07:32 -08:00
2013-09-30 20:55:57 +01:00
test_passing = 1;
2013-09-23 22:41:58 +01:00
strcpy(assert_err, "");
strcpy(assert_err_buff, "");
assert_err_num = 0;
printf(" | %s ... ", test.name);
2015-02-22 17:22:34 +00:00
fflush(stdout);
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
test.func();
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
suite_passing = suite_passing && test_passing;
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
if (test_passing) {
num_tests_passes++;
2015-02-22 17:22:34 +00:00
pt_color(GREEN);
puts("Passed!");
pt_color(DEFAULT);
2013-09-23 22:41:58 +01:00
} else {
num_tests_fails++;
2020-01-08 22:07:32 -08:00
pt_color(RED);
2015-02-22 17:22:34 +00:00
printf("Failed! \n\n%s\n", assert_err);
pt_color(DEFAULT);
2013-09-23 22:41:58 +01:00
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
if (suite_passing) {
num_suites_passes++;
} else {
num_suites_fails++;
}
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
end = clock();
2020-01-08 22:07:32 -08:00
2015-02-22 17:22:34 +00:00
puts("");
puts(" +---------------------------------------------------+");
puts(" | Summary |");
puts(" +---------++------------+-------------+-------------+");
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
printf(" | Suites ||");
2020-01-08 22:07:32 -08:00
pt_color(YELLOW); printf(" Total %4d ", num_suites);
2015-02-22 17:22:34 +00:00
pt_color(DEFAULT); putchar('|');
2020-01-08 22:07:32 -08:00
pt_color(GREEN); printf(" Passed %4d ", num_suites_passes);
2015-02-22 17:22:34 +00:00
pt_color(DEFAULT); putchar('|');
2020-01-08 22:07:32 -08:00
pt_color(RED); printf(" Failed %4d ", num_suites_fails);
2015-02-22 17:22:34 +00:00
pt_color(DEFAULT); puts("|");
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
printf(" | Tests ||");
2020-01-08 22:07:32 -08:00
pt_color(YELLOW); printf(" Total %4d ", num_tests);
2015-02-22 17:22:34 +00:00
pt_color(DEFAULT); putchar('|');
2020-01-08 22:07:32 -08:00
pt_color(GREEN); printf(" Passed %4d ", num_tests_passes);
2015-02-22 17:22:34 +00:00
pt_color(DEFAULT); putchar('|');
2020-01-08 22:07:32 -08:00
pt_color(RED); printf(" Failed %4d ", num_tests_fails);
2015-02-22 17:22:34 +00:00
pt_color(DEFAULT); puts("|");
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
printf(" | Asserts ||");
2020-01-08 22:07:32 -08:00
pt_color(YELLOW); printf(" Total %4d ", num_asserts);
2015-02-22 17:22:34 +00:00
pt_color(DEFAULT); putchar('|');
2020-01-08 22:07:32 -08:00
pt_color(GREEN); printf(" Passed %4d ", num_assert_passes);
2015-02-22 17:22:34 +00:00
pt_color(DEFAULT); putchar('|');
2020-01-08 22:07:32 -08:00
pt_color(RED); printf(" Failed %4d ", num_assert_fails);
2015-02-22 17:22:34 +00:00
pt_color(DEFAULT); puts("|");
2020-01-08 22:07:32 -08:00
2015-02-22 17:22:34 +00:00
puts(" +---------++------------+-------------+-------------+");
puts("");
2020-01-08 22:07:32 -08:00
2013-09-30 20:55:57 +01:00
total = (double)(end - start) / CLOCKS_PER_SEC;
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
printf(" Total Running Time: %0.3fs\n\n", total);
2020-01-08 22:07:32 -08:00
2013-09-23 22:41:58 +01:00
if (num_suites_fails > 0) { return 1; } else { return 0; }
}