From 509ff4c7e0d31fb18f76dc7af3c9702095eb20fe Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Fri, 3 Feb 2023 11:21:08 +0000 Subject: [PATCH] Generic TEST that executes a function --- test/test.h | 23 +++++++++++++++++++++++ test/test_battle.h | 2 ++ test/test_runner.c | 41 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/test/test.h b/test/test.h index 27475bb48e..764443302f 100644 --- a/test/test.h +++ b/test/test.h @@ -53,6 +53,16 @@ extern const u8 gTestRunnerI; extern const char gTestRunnerArgv[256]; extern const struct TestRunner gAssumptionsRunner; + +struct FunctionTestRunnerState +{ + u8 parameters; + u8 runParameter; +}; + +extern const struct TestRunner gFunctionTestRunner; +extern struct FunctionTestRunnerState *gFunctionTestRunnerState; + extern struct TestRunnerState gTestRunnerState; void CB2_TestRunner(void); @@ -62,6 +72,17 @@ void Test_ExitWithResult(enum TestResult, const char *fmt, ...); s32 MgbaPrintf_(const char *fmt, ...); +#define TEST(_name) \ + static void CAT(Test, __LINE__)(void); \ + __attribute__((section(".tests"))) static const struct Test CAT(sTest, __LINE__) = \ + { \ + .name = _name, \ + .filename = __FILE__, \ + .runner = &gFunctionTestRunner, \ + .data = (void *)CAT(Test, __LINE__), \ + }; \ + static void CAT(Test, __LINE__)(void) + #define ASSUMPTIONS \ static void Assumptions(void); \ __attribute__((section(".tests"))) static const struct Test sAssumptions = \ @@ -138,4 +159,6 @@ s32 MgbaPrintf_(const char *fmt, ...); #define KNOWN_FAILING \ Test_ExpectedResult(TEST_RESULT_FAIL) +#define PARAMETRIZE if (gFunctionTestRunnerState->parameters++ == gFunctionTestRunnerState->runParameter) + #endif diff --git a/test/test_battle.h b/test/test_battle.h index 16918251b1..a447102f32 100644 --- a/test/test_battle.h +++ b/test/test_battle.h @@ -639,6 +639,8 @@ extern struct BattleTestRunnerState *gBattleTestRunnerState; /* Parametrize */ +#undef PARAMETRIZE // Override test/test.h's implementation. + #define PARAMETRIZE if (gBattleTestRunnerState->parametersCount++ == i) /* Randomly */ diff --git a/test/test_runner.c b/test/test_runner.c index f2d4d5de3f..e3d286c55a 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -4,6 +4,7 @@ #include "gpu_regs.h" #include "main.h" #include "malloc.h" +#include "random.h" #include "test.h" #include "test_runner.h" @@ -12,6 +13,7 @@ void CB2_TestRunner(void); EWRAM_DATA struct TestRunnerState gTestRunnerState; +EWRAM_DATA struct FunctionTestRunnerState *gFunctionTestRunnerState; void TestRunner_Battle(const struct Test *); @@ -230,6 +232,38 @@ void Test_ExpectedResult(enum TestResult result) gTestRunnerState.expectedResult = result; } +static void FunctionTest_SetUp(void *data) +{ + (void)data; + gFunctionTestRunnerState = AllocZeroed(sizeof(*gFunctionTestRunnerState)); + SeedRng(0); +} + +static void FunctionTest_Run(void *data) +{ + void (*function)(void) = data; + do + { + if (gFunctionTestRunnerState->parameters) + MgbaPrintf_(":N%s %d/%d", gTestRunnerState.test->name, gFunctionTestRunnerState->runParameter + 1, gFunctionTestRunnerState->parameters); + gFunctionTestRunnerState->parameters = 0; + function(); + } while (++gFunctionTestRunnerState->runParameter < gFunctionTestRunnerState->parameters); +} + +static void FunctionTest_TearDown(void *data) +{ + (void)data; + FREE_AND_SET_NULL(gFunctionTestRunnerState); +} + +const struct TestRunner gFunctionTestRunner = +{ + .setUp = FunctionTest_SetUp, + .run = FunctionTest_Run, + .tearDown = FunctionTest_TearDown, +}; + static void Assumptions_Run(void *data) { void (*function)(void) = data; @@ -288,11 +322,12 @@ static void Intr_Timer2(void) void Test_ExitWithResult(enum TestResult result, const char *fmt, ...) { + bool32 handled = FALSE; gTestRunnerState.result = result; ReinitCallbacks(); - if (gTestRunnerState.test->runner->handleExitWithResult - && !gTestRunnerState.test->runner->handleExitWithResult(gTestRunnerState.test->data, result) - && gTestRunnerState.result != gTestRunnerState.expectedResult) + if (gTestRunnerState.test->runner->handleExitWithResult) + handled = gTestRunnerState.test->runner->handleExitWithResult(gTestRunnerState.test->data, result); + if (!handled && gTestRunnerState.result != gTestRunnerState.expectedResult) { va_list va; va_start(va, fmt);