FxLibcTest/src/test.c

135 lines
2.7 KiB
C

#include <ft/test.h>
#include <gint/std/stdio.h>
#include <gint/std/stdlib.h>
#include <stdarg.h>
#undef ft_assert
//---
// Test framework
//---
void ft_test_init(ft_test *test)
{
test->passed = 0;
test->skipped = 0;
test->failed = 0;
test->log = NULL;
test->log_size = 0;
}
void ft_test_run(ft_test *test)
{
if(test->log) free(test->log);
ft_test_init(test);
test->run = true;
if(!test->function) return;
test->function(test);
}
int ft_assert(ft_test *test, int expression, char const *file, int line,
char const *str)
{
if(expression) {
test->passed++;
}
else {
test->failed++;
ft_log(test, "%s:%d: assertion failed:\n %s\n", file, line, str);
}
return expression;
}
void ft_skip(ft_test *test, int count)
{
test->skipped += count;
}
void ft_log(ft_test *test, char const *format, ...)
{
va_list args1, args2;
va_start(args1, format);
va_copy(args2, args1);
int size = vsnprintf(NULL, 0, format, args1);
if(test->log_size + size > 0xffff) return;
char *newlog = realloc(test->log, test->log_size + size + 1);
if(!newlog) return;
vsnprintf(newlog + test->log_size, size + 1, format, args2);
test->log = newlog;
test->log_size += size;
}
//---
// Test lists (to organize by header)
//---
void ft_list_init(ft_list *list)
{
list->passed = 0;
list->skipped = 0;
list->failed = 0;
if(!list->children) return;
for(int i = 0; list->children[i]; i++) {
ft_test_init(list->children[i]);
}
}
void ft_list_run(ft_list *list)
{
ft_list_init(list);
if(!list->children) return;
for(int i = 0; list->children[i]; i++) {
ft_test_run(list->children[i]);
}
ft_list_aggregate(list);
}
void ft_list_aggregate(ft_list *l)
{
l->passed = 0;
l->skipped = 0;
l->failed = 0;
if(!l->children) return;
for(int i = 0; l->children[i]; i++) {
ft_test const *t = l->children[i];
l->passed += t->passed;
l->skipped += t->skipped;
l->failed += t->failed;
}
}
//---
// Utilities
//---
int ft_test_color(ft_test const *t)
{
if(t->failed > 0) return FT_TEST_FAILED;
if(t->skipped > 0) return FT_TEST_SKIPPED;
if(t->passed > 0) return FT_TEST_PASSED;
return (t->function && !t->run) ? FT_TEST_PENDING : FT_TEST_EMPTY;
}
int ft_list_color(ft_list const *l)
{
if(l->failed > 0) return FT_TEST_FAILED;
if(l->skipped > 0) return FT_TEST_SKIPPED;
if(l->children) {
for(int i = 0; l->children[i]; i++) {
if(l->children[i]->function && l->children[i]->run == 0)
return FT_TEST_PENDING;
}
}
if(l->passed > 0) return FT_TEST_PASSED;
return FT_TEST_EMPTY;
}