aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2020-08-07 22:47:46 +0200
committerTom Smeding <tom.smeding@gmail.com>2020-08-07 22:47:46 +0200
commit8f17684810718973c8ea0f1150e46d6c1b8c0ef1 (patch)
treed03b30c0a14e75e6c3374af3744cf7d7b1789f39 /test
parenta260f02eac411171a827c9e0aeb31b8de397a5b5 (diff)
server: Add basic unit test framework
Diffstat (limited to 'test')
-rw-r--r--test/hashtable.c8
-rw-r--r--test/main.c49
-rw-r--r--test/test_framework.c14
-rw-r--r--test/test_framework.h25
4 files changed, 96 insertions, 0 deletions
diff --git a/test/hashtable.c b/test/hashtable.c
new file mode 100644
index 0000000..cfb2d9d
--- /dev/null
+++ b/test/hashtable.c
@@ -0,0 +1,8 @@
+#include "test_framework.h"
+
+
+DEFINE_TEST(hashtable) {
+ EXPECT(1);
+ EXPECT(0);
+ return 0;
+}
diff --git a/test/main.c b/test/main.c
new file mode 100644
index 0000000..ebfe3da
--- /dev/null
+++ b/test/main.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdatomic.h>
+#include <time.h>
+#include "test_framework.h"
+#include "test_declarations.h"
+
+#define STR_(x) #x
+#define STR(x) STR_(x)
+
+
+// Referred to via extern in 'test_framework.c'
+atomic_flag test_framework_assertion_failed = ATOMIC_FLAG_INIT;
+
+
+static void report(const char *clr, const char *label, const char *name, clock_t taken) {
+ printf("\x1B[%sm[%s] %s (%lfs)\n",
+ clr, label, name, (double)taken / CLOCKS_PER_SEC);
+}
+
+static void report_success(const char *name, clock_t taken) {
+ report("32", " OK ", name, taken);
+}
+
+static void report_failure(const char *name, clock_t taken) {
+ report("31", "FAILED", name, taken);
+}
+
+#define RUN_TEST(name) do { \
+ atomic_flag_clear(&test_framework_assertion_failed); \
+ clock_t start_ = clock(); \
+ int ret_ = TEST(name)(); \
+ clock_t diff_ = clock() - start_; \
+ if (ret_ == 0 && !atomic_flag_test_and_set(&test_framework_assertion_failed)) { \
+ report_success(STR(name), diff_); \
+ } else { \
+ report_failure(STR(name), diff_); \
+ return 1; \
+ } \
+ } while (0)
+
+static int run_tests(void) {
+ RUN_TEST(hashtable);
+ return 0;
+}
+
+
+int main(void) {
+ return run_tests();
+}
diff --git a/test/test_framework.c b/test/test_framework.c
new file mode 100644
index 0000000..8cd53ac
--- /dev/null
+++ b/test/test_framework.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdatomic.h>
+#include "test_framework.h"
+
+
+extern atomic_flag test_framework_assertion_failed;
+
+
+void test_report_error(
+ const char *type, const char *condition, const char *fname, int lineno) {
+ printf("\x1B[31;1m%s:%d: Assertion failed:\n %s(%s)\x1B[0m\n",
+ fname, lineno, type, condition);
+ atomic_flag_test_and_set(&test_framework_assertion_failed);
+}
diff --git a/test/test_framework.h b/test/test_framework.h
new file mode 100644
index 0000000..7ab4816
--- /dev/null
+++ b/test/test_framework.h
@@ -0,0 +1,25 @@
+#pragma once
+
+
+#define TEST(name) testfn__ ## name
+
+// Test function should return 0 on success, nonzero value on error
+#ifdef TEST_HEADER_GENERATION
+#define DEFINE_TEST(name) XXTEST_DECLARATION(TEST(name))
+#else
+#define DEFINE_TEST(name) int TEST(name)(void)
+#endif
+
+void test_report_error(
+ const char *type, const char *condition, const char *fname, int lineno);
+
+#define EXPECT(cond_) do { \
+ if (!(cond_)) test_report_error("EXPECT", #cond_, __FILE__, __LINE__); \
+ } while (0)
+
+#define EXPECTRET(cond_, ret_) do { \
+ if (!(cond_)) { \
+ test_report_error("EXPECT", #cond_, __FILE__, __LINE__); \
+ return (ret_); \
+ } \
+ }