summaryrefslogtreecommitdiff
path: root/lily-test.h
diff options
context:
space:
mode:
Diffstat (limited to 'lily-test.h')
-rw-r--r--lily-test.h104
1 files changed, 104 insertions, 0 deletions
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