From 9d5e253867a7f56b31b14d4596d0fa595c0be1c7 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 20 Jul 2024 12:22:40 -0400 Subject: [PATCH] Improved Test Runner Summary (#4641) * Filename in list (no proper sorting yet) * Line number and message in error list + removed sorting * Style adjustment * Added missing file/line number to "expected N passes/successes" * Fixed Known Failing Passing test list * Separated test list from totals * Assumption fails list * Better names * Filename for KNOWN_FAILINGs passing * Moved total back to the bottom * Spaces correction * Fixed test list count * Source file for Alloc fails on tests * Moved sourceLine from BattleTest to Test struct * Fixed assumptions failed "and more" counter * Fixed ASSUMPTION block not printing their line numbers * Fixed when stopLine is printed * Renamed stopLine to failedAssumptionsBlockLine --- gflib/malloc.c | 2 +- include/test/battle.h | 7 +- include/test/test.h | 30 +++++--- test/test_runner.c | 26 ++++++- test/test_runner_battle.c | 127 ++++++++++++++----------------- tools/mgba-rom-test-hydra/main.c | 113 +++++++++++++++++++++------ 6 files changed, 191 insertions(+), 114 deletions(-) diff --git a/gflib/malloc.c b/gflib/malloc.c index 3c15dd944781..96f6aacda8a5 100644 --- a/gflib/malloc.c +++ b/gflib/malloc.c @@ -99,7 +99,7 @@ void *AllocInternal(void *heapStart, u32 size, const char *location) block = block->next; } while (block != head); - Test_ExitWithResult(TEST_RESULT_ERROR, "%s: OOM allocating %d bytes", location, size); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":L%s:%d, %s: OOM allocating %d bytes", gTestRunnerState.test->filename, SourceLine(0), location, size); #endif return NULL; } diff --git a/include/test/battle.h b/include/test/battle.h index b35af49be63c..24998b8fa506 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -518,7 +518,6 @@ typedef void (*DoubleBattleTestFunction)(void *, const u32, struct BattlePokemon struct BattleTest { u8 type; - u16 sourceLine; union { SingleBattleTestFunction singles; @@ -762,10 +761,10 @@ extern struct BattleTestRunnerState *const gBattleTestRunnerState; .name = _name, \ .filename = __FILE__, \ .runner = &gBattleTestRunner, \ + .sourceLine = __LINE__, \ .data = (void *)&(const struct BattleTest) \ { \ .type = _type, \ - .sourceLine = __LINE__, \ .function = { .singles = (SingleBattleTestFunction)CAT(Test, __LINE__) }, \ .resultsSize = sizeof(struct CAT(Result, __LINE__)), \ }, \ @@ -780,10 +779,10 @@ extern struct BattleTestRunnerState *const gBattleTestRunnerState; .name = _name, \ .filename = __FILE__, \ .runner = &gBattleTestRunner, \ + .sourceLine = __LINE__, \ .data = (void *)&(const struct BattleTest) \ { \ .type = _type, \ - .sourceLine = __LINE__, \ .function = { .doubles = (DoubleBattleTestFunction)CAT(Test, __LINE__) }, \ .resultsSize = sizeof(struct CAT(Result, __LINE__)), \ }, \ @@ -1091,7 +1090,7 @@ void ValidateFinally(u32 sourceLine); s32 _am = Q_4_12_TO_INT(_a * _m); \ s32 _t = max(Q_4_12_TO_INT(abs(_m) + Q_4_12_ROUND), 1); \ if (abs(_am-_b) > _t) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_MUL_EQ(%d, %q, %d) failed: %d not in [%d..%d]", gTestRunnerState.test->filename, __LINE__, _a, _m, _b, _am, _b-_t, _b+_t); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT_MUL_EQ(%d, %q, %d) failed: %d not in [%d..%d]", gTestRunnerState.test->filename, __LINE__, _a, _m, _b, _am, _b-_t, _b+_t); \ } while (0) #endif diff --git a/include/test/test.h b/include/test/test.h index 790563e77227..437b0b6b40db 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -33,6 +33,7 @@ struct Test const char *filename; const struct TestRunner *runner; void *data; + u16 sourceLine; }; struct TestRunnerState @@ -40,6 +41,7 @@ struct TestRunnerState u8 state; u8 exitCode; const char *skipFilename; + u32 failedAssumptionsBlockLine; const struct Test *test; u32 processCosts[MAX_PROCESSES]; @@ -73,7 +75,9 @@ void CB2_TestRunner(void); void Test_ExpectedResult(enum TestResult); void Test_ExpectLeaks(bool32); -void Test_ExitWithResult(enum TestResult, const char *fmt, ...); +void Test_ExitWithResult(enum TestResult, u32 stopLine, const char *fmt, ...); +u32 SourceLine(u32 sourceLineOffset); +u32 SourceLineOffset(u32 sourceLine); s32 MgbaPrintf_(const char *fmt, ...); @@ -84,6 +88,7 @@ s32 MgbaPrintf_(const char *fmt, ...); .name = _name, \ .filename = __FILE__, \ .runner = &gFunctionTestRunner, \ + .sourceLine = __LINE__, \ .data = (void *)CAT(Test, __LINE__), \ }; \ static void CAT(Test, __LINE__)(void) @@ -95,6 +100,7 @@ s32 MgbaPrintf_(const char *fmt, ...); .name = "ASSUMPTIONS: " __FILE__, \ .filename = __FILE__, \ .runner = &gAssumptionsRunner, \ + .sourceLine = __LINE__, \ .data = Assumptions, \ }; \ static void Assumptions(void) @@ -103,14 +109,14 @@ s32 MgbaPrintf_(const char *fmt, ...); do \ { \ if (!(c)) \ - Test_ExitWithResult(TEST_RESULT_ASSUMPTION_FAIL, "%s:%d: ASSUME failed", gTestRunnerState.test->filename, __LINE__); \ + Test_ExitWithResult(TEST_RESULT_ASSUMPTION_FAIL, __LINE__, ":L%s:%d: ASSUME failed", gTestRunnerState.test->filename, __LINE__); \ } while (0) #define EXPECT(c) \ do \ { \ if (!(c)) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT failed", gTestRunnerState.test->filename, __LINE__); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT failed", gTestRunnerState.test->filename, __LINE__); \ } while (0) #define EXPECT_EQ(a, b) \ @@ -118,7 +124,7 @@ s32 MgbaPrintf_(const char *fmt, ...); { \ typeof(a) _a = (a), _b = (b); \ if (_a != _b) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_EQ(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT_EQ(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ } while (0) #define EXPECT_NE(a, b) \ @@ -126,7 +132,7 @@ s32 MgbaPrintf_(const char *fmt, ...); { \ typeof(a) _a = (a), _b = (b); \ if (_a == _b) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_NE(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT_NE(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ } while (0) #define EXPECT_LT(a, b) \ @@ -134,7 +140,7 @@ s32 MgbaPrintf_(const char *fmt, ...); { \ typeof(a) _a = (a), _b = (b); \ if (_a >= _b) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_LT(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT_LT(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ } while (0) #define EXPECT_LE(a, b) \ @@ -142,7 +148,7 @@ s32 MgbaPrintf_(const char *fmt, ...); { \ typeof(a) _a = (a), _b = (b); \ if (_a > _b) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_LE(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT_LE(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ } while (0) #define EXPECT_GT(a, b) \ @@ -150,7 +156,7 @@ s32 MgbaPrintf_(const char *fmt, ...); { \ typeof(a) _a = (a), _b = (b); \ if (_a <= _b) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_GT(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT_GT(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ } while (0) #define EXPECT_GE(a, b) \ @@ -158,7 +164,7 @@ s32 MgbaPrintf_(const char *fmt, ...); { \ typeof(a) _a = (a), _b = (b); \ if (_a < _b) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_GE(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT_GE(%d, %d) failed", gTestRunnerState.test->filename, __LINE__, _a, _b); \ } while (0) struct Benchmark { s32 ticks; }; @@ -195,7 +201,7 @@ static inline struct Benchmark BenchmarkStop(void) u32 a_ = (a).ticks; u32 b_ = (b).ticks; \ MgbaPrintf_(#a ": %d ticks, " #b ": %d ticks", a_, b_); \ if (((a_ - BENCHMARK_ABS) * BENCHMARK_REL) >= (b_ * 100)) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_FASTER(" #a ", " #b ") failed", gTestRunnerState.test->filename, __LINE__); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT_FASTER(" #a ", " #b ") failed", gTestRunnerState.test->filename, __LINE__); \ } while (0) #define EXPECT_SLOWER(a, b) \ @@ -204,7 +210,7 @@ static inline struct Benchmark BenchmarkStop(void) u32 a_ = (a).ticks; u32 b_ = (b).ticks; \ MgbaPrintf_(#a ": %d ticks, " #b ": %d ticks", a_, b_); \ if ((a_ * 100) <= ((b_ - BENCHMARK_ABS) * BENCHMARK_REL)) \ - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_SLOWER(" #a ", " #b ") failed", gTestRunnerState.test->filename, __LINE__); \ + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: EXPECT_SLOWER(" #a ", " #b ") failed", gTestRunnerState.test->filename, __LINE__); \ } while (0) #define KNOWN_FAILING \ @@ -218,7 +224,7 @@ static inline struct Benchmark BenchmarkStop(void) #define TO_DO \ do { \ Test_ExpectedResult(TEST_RESULT_TODO); \ - Test_ExitWithResult(TEST_RESULT_TODO, "%s:%d: EXPECT_TO_DO", gTestRunnerState.test->filename, __LINE__); \ + Test_ExitWithResult(TEST_RESULT_TODO, __LINE__, ":L%s:%d: EXPECT_TO_DO", gTestRunnerState.test->filename, __LINE__); \ } while (0) #endif diff --git a/test/test_runner.c b/test/test_runner.c index cbe9a6c6e07b..169d2e40619d 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -179,6 +179,7 @@ void CB2_TestRunner(void) } MgbaPrintf_(":N%s", gTestRunnerState.test->name); + MgbaPrintf_(":L%s:%d", gTestRunnerState.test->filename); gTestRunnerState.result = TEST_RESULT_PASS; gTestRunnerState.expectedResult = TEST_RESULT_PASS; gTestRunnerState.expectLeaks = FALSE; @@ -216,6 +217,7 @@ void CB2_TestRunner(void) // NOTE: Assumes that the compiler interns __FILE__. if (gTestRunnerState.skipFilename == gTestRunnerState.test->filename) // Assumption fails for tests in this file. { + MgbaPrintf_(":L%s:%d", gTestRunnerState.test->filename, gTestRunnerState.failedAssumptionsBlockLine); gTestRunnerState.result = TEST_RESULT_ASSUMPTION_FAIL; return; } @@ -480,9 +482,10 @@ static void Intr_Timer2(void) } } -void Test_ExitWithResult(enum TestResult result, const char *fmt, ...) +void Test_ExitWithResult(enum TestResult result, u32 stopLine, const char *fmt, ...) { gTestRunnerState.result = result; + gTestRunnerState.failedAssumptionsBlockLine = stopLine; ReinitCallbacks(); if (gTestRunnerState.state == STATE_REPORT_RESULT && gTestRunnerState.result != gTestRunnerState.expectedResult) @@ -690,3 +693,24 @@ void DACSHandle(void) ReinitCallbacks(); DACS_LR = ((uintptr_t)JumpToAgbMainLoop & ~1) + 4; } + +static const struct Test *GetTest(void) +{ + const struct Test *test = gTestRunnerState.test; + return test; +} + +u32 SourceLine(u32 sourceLineOffset) +{ + const struct Test *test = GetTest(); + return test->sourceLine + sourceLineOffset; +} + +u32 SourceLineOffset(u32 sourceLine) +{ + const struct Test *test = GetTest(); + if (sourceLine - test->sourceLine > 0xFF) + return 0; + else + return sourceLine - test->sourceLine; +} diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 376c3be8a55b..2930c7dd6158 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -25,10 +25,10 @@ #undef TestRunner_Battle_GetForcedAbility #endif -#define INVALID(fmt, ...) Test_ExitWithResult(TEST_RESULT_INVALID, "%s:%d: " fmt, gTestRunnerState.test->filename, sourceLine, ##__VA_ARGS__) -#define INVALID_IF(c, fmt, ...) do { if (c) Test_ExitWithResult(TEST_RESULT_INVALID, "%s:%d: " fmt, gTestRunnerState.test->filename, sourceLine, ##__VA_ARGS__); } while (0) +#define INVALID(fmt, ...) Test_ExitWithResult(TEST_RESULT_INVALID, sourceLine, ":L%s:%d: " fmt, gTestRunnerState.test->filename, sourceLine, ##__VA_ARGS__) +#define INVALID_IF(c, fmt, ...) do { if (c) Test_ExitWithResult(TEST_RESULT_INVALID, sourceLine, ":L%s:%d: " fmt, gTestRunnerState.test->filename, sourceLine, ##__VA_ARGS__); } while (0) -#define ASSUMPTION_FAIL_IF(c, fmt, ...) do { if (c) Test_ExitWithResult(TEST_RESULT_ASSUMPTION_FAIL, "%s:%d: " fmt, gTestRunnerState.test->filename, sourceLine, ##__VA_ARGS__); } while (0) +#define ASSUMPTION_FAIL_IF(c, fmt, ...) do { if (c) Test_ExitWithResult(TEST_RESULT_ASSUMPTION_FAIL, sourceLine, ":L%s:%d: " fmt, gTestRunnerState.test->filename, sourceLine, ##__VA_ARGS__); } while (0) #define STATE gBattleTestRunnerState #define DATA gBattleTestRunnerState->data @@ -145,21 +145,6 @@ static bool32 IsAITest(void) return FALSE; } -static u32 SourceLine(u32 sourceLineOffset) -{ - const struct BattleTest *test = GetBattleTest(); - return test->sourceLine + sourceLineOffset; -} - -static u32 SourceLineOffset(u32 sourceLine) -{ - const struct BattleTest *test = GetBattleTest(); - if (sourceLine - test->sourceLine > 0xFF) - return 0; - else - return sourceLine - test->sourceLine; -} - static u32 BattleTest_EstimateCost(void *data) { u32 cost; @@ -184,9 +169,9 @@ static void BattleTest_SetUp(void *data) InvokeTestFunction(test); STATE->parameters = STATE->parametersCount; if (STATE->parametersCount == 0 && test->resultsSize > 0) - Test_ExitWithResult(TEST_RESULT_INVALID, "results without PARAMETRIZE"); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":Lresults without PARAMETRIZE"); if (sizeof(*STATE) + test->resultsSize * STATE->parameters > sizeof(sBackupMapData)) - Test_ExitWithResult(TEST_RESULT_ERROR, "OOM: STATE (%d) + STATE->results (%d) too big for sBackupMapData (%d)", sizeof(*STATE), test->resultsSize * STATE->parameters, sizeof(sBackupMapData)); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LOOM: STATE (%d) + STATE->results (%d) too big for sBackupMapData (%d)", sizeof(*STATE), test->resultsSize * STATE->parameters, sizeof(sBackupMapData)); STATE->results = (void *)((char *)sBackupMapData + sizeof(struct BattleTestRunnerState)); memset(STATE->results, 0, test->resultsSize * STATE->parameters); switch (test->type) @@ -260,7 +245,7 @@ static void SetImplicitSpeeds(void) } } if (!madeProgress) - Test_ExitWithResult(TEST_RESULT_INVALID, "TURNs have contradictory speeds"); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LTURNs have contradictory speeds"); } } @@ -334,9 +319,9 @@ static void BattleTest_Run(void *data) requiredOpponentPartySize = DATA.currentMonIndexes[i] + 1; } if (DATA.playerPartySize < requiredPlayerPartySize) - Test_ExitWithResult(TEST_RESULT_INVALID, "%d PLAYER Pokemon required", requiredPlayerPartySize); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":L%d PLAYER Pokemon required", requiredPlayerPartySize); if (DATA.opponentPartySize < requiredOpponentPartySize) - Test_ExitWithResult(TEST_RESULT_INVALID, "%d OPPONENT Pokemon required", requiredOpponentPartySize); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":L%d OPPONENT Pokemon required", requiredOpponentPartySize); for (i = 0; i < STATE->battlersCount; i++) PushBattlerAction(0, i, RECORDED_BYTE, 0xFF); @@ -346,7 +331,7 @@ static void BattleTest_Run(void *data) if (DATA.explicitSpeeds[B_SIDE_PLAYER] != (1 << DATA.playerPartySize) - 1 && DATA.explicitSpeeds[B_SIDE_OPPONENT] != (1 << DATA.opponentPartySize) - 1) { - Test_ExitWithResult(TEST_RESULT_INVALID, "Speed required for all PLAYERs and OPPONENTs"); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LSpeed required for all PLAYERs and OPPONENTs"); } } else @@ -392,7 +377,7 @@ u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi) } else if (STATE->trials != n) { - Test_ExitWithResult(TEST_RESULT_ERROR, "RandomUniform called with inconsistent trials %d and %d", STATE->trials, n); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomUniform called with inconsistent trials %d and %d", STATE->trials, n); } STATE->trialRatio = Q_4_12(1) / STATE->trials; return STATE->runTrial + lo; @@ -413,7 +398,7 @@ u32 RandomUniformExcept(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32 if (turn && turn->rng.tag == tag) { if (reject(turn->rng.value)) - Test_ExitWithResult(TEST_RESULT_INVALID, "WITH_RNG specified a rejected value (%d)", turn->rng.value); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LWITH_RNG specified a rejected value (%d)", turn->rng.value); return turn->rng.value; } } @@ -434,7 +419,7 @@ u32 RandomUniformExcept(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32 while (reject(STATE->runTrial + lo + STATE->rngTrialOffset)) { if (STATE->runTrial + lo + STATE->rngTrialOffset > hi) - Test_ExitWithResult(TEST_RESULT_INVALID, "RandomUniformExcept called with inconsistent reject"); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LRandomUniformExcept called with inconsistent reject"); STATE->rngTrialOffset++; } @@ -445,7 +430,7 @@ u32 RandomUniformExcept(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32 while (reject(default_)) { if (default_ == lo) - Test_ExitWithResult(TEST_RESULT_INVALID, "RandomUniformExcept rejected all values"); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LRandomUniformExcept rejected all values"); default_--; } return default_; @@ -456,7 +441,7 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) const struct BattlerTurn *turn = NULL; if (sum == 0) - Test_ExitWithResult(TEST_RESULT_ERROR, "RandomWeightedArray called with zero sum"); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeightedArray called with zero sum"); if (gCurrentTurnActionNumber < gBattlersCount) { @@ -475,7 +460,7 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) } else if (STATE->trials != n) { - Test_ExitWithResult(TEST_RESULT_ERROR, "RandomWeighted called with inconsistent trials %d and %d", STATE->trials, n); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeighted called with inconsistent trials %d and %d", STATE->trials, n); } // TODO: Detect inconsistent sum. STATE->trialRatio = Q_4_12(weights[STATE->runTrial]) / sum; @@ -509,7 +494,7 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) while (weights[n-1] == 0) { if (n == 1) - Test_ExitWithResult(TEST_RESULT_ERROR, "RandomWeightedArray called with all zero weights"); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeightedArray called with all zero weights"); n--; } return n-1; @@ -535,7 +520,7 @@ const void *RandomElementArray(enum RandomTag tag, const void *array, size_t siz return (const u8 *)array + size * index; } // TODO: Incorporate the line number. - Test_ExitWithResult(TEST_RESULT_ERROR, "%s: RandomElement illegal value requested: %d", gTestRunnerState.test->filename, turn->rng.value); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":L%s: RandomElement illegal value requested: %d", gTestRunnerState.test->filename, turn->rng.value); } } @@ -548,7 +533,7 @@ const void *RandomElementArray(enum RandomTag tag, const void *array, size_t siz } else if (STATE->trials != count) { - Test_ExitWithResult(TEST_RESULT_ERROR, "RandomElement called with inconsistent trials %d and %d", STATE->trials, count); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomElement called with inconsistent trials %d and %d", STATE->trials, count); } STATE->trialRatio = Q_4_12(1) / count; return (const u8 *)array + size * STATE->runTrial; @@ -599,7 +584,7 @@ void TestRunner_Battle_RecordAbilityPopUp(u32 battlerId, u32 ability) { const char *filename = gTestRunnerState.test->filename; u32 line = SourceLine(DATA.queuedEvents[match].sourceLineOffset); - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Matched ABILITY_POPUP", filename, line); + Test_ExitWithResult(TEST_RESULT_FAIL, line, ":L%s:%d: Matched ABILITY_POPUP", filename, line); } queuedEvent += event->groupSize; @@ -662,7 +647,7 @@ void TestRunner_Battle_RecordAnimation(u32 animType, u32 animId) { const char *filename = gTestRunnerState.test->filename; u32 line = SourceLine(DATA.queuedEvents[match].sourceLineOffset); - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Matched ANIMATION", filename, line); + Test_ExitWithResult(TEST_RESULT_FAIL, line, ":L%s:%d: Matched ANIMATION", filename, line); } queuedEvent += event->groupSize; @@ -752,7 +737,7 @@ void TestRunner_Battle_RecordHP(u32 battlerId, u32 oldHP, u32 newHP) { const char *filename = gTestRunnerState.test->filename; u32 line = SourceLine(DATA.queuedEvents[match].sourceLineOffset); - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Matched HP_BAR", filename, line); + Test_ExitWithResult(TEST_RESULT_FAIL, line, ":L%s:%d: Matched HP_BAR", filename, line); } queuedEvent += event->groupSize; @@ -807,10 +792,10 @@ void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target) bool32 movePasses = FALSE; if (expectedAction->type != B_ACTION_USE_MOVE) - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Expected %s, got MOVE", filename, expectedAction->sourceLine, sBattleActionNames[expectedAction->type]); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Expected %s, got MOVE", filename, expectedAction->sourceLine, sBattleActionNames[expectedAction->type]); if (expectedAction->explicitTarget && expectedAction->target != target) - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Expected target %s, got %s", filename, expectedAction->sourceLine, BattlerIdentifier(expectedAction->target), BattlerIdentifier(target)); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Expected target %s, got %s", filename, expectedAction->sourceLine, BattlerIdentifier(expectedAction->target), BattlerIdentifier(target)); for (i = 0; i < MAX_MON_MOVES; i++) { @@ -844,16 +829,16 @@ void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target) u32 moveSlot = GetMoveSlot(gBattleMons[battlerId].moves, moveId); PrintAiMoveLog(battlerId, moveSlot, moveId, gBattleStruct->aiFinalScore[battlerId][expectedAction->target][moveSlot]); if (countExpected > 1) - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Unmatched EXPECT_MOVES %S, got %S", filename, expectedAction->sourceLine, GetMoveName(expectedMoveId), GetMoveName(moveId)); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Unmatched EXPECT_MOVES %S, got %S", filename, expectedAction->sourceLine, GetMoveName(expectedMoveId), GetMoveName(moveId)); else - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Unmatched EXPECT_MOVE %S, got %S", filename, expectedAction->sourceLine, GetMoveName(expectedMoveId), GetMoveName(moveId)); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Unmatched EXPECT_MOVE %S, got %S", filename, expectedAction->sourceLine, GetMoveName(expectedMoveId), GetMoveName(moveId)); } if (expectedAction->notMove && !movePasses) { if (countExpected > 1) - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Unmatched NOT_EXPECT_MOVES %S", filename, expectedAction->sourceLine, GetMoveName(expectedMoveId)); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Unmatched NOT_EXPECT_MOVES %S", filename, expectedAction->sourceLine, GetMoveName(expectedMoveId)); else - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Unmatched NOT_EXPECT_MOVE %S", filename, expectedAction->sourceLine, GetMoveName(expectedMoveId)); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Unmatched NOT_EXPECT_MOVE %S", filename, expectedAction->sourceLine, GetMoveName(expectedMoveId)); } } // Turn passed, clear logs from the turn @@ -873,17 +858,17 @@ void TestRunner_Battle_CheckSwitch(u32 battlerId, u32 partyIndex) if (!expectedAction->pass) { if (expectedAction->type != B_ACTION_SWITCH) - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Expected %s, got SWITCH/SEND_OUT", filename, expectedAction->sourceLine, sBattleActionNames[expectedAction->type]); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Expected %s, got SWITCH/SEND_OUT", filename, expectedAction->sourceLine, sBattleActionNames[expectedAction->type]); if (expectedAction->target != partyIndex) - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Expected partyIndex %d, got %d", filename, expectedAction->sourceLine, expectedAction->target, partyIndex); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Expected partyIndex %d, got %d", filename, expectedAction->sourceLine, expectedAction->target, partyIndex); } DATA.aiActionsPlayed[battlerId]++; } void TestRunner_Battle_InvalidNoHPMon(u32 battlerId, u32 partyIndex) { - Test_ExitWithResult(TEST_RESULT_INVALID, "%s: INVALID: %s trying to send out a mon(id: %d) with 0 HP.", + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":L%s: INVALID: %s trying to send out a mon(id: %d) with 0 HP.", gTestRunnerState.test->filename, BattlerIdentifier(battlerId), gBattlerPartyIndexes[battlerId]); } @@ -933,7 +918,7 @@ static void CheckIfMaxScoreEqualExpectMove(u32 battlerId, s32 target, struct Exp && (aiAction->moveSlots & gBitTable[i]) && !(aiAction->moveSlots & gBitTable[bestScoreId])) { - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: EXPECT_MOVE %S has the same best score(%d) as not expected MOVE %S", filename, + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: EXPECT_MOVE %S has the same best score(%d) as not expected MOVE %S", filename, aiAction->sourceLine, GetMoveName(moves[i]), scores[i], GetMoveName(moves[bestScoreId])); } // We DO NOT expect move 'i', but it has the same best score as another move. @@ -942,7 +927,7 @@ static void CheckIfMaxScoreEqualExpectMove(u32 battlerId, s32 target, struct Exp && (aiAction->moveSlots & gBitTable[i]) && !(aiAction->moveSlots & gBitTable[bestScoreId])) { - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: NOT_EXPECT_MOVE %S has the same best score(%d) as MOVE %S", filename, + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: NOT_EXPECT_MOVE %S has the same best score(%d) as MOVE %S", filename, aiAction->sourceLine, GetMoveName(moves[i]), scores[i], GetMoveName(moves[bestScoreId])); } } @@ -985,7 +970,7 @@ static void PrintAiMoveLog(u32 battlerId, u32 moveSlot, u32 moveId, s32 totalSco } if (scoreFromLogs != totalScore) { - Test_ExitWithResult(TEST_RESULT_ERROR, "Warning! Score from logs(%d) is different than actual score(%d). Make sure all of the score adjustments use the ADJUST_SCORE macro\n", scoreFromLogs, totalScore); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LWarning! Score from logs(%d) is different than actual score(%d). Make sure all of the score adjustments use the ADJUST_SCORE macro\n", scoreFromLogs, totalScore); } MgbaPrintf_("Total: %d\n", totalScore); } @@ -1023,7 +1008,7 @@ void TestRunner_Battle_CheckAiMoveScores(u32 battlerId) PrintAiMoveLog(battlerId, scoreCtx->moveSlot1, moveId1, scores[scoreCtx->moveSlot1]); if (!CheckComparision(scores[scoreCtx->moveSlot1], scoreCtx->value, scoreCtx->cmp)) { - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Unmatched SCORE_%s_VAL %S %d, got %d", + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Unmatched SCORE_%s_VAL %S %d, got %d", filename, scoreCtx->sourceLine, sCmpToStringTable[scoreCtx->cmp], GetMoveName(moveId1), scoreCtx->value, scores[scoreCtx->moveSlot1]); } } @@ -1034,7 +1019,7 @@ void TestRunner_Battle_CheckAiMoveScores(u32 battlerId) PrintAiMoveLog(battlerId, scoreCtx->moveSlot2, moveId2, scores[scoreCtx->moveSlot2]); if (!CheckComparision(scores[scoreCtx->moveSlot1], scores[scoreCtx->moveSlot2], scoreCtx->cmp)) { - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Unmatched SCORE_%s, got %S: %d, %S: %d", + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Unmatched SCORE_%s, got %S: %d, %S: %d", filename, scoreCtx->sourceLine, sCmpToStringTable[scoreCtx->cmp], GetMoveName(moveId1), scores[scoreCtx->moveSlot1], GetMoveName(moveId2), scores[scoreCtx->moveSlot2]); } } @@ -1134,7 +1119,7 @@ void TestRunner_Battle_RecordExp(u32 battlerId, u32 oldExp, u32 newExp) { const char *filename = gTestRunnerState.test->filename; u32 line = SourceLine(DATA.queuedEvents[match].sourceLineOffset); - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Matched EXPERIENCE_BAR", filename, line); + Test_ExitWithResult(TEST_RESULT_FAIL, line, ":L%s:%d: Matched EXPERIENCE_BAR", filename, line); } queuedEvent += event->groupSize; @@ -1223,7 +1208,7 @@ void TestRunner_Battle_RecordMessage(const u8 *string) { const char *filename = gTestRunnerState.test->filename; u32 line = SourceLine(DATA.queuedEvents[match].sourceLineOffset); - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Matched MESSAGE", filename, line); + Test_ExitWithResult(TEST_RESULT_FAIL, line, ":L%s:%d: Matched MESSAGE", filename, line); } queuedEvent += event->groupSize; @@ -1288,7 +1273,7 @@ void TestRunner_Battle_RecordStatus1(u32 battlerId, u32 status1) { const char *filename = gTestRunnerState.test->filename; u32 line = SourceLine(DATA.queuedEvents[match].sourceLineOffset); - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Matched STATUS_ICON", filename, line); + Test_ExitWithResult(TEST_RESULT_FAIL, line, ":L%s:%d: Matched STATUS_ICON", filename, line); } queuedEvent += event->groupSize; @@ -1323,7 +1308,7 @@ void TestRunner_Battle_AfterLastTurn(void) if (DATA.turns - 1 != DATA.lastActionTurn) { const char *filename = gTestRunnerState.test->filename; - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: %d TURNs specified, but %d ran", filename, SourceLine(0), DATA.turns, DATA.lastActionTurn + 1); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: %d TURNs specified, but %d ran", filename, SourceLine(0), DATA.turns, DATA.lastActionTurn + 1); } while (DATA.queuedEvent < DATA.queuedEventsCount @@ -1336,7 +1321,7 @@ void TestRunner_Battle_AfterLastTurn(void) const char *filename = gTestRunnerState.test->filename; u32 line = SourceLine(DATA.queuedEvents[DATA.queuedEvent].sourceLineOffset); const char *macro = sEventTypeMacros[DATA.queuedEvents[DATA.queuedEvent].type]; - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: Unmatched %s", filename, line, macro); + Test_ExitWithResult(TEST_RESULT_FAIL, line, ":L%s:%d: Unmatched %s", filename, line, macro); } STATE->runThen = TRUE; @@ -1418,7 +1403,7 @@ static void CB2_BattleTest_NextTrial(void) if (abs(STATE->observedRatio - STATE->expectedRatio) <= Q_4_12(0.02)) gTestRunnerState.result = TEST_RESULT_PASS; else - Test_ExitWithResult(TEST_RESULT_FAIL, "Expected %q passes/successes, observed %q", STATE->expectedRatio, STATE->observedRatio); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Expected %q passes/successes, observed %q", gTestRunnerState.test->filename, SourceLine(0), STATE->expectedRatio, STATE->observedRatio); } } @@ -1831,7 +1816,7 @@ static void PushBattlerAction(u32 sourceLine, s32 battlerId, u32 actionType, u32 { u32 recordIndex = DATA.recordIndexes[battlerId]++; if (recordIndex >= BATTLER_RECORD_SIZE) - Test_ExitWithResult(TEST_RESULT_INVALID, "Too many actions"); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LToo many actions"); DATA.battleRecordTypes[battlerId][recordIndex] = actionType; DATA.battleRecordSourceLineOffsets[battlerId][recordIndex] = SourceLineOffset(sourceLine); DATA.recordedBattle.battleRecord[battlerId][recordIndex] = byte; @@ -1853,10 +1838,10 @@ void TestRunner_Battle_CheckBattleRecordActionType(u32 battlerId, u32 recordInde && DATA.recordedBattle.battleRecord[battlerId][i-1] == B_ACTION_USE_MOVE) { u32 line = SourceLine(DATA.battleRecordSourceLineOffsets[battlerId][i-1]); - Test_ExitWithResult(TEST_RESULT_INVALID, "%s:%d: Illegal MOVE", filename, line); + Test_ExitWithResult(TEST_RESULT_INVALID, line, ":L%s:%d: Illegal MOVE", filename, line); } } - Test_ExitWithResult(TEST_RESULT_INVALID, "%s:%d: Illegal MOVE", filename, SourceLine(0)); + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":L%s:%d: Illegal MOVE", filename, SourceLine(0)); } if (DATA.battleRecordTypes[battlerId][recordIndex] != RECORDED_BYTE) @@ -1884,13 +1869,13 @@ void TestRunner_Battle_CheckBattleRecordActionType(u32 battlerId, u32 recordInde switch (actionType) { case RECORDED_ACTION_TYPE: - Test_ExitWithResult(TEST_RESULT_INVALID, "%s:%d: Expected MOVE/SWITCH, got %s", filename, line, actualMacro); + Test_ExitWithResult(TEST_RESULT_INVALID, line, ":L%s:%d: Expected MOVE/SWITCH, got %s", filename, line, actualMacro); case RECORDED_PARTY_INDEX: - Test_ExitWithResult(TEST_RESULT_INVALID, "%s:%d: Expected SEND_OUT, got %s", filename, line, actualMacro); + Test_ExitWithResult(TEST_RESULT_INVALID, line, ":L%s:%d: Expected SEND_OUT, got %s", filename, line, actualMacro); } } - Test_ExitWithResult(TEST_RESULT_ERROR, "%s:%d: Illegal battle record", filename, line); + Test_ExitWithResult(TEST_RESULT_ERROR, line, ":L%s:%d: Illegal battle record", filename, line); } } else @@ -1898,7 +1883,7 @@ void TestRunner_Battle_CheckBattleRecordActionType(u32 battlerId, u32 recordInde if (DATA.lastActionTurn == gBattleResults.battleTurnCounter) { const char *filename = gTestRunnerState.test->filename; - Test_ExitWithResult(TEST_RESULT_FAIL, "%s:%d: TURN %d incomplete", filename, SourceLine(0), gBattleResults.battleTurnCounter + 1); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: TURN %d incomplete", filename, SourceLine(0), gBattleResults.battleTurnCounter + 1); } } } @@ -1907,7 +1892,7 @@ void OpenTurn(u32 sourceLine) { INVALID_IF(DATA.turnState != TURN_CLOSED, "Nested TURN"); if (DATA.turns == MAX_TURNS) - Test_ExitWithResult(TEST_RESULT_ERROR, "%s:%d: TURN exceeds MAX_TURNS", gTestRunnerState.test->filename, sourceLine); + Test_ExitWithResult(TEST_RESULT_ERROR, sourceLine, ":L%s:%d: TURN exceeds MAX_TURNS", gTestRunnerState.test->filename, sourceLine); DATA.turnState = TURN_OPEN; DATA.actionBattlers = 0x00; DATA.moveBattlers = 0x00; @@ -2422,7 +2407,7 @@ void QueueAbility(u32 sourceLine, struct BattlePokemon *battler, struct AbilityE s32 battlerId = battler - gBattleMons; INVALID_IF(!STATE->runScene, "ABILITY_POPUP outside of SCENE"); if (DATA.queuedEventsCount == MAX_QUEUED_EVENTS) - Test_ExitWithResult(TEST_RESULT_ERROR, "%s:%d: ABILITY exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); + Test_ExitWithResult(TEST_RESULT_ERROR, sourceLine, ":L%s:%d: ABILITY exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); DATA.queuedEvents[DATA.queuedEventsCount++] = (struct QueuedEvent) { .type = QUEUED_ABILITY_POPUP_EVENT, .sourceLineOffset = SourceLineOffset(sourceLine), @@ -2442,7 +2427,7 @@ void QueueAnimation(u32 sourceLine, u32 type, u32 id, struct AnimationEventConte INVALID_IF(!STATE->runScene, "ANIMATION outside of SCENE"); if (DATA.queuedEventsCount == MAX_QUEUED_EVENTS) - Test_ExitWithResult(TEST_RESULT_ERROR, "%s:%d: ANIMATION exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); + Test_ExitWithResult(TEST_RESULT_ERROR, sourceLine, ":L%s:%d: ANIMATION exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); attackerId = ctx.attacker ? ctx.attacker - gBattleMons : 0xF; if (type == ANIM_TYPE_MOVE) @@ -2477,7 +2462,7 @@ void QueueHP(u32 sourceLine, struct BattlePokemon *battler, struct HPEventContex INVALID_IF(!STATE->runScene, "HP_BAR outside of SCENE"); if (DATA.queuedEventsCount == MAX_QUEUED_EVENTS) - Test_ExitWithResult(TEST_RESULT_ERROR, "%s:%d: HP_BAR exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); + Test_ExitWithResult(TEST_RESULT_ERROR, sourceLine, ":L%s:%d: HP_BAR exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); if (ctx.explicitHP) { @@ -2530,7 +2515,7 @@ void QueueExp(u32 sourceLine, struct BattlePokemon *battler, struct ExpEventCont INVALID_IF(!STATE->runScene, "EXPERIENCE_BAR outside of SCENE"); if (DATA.queuedEventsCount == MAX_QUEUED_EVENTS) - Test_ExitWithResult(TEST_RESULT_ERROR, "%s:%d: EXPERIENCE_BAR exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); + Test_ExitWithResult(TEST_RESULT_ERROR, sourceLine, ":L%s:%d: EXPERIENCE_BAR exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); if (ctx.explicitExp) { @@ -2567,7 +2552,7 @@ void QueueMessage(u32 sourceLine, const u8 *pattern) { INVALID_IF(!STATE->runScene, "MESSAGE outside of SCENE"); if (DATA.queuedEventsCount == MAX_QUEUED_EVENTS) - Test_ExitWithResult(TEST_RESULT_ERROR, "%s:%d: MESSAGE exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); + Test_ExitWithResult(TEST_RESULT_ERROR, sourceLine, ":L%s:%d: MESSAGE exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); DATA.queuedEvents[DATA.queuedEventsCount++] = (struct QueuedEvent) { .type = QUEUED_MESSAGE_EVENT, .sourceLineOffset = SourceLineOffset(sourceLine), @@ -2586,7 +2571,7 @@ void QueueStatus(u32 sourceLine, struct BattlePokemon *battler, struct StatusEve INVALID_IF(!STATE->runScene, "STATUS_ICON outside of SCENE"); if (DATA.queuedEventsCount == MAX_QUEUED_EVENTS) - Test_ExitWithResult(TEST_RESULT_ERROR, "%s:%d: STATUS_ICON exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); + Test_ExitWithResult(TEST_RESULT_ERROR, sourceLine, ":L%s:%d: STATUS_ICON exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); if (ctx.none) mask = 0; @@ -2645,7 +2630,7 @@ struct AILogLine *GetLogLine(u32 battlerId, u32 moveIndex) } } - Test_ExitWithResult(TEST_RESULT_ERROR, "Too many AI log lines"); + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LToo many AI log lines"); return NULL; } diff --git a/tools/mgba-rom-test-hydra/main.c b/tools/mgba-rom-test-hydra/main.c index d4f39feb736e..d9d8417e180d 100644 --- a/tools/mgba-rom-test-hydra/main.c +++ b/tools/mgba-rom-test-hydra/main.c @@ -8,6 +8,7 @@ * * COMMANDS * N: Sets the test name to the remainder of the line. + * L: Sets the filename to the remainder of the line. * R: Sets the result to the remainder of the line, and flushes any * output buffered since the previous R. * P/K/F/A: Sets the result to the remaining of the line, flushes any @@ -46,6 +47,7 @@ struct Runner int outfd; char rom_path[FILENAME_MAX]; char test_name[256]; + char filename_line[256]; size_t input_buffer_size; size_t input_buffer_capacity; char *input_buffer; @@ -59,8 +61,12 @@ struct Runner int assumptionFails; int fails; int results; - char failedTestNames[MAX_SUMMARY_TESTS_TO_LIST][MAX_TEST_LIST_BUFFER_LENGTH]; - char knownFailingPassedTestNames[MAX_SUMMARY_TESTS_TO_LIST][MAX_TEST_LIST_BUFFER_LENGTH]; + char failed_TestNames[MAX_SUMMARY_TESTS_TO_LIST][MAX_TEST_LIST_BUFFER_LENGTH]; + char failed_TestFilenameLine[MAX_SUMMARY_TESTS_TO_LIST][MAX_TEST_LIST_BUFFER_LENGTH]; + char knownFailingPassed_TestNames[MAX_SUMMARY_TESTS_TO_LIST][MAX_TEST_LIST_BUFFER_LENGTH]; + char knownFailingPassed_FilenameLine[MAX_SUMMARY_TESTS_TO_LIST][MAX_TEST_LIST_BUFFER_LENGTH]; + char assumeFailed_TestNames[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; + char assumeFailed_FilenameLine[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; }; static unsigned nrunners = 0; @@ -102,6 +108,16 @@ static void handle_read(int i, struct Runner *runner) strncpy(runner->test_name, soc, eol - soc - 1); runner->test_name[eol - soc - 1] = '\0'; break; + case 'L': + soc += 2; + if (sizeof(runner->filename_line) <= eol - soc - 1) + { + fprintf(stderr, "filename_line too long\n"); + exit(2); + } + strncpy(runner->filename_line, soc, eol - soc - 1); + runner->filename_line[eol - soc - 1] = '\0'; + break; case 'P': runner->passes++; @@ -111,18 +127,29 @@ static void handle_read(int i, struct Runner *runner) goto add_to_results; case 'U': if (runner->knownFailsPassing < MAX_SUMMARY_TESTS_TO_LIST) - strcpy(runner->knownFailingPassedTestNames[runner->knownFailsPassing], runner->test_name); + { + strcpy(runner->knownFailingPassed_TestNames[runner->knownFailsPassing], runner->test_name); + strcpy(runner->knownFailingPassed_FilenameLine[runner->knownFailsPassing], runner->filename_line); + } runner->knownFailsPassing++; goto add_to_results; case 'T': runner->todos++; goto add_to_results; case 'A': + if (runner->assumptionFails < MAX_SUMMARY_TESTS_TO_LIST) + { + strcpy(runner->assumeFailed_TestNames[runner->assumptionFails], runner->test_name); + strcpy(runner->assumeFailed_FilenameLine[runner->assumptionFails], runner->filename_line); + } runner->assumptionFails++; goto add_to_results; case 'F': if (runner->fails < MAX_SUMMARY_TESTS_TO_LIST) - strcpy(runner->failedTestNames[runner->fails], runner->test_name); + { + strcpy(runner->failed_TestNames[runner->fails], runner->test_name); + strcpy(runner->failed_TestFilenameLine[runner->fails], runner->filename_line); + } runner->fails++; add_to_results: runner->results++; @@ -532,8 +559,14 @@ int main(int argc, char *argv[]) int fails = 0; int results = 0; - char failedTestNames[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; - char knownFailingPassedTestNames[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; + char failed_TestNames[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; + char failed_TestFilenameLine[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; + + char knownFailingPassed_TestNames[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; + char knownFailingPassed_FilenameLine[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; + + char assumeFailed_TestNames[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; + char assumeFailed_FilenameLine[MAX_SUMMARY_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH]; for (int i = 0; i < nrunners; i++) { @@ -552,33 +585,43 @@ int main(int argc, char *argv[]) for (int j = 0; j < runners[i].knownFailsPassing; j++) { if (j < MAX_SUMMARY_TESTS_TO_LIST) - strcpy(knownFailingPassedTestNames[fails], runners[i].knownFailingPassedTestNames[j]); + { + strcpy(knownFailingPassed_TestNames[knownFailsPassing], runners[i].knownFailingPassed_TestNames[j]); + strcpy(knownFailingPassed_FilenameLine[knownFailsPassing], runners[i].knownFailingPassed_FilenameLine[j]); + } knownFailsPassing++; } todos += runners[i].todos; - assumptionFails += runners[i].assumptionFails; + for (int j = 0; j < runners[i].assumptionFails; j++) + { + if (j < MAX_SUMMARY_TESTS_TO_LIST) + { + strcpy(assumeFailed_TestNames[assumptionFails], runners[i].assumeFailed_TestNames[j]); + strcpy(assumeFailed_FilenameLine[assumptionFails], runners[i].assumeFailed_FilenameLine[j]); + } + assumptionFails++; + } for (int j = 0; j < runners[i].fails; j++) { if (j < MAX_SUMMARY_TESTS_TO_LIST) - strcpy(failedTestNames[fails], runners[i].failedTestNames[j]); + { + strcpy(failed_TestNames[fails], runners[i].failed_TestNames[j]); + strcpy(failed_TestFilenameLine[fails], runners[i].failed_TestFilenameLine[j]); + } fails++; } results += runners[i].results; } - qsort(failedTestNames, min(fails, MAX_SUMMARY_TESTS_TO_LIST), sizeof(char) * MAX_TEST_LIST_BUFFER_LENGTH, compare_strings); - qsort(knownFailingPassedTestNames, min(fails, MAX_SUMMARY_TESTS_TO_LIST), sizeof(char) * MAX_TEST_LIST_BUFFER_LENGTH, compare_strings); - if (results == 0) { fprintf(stdout, "\nNo tests found.\n"); } else { - fprintf(stdout, "\n"); if (fails > 0) { - fprintf(stdout, "- Tests \e[31mFAILED\e[0m : %d Add TESTS='X' to run tests with the defined prefix.\n", fails); + fprintf(stdout, "\n \e[31mFAILED\e[0m tests:\n"); for (int i = 0; i < fails; i++) { if (i >= MAX_SUMMARY_TESTS_TO_LIST) @@ -586,31 +629,51 @@ int main(int argc, char *argv[]) fprintf(stdout, " - \e[31mand %d more...\e[0m\n", fails - MAX_SUMMARY_TESTS_TO_LIST); break; } - fprintf(stdout, " - \e[31m%s\e[0m.\n", failedTestNames[i]); + fprintf(stdout, " - \e[31m%s\e[0m - %s.\n", failed_TestFilenameLine[i], failed_TestNames[i]); } } + + if (assumptionFails > 0) + { + fprintf(stdout, "\n Tests with \e[33mASSUMPTIONS_FAILED\e[0m:\n"); + for (int i = 0; i < assumptionFails; i++) + { + if (i >= MAX_SUMMARY_TESTS_TO_LIST) + { + fprintf(stdout, " - \e[33mand %d more...\e[0m\n", assumptionFails - MAX_SUMMARY_TESTS_TO_LIST); + break; + } + fprintf(stdout, " - \e[33m%s\e[0m - %s.\n", assumeFailed_FilenameLine[i], assumeFailed_TestNames[i]); + } + } + if (knownFailsPassing > 0) { - fprintf(stdout, "- \e[31mKNOWN_FAILING_PASSED\e[0m: %d \e[31mPlease remove KNOWN_FAILING if these tests intentionally PASS\e[0m\n", knownFailsPassing); + fprintf(stdout, "\n \e[33mKNOWN_FAILING\e[0m tests \e[32mPASSING\e[0m:\n"); for (int i = 0; i < knownFailsPassing; i++) { if (i >= MAX_SUMMARY_TESTS_TO_LIST) { - fprintf(stdout, " - \e[31mand %d more...\e[0m\n", knownFailsPassing - MAX_SUMMARY_TESTS_TO_LIST); + fprintf(stdout, " - \e[32mand %d more...\e[0m\n", knownFailsPassing - MAX_SUMMARY_TESTS_TO_LIST); break; } - fprintf(stdout, " - \e[31m%s\e[0m.\n", knownFailingPassedTestNames[i]); + fprintf(stdout, " - \e[32m%s\e[0m - %s.\n", knownFailingPassed_FilenameLine[i], knownFailingPassed_TestNames[i]); } } - fprintf(stdout, "- Tests \e[32mPASSED\e[0m: %d\n", passes); + + fprintf(stdout, "\n"); + if (fails > 0) + fprintf(stdout, "- Tests \e[31mFAILED\e[0m : %d Add TESTS='X' to run tests with the defined prefix.\n", fails); if (knownFails > 0) - fprintf(stdout, "- Tests \e[33mKNOWN_FAILING\e[0m: %d\n", knownFails); - if (todos > 0) - fprintf(stdout, "- Tests \e[33mTO_DO\e[0m: %d\n", todos); + fprintf(stdout, "- Tests \e[33mKNOWN_FAILING\e[0m: %d\n", knownFails); if (assumptionFails > 0) - fprintf(stdout, "- \e[33mASSUMPTIONS_FAILED\e[0m: %d\n", assumptionFails); - - fprintf(stdout, "- Tests \e[34mTOTAL\e[0m: %d\n", results); + fprintf(stdout, "- \e[33mASSUMPTIONS_FAILED\e[0m: %d\n", assumptionFails); + if (todos > 0) + fprintf(stdout, "- Tests \e[33mTO_DO\e[0m: %d\n", todos); + if (knownFailsPassing > 0) + fprintf(stdout, "- \e[32mKNOWN_FAILING_PASSING\e[0m: %d \e[33mPlease remove KNOWN_FAILING if these tests intentionally PASS\e[0m\n", knownFailsPassing); + fprintf(stdout, "- Tests \e[32mPASSED\e[0m: %d\n", passes); + fprintf(stdout, "- Tests \e[34mTOTAL\e[0m: %d\n", results); } fprintf(stdout, "\n");