From: TimePath Date: Mon, 4 Jan 2016 09:18:46 +0000 (+1100) Subject: Testing: improve macros X-Git-Tag: xonotic-v0.8.2~1287 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=f099f166c5d50cebd0b7083a31ccf26e3df213b7;p=xonotic%2Fxonotic-data.pk3dir.git Testing: improve macros --- diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7de5568c1..bd671bf5c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,5 +18,5 @@ build: - while read line; do echo $line; if [[ $line == "All tests OK" ]]; then exit 0; fi; - done < <(${ENGINE} +map gitlab-ci +sv_cmd runtest +exit) + done < <(${ENGINE} +developer 1 +map gitlab-ci +sv_cmd runtest +exit) - exit 1 diff --git a/qcsrc/common/command/generic.qc b/qcsrc/common/command/generic.qc index 378d8c8c6..5b5359283 100644 --- a/qcsrc/common/command/generic.qc +++ b/qcsrc/common/command/generic.qc @@ -495,7 +495,7 @@ void GenericCommand_runtest(float request, float argc) TEST_Run(argv(i)); } else - TEST_RunAll(); + RUN_ALL_TESTS(); return; } diff --git a/qcsrc/lib/test.qc b/qcsrc/lib/test.qc index 1a71c7529..41e1f294a 100644 --- a/qcsrc/lib/test.qc +++ b/qcsrc/lib/test.qc @@ -1,22 +1,7 @@ #include "test.qh" -int TEST_failed; -bool TEST_ok; - -void TEST_Fail(string cond) -{ - LOG_INFOF("Assertion failed: %s", cond); - // backtrace(); - ++TEST_failed; -} - -void TEST_OK() -{ - TEST_ok = true; -} - int TEST_RunAll_accumulated(int init); -bool TEST_RunAll() +bool RUN_ALL_TESTS() { int f = TEST_RunAll_accumulated(0); if (f) @@ -35,6 +20,7 @@ bool TEST_Run(string s) { LOG_INFOF("%s: testing...\n", s); TEST_failed = 0; + TEST_fatal = 0; TEST_ok = false; callfunction(strcat("_TEST_", s)); if (TEST_failed > 0) diff --git a/qcsrc/lib/test.qh b/qcsrc/lib/test.qh index 9173696bf..af00f979c 100644 --- a/qcsrc/lib/test.qh +++ b/qcsrc/lib/test.qh @@ -1,5 +1,8 @@ #pragma once +// public: + +/** Use UpperCamelCase for suite and test only */ #define TEST(suite, test) \ void _TEST_##suite##_##test(); \ [[accumulate]] int TEST_RunAll_accumulated(int f) { \ @@ -8,10 +11,86 @@ } \ void _TEST_##suite##_##test() -#define TEST_Check(cond) MACRO_BEGIN { if (!(cond)) TEST_Fail(#cond); } MACRO_END +/** Must be present at the end of a test */ +#define SUCCEED() (TEST_ok = true) + +/** Add a failure, but continue */ +#define ADD_FAILURE(msg) MACRO_BEGIN { ++TEST_failed; LOG_WARNINGF(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) -void TEST_OK(); -void TEST_Fail(string cond); +#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_RunAll(); 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_WARNINGF( \ + " Actual: %d fatal failures\n" \ + "Expected: no fatal failures\n", \ + TEST_fatal - TEST_prevfatal \ + ); \ + LAMBDA(then); \ + }) diff --git a/qcsrc/lib/yenc.qh b/qcsrc/lib/yenc.qh index a9d9ed1f1..a8389e240 100644 --- a/qcsrc/lib/yenc.qh +++ b/qcsrc/lib/yenc.qh @@ -59,7 +59,7 @@ TEST(yEnc, EncodeDecode) STRING_ITERATOR(fragmentiterator, fragment, 0); ydec_single(fragmentiterator, encdec); - TEST_Check(encdec == expect); + EXPECT_EQ(expect, encdec); } - TEST_OK(); + SUCCEED(); } diff --git a/qcsrc/menu/xonotic/slider_decibels.qc b/qcsrc/menu/xonotic/slider_decibels.qc index f34528da6..c3eb4b0ab 100644 --- a/qcsrc/menu/xonotic/slider_decibels.qc +++ b/qcsrc/menu/xonotic/slider_decibels.qc @@ -97,7 +97,7 @@ string XonoticDecibelsSlider_valueToText(entity me, float v) bool autocvar_test_XonoticDecibelsSlider = false; TEST(XonoticDecibelsSlider, SoundTest) { - if (!autocvar_test_XonoticDecibelsSlider) { TEST_OK(); return; } + if (!autocvar_test_XonoticDecibelsSlider) { SUCCEED(); return; } for (int i = -400; i < 0; ++i) { float db = i * 0.1; @@ -105,9 +105,9 @@ TEST(XonoticDecibelsSlider, SoundTest) float dbv = toDecibelOfSquare(v, -40); float d = dbv - db; LOG_INFOF("%f -> %f -> %f (diff: %f)\n", db, v, dbv, d); - TEST_Check(fabs(d) > 0.02); + EXPECT_GT(fabs(d), 0.02); } - TEST_OK(); + SUCCEED(); } #endif