Merge branch '_RHH/master' into _RHH/upcoming
# Conflicts: # ld_script_modern.ld # src/battle_ai_switch_items.c
This commit is contained in:
commit
09d12fb154
11 changed files with 139 additions and 58 deletions
|
@ -7,11 +7,11 @@ JASC-PAL
|
|||
201 201 201
|
||||
169 169 169
|
||||
129 129 129
|
||||
249 153 161
|
||||
233 49 49
|
||||
193 33 41
|
||||
145 17 33
|
||||
249 153 161
|
||||
106 106 106
|
||||
37 37 37
|
||||
106 106 106
|
||||
0 0 0
|
||||
106 106 106
|
||||
193 33 41
|
||||
141 251 184
|
||||
52 66 162
|
||||
|
|
|
@ -337,7 +337,7 @@ struct AiLogicData
|
|||
bool8 shouldSwitchMon; // Because all available moves have no/little effect. Each bit per battler.
|
||||
u8 monToSwitchId[MAX_BATTLERS_COUNT]; // ID of the mon to switch.
|
||||
bool8 weatherHasEffect; // The same as WEATHER_HAS_EFFECT. Stored here, so it's called only once.
|
||||
u8 mostSuitableMonId; // Stores result of GetMostSuitableMonToSwitchInto, which decides which generic mon the AI would switch into if they decide to switch. This can be overruled by specific mons found in ShouldSwitch; the final resulting mon is stored in AI_monToSwitchIntoId.
|
||||
u8 mostSuitableMonId[MAX_BATTLERS_COUNT]; // Stores result of GetMostSuitableMonToSwitchInto, which decides which generic mon the AI would switch into if they decide to switch. This can be overruled by specific mons found in ShouldSwitch; the final resulting mon is stored in AI_monToSwitchIntoId.
|
||||
struct SwitchinCandidate switchinCandidate; // Struct used for deciding which mon to switch to in battle_ai_switch_items.c
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,11 @@ SECTIONS {
|
|||
ALIGN(4)
|
||||
{
|
||||
__ewram_start = .;
|
||||
/*
|
||||
We link malloc.o here to prevent `gHeap` from landing in the middle of EWRAM.
|
||||
Otherwise this causes corruption issues on some ld versions
|
||||
*/
|
||||
gflib/malloc.o(ewram_data);
|
||||
*(.ewram*)
|
||||
__ewram_end = .;
|
||||
} > EWRAM
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "battle_anim.h"
|
||||
#include "battle_ai_util.h"
|
||||
#include "battle_ai_main.h"
|
||||
#include "battle_controllers.h"
|
||||
#include "battle_factory.h"
|
||||
#include "battle_setup.h"
|
||||
#include "battle_z_move.h"
|
||||
|
@ -455,11 +456,21 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData)
|
|||
}
|
||||
}
|
||||
|
||||
static bool32 AI_SwitchMonIfSuitable(u32 battler)
|
||||
static bool32 AI_SwitchMonIfSuitable(u32 battler, bool32 doubleBattle)
|
||||
{
|
||||
u32 monToSwitchId = AI_DATA->mostSuitableMonId;
|
||||
if (monToSwitchId != PARTY_SIZE)
|
||||
u32 monToSwitchId = AI_DATA->mostSuitableMonId[battler];
|
||||
if (monToSwitchId != PARTY_SIZE && IsValidForBattle(&GetBattlerParty(battler)[monToSwitchId]))
|
||||
{
|
||||
gBattleMoveDamage = monToSwitchId;
|
||||
// Edge case: See if partner already chose to switch into the same mon
|
||||
if (doubleBattle)
|
||||
{
|
||||
u32 partner = BATTLE_PARTNER(battler);
|
||||
if (AI_DATA->shouldSwitchMon & gBitTable[partner] && AI_DATA->monToSwitchId[partner] == monToSwitchId)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
AI_DATA->shouldSwitchMon |= gBitTable[battler];
|
||||
AI_DATA->monToSwitchId[battler] = monToSwitchId;
|
||||
return TRUE;
|
||||
|
@ -496,7 +507,7 @@ static bool32 AI_ShouldSwitchIfBadMoves(u32 battler, bool32 doubleBattle)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_BATTLERS_COUNT && AI_SwitchMonIfSuitable(battler))
|
||||
if (i == MAX_BATTLERS_COUNT && AI_SwitchMonIfSuitable(battler, doubleBattle))
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
|
@ -507,7 +518,7 @@ static bool32 AI_ShouldSwitchIfBadMoves(u32 battler, bool32 doubleBattle)
|
|||
break;
|
||||
}
|
||||
|
||||
if (i == MAX_MON_MOVES && AI_SwitchMonIfSuitable(battler))
|
||||
if (i == MAX_MON_MOVES && AI_SwitchMonIfSuitable(battler, doubleBattle))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -519,7 +530,7 @@ static bool32 AI_ShouldSwitchIfBadMoves(u32 battler, bool32 doubleBattle)
|
|||
&& IsTruantMonVulnerable(battler, gBattlerTarget)
|
||||
&& gDisableStructs[battler].truantCounter
|
||||
&& gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2
|
||||
&& AI_SwitchMonIfSuitable(battler))
|
||||
&& AI_SwitchMonIfSuitable(battler, doubleBattle))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult)
|
|||
}
|
||||
|
||||
// If we don't have any other viable options, don't switch out
|
||||
if (AI_DATA->mostSuitableMonId == PARTY_SIZE)
|
||||
if (AI_DATA->mostSuitableMonId[battler] == PARTY_SIZE)
|
||||
return FALSE;
|
||||
|
||||
// Start assessing whether or not mon has bad odds
|
||||
|
@ -603,12 +603,12 @@ static bool32 ShouldSwitchIfAbilityBenefit(u32 battler, bool32 emitResult)
|
|||
moduloChance = 4; //25%
|
||||
//Attempt to cure bad ailment
|
||||
if (gBattleMons[battler].status1 & (STATUS1_SLEEP | STATUS1_FREEZE | STATUS1_TOXIC_POISON)
|
||||
&& AI_DATA->mostSuitableMonId != PARTY_SIZE)
|
||||
&& AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE)
|
||||
break;
|
||||
//Attempt to cure lesser ailment
|
||||
if ((gBattleMons[battler].status1 & STATUS1_ANY)
|
||||
&& (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2)
|
||||
&& AI_DATA->mostSuitableMonId != PARTY_SIZE
|
||||
&& AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE
|
||||
&& Random() % (moduloChance*chanceReducer) == 0)
|
||||
break;
|
||||
|
||||
|
@ -620,7 +620,7 @@ static bool32 ShouldSwitchIfAbilityBenefit(u32 battler, bool32 emitResult)
|
|||
if (gBattleMons[battler].status1 & STATUS1_ANY)
|
||||
return FALSE;
|
||||
if ((gBattleMons[battler].hp <= ((gBattleMons[battler].maxHP * 2) / 3))
|
||||
&& AI_DATA->mostSuitableMonId != PARTY_SIZE
|
||||
&& AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE
|
||||
&& Random() % (moduloChance*chanceReducer) == 0)
|
||||
break;
|
||||
|
||||
|
@ -856,7 +856,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler, bool32 emitResult)
|
|||
return FALSE;
|
||||
|
||||
// If not Encored or if no good switchin, don't switch
|
||||
if (gDisableStructs[battler].encoredMove == MOVE_NONE || AI_DATA->mostSuitableMonId == PARTY_SIZE)
|
||||
if (gDisableStructs[battler].encoredMove == MOVE_NONE || AI_DATA->mostSuitableMonId[battler] == PARTY_SIZE)
|
||||
return FALSE;
|
||||
|
||||
// Otherwise 50% chance to switch out
|
||||
|
@ -890,7 +890,7 @@ static bool32 AreAttackingStatsLowered(u32 battler, bool32 emitResult)
|
|||
// 50% chance if attack at -2 and have a good candidate mon
|
||||
else if (attackingStage == DEFAULT_STAT_STAGE - 2)
|
||||
{
|
||||
if (AI_DATA->mostSuitableMonId != PARTY_SIZE && (Random() & 1))
|
||||
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (Random() & 1))
|
||||
{
|
||||
gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(battler, 1, B_ACTION_SWITCH, 0);
|
||||
|
@ -915,7 +915,7 @@ static bool32 AreAttackingStatsLowered(u32 battler, bool32 emitResult)
|
|||
// 50% chance if attack at -2 and have a good candidate mon
|
||||
else if (spAttackingStage == DEFAULT_STAT_STAGE - 2)
|
||||
{
|
||||
if (AI_DATA->mostSuitableMonId != PARTY_SIZE && (Random() & 1))
|
||||
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (Random() & 1))
|
||||
{
|
||||
gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(battler, 1, B_ACTION_SWITCH, 0);
|
||||
|
@ -1064,7 +1064,7 @@ void AI_TrySwitchOrUseItem(u32 battler)
|
|||
{
|
||||
if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE)
|
||||
{
|
||||
s32 monToSwitchId = AI_DATA->mostSuitableMonId;
|
||||
s32 monToSwitchId = AI_DATA->mostSuitableMonId[battler];
|
||||
if (monToSwitchId == PARTY_SIZE)
|
||||
{
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
|
||||
|
|
|
@ -4075,7 +4075,7 @@ static void HandleTurnActionSelectionState(void)
|
|||
if ((gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart())
|
||||
&& (BattlerHasAi(battler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE)))
|
||||
{
|
||||
AI_DATA->mostSuitableMonId = GetMostSuitableMonToSwitchInto(battler, FALSE);
|
||||
AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, FALSE);
|
||||
gBattleStruct->aiMoveOrAction[battler] = ComputeBattleAiScores(battler);
|
||||
}
|
||||
// fallthrough
|
||||
|
|
|
@ -6550,7 +6550,7 @@ static u8 ItemHealHp(u32 battler, u32 itemId, bool32 end2, bool32 percentHeal)
|
|||
gBattlescriptCurrInstr = BattleScript_ItemHealHP_RemoveItemRet;
|
||||
}
|
||||
if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_EMERGENCY_EXIT
|
||||
&& GetNonDynamaxMaxHP(battler) > gBattleMons[battler].maxHP / 2)
|
||||
&& GetNonDynamaxHP(battler) >= GetNonDynamaxMaxHP(battler) / 2)
|
||||
gBattleResources->flags->flags[battler] &= ~RESOURCE_FLAG_EMERGENCY_EXIT;
|
||||
|
||||
return ITEM_HP_CHANGE;
|
||||
|
|
|
@ -8,10 +8,7 @@ SINGLE_BATTLE_TEST("Emergency Exit switches out when taking 50% max-hp damage")
|
|||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(262); };
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(player, MOVE_SUPER_FANG);
|
||||
SEND_OUT(opponent, 1);
|
||||
}
|
||||
TURN { MOVE(player, MOVE_SUPER_FANG); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUPER_FANG, player);
|
||||
HP_BAR(opponent);
|
||||
|
@ -19,16 +16,14 @@ SINGLE_BATTLE_TEST("Emergency Exit switches out when taking 50% max-hp damage")
|
|||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit switches out when taking 50% max-hp damage after a restore hp hold effect was used")
|
||||
SINGLE_BATTLE_TEST("Emergency Exit does not switch out when going below 50% max-HP but healed via held item back above the threshold")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET)
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(262); Item(ITEM_SITRUS_BERRY); };
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(player, MOVE_SUPER_FANG);
|
||||
}
|
||||
TURN { MOVE(player, MOVE_SUPER_FANG); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUPER_FANG, player);
|
||||
HP_BAR(opponent);
|
||||
|
@ -36,3 +31,19 @@ SINGLE_BATTLE_TEST("Emergency Exit switches out when taking 50% max-hp damage af
|
|||
NOT ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit switches out when going below 50% max-HP but healing via held item is not enough to go back above the threshold")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET)
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(133); Item(ITEM_ORAN_BERRY); };
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SUPER_FANG); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUPER_FANG, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -702,3 +702,31 @@ AI_SINGLE_BATTLE_TEST("First Impression is not chosen if it's blocked by certain
|
|||
TURN { EXPECT_MOVE(opponent, MOVE_LUNGE); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2 spots in a double battle")
|
||||
{
|
||||
u32 flags;
|
||||
|
||||
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
|
||||
PARAMETRIZE {flags = 0; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags);
|
||||
PLAYER(SPECIES_RATTATA);
|
||||
PLAYER(SPECIES_RATTATA);
|
||||
// No moves to damage player.
|
||||
OPPONENT(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); }
|
||||
OPPONENT(SPECIES_HAUNTER) { Moves(MOVE_SHADOW_BALL); }
|
||||
OPPONENT(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); }
|
||||
OPPONENT(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_SWITCH(opponentLeft, 3); };
|
||||
} SCENE {
|
||||
MESSAGE("{PKMN} TRAINER LEAF withdrew Gengar!");
|
||||
MESSAGE("{PKMN} TRAINER LEAF sent out Raticate!");
|
||||
NONE_OF {
|
||||
MESSAGE("{PKMN} TRAINER LEAF withdrew Haunter!");
|
||||
MESSAGE("{PKMN} TRAINER LEAF sent out Raticate!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ void TestRunner_Battle(const struct Test *);
|
|||
|
||||
static bool32 MgbaOpen_(void);
|
||||
static void MgbaExit_(u8 exitCode);
|
||||
static s32 MgbaPuts_(const char *s);
|
||||
static s32 MgbaVPrintf_(const char *fmt, va_list va);
|
||||
static void Intr_Timer2(void);
|
||||
|
||||
|
@ -293,12 +292,6 @@ top:
|
|||
color = "";
|
||||
}
|
||||
|
||||
if (gTestRunnerState.result == TEST_RESULT_PASS
|
||||
&& gTestRunnerState.result != gTestRunnerState.expectedResult)
|
||||
{
|
||||
MgbaPuts_("\e[31mPlease remove KNOWN_FAILING if this test intentionally PASSes\e[0m");
|
||||
}
|
||||
|
||||
switch (gTestRunnerState.result)
|
||||
{
|
||||
case TEST_RESULT_FAIL:
|
||||
|
@ -313,7 +306,10 @@ top:
|
|||
}
|
||||
break;
|
||||
case TEST_RESULT_PASS:
|
||||
result = "PASS";
|
||||
if (gTestRunnerState.result != gTestRunnerState.expectedResult)
|
||||
result = "KNOWN_FAILING_PASS";
|
||||
else
|
||||
result = "PASS";
|
||||
break;
|
||||
case TEST_RESULT_ASSUMPTION_FAIL:
|
||||
result = "ASSUMPTION_FAIL";
|
||||
|
@ -341,7 +337,12 @@ top:
|
|||
}
|
||||
|
||||
if (gTestRunnerState.result == TEST_RESULT_PASS)
|
||||
MgbaPrintf_(":P%s%s\e[0m", color, result);
|
||||
{
|
||||
if (gTestRunnerState.result != gTestRunnerState.expectedResult)
|
||||
MgbaPrintf_(":U%s%s\e[0m", color, result);
|
||||
else
|
||||
MgbaPrintf_(":P%s%s\e[0m", color, result);
|
||||
}
|
||||
else if (gTestRunnerState.result == TEST_RESULT_ASSUMPTION_FAIL)
|
||||
MgbaPrintf_(":A%s%s\e[0m", color, result);
|
||||
else if (gTestRunnerState.result == TEST_RESULT_TODO)
|
||||
|
@ -513,11 +514,6 @@ static void MgbaExit_(u8 exitCode)
|
|||
asm("swi 0x3" :: "r" (_exitCode));
|
||||
}
|
||||
|
||||
static s32 MgbaPuts_(const char *s)
|
||||
{
|
||||
return MgbaPrintf_("%s", s);
|
||||
}
|
||||
|
||||
s32 MgbaPrintf_(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define MAX_PROCESSES 32 // See also test/test.h
|
||||
#define MAX_FAILED_TESTS_TO_LIST 100
|
||||
#define MAX_SUMMARY_TESTS_TO_LIST 50
|
||||
#define MAX_TEST_LIST_BUFFER_LENGTH 256
|
||||
|
||||
#define ARRAY_COUNT(arr) (sizeof((arr)) / sizeof((arr)[0]))
|
||||
|
@ -54,11 +54,13 @@ struct Runner
|
|||
char *output_buffer;
|
||||
int passes;
|
||||
int knownFails;
|
||||
int knownFailsPassing;
|
||||
int todos;
|
||||
int assumptionFails;
|
||||
int fails;
|
||||
int results;
|
||||
char failedTestNames[MAX_FAILED_TESTS_TO_LIST][MAX_TEST_LIST_BUFFER_LENGTH];
|
||||
char failedTestNames[MAX_SUMMARY_TESTS_TO_LIST][MAX_TEST_LIST_BUFFER_LENGTH];
|
||||
char knownFailingPassedTestNames[MAX_SUMMARY_TESTS_TO_LIST][MAX_TEST_LIST_BUFFER_LENGTH];
|
||||
};
|
||||
|
||||
static unsigned nrunners = 0;
|
||||
|
@ -107,6 +109,11 @@ static void handle_read(int i, struct Runner *runner)
|
|||
case 'K':
|
||||
runner->knownFails++;
|
||||
goto add_to_results;
|
||||
case 'U':
|
||||
if (runner->knownFailsPassing < MAX_SUMMARY_TESTS_TO_LIST)
|
||||
strcpy(runner->knownFailingPassedTestNames[runner->knownFailsPassing], runner->test_name);
|
||||
runner->knownFailsPassing++;
|
||||
goto add_to_results;
|
||||
case 'T':
|
||||
runner->todos++;
|
||||
goto add_to_results;
|
||||
|
@ -114,7 +121,7 @@ static void handle_read(int i, struct Runner *runner)
|
|||
runner->assumptionFails++;
|
||||
goto add_to_results;
|
||||
case 'F':
|
||||
if (runner->fails < MAX_FAILED_TESTS_TO_LIST)
|
||||
if (runner->fails < MAX_SUMMARY_TESTS_TO_LIST)
|
||||
strcpy(runner->failedTestNames[runner->fails], runner->test_name);
|
||||
runner->fails++;
|
||||
add_to_results:
|
||||
|
@ -519,12 +526,14 @@ int main(int argc, char *argv[])
|
|||
int exit_code = 0;
|
||||
int passes = 0;
|
||||
int knownFails = 0;
|
||||
int knownFailsPassing = 0;
|
||||
int todos = 0;
|
||||
int assumptionFails = 0;
|
||||
int fails = 0;
|
||||
int results = 0;
|
||||
|
||||
char failedTestNames[MAX_FAILED_TESTS_TO_LIST * MAX_PROCESSES][MAX_TEST_LIST_BUFFER_LENGTH];
|
||||
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];
|
||||
|
||||
for (int i = 0; i < nrunners; i++)
|
||||
{
|
||||
|
@ -540,18 +549,25 @@ int main(int argc, char *argv[])
|
|||
exit_code = WEXITSTATUS(wstatus);
|
||||
passes += runners[i].passes;
|
||||
knownFails += runners[i].knownFails;
|
||||
for (int j = 0; j < runners[i].knownFailsPassing; j++)
|
||||
{
|
||||
if (j < MAX_SUMMARY_TESTS_TO_LIST)
|
||||
strcpy(knownFailingPassedTestNames[fails], runners[i].knownFailingPassedTestNames[j]);
|
||||
knownFailsPassing++;
|
||||
}
|
||||
todos += runners[i].todos;
|
||||
assumptionFails += runners[i].assumptionFails;
|
||||
for (int j = 0; j < runners[i].fails; j++)
|
||||
{
|
||||
if (j < MAX_FAILED_TESTS_TO_LIST)
|
||||
if (j < MAX_SUMMARY_TESTS_TO_LIST)
|
||||
strcpy(failedTestNames[fails], runners[i].failedTestNames[j]);
|
||||
fails++;
|
||||
}
|
||||
results += runners[i].results;
|
||||
}
|
||||
|
||||
qsort(failedTestNames, min(fails, MAX_FAILED_TESTS_TO_LIST), sizeof(char) * MAX_TEST_LIST_BUFFER_LENGTH, compare_strings);
|
||||
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)
|
||||
{
|
||||
|
@ -559,28 +575,42 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
fprintf(stdout, "\n");
|
||||
if (fails > 0)
|
||||
{
|
||||
fprintf(stdout, "\n- Tests \e[31mFAILED\e[0m : %d Add TESTS='X' to run tests with the defined prefix.\n", fails);
|
||||
fprintf(stdout, "- Tests \e[31mFAILED\e[0m : %d Add TESTS='X' to run tests with the defined prefix.\n", fails);
|
||||
for (int i = 0; i < fails; i++)
|
||||
{
|
||||
if (i >= MAX_FAILED_TESTS_TO_LIST)
|
||||
if (i >= MAX_SUMMARY_TESTS_TO_LIST)
|
||||
{
|
||||
fprintf(stdout, " - \e[31mand %d more...\e[0m\n", fails - MAX_FAILED_TESTS_TO_LIST);
|
||||
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, "- Tests \e[32mPASSED\e[0m: %d\n", passes);
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
fprintf(stdout, " - \e[31m%s\e[0m.\n", knownFailingPassedTestNames[i]);
|
||||
}
|
||||
}
|
||||
fprintf(stdout, "- Tests \e[32mPASSED\e[0m: %d\n", passes);
|
||||
if (knownFails > 0)
|
||||
fprintf(stdout, "- Tests \e[33mKNOWN_FAILING\e[0m: %d\n", knownFails);
|
||||
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[33mTO_DO\e[0m: %d\n", todos);
|
||||
if (assumptionFails > 0)
|
||||
fprintf(stdout, "- \e[33mASSUMPTIONS_FAILED\e[0m: %d\n", assumptionFails);
|
||||
fprintf(stdout, "- \e[33mASSUMPTIONS_FAILED\e[0m: %d\n", assumptionFails);
|
||||
|
||||
fprintf(stdout, "- Tests \e[34mTOTAL\e[0m: %d\n", results);
|
||||
fprintf(stdout, "- Tests \e[34mTOTAL\e[0m: %d\n", results);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
|
|
Loading…
Reference in a new issue