diff options
Diffstat (limited to 'test/unit/TestRunner.c')
| -rw-r--r-- | test/unit/TestRunner.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/test/unit/TestRunner.c b/test/unit/TestRunner.c new file mode 100644 index 0000000..4c90cb3 --- /dev/null +++ b/test/unit/TestRunner.c @@ -0,0 +1,152 @@ +#include <stdlib.h> +#if WINDOWS +#include <io.h> +#endif + +#include "unit/TestRunner.h" + +void addTestToTestSuite(TestSuite testSuite, TestCase testCase) +{ + linkedListAppend(testSuite->testCases, testCase); +} + +const LogColor getLogColor(TestLogEventType eventType) +{ + switch (eventType) { + case kTestLogEventSection: + return isatty(1) ? COLOR_FG_CYAN : COLOR_NONE; + + case kTestLogEventPass: + return isatty(1) ? COLOR_FG_GREEN : COLOR_NONE; + + case kTestLogEventFail: + return isatty(1) ? COLOR_BG_MAROON : COLOR_NONE; + + case kTestLogEventSkip: + return isatty(1) ? COLOR_FG_YELLOW : COLOR_NONE; + + case kTestLogEventReset: + return isatty(1) ? COLOR_RESET : COLOR_NONE; + + default: + return COLOR_NONE; + } +} + +void printTestSuccess(void) +{ + printToLog(getLogColor(kTestLogEventPass), NULL, "OK"); + flushLog(NULL); +} + +void printTestFail(void) +{ + printToLog(getLogColor(kTestLogEventFail), NULL, "FAIL"); + flushLog(NULL); +} + +static void _printTestSkipped(void) +{ + printToLog(getLogColor(kTestLogEventSkip), NULL, "Skipped"); + flushLog(NULL); +} + +void printTestName(const char *testName) +{ + fprintf(stderr, " %s: ", testName); + // Flush standard output in case the test crashes. That way at least the + // crashing test name is seen. + fflush(stderr); +} + +void runTestCase(void *item, void *extraData) +{ + TestCase testCase = (TestCase)item; + TestSuite testSuite = (TestSuite)extraData; + int result; + + if (!testSuite->onlyPrintFailing) { + printTestName(testCase->name); + } + + if (testCase->testCaseFunc != NULL) { + if (testSuite->setup != NULL) { + testSuite->setup(); + } + + result = testCase->testCaseFunc(); + + if (result == 0) { + if (!testSuite->onlyPrintFailing) { + printTestSuccess(); + } + + testSuite->numSuccess++; + } else { + printTestFail(); + testSuite->numFail++; + } + + if (testSuite->teardown != NULL) { + testSuite->teardown(); + } + } else { + if (!testSuite->onlyPrintFailing) { + _printTestSkipped(); + } + + testSuite->numSkips++; + } +} + +void runTestSuite(void *testSuitePtr, void *extraData) +{ + TestSuite testSuite = (TestSuite)testSuitePtr; + + printToLog(getLogColor(kTestLogEventReset), NULL, "Running tests in "); + printToLog(getLogColor(kTestLogEventSection), NULL, testSuite->name); + flushLog(NULL); + + linkedListForeach(testSuite->testCases, runTestCase, testSuite); +} + +// In both the TestSuite and TestCase objects we assume that we do not need ownership of +// the strings passed in, since they should be allocated on the heap and live for the +// lifetime of the program. +TestSuite newTestSuite(char *name, TestCaseSetupFunc setup, TestCaseTeardownFunc teardown) +{ + TestSuite testSuite = (TestSuite)malloc(sizeof(TestSuiteMembers)); + testSuite->name = name; + testSuite->numSuccess = 0; + testSuite->numFail = 0; + testSuite->numSkips = 0; + testSuite->testCases = newLinkedList(); + testSuite->setup = setup; + testSuite->teardown = teardown; + testSuite->onlyPrintFailing = false; + testSuite->keepFiles = false; + return testSuite; +} + +TestCase newTestCase(char *name, char *filename, int lineNumber, TestCaseExecFunc testCaseFunc) +{ + TestCase testCase = (TestCase)malloc(sizeof(TestCaseMembers)); + testCase->name = name; + testCase->filename = filename; + testCase->lineNumber = lineNumber; + testCase->testCaseFunc = testCaseFunc; + return testCase; +} + +void freeTestCase(TestCase self) +{ + free(self); +} + +void freeTestSuite(TestSuite self) +{ + if (self != NULL) { + freeLinkedListAndItems(self->testCases, (LinkedListFreeItemFunc)freeTestCase); + free(self); + } +} |
