summaryrefslogtreecommitdiff
path: root/test/unit/TestRunner.h
diff options
context:
space:
mode:
authorpepper <peppersclothescult@gmail.com>2015-01-10 21:32:32 -0800
committerpepper <peppersclothescult@gmail.com>2015-01-10 21:32:32 -0800
commitd53fa8a169832563c62262078b8d2ffe5cab8473 (patch)
treeb911d06d357d009c976709780f10e92ce915228a /test/unit/TestRunner.h
first
Diffstat (limited to 'test/unit/TestRunner.h')
-rw-r--r--test/unit/TestRunner.h173
1 files changed, 173 insertions, 0 deletions
diff --git a/test/unit/TestRunner.h b/test/unit/TestRunner.h
new file mode 100644
index 0000000..597a80a
--- /dev/null
+++ b/test/unit/TestRunner.h
@@ -0,0 +1,173 @@
+#ifndef MrsWatsonTest_TestRunner_h
+#define MrsWatsonTest_TestRunner_h
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "base/CharString.h"
+#include "base/File.h"
+#include "logging/LogPrinter.h"
+
+#if UNIX
+#include <unistd.h>
+#endif
+
+#ifndef __func__
+#define __func__ __FUNCTION__
+#endif
+
+typedef enum {
+ kTestLogEventSection,
+ kTestLogEventPass,
+ kTestLogEventFail,
+ kTestLogEventSkip,
+ kTestLogEventReset,
+ kTestLogEventInvalid
+} TestLogEventType;
+const LogColor getLogColor(TestLogEventType eventType);
+
+typedef int (*TestCaseExecFunc)(void);
+typedef void (*TestCaseSetupFunc)(void);
+typedef void (*TestCaseTeardownFunc)(void);
+
+typedef struct {
+ char *name;
+ char *filename;
+ int lineNumber;
+ TestCaseExecFunc testCaseFunc;
+} TestCaseMembers;
+typedef TestCaseMembers *TestCase;
+
+typedef struct {
+ char *name;
+ int numSuccess;
+ int numFail;
+ int numSkips;
+ LinkedList testCases;
+ TestCaseSetupFunc setup;
+ TestCaseTeardownFunc teardown;
+ boolByte onlyPrintFailing;
+ boolByte keepFiles;
+} TestSuiteMembers;
+typedef TestSuiteMembers *TestSuite;
+
+void addTestToTestSuite(TestSuite testSuite, TestCase testCase);
+void runTestSuite(void *testSuitePtr, void *extraData);
+void runTestCase(void *item, void *extraData);
+void printTestName(const char *testName);
+void printTestSuccess(void);
+void printTestFail(void);
+
+TestSuite newTestSuite(char *name, TestCaseSetupFunc setup, TestCaseTeardownFunc teardown);
+TestCase newTestCase(char *name, char *filename, int lineNumber, TestCaseExecFunc testCaseFunc);
+
+void freeTestCase(TestCase self);
+void freeTestSuite(TestSuite self);
+
+static const char *_getFileBasename(const char *filename)
+{
+ const char *lastDelimiter;
+
+ if (filename == NULL) {
+ return NULL;
+ }
+
+ lastDelimiter = strrchr(filename, PATH_DELIMITER);
+
+ if (lastDelimiter == NULL) {
+ return (char *)filename;
+ } else {
+ return lastDelimiter + 1;
+ }
+}
+
+#define addTest(testSuite, name, testCaseFunc) { \
+ addTestToTestSuite(testSuite, newTestCase(name, __FILE__, __LINE__, testCaseFunc)); \
+ }
+
+#define assert(_result) { \
+ if(!(_result)) { \
+ fprintf(stderr, "\nAssertion failed at %s:%d. ", _getFileBasename(__FILE__), __LINE__); \
+ return 1; \
+ } \
+ }
+
+#define assertFalse(_result) assert((_result) == false)
+#define assertIsNull(_result) assert((_result) == NULL)
+#define assertNotNull(_result) assert((_result) != NULL)
+
+#define assertIntEquals(expected, _result) { \
+ int _resultInt = _result; \
+ if(_resultInt != expected) { \
+ fprintf(stderr, "Assertion failed at %s:%d. Expected %d, got %d. ", _getFileBasename(__FILE__), __LINE__, expected, _resultInt); \
+ return 1; \
+ } \
+ }
+
+#define assertLongEquals(expected, _result) { \
+ long _resultLong = _result; \
+ if(_resultLong != expected) { \
+ fprintf(stderr, "Assertion failed at %s:%d. Expected %lu, got %lu. ", _getFileBasename(__FILE__), __LINE__, expected, _resultLong); \
+ return 1; \
+ } \
+ }
+
+#define ZERO_UNSIGNED_LONG (unsigned long)0
+#define assertUnsignedLongEquals(expected, _result) { \
+ unsigned long _resultULong = _result; \
+ if(_resultULong != expected) { \
+ fprintf(stderr, "Assertion failed at %s:%d. Expected %ld, got %ld. ", _getFileBasename(__FILE__), __LINE__, expected, _resultULong); \
+ return 1; \
+ } \
+ }
+
+#define assertSizeEquals(expected, _result) { \
+ size_t _resultSize = _result; \
+ if(_result != expected) { \
+ fprintf(stderr, "Assertion failed at %s:%d. Expected %zu, got %zu. ", _getFileBasename(__FILE__), __LINE__, expected, _resultSize); \
+ return 1; \
+ } \
+ }
+
+#define TEST_DEFAULT_TOLERANCE 0.01
+#define TEST_EXACT_TOLERANCE 0.0
+
+#define assertDoubleEquals(expected, _result, tolerance) { \
+ double resultRounded = floor(_result * 100.0) / 100.0; \
+ double expectedRounded = floor(expected * 100.0) / 100.0; \
+ double _resultDiff = fabs(resultRounded - expectedRounded); \
+ if(_resultDiff > tolerance) { \
+ fprintf(stderr, "Assertion failed at %s:%d. Expected %g, got %g. ", _getFileBasename(__FILE__), __LINE__, expectedRounded, resultRounded); \
+ return 1; \
+ } \
+ }
+
+ // Timing assertions fail all the time in debug mode, because the binary is
+ // running in the debugger, is not optimized, is being profiled, etc. So for
+ // debug builds, we should not return early here, or else that will cause
+ // valgrind to go crazy and report a bunch of leaks.
+#define assertTimeEquals(expected, _result, tolerance) { \
+ double resultRounded = floor(_result * 100.0) / 100.0; \
+ double expectedRounded = floor(expected * 100.0) / 100.0; \
+ double _resultDiff = fabs(resultRounded - expectedRounded); \
+ if(_resultDiff > tolerance) { \
+ fprintf(stderr, "Warning: timing assertion failed at %s:%d. Expected %gms, got %gms. ", _getFileBasename(__FILE__), __LINE__, expectedRounded, resultRounded); \
+ } \
+ }
+
+#define assertCharStringEquals(expected, _result) { \
+ if(!charStringIsEqualToCString(_result, expected, false)) { \
+ fprintf(stderr, "Assertion failed at %s:%d. Expected '%s', got '%s'. ", _getFileBasename(__FILE__), __LINE__, expected, _result->data); \
+ return 1; \
+ } \
+ }
+
+#define assertCharStringContains(expected, _result) { \
+ if(strstr(_result->data, expected) == NULL) { \
+ fprintf(stderr, "Assertion failed at %s:%d. Expected '%s' to contain '%s'. ", _getFileBasename(__FILE__), __LINE__, _result->data, expected); \
+ return 1; \
+ } \
+ }
+
+#endif