mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-02-05 10:52:35 +01:00
Detect more invalid test cases (#2955)
This commit is contained in:
commit
b6722ad5b1
@ -658,6 +658,7 @@ struct BattleStruct
|
||||
u8 storedLunarDance:4; // Each battler as a bit.
|
||||
u16 supremeOverlordModifier[MAX_BATTLERS_COUNT];
|
||||
u8 itemPartyIndex[MAX_BATTLERS_COUNT];
|
||||
u8 itemMoveIndex[MAX_BATTLERS_COUNT];
|
||||
bool8 trainerSlideHalfHpMsgDone;
|
||||
u8 trainerSlideFirstCriticalHitMsgState:2;
|
||||
u8 trainerSlideFirstSuperEffectiveHitMsgState:2;
|
||||
|
@ -1443,7 +1443,7 @@ static void RecordedOpponentHandleChooseItem(void)
|
||||
u8 byte2 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler);
|
||||
gBattleStruct->chosenItem[gActiveBattler] = (byte1 << 8) | byte2;
|
||||
gBattleStruct->itemPartyIndex[gActiveBattler] = RecordedBattle_GetBattlerAction(RECORDED_ITEM_TARGET, gActiveBattler);
|
||||
gChosenMovePos = RecordedBattle_GetBattlerAction(RECORDED_ITEM_MOVE, gActiveBattler);
|
||||
gBattleStruct->itemMoveIndex[gActiveBattler] = RecordedBattle_GetBattlerAction(RECORDED_ITEM_MOVE, gActiveBattler);
|
||||
BtlController_EmitOneReturnValue(BUFFER_B, gBattleStruct->chosenItem[gActiveBattler]);
|
||||
RecordedOpponentBufferExecCompleted();
|
||||
}
|
||||
|
@ -1467,7 +1467,7 @@ static void RecordedPlayerHandleChooseItem(void)
|
||||
u8 byte2 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler);
|
||||
gBattleStruct->chosenItem[gActiveBattler] = (byte1 << 8) | byte2;
|
||||
gBattleStruct->itemPartyIndex[gActiveBattler] = RecordedBattle_GetBattlerAction(RECORDED_ITEM_TARGET, gActiveBattler);
|
||||
gChosenMovePos = RecordedBattle_GetBattlerAction(RECORDED_ITEM_MOVE, gActiveBattler);
|
||||
gBattleStruct->itemMoveIndex[gActiveBattler] = RecordedBattle_GetBattlerAction(RECORDED_ITEM_MOVE, gActiveBattler);
|
||||
BtlController_EmitOneReturnValue(BUFFER_B, gBattleStruct->chosenItem[gActiveBattler]);
|
||||
RecordedPlayerBufferExecCompleted();
|
||||
}
|
||||
|
@ -16536,10 +16536,10 @@ void BS_ItemRestorePP(void) {
|
||||
// Check whether to apply to all moves.
|
||||
if (effect[4] & ITEM4_HEAL_PP_ONE)
|
||||
{
|
||||
i = gChosenMovePos;
|
||||
loopEnd = gChosenMovePos + 1;
|
||||
i = gBattleStruct->itemMoveIndex[gBattlerAttacker];
|
||||
loopEnd = i + 1;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
loopEnd = MAX_MON_MOVES;
|
||||
|
@ -4944,7 +4944,7 @@ static void TryUseItemOnMove(u8 taskId)
|
||||
else
|
||||
{
|
||||
gBattleStruct->itemPartyIndex[gBattlerInMenuId] = GetPartyIdFromBattleSlot(gPartyMenu.slotId);
|
||||
gChosenMovePos = ptr->data1;
|
||||
gBattleStruct->itemMoveIndex[gBattlerInMenuId] = ptr->data1;
|
||||
gPartyMenuUseExitCallback = TRUE;
|
||||
RemoveBagItem(gSpecialVar_ItemId, 1);
|
||||
ScheduleBgCopyTilemapToVram(2);
|
||||
|
@ -6,7 +6,7 @@ SINGLE_BATTLE_TEST("Compound Eyes raises accuracy")
|
||||
PASSES_RANDOMLY(91, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
ASSUME(gBattleMoves[MOVE_THUNDER].accuracy == 70);
|
||||
PLAYER(SPECIES_BUTTERFREE) { Ability(ABILITY_COMPOUND_EYES); };
|
||||
PLAYER(SPECIES_BUTTERFREE) { Ability(ABILITY_COMPOUND_EYES); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_THUNDER); }
|
||||
@ -16,16 +16,13 @@ SINGLE_BATTLE_TEST("Compound Eyes raises accuracy")
|
||||
}
|
||||
}
|
||||
|
||||
// This fails even though the ability works correctly. The failure is due to
|
||||
// a statistical anomaly in the test system where FISSURE hits 3 times more often
|
||||
// than we expect.
|
||||
SINGLE_BATTLE_TEST("Compound Eyes does not affect OHKO moves")
|
||||
{
|
||||
PASSES_RANDOMLY(30, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
ASSUME(gBattleMoves[MOVE_FISSURE].accuracy == 30);
|
||||
ASSUME(gBattleMoves[MOVE_FISSURE].effect == EFFECT_OHKO);
|
||||
PLAYER(SPECIES_BUTTERFREE) { Ability(ABILITY_COMPOUND_EYES); };
|
||||
PLAYER(SPECIES_BUTTERFREE) { Ability(ABILITY_COMPOUND_EYES); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FISSURE); }
|
||||
|
@ -33,10 +33,13 @@ SINGLE_BATTLE_TEST("Dry Skin heals 1/8th Max HP in Rain")
|
||||
|
||||
SINGLE_BATTLE_TEST("Dry Skin increases damage taken from Fire-type moves by 25%", s16 damage)
|
||||
{
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_EFFECT_SPORE; }
|
||||
PARAMETRIZE { ability = ABILITY_DRY_SKIN; }
|
||||
GIVEN {
|
||||
ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_PARASECT) { Ability(ABILITY_DRY_SKIN); };
|
||||
OPPONENT(SPECIES_PARASECT) { Ability(ability); };
|
||||
} WHEN {
|
||||
TURN {MOVE(player, MOVE_EMBER); }
|
||||
} SCENE {
|
||||
|
@ -63,8 +63,9 @@ SINGLE_BATTLE_TEST("Volt Absorb is only triggered once on multi strike moves")
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Volt Absorb does not stop Electric Typed Explosion from damaging other pokemon", s16 damage1, s16 damage2) // Fixed issue #1961
|
||||
DOUBLE_BATTLE_TEST("Volt Absorb does not stop Electric Typed Explosion from damaging other pokemon") // Fixed issue #1961
|
||||
{
|
||||
s16 damage1, damage2;
|
||||
GIVEN {
|
||||
ASSUME(gBattleMoves[MOVE_EXPLOSION].effect == EFFECT_EXPLOSION);
|
||||
ASSUME(gBattleMoves[MOVE_EXPLOSION].type == TYPE_NORMAL);
|
||||
@ -78,12 +79,11 @@ DOUBLE_BATTLE_TEST("Volt Absorb does not stop Electric Typed Explosion from dama
|
||||
ABILITY_POPUP(playerLeft, ABILITY_VOLT_ABSORB);
|
||||
HP_BAR(playerLeft, hp: TEST_MAX_HP / 4 + 1);
|
||||
MESSAGE("Jolteon restored HP using its Volt Absorb!");
|
||||
HP_BAR(playerRight, captureDamage: &results->damage1);
|
||||
HP_BAR(opponentRight, captureDamage: &results->damage2);
|
||||
}
|
||||
FINALLY {
|
||||
EXPECT_NE(results[0].damage1, 0);
|
||||
EXPECT_NE(results[0].damage2, 0);
|
||||
HP_BAR(playerRight, captureDamage: &damage1);
|
||||
HP_BAR(opponentRight, captureDamage: &damage2);
|
||||
} THEN {
|
||||
EXPECT_NE(damage1, 0);
|
||||
EXPECT_NE(damage2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,14 +11,11 @@ SINGLE_BATTLE_TEST("Berserk Gene sharply raises attack at the start of battle",
|
||||
u16 useItem;
|
||||
PARAMETRIZE { useItem = FALSE; }
|
||||
PARAMETRIZE { useItem = TRUE; }
|
||||
if (useItem) PASSES_RANDOMLY(66, 100, RNG_CONFUSION);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); };
|
||||
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(player, MOVE_TACKLE);
|
||||
}
|
||||
TURN { MOVE(player, MOVE_TACKLE, WITH_RNG(RNG_CONFUSION, FALSE)); }
|
||||
} SCENE {
|
||||
if (useItem)
|
||||
{
|
||||
@ -38,17 +35,13 @@ SINGLE_BATTLE_TEST("Berserk Gene activates on switch in", s16 damage)
|
||||
u16 useItem;
|
||||
PARAMETRIZE { useItem = FALSE; }
|
||||
PARAMETRIZE { useItem = TRUE; }
|
||||
if (useItem) PASSES_RANDOMLY(66, 100, RNG_CONFUSION);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); };
|
||||
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
SWITCH(player, 1);
|
||||
} TURN {
|
||||
MOVE(player, MOVE_TACKLE);
|
||||
}
|
||||
TURN { SWITCH(player, 1); }
|
||||
TURN { MOVE(player, MOVE_TACKLE, WITH_RNG(RNG_CONFUSION, FALSE)); }
|
||||
} SCENE {
|
||||
if (useItem)
|
||||
{
|
||||
|
@ -9,8 +9,8 @@ ASSUMPTIONS
|
||||
SINGLE_BATTLE_TEST("Mirror Herb copies all of foe's stat changes in a turn", s16 damage)
|
||||
{
|
||||
u32 item;
|
||||
PARAMETRIZE{ item = ITEM_NONE; }
|
||||
PARAMETRIZE{ item = ITEM_MIRROR_HERB; }
|
||||
PARAMETRIZE { item = ITEM_NONE; }
|
||||
PARAMETRIZE { item = ITEM_MIRROR_HERB; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); Item(item); }
|
||||
@ -34,7 +34,7 @@ SINGLE_BATTLE_TEST("Mirror Herb copies all of foe's stat changes in a turn", s16
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Mirror Herb copies all of of Stuff Cheeks", s16 damage)
|
||||
SINGLE_BATTLE_TEST("Mirror Herb copies all of of Stuff Cheeks")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItems[ITEM_LIECHI_BERRY].holdEffect == HOLD_EFFECT_ATTACK_UP);
|
||||
|
@ -126,7 +126,7 @@ SINGLE_BATTLE_TEST("X Speed sharply raises battler's Speed stat", s16 damage)
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("X Accuracy sharply raises battler's Accuracy stat", s16 damage)
|
||||
SINGLE_BATTLE_TEST("X Accuracy sharply raises battler's Accuracy stat")
|
||||
{
|
||||
|
||||
ASSUME(gBattleMoves[MOVE_SING].accuracy == 55);
|
||||
|
@ -183,4 +183,4 @@ SINGLE_BATTLE_TEST("Sitrus Berry restores a battler's HP by 25% of its max HP(30
|
||||
}
|
||||
|
||||
#undef TEST_HP
|
||||
#undef MAX_HP
|
||||
#undef MAX_HP
|
||||
|
@ -28,7 +28,7 @@ SINGLE_BATTLE_TEST("Bide deals twice the taken damage over two turns")
|
||||
MESSAGE("Wobbuffet unleashed energy!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BIDE, player);
|
||||
HP_BAR(opponent, captureDamage: &bideDamage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(bideDamage, damage1 + damage2);
|
||||
} THEN {
|
||||
EXPECT_EQ(bideDamage, 2 * (damage1 + damage2));
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ ASSUMPTIONS
|
||||
ASSUME(gBattleMoves[MOVE_TRIPLE_KICK].effect & EFFECT_TRIPLE_KICK);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Triple Kick damage is increaased by its base damage for each hit")
|
||||
SINGLE_BATTLE_TEST("Triple Kick damage is increased by its base damage for each hit")
|
||||
{
|
||||
s16 firstHit;
|
||||
s16 secondHit;
|
||||
@ -24,8 +24,8 @@ SINGLE_BATTLE_TEST("Triple Kick damage is increaased by its base damage for each
|
||||
HP_BAR(opponent, captureDamage: &secondHit);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRIPLE_KICK, player);
|
||||
HP_BAR(opponent, captureDamage: &thirdHit);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(secondHit, firstHit * 2);
|
||||
EXPECT_EQ(thirdHit, firstHit * 3);
|
||||
} THEN {
|
||||
EXPECT_MUL_EQ(firstHit, Q_4_12(2.0), secondHit);
|
||||
EXPECT_MUL_EQ(firstHit, Q_4_12(3.0), thirdHit);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Three-strike flag turns a move into a 3-hit move")
|
||||
HP_BAR(opponent, captureDamage: &secondHit);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRIPLE_DIVE, player);
|
||||
HP_BAR(opponent, captureDamage: &thirdHit);
|
||||
} FINALLY {
|
||||
} THEN {
|
||||
EXPECT_EQ(firstHit, secondHit);
|
||||
EXPECT_EQ(secondHit, thirdHit);
|
||||
EXPECT_EQ(firstHit, thirdHit);
|
||||
@ -49,7 +49,7 @@ SINGLE_BATTLE_TEST("Surging Strikes hits 3 times with each hit being a critical
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SURGING_STRIKES, player);
|
||||
HP_BAR(opponent, captureDamage: &thirdHit);
|
||||
MESSAGE("A critical hit!");
|
||||
} FINALLY {
|
||||
} THEN {
|
||||
EXPECT_EQ(firstHit, secondHit);
|
||||
EXPECT_EQ(secondHit, thirdHit);
|
||||
EXPECT_EQ(firstHit, thirdHit);
|
||||
|
@ -34,7 +34,7 @@ SINGLE_BATTLE_TEST("Electric Terrain activates Electric Seed and Mimicry")
|
||||
MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!");
|
||||
ABILITY_POPUP(opponent);
|
||||
MESSAGE("Foe Stunfisk's type changed to Electr!");
|
||||
} FINALLY {
|
||||
} THEN {
|
||||
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_ELECTRIC);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ SINGLE_BATTLE_TEST("Grassy Terrain activates Grassy Seed and Mimicry")
|
||||
MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!");
|
||||
ABILITY_POPUP(opponent);
|
||||
MESSAGE("Foe Stunfisk's type changed to Grass!");
|
||||
} FINALLY {
|
||||
} THEN {
|
||||
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_GRASS);
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ SINGLE_BATTLE_TEST("Misty Terrain activates Misty Seed and Mimicry")
|
||||
MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!");
|
||||
ABILITY_POPUP(opponent);
|
||||
MESSAGE("Foe Stunfisk's type changed to Fairy!");
|
||||
} FINALLY {
|
||||
} THEN {
|
||||
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_FAIRY);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ SINGLE_BATTLE_TEST("Psychic Terrain activates Psychic Seed and Mimicry")
|
||||
MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!");
|
||||
ABILITY_POPUP(opponent);
|
||||
MESSAGE("Foe Stunfisk's type changed to Psychc!");
|
||||
} FINALLY {
|
||||
} THEN {
|
||||
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_PSYCHIC);
|
||||
}
|
||||
}
|
||||
@ -61,7 +61,7 @@ SINGLE_BATTLE_TEST("Psychic Terrain increases power of Psychic-type moves by 30/
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target the user", s16 damage)
|
||||
SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target the user")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); HP(1); }
|
||||
@ -76,7 +76,7 @@ SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target the
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all battlers", s16 damage)
|
||||
SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all battlers")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
@ -91,7 +91,7 @@ SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all opponents", s16 damage)
|
||||
SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all opponents")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
@ -106,7 +106,7 @@ SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target allies", s16 damage)
|
||||
DOUBLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target allies")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); }
|
||||
@ -122,7 +122,7 @@ DOUBLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority field moves", s16 damage)
|
||||
SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority field moves")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
|
@ -897,7 +897,9 @@ void QueueStatus(u32 sourceLine, struct BattlePokemon *battler, struct StatusEve
|
||||
|
||||
/* Finally */
|
||||
|
||||
#define FINALLY for (; gBattleTestRunnerState->runFinally; gBattleTestRunnerState->runFinally = FALSE) if ((gBattleTestRunnerState->runningFinally = TRUE))
|
||||
#define FINALLY for (ValidateFinally(__LINE__); gBattleTestRunnerState->runFinally; gBattleTestRunnerState->runFinally = FALSE) if ((gBattleTestRunnerState->runningFinally = TRUE))
|
||||
|
||||
void ValidateFinally(u32 sourceLine);
|
||||
|
||||
/* Expect */
|
||||
|
||||
|
@ -42,7 +42,14 @@ static bool32 PrefixMatch(const char *pattern, const char *string)
|
||||
}
|
||||
}
|
||||
|
||||
enum { STATE_INIT, STATE_NEXT_TEST, STATE_REPORT_RESULT, STATE_EXIT };
|
||||
enum
|
||||
{
|
||||
STATE_INIT,
|
||||
STATE_NEXT_TEST,
|
||||
STATE_RUN_TEST,
|
||||
STATE_REPORT_RESULT,
|
||||
STATE_EXIT,
|
||||
};
|
||||
|
||||
void CB2_TestRunner(void)
|
||||
{
|
||||
@ -81,6 +88,26 @@ void CB2_TestRunner(void)
|
||||
return;
|
||||
}
|
||||
|
||||
MgbaPrintf_(":N%s", gTestRunnerState.test->name);
|
||||
gTestRunnerState.result = TEST_RESULT_PASS;
|
||||
gTestRunnerState.expectedResult = TEST_RESULT_PASS;
|
||||
gTestRunnerState.expectLeaks = FALSE;
|
||||
if (gTestRunnerHeadless)
|
||||
gTestRunnerState.timeoutSeconds = TIMEOUT_SECONDS;
|
||||
else
|
||||
gTestRunnerState.timeoutSeconds = UINT_MAX;
|
||||
InitHeap(gHeap, HEAP_SIZE);
|
||||
EnableInterrupts(INTR_FLAG_TIMER2);
|
||||
REG_TM2CNT_L = UINT16_MAX - (274 * 60); // Approx. 1 second.
|
||||
REG_TM2CNT_H = TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_1024CLK;
|
||||
|
||||
// NOTE: Assumes that the compiler interns __FILE__.
|
||||
if (gTestRunnerState.skipFilename == gTestRunnerState.test->filename)
|
||||
{
|
||||
gTestRunnerState.result = TEST_RESULT_ASSUMPTION_FAIL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Greedily assign tests to processes based on estimated cost.
|
||||
// TODO: Make processCosts a min heap.
|
||||
if (gTestRunnerState.test->runner != &gAssumptionsRunner)
|
||||
@ -98,40 +125,26 @@ void CB2_TestRunner(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (minCostProcess == gTestRunnerI)
|
||||
gTestRunnerState.state = STATE_RUN_TEST;
|
||||
else
|
||||
gTestRunnerState.state = STATE_NEXT_TEST;
|
||||
|
||||
// XXX: If estimateCost exits only on some processes then
|
||||
// processCosts will be inconsistent.
|
||||
if (gTestRunnerState.test->runner->estimateCost)
|
||||
gTestRunnerState.processCosts[minCostProcess] += gTestRunnerState.test->runner->estimateCost(gTestRunnerState.test->data);
|
||||
else
|
||||
gTestRunnerState.processCosts[minCostProcess] += 1;
|
||||
|
||||
if (minCostProcess != gTestRunnerI)
|
||||
return;
|
||||
}
|
||||
|
||||
MgbaPrintf_(":N%s", gTestRunnerState.test->name);
|
||||
break;
|
||||
|
||||
case STATE_RUN_TEST:
|
||||
gTestRunnerState.state = STATE_REPORT_RESULT;
|
||||
gTestRunnerState.result = TEST_RESULT_PASS;
|
||||
gTestRunnerState.expectedResult = TEST_RESULT_PASS;
|
||||
gTestRunnerState.expectLeaks = FALSE;
|
||||
if (gTestRunnerHeadless)
|
||||
gTestRunnerState.timeoutSeconds = TIMEOUT_SECONDS;
|
||||
else
|
||||
gTestRunnerState.timeoutSeconds = UINT_MAX;
|
||||
InitHeap(gHeap, HEAP_SIZE);
|
||||
EnableInterrupts(INTR_FLAG_TIMER2);
|
||||
REG_TM2CNT_L = UINT16_MAX - (274 * 60); // Approx. 1 second.
|
||||
REG_TM2CNT_H = TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_1024CLK;
|
||||
|
||||
// NOTE: Assumes that the compiler interns __FILE__.
|
||||
if (gTestRunnerState.skipFilename == gTestRunnerState.test->filename)
|
||||
{
|
||||
gTestRunnerState.result = TEST_RESULT_ASSUMPTION_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gTestRunnerState.test->runner->setUp)
|
||||
gTestRunnerState.test->runner->setUp(gTestRunnerState.test->data);
|
||||
gTestRunnerState.test->runner->run(gTestRunnerState.test->data);
|
||||
}
|
||||
if (gTestRunnerState.test->runner->setUp)
|
||||
gTestRunnerState.test->runner->setUp(gTestRunnerState.test->data);
|
||||
gTestRunnerState.test->runner->run(gTestRunnerState.test->data);
|
||||
break;
|
||||
|
||||
case STATE_REPORT_RESULT:
|
||||
@ -345,6 +358,8 @@ static void Intr_Timer2(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gTestRunnerState.state == STATE_RUN_TEST)
|
||||
gTestRunnerState.state = STATE_REPORT_RESULT;
|
||||
gTestRunnerState.result = TEST_RESULT_TIMEOUT;
|
||||
ReinitCallbacks();
|
||||
IRQ_LR = ((uintptr_t)JumpToAgbMainLoop & ~1) + 4;
|
||||
@ -354,16 +369,19 @@ 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)
|
||||
handled = gTestRunnerState.test->runner->handleExitWithResult(gTestRunnerState.test->data, result);
|
||||
if (!handled && gTestRunnerState.result != gTestRunnerState.expectedResult)
|
||||
if (gTestRunnerState.state == STATE_REPORT_RESULT
|
||||
&& gTestRunnerState.test->runner->handleExitWithResult)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
MgbaVPrintf_(fmt, va);
|
||||
if (!gTestRunnerState.test->runner->handleExitWithResult(gTestRunnerState.test->data, result)
|
||||
&& gTestRunnerState.result != gTestRunnerState.expectedResult)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
MgbaVPrintf_(fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
}
|
||||
JumpToAgbMainLoop();
|
||||
}
|
||||
|
@ -134,6 +134,8 @@ static void BattleTest_SetUp(void *data)
|
||||
Test_ExitWithResult(TEST_RESULT_ERROR, "OOM: STATE = AllocZerod(%d)", sizeof(*STATE));
|
||||
InvokeTestFunction(test);
|
||||
STATE->parameters = STATE->parametersCount;
|
||||
if (STATE->parametersCount == 0 && test->resultsSize > 0)
|
||||
Test_ExitWithResult(TEST_RESULT_INVALID, "results without PARAMETRIZE");
|
||||
STATE->results = AllocZeroed(test->resultsSize * STATE->parameters);
|
||||
if (!STATE->results)
|
||||
Test_ExitWithResult(TEST_RESULT_ERROR, "OOM: STATE->results = AllocZerod(%d)", sizeof(test->resultsSize * STATE->parameters));
|
||||
@ -939,6 +941,8 @@ static bool32 BattleTest_HandleExitWithResult(void *data, enum TestResult result
|
||||
|
||||
void Randomly(u32 sourceLine, u32 passes, u32 trials, struct RandomlyContext ctx)
|
||||
{
|
||||
const struct BattleTest *test = gTestRunnerState.test->data;
|
||||
INVALID_IF(test->resultsSize > 0, "PASSES_RANDOMLY is incompatible with results");
|
||||
INVALID_IF(passes > trials, "%d passes specified, but only %d trials", passes, trials);
|
||||
STATE->rngTag = ctx.tag;
|
||||
STATE->runTrial = 0;
|
||||
@ -1564,6 +1568,10 @@ void UseItem(u32 sourceLine, struct BattlePokemon *battler, struct ItemContext c
|
||||
}
|
||||
INVALID_IF(i == MAX_MON_MOVES, "USE_ITEM on invalid move: %d", ctx.move);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
PushBattlerAction(sourceLine, battlerId, RECORDED_ACTION_TYPE, B_ACTION_USE_ITEM);
|
||||
PushBattlerAction(sourceLine, battlerId, RECORDED_ITEM_ID, (ctx.itemId >> 8) & 0xFF);
|
||||
PushBattlerAction(sourceLine, battlerId, RECORDED_ITEM_ID, ctx.itemId & 0xFF);
|
||||
@ -1719,7 +1727,6 @@ void QueueMessage(u32 sourceLine, const u8 *pattern)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void QueueStatus(u32 sourceLine, struct BattlePokemon *battler, struct StatusEventContext ctx)
|
||||
{
|
||||
s32 battlerId = battler - gBattleMons;
|
||||
@ -1759,3 +1766,11 @@ void QueueStatus(u32 sourceLine, struct BattlePokemon *battler, struct StatusEve
|
||||
}},
|
||||
};
|
||||
}
|
||||
|
||||
void ValidateFinally(u32 sourceLine)
|
||||
{
|
||||
// Defer this error until after estimating the cost.
|
||||
if (STATE->results == NULL)
|
||||
return;
|
||||
INVALID_IF(STATE->parametersCount == 0, "FINALLY without PARAMETRIZE");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user