summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--lily-test.h104
-rw-r--r--tests/assertions.c79
-rw-r--r--tests/main.c2
-rw-r--r--tests/tests.h2
5 files changed, 188 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 15f0ce8..0758722 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,7 @@ add_executable(lily-metatest
${TEST_SRC}/main.c
${TEST_SRC}/helpers.c
${TEST_SRC}/macro-tests.c
+ ${TEST_SRC}/assertions.c
)
set_target_properties(lily-metatest PROPERTIES
C_STANDARD 90
diff --git a/lily-test.h b/lily-test.h
index 8f8b61c..c3f6f8c 100644
--- a/lily-test.h
+++ b/lily-test.h
@@ -53,6 +53,8 @@
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
+#include <stdio.h>
+#include <stdarg.h>
#define STR_IMP(x) #x
#define STR(x) STR_IMP(x)
@@ -106,6 +108,108 @@ static void f()
#define LILY_TEST(description) LILY_TEST_(LILY_ANON_FUNC, LILY_ANON_DESC, description)
+/* assertions */
+typedef struct lily_test_msg_t {
+ struct lily_test_msg_t *next;
+ char *msg;
+ const char *location;
+} lily_test_msg_t;
+void lily_msg_destroy(lily_test_msg_t *m);
+
+void lily_check(int x, const char *location, const char *fmt, ...);
+#define LILY_CHECK_(str, x, location) \
+ lily_check(x, location, "%s", str)
+#define LILY_CHECK(x) LILY_CHECK_(STR(x), x, LILY_LOCATION)
+#define CHECK(x) LILY_CHECK(x)
+
+
+void lily_require(int x, const char *location, const char *fmt, ...);
+#define LILY_REQUIRE_(str, x, location) \
+ lily_require(x, location, "%s", str)
+#define LILY_REQUIRE(x) LILY_REQUIRE_(STR(x), x, LILY_LOCATION)
+#define REQUIRE(x) LILY_REQUIRE(x)
+
+
+struct lily_global_t {
+ int failed;
+ jmp_buf env;
+ lily_test_msg_t HEAD;
+ lily_test_msg_t *TAIL;
+} extern lily_g;
+
+#ifdef LILY_IMPLEMENTATION
+struct lily_global_t lily_g;
+
+lily_test_msg_t *lily_msg_create(const char *location, const char *fmt, va_list args)
+{
+ lily_test_msg_t *m = malloc(sizeof(lily_test_msg_t));
+ if (m == NULL) {
+ return NULL;
+ }
+ m->next = NULL;
+ m->location = location;
+
+ va_list args_len;
+ va_copy(args_len, args);
+ size_t len = vsnprintf(NULL, 0, fmt, args_len) + 1;
+ va_end(args_len);
+
+ m->msg = malloc(len * sizeof(char));
+ if (m->msg == NULL) {
+ free(m);
+ return NULL;
+ }
+ vsnprintf(m->msg, len, fmt, args);
+
+ return m;
+}
+
+void lily_msg_destroy(lily_test_msg_t *m)
+{
+ if (m->next != NULL) {
+ // destroy the whole chain
+ lily_msg_destroy(m->next);
+ }
+
+ free(m->msg);
+ free(m);
+}
+
+void lily_check(int x, const char *location, const char *fmt, ...)
+{
+ if (!x) {
+ // assertion failed
+ va_list args;
+ va_start(args, fmt);
+ lily_test_msg_t *m = lily_msg_create(location, fmt, args);
+ va_end(args);
+
+ lily_g.TAIL->next = m;
+ lily_g.TAIL = m;
+ lily_g.failed = 1;
+ }
+}
+
+
+void lily_require(int x, const char *location, const char *fmt, ...)
+{
+ if (!x) {
+ // assertion failed
+ va_list args;
+ va_start(args, fmt);
+ lily_test_msg_t *m = lily_msg_create(location, fmt, args);
+ va_end(args);
+
+ lily_g.TAIL->next = m;
+ lily_g.TAIL = m;
+ lily_g.failed = 1;
+
+ /* longjump out of test */
+ longjmp(lily_g.env, 1);
+ }
+}
+#endif
+
/* ifdef LILY_TEST_H */
#else
diff --git a/tests/assertions.c b/tests/assertions.c
new file mode 100644
index 0000000..6ad855a
--- /dev/null
+++ b/tests/assertions.c
@@ -0,0 +1,79 @@
+#include "lily-test.h"
+#include "tests.h"
+
+
+const char * test_CHECK()
+{
+ lily_g.HEAD.next = NULL;
+ lily_g.TAIL = &(lily_g.HEAD);
+ lily_g.failed = 0;
+ CHECK(1 == 0);
+ CHECK(0 == 0);
+ CHECK(4 == 3);
+
+ if (lily_g.HEAD.next == NULL)
+ return "CHECK did not append any failure messages";
+ lily_test_msg_t *m = lily_g.HEAD.next;
+
+ if (strcmp(m->msg, "1 == 0") != 0)
+ return "first assert has wrong message";
+
+ if (m->next == NULL)
+ return "only one message appended";
+ m = m->next;
+
+ if (strcmp(m->msg, "4 == 3") != 0)
+ return "second message is incorrect";
+
+ if (m->next != NULL)
+ return "more than two messages appended!";
+
+ if (!lily_g.failed)
+ return "test did not fail!";
+
+ lily_msg_destroy(lily_g.HEAD.next);
+
+ return 0;
+}
+
+
+int aR, bR;
+static void f_test_REQUIRE()
+{
+ aR = 5;
+ REQUIRE(2+2 == 5);
+ bR = 5;
+}
+
+const char * test_REQUIRE()
+{
+ lily_g.HEAD.next = NULL;
+ lily_g.TAIL = &(lily_g.HEAD);
+ lily_g.failed = 0;
+ aR = 0; bR = 0;
+ int test_failed = setjmp(lily_g.env);
+
+ if (test_failed) {
+ if (!lily_g.failed)
+ return "test did not fail!";
+
+ if (lily_g.HEAD.next == NULL)
+ return "test did not generate any messages";
+
+ if (strcmp(lily_g.HEAD.next->msg, "2+2 == 5") != 0)
+ return "test generated incorrect message";
+
+ if (lily_g.HEAD.next->next != NULL)
+ return "test generated too many messages";
+
+ if (bR == 5)
+ return "test kept executing after failed REQUIRE";
+
+ lily_msg_destroy(lily_g.HEAD.next);
+ return 0;
+ }
+ else {
+ f_test_REQUIRE();
+ return "test function did not longjump!";
+ }
+}
diff --git a/tests/main.c b/tests/main.c
index 1598190..f1a6de6 100644
--- a/tests/main.c
+++ b/tests/main.c
@@ -3,6 +3,8 @@
#include <string.h>
#include <stdlib.h>
+#define LILY_IMPLEMENTATION
+#include "lily-test.h"
#include "tests.h"
int main()
diff --git a/tests/tests.h b/tests/tests.h
index 481260e..06c35af 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -12,6 +12,8 @@ int validate_message(const char* received, const char* expected,
X(test_LILY_COUNTER) \
X(test_LILY_COUNTER_DECREMENT) \
X(test_auto_registration) \
+ X(test_CHECK) \
+ X(test_REQUIRE) \
#define X(test) const char * test();
TESTS