1
0
mirror of https://github.com/vcmi/vcmi.git synced 2026-05-22 09:55:17 +02:00
Files
vcmi/test/game/HeroRecruitmentTest.cpp
T
2026-01-25 21:21:01 +00:00

140 lines
4.4 KiB
C++

/*
* HeroRecruitmentTest.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "GameStateTest.h"
#include "../../lib/gameState/TavernHeroesPool.h"
#include "../../lib/networkPacks/PacksForClient.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CGTownInstance.h"
#include "../../lib/CPlayerState.h"
/**
* Test fixture for hero recruitment netpack tests.
* Inherits game setup and state management from GameStateTest.
*/
class HeroRecruitmentTest : public GameStateTest
{
};
// Test that hero recruitment properly assigns an ID to the recruited hero
TEST_F(HeroRecruitmentTest, DISABLED_recruitedHeroGetsId)
{
startTestGame();
// Get the first player and find a town
PlayerColor playerColor = PlayerColor(0);
auto * playerState = gameState->getPlayerState(playerColor);
ASSERT_NE(playerState, nullptr);
// Get initial state
auto initialHeroes = playerState->getHeroes();
size_t initialHeroCount = initialHeroes.size();
// Find a town for recruitment
auto towns = playerState->getTowns();
ASSERT_FALSE(towns.empty()) << "Player must have at least one town for hero recruitment";
auto * town = towns.front();
ASSERT_NE(town, nullptr);
// Get a hero type from the pool
auto poolHeroes = gameState->heroesPool->getHeroesFor(playerColor);
ASSERT_FALSE(poolHeroes.empty()) << "Hero pool must have heroes available";
const auto * poolHero = poolHeroes.front();
ASSERT_NE(poolHero, nullptr);
HeroTypeID heroType = poolHero->getHeroTypeID();
// Create and apply HeroRecruited pack
HeroRecruited pack;
pack.tid = town->id;
pack.hid = heroType;
pack.player = playerColor;
pack.tile = town->visitablePos();
gameEventCallback->sendAndApply(pack);
// Verify player now has one more hero
auto finalHeroes = playerState->getHeroes();
EXPECT_EQ(finalHeroes.size(), initialHeroCount + 1)
<< "Player should have exactly one more hero after recruitment";
// Find the newly recruited hero
CGHeroInstance * recruitedHero = nullptr;
for (auto * hero : finalHeroes)
{
if (std::find(initialHeroes.begin(), initialHeroes.end(), hero) == initialHeroes.end())
{
recruitedHero = hero;
break;
}
}
ASSERT_NE(recruitedHero, nullptr) << "Recruited hero must exist in player's hero list";
// This is the key assertion that validates our fix:
// The hero must have an ID assigned after being added to the map
EXPECT_TRUE(recruitedHero->id.hasValue())
<< "Recruited hero must have an ID assigned (validates fix for assertion crash)";
// Verify other properties
EXPECT_EQ(recruitedHero->getOwner(), playerColor)
<< "Recruited hero must be owned by the recruiting player";
EXPECT_EQ(recruitedHero->visitablePos(), town->visitablePos())
<< "Recruited hero must be at town's position";
EXPECT_EQ(recruitedHero->getHeroTypeID(), heroType)
<< "Recruited hero must have the correct hero type";
// Verify the hero is on the map
auto * heroOnMap = dynamic_cast<CGHeroInstance *>(map->getObject(recruitedHero->id));
EXPECT_EQ(heroOnMap, recruitedHero)
<< "Recruited hero must be retrievable from map by ID";
}
// Test hero recruitment without a town (should still assign ID)
TEST_F(HeroRecruitmentTest, DISABLED_recruitedHeroWithoutTownGetsId)
{
startTestGame();
PlayerColor playerColor = PlayerColor(0);
auto * playerState = gameState->getPlayerState(playerColor);
ASSERT_NE(playerState, nullptr);
auto poolHeroes = gameState->heroesPool->getHeroesFor(playerColor);
ASSERT_FALSE(poolHeroes.empty());
const auto * poolHero = poolHeroes.front();
HeroTypeID heroType = poolHero->getHeroTypeID();
// Recruit hero without a town (tavern can be in random locations)
HeroRecruited pack;
pack.tid = ObjectInstanceID(); // No town
pack.hid = heroType;
pack.player = playerColor;
pack.tile = int3(5, 5, 0); // Random valid position
gameEventCallback->sendAndApply(pack);
// Find the recruited hero
auto finalHeroes = playerState->getHeroes();
ASSERT_FALSE(finalHeroes.empty());
auto * recruitedHero = finalHeroes.back();
ASSERT_NE(recruitedHero, nullptr);
// Key assertion: ID must be assigned even without a town
EXPECT_TRUE(recruitedHero->id.hasValue())
<< "Hero recruited without town must still have ID assigned";
EXPECT_EQ(recruitedHero->getOwner(), playerColor);
EXPECT_EQ(recruitedHero->getHeroTypeID(), heroType);
}