#include #include #include #include #include <9p.h> #include "common.h" #include "debug.h" #include "unittest.h" #define DEBUG_TESTCASE true #define DEBUG_TESTSUITE true #define DEBUG_TESTRESULT true void abstracttest_init(AbstractTest *self, char *name) { assert_valid(self); assert_valid(name); self->name = estrdup_fs(name); self->next = nil; } void abstracttest_run(AbstractTest *self, TestResult *result) { assert_valid(self); assert_valid(result); assert_valid(self->run); self->run(self, result); } void abstracttest_free(AbstractTest *self) { if(self == nil) { return; } assert_valid(self->free); abstracttest_free(self->next); self->free(self); free(self->name); free(self); } void testresult_init(TestResult *self) { assert_valid(self); self->totalsuccess = 0; self->totalfailure = 0; self->totalerror = 0; } static void testresult_add_failure(TestResult *self, AbstractTest *test) { assert_valid(self); assert_valid(test); ++(self->totalfailure); INFO(DEBUG_TESTRESULT, "testcase %s FAILED", test->name); } static void testresult_add_error(TestResult *self, AbstractTest *test) { assert_valid(self); assert_valid(test); ++(self->totalerror); INFO(DEBUG_TESTRESULT, "testcase %s generated ERROR", test->name); } static void testresult_add_success(TestResult *self, AbstractTest *test) { assert_valid(self); assert_valid(test); ++(self->totalsuccess); INFO(DEBUG_TESTRESULT, "testcase %s PASSED", test->name); } uint testresult_total_tests(TestResult *self) { assert_valid(self); return self->totalfailure + self->totalsuccess + self->totalerror; } float testresult_success_rate(TestResult *self) { assert_valid(self); return ((float) self->totalsuccess) / testresult_total_tests(self); } void testresult_report(TestResult *self) { assert_valid(self); INFO(DEBUG_TESTRESULT, "Total %d tests" " success: %d, failure: %d, error: %d, success rate: %f", testresult_total_tests(self), self->totalsuccess, self->totalfailure, self->totalerror, testresult_success_rate(self)); } void testcase_run(AbstractTest *test, TestResult *result) { void *data; TestCase *self = (TestCase *)test; assert_valid(self); assert_valid(result); assert_valid(self->setup); assert_valid(self->teardown); INFO(DEBUG_TESTCASE, "testcase_run running %s", test->name); data = self->setup(); if(!self->test(data)) { testresult_add_failure(result, (AbstractTest *)self); } else { testresult_add_success(result, (AbstractTest *)self); } self->teardown(data); } void testcase_free(AbstractTest *test) { if(test == nil) { return; } NOISE(DEBUG_TESTCASE, "testcase_free freeing %s", test->name); } TestCase *testcase_new_fixure(char *name, TestFixure *fixure, testcase_test test) { assert_valid(fixure); return testcase_new(name, fixure->setup, fixure->teardown, test); } TestCase *testcase_new(char *name, testcase_setup setup, testcase_teardown teardown, testcase_test test) { TestCase *result; assert_valid(test); result = (TestCase *)emalloc_fs(sizeof(*result)); abstracttest_init(result, name); result->run = testcase_run; result->free = testcase_free; result->setup = setup; result->teardown = teardown; result->test = test; return result; } void testsuite_run(AbstractTest *test, TestResult *result) { AbstractTest *current; TestSuite *self = (TestSuite *)test; assert_valid(self); assert_valid(result); INFO(DEBUG_TESTSUITE, "testsuite_run running %s", test->name); current = self->head; while(current != nil) { abstracttest_run(current, result); current = current->next; } } void testsuite_free(AbstractTest *test) { TestSuite *self = (TestSuite *)test; if(self == nil) { return; } NOISE(DEBUG_TESTSUITE, "testsuite_free freeing %s", test->name); abstracttest_free(self->head); } TestSuite *testsuite_new(char *name) { TestSuite *result; assert_valid(name); result = (TestSuite *)emalloc_fs(sizeof(*result)); abstracttest_init(result, name); result->run = testsuite_run; result->free = testsuite_free; result->head = nil; return result; } void testsuite_add(TestSuite *self, AbstractTest *test) { assert_valid(self); assert_valid(test); NOISE(DEBUG_TESTSUITE, "testsuite_add adding %s", test->name); test->next = self->head; self->head = test; } TestSuite *testsuite_make(char *name, TestCaseNamePair *pairs, uint total, TestFixure *fixure) { int i; TestSuite *result; assert_valid(name); assert_valid(pairs); assert_valid(fixure); result = testsuite_new(name); for(i = 0; i < total; ++i) { testsuite_add(result, (AbstractTest *)testcase_new_fixure( pairs[i].name, fixure, pairs[i].test)); } return result; }