]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/lib/test.qh
Unnecessary newlines are unnecessary
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / test.qh
index d1f5357a5ef39bb5c8bddde4a8a4671b64c07c4d..ff6f2d23d5b52f1e00d75ba699c6552031ba8f5b 100644 (file)
@@ -1,13 +1,96 @@
-#ifndef TEST_H
-#define TEST_H
+#pragma once
 
-#include "../common/util.qh"
+// public:
 
-#define TEST_Check(cond) do { if(!(cond)) TEST_Fail(#cond); } while(0)
+/** Use UpperCamelCase for suite and test only */
+#define TEST(suite, test) \
+       void _TEST_##suite##_##test(); \
+       [[accumulate]] int TEST_RunAll_accumulated(int f) { \
+               if (!TEST_Run(#suite "_" #test)) ++f; \
+               return = f; \
+       } \
+       void _TEST_##suite##_##test()
 
-void TEST_OK();
-void TEST_Fail(string cond);
+/** Must be present at the end of a test */
+#define SUCCEED() (TEST_ok = true)
 
-float TEST_RunAll();
-float TEST_Run(string test);
-#endif
+/** Add a failure, but continue */
+#define ADD_FAILURE(msg) MACRO_BEGIN { ++TEST_failed; LOG_WARN(msg); } MACRO_END
+
+/** Add a failure and return */
+#define FAIL(msg) _TEST_ASSERT(ADD_FAILURE(msg))
+
+#define HasFatalFailure() (TEST_fatal > 0)
+
+bool RUN_ALL_TESTS();
+
+// difference between expect/assert: assert returns early
+
+#define EXPECT_EQ(expected_, actual_) MACRO_BEGIN { \
+       int expected = expected_; \
+       int actual = actual_; \
+       if ((expected) != (actual)) { \
+               ADD_FAILURE(sprintf( \
+                       "Value of: " #actual_ "\n" \
+                       "  Actual: %d\n" \
+                       "Expected: %d\n", \
+                       actual, expected \
+               )); \
+       } \
+} MACRO_END
+#define ASSERT_EQ(expected, actual) _TEST_ASSERT(EXPECT_EQ(expected, actual))
+
+#define EXPECT_TRUE(condition) EXPECT_EQ(true, condition)
+#define ASSERT_TRUE(condition) ASSERT_EQ(true, condition)
+
+#define EXPECT_FALSE(condition) EXPECT_EQ(false, condition)
+#define ASSERT_FALSE(condition) ASSERT_EQ(false, condition)
+
+#define EXPECT_NE(val1, val2) EXPECT_TRUE((val1) != (val2))
+#define ASSERT_NE(val1, val2) _TEST_ASSERT(EXPECT_NE(val1, val2))
+
+#define EXPECT_LT(val1, val2) EXPECT_TRUE((val1) < (val2))
+#define ASSERT_LT(val1, val2) _TEST_ASSERT(EXPECT_LT(val1, val2))
+
+#define EXPECT_LE(val1, val2) EXPECT_TRUE((val1) <= (val2))
+#define ASSERT_LE(val1, val2) _TEST_ASSERT(EXPECT_LE(val1, val2))
+
+#define EXPECT_GT(val1, val2) EXPECT_TRUE((val1) > (val2))
+#define ASSERT_GT(val1, val2) _TEST_ASSERT(EXPECT_GT(val1, val2))
+
+#define EXPECT_GE(val1, val2) EXPECT_TRUE((val1) >= (val2))
+#define ASSERT_GE(val1, val2) _TEST_ASSERT(EXPECT_GE(val1, val2))
+
+#define EXPECT_NO_FATAL_FAILURE(statement) EXPECT_NO_FATAL_FAILURE_(statement, { })
+#define ASSERT_NO_FATAL_FAILURE(statement) EXPECT_NO_FATAL_FAILURE_(statement, { ++TEST_fatal; return; })
+
+// private:
+
+bool TEST_Run(string test);
+int TEST_fatal;
+bool TEST_ok;
+int TEST_failed;
+
+#define _TEST_ASSERT(statement) \
+       MACRO_BEGIN { \
+               LAMBDA(statement); \
+               ++TEST_fatal; return; \
+       } MACRO_END
+
+#define EXPECT_NO_FATAL_FAILURE__(statement, then) \
+       MACRO_BEGIN { \
+               int TEST_prevfatal = TEST_fatal; \
+               LAMBDA(statement); \
+               if (TEST_fatal != TEST_prevfatal) \
+                       LAMBDA(then); \
+       } MACRO_END
+
+#define EXPECT_NO_FATAL_FAILURE_(statement, then) \
+       EXPECT_NO_FATAL_FAILURE__(statement, { \
+               LOG_WARNF( \
+                       "  Actual: %d fatal failures\n" \
+                       "Expected: no fatal failures\n", \
+                       TEST_fatal - TEST_prevfatal \
+               ); \
+               LAMBDA(then); \
+       })