123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /*
- * SummonTest.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 "EffectFixture.h"
- #include <vstd/RNG.h>
- #include "../../../lib/CCreatureHandler.h"
- #include "../../../lib/json/JsonNode.h"
- namespace test
- {
- using namespace ::spells;
- using namespace ::spells::effects;
- using namespace ::testing;
- static const CreatureID creature1(CreatureID::AIR_ELEMENTAL);
- static const CreatureID creature2(CreatureID::FIRE_ELEMENTAL);
- static const int summonSpellPower = 100; // enough to summon at least 1 unit
- class SummonTest : public TestWithParam<::testing::tuple<CreatureID, bool, bool>>, public EffectFixture
- {
- public:
- CreatureID toSummon;
- CreatureID otherSummoned;
- bool exclusive;
- bool summonSameUnit;
- const battle::Unit * otherSummonedUnit;
- SummonTest()
- : EffectFixture("core:summon"),
- otherSummonedUnit(nullptr)
- {
- }
- void addOtherSummoned(bool expectAlive)
- {
- auto & unit = unitsFake.add(BattleSide::ATTACKER);
- EXPECT_CALL(unit, unitOwner()).WillRepeatedly(Return(PlayerColor(5)));
- EXPECT_CALL(unit, isClone()).WillRepeatedly(Return(false));
- EXPECT_CALL(unit, creatureId()).WillRepeatedly(Return(otherSummoned));
- EXPECT_CALL(unit, isValidTarget(Eq(false))).WillRepeatedly(Return(true));
- EXPECT_CALL(unit, getPosition()).WillRepeatedly(Return(BattleHex(5,5)));
- EXPECT_CALL(unit, doubleWide()).WillRepeatedly(Return(false));
- EXPECT_CALL(unit, unitSide()).Times(AnyNumber());
- EXPECT_CALL(unit, unitSlot()).WillRepeatedly(Return(SlotID::SUMMONED_SLOT_PLACEHOLDER));
- if(expectAlive)
- EXPECT_CALL(unit, alive()).WillRepeatedly(Return(true));
- else
- EXPECT_CALL(unit, alive()).Times(0);
- otherSummonedUnit = &unit;
- }
- protected:
- void SetUp() override
- {
- EffectFixture::setUp();
- otherSummoned = ::testing::get<0>(GetParam());
- exclusive = ::testing::get<1>(GetParam());
- summonSameUnit = ::testing::get<2>(GetParam());
- toSummon = creature1;
- JsonNode options;
- options["id"].String() = "airElemental";
- options["exclusive"].Bool() = exclusive;
- options["summonSameUnit"].Bool() = summonSameUnit;
- EffectFixture::setupEffect(options);
- }
- };
- TEST_P(SummonTest, Applicable)
- {
- const bool expectedApplicable = !exclusive || otherSummoned == CreatureID() || otherSummoned == toSummon;
- if(otherSummoned != CreatureID())
- addOtherSummoned(false);
- if(otherSummoned != CreatureID() && !expectedApplicable)
- EXPECT_CALL(problemMock, add(_));
- if(exclusive)
- EXPECT_CALL(*battleFake, getUnitsIf(_)).Times(AtLeast(1));
- else
- EXPECT_CALL(*battleFake, getUnitsIf(_)).Times(0);
- EXPECT_CALL(mechanicsMock, getCasterColor()).WillRepeatedly(Return(PlayerColor(5)));
- EXPECT_CALL(mechanicsMock, getEffectPower()).WillRepeatedly(Return(summonSpellPower));
- EXPECT_CALL(mechanicsMock, calculateRawEffectValue(0, summonSpellPower)).WillRepeatedly(Return(summonSpellPower));
- EXPECT_CALL(mechanicsMock, applySpecificSpellBonus(summonSpellPower)).WillRepeatedly(Return(summonSpellPower));
- EXPECT_EQ(expectedApplicable, subject->applicable(problemMock, &mechanicsMock));
- }
- TEST_P(SummonTest, Transform)
- {
- if(otherSummoned != CreatureID())
- addOtherSummoned(true);
- battleFake->setupEmptyBattlefield();
- EXPECT_CALL(*battleFake, getUnitsIf(_)).Times(AtLeast(1));
- EXPECT_CALL(mechanicsMock, getCasterColor()).WillRepeatedly(Return(PlayerColor(5)));
- EXPECT_CALL(mechanicsMock, getEffectPower()).WillRepeatedly(Return(summonSpellPower));
- EXPECT_CALL(mechanicsMock, calculateRawEffectValue(0, summonSpellPower)).WillRepeatedly(Return(summonSpellPower));
- EXPECT_CALL(mechanicsMock, applySpecificSpellBonus(summonSpellPower)).WillRepeatedly(Return(summonSpellPower));
- EffectTarget transformed = subject->transformTarget(&mechanicsMock, Target(), Target());
- EffectTarget expected;
- if(otherSummoned == toSummon && summonSameUnit)
- {
- expected.emplace_back(otherSummonedUnit);
- }
- else
- {
- expected.emplace_back(BattleHex(1));
- }
- EXPECT_THAT(transformed, ContainerEq(expected));
- }
- INSTANTIATE_TEST_SUITE_P
- (
- ByConfig,
- SummonTest,
- Combine
- (
- Values(CreatureID(), creature1, creature2),
- Values(false, true),
- Values(false, true)
- )
- );
- class SummonApplyTest : public TestWithParam<::testing::tuple<bool, bool>>, public EffectFixture
- {
- public:
- const CreatureID toSummon = CreatureID::AIR_ELEMENTAL;
- bool permanent = false;
- bool summonByHealth = false;
- const uint32_t unitId = 42;
- const int32_t unitAmount = 123;
- const int32_t unitHealth = 479;
- const int64_t unitTotalHealth = unitAmount * unitHealth;
- const BattleHex unitPosition = BattleHex(5,5);
- std::shared_ptr<::battle::UnitInfo> unitAddInfo;
- std::shared_ptr<battle::UnitFake> acquired;
- StrictMock<CreatureMock> toSummonType;
- SummonApplyTest()
- : EffectFixture("core:summon")
- {
- }
- void setDefaultExpectations()
- {
- EXPECT_CALL(mechanicsMock, creatures()).Times(AnyNumber());
- EXPECT_CALL(creatureServiceMock, getById(Eq(toSummon))).WillRepeatedly(Return(&toSummonType));
- EXPECT_CALL(creatureServiceMock, getByIndex(Eq(toSummon.getNum()))).WillRepeatedly(Return(&toSummonType));
- EXPECT_CALL(toSummonType, getMaxHealth()).WillRepeatedly(Return(unitHealth));
- expectAmountCalculation();
- }
- void expectAmountCalculation()
- {
- InSequence local;
- EXPECT_CALL(mechanicsMock, getEffectPower()).WillOnce(Return(38));
- EXPECT_CALL(mechanicsMock, calculateRawEffectValue(Eq(0), Eq(38))).WillOnce(Return(567));
- if(summonByHealth)
- {
- EXPECT_CALL(mechanicsMock, applySpecificSpellBonus(Eq(567))).WillOnce(Return(unitTotalHealth));
- }
- else
- {
- EXPECT_CALL(mechanicsMock, applySpecificSpellBonus(Eq(567))).WillOnce(Return(unitAmount));
- }
- }
- void onUnitAdded(uint32_t id, const JsonNode & data)
- {
- unitAddInfo->load(id, data);
- }
- protected:
- void SetUp() override
- {
- EffectFixture::setUp();
- permanent = ::testing::get<0>(GetParam());
- summonByHealth = ::testing::get<1>(GetParam());
- JsonNode options;
- options["id"].String() = "airElemental";
- options["permanent"].Bool() = permanent;
- options["summonByHealth"].Bool() = summonByHealth;
- EffectFixture::setupEffect(options);
- unitAddInfo = std::make_shared<::battle::UnitInfo>();
- }
- void TearDown() override
- {
- acquired.reset();
- unitAddInfo.reset();
- }
- };
- TEST_P(SummonApplyTest, SpawnsNewUnit)
- {
- setDefaultExpectations();
- EXPECT_CALL(*battleFake, nextUnitId()).WillOnce(Return(unitId));
- EXPECT_CALL(*battleFake, addUnit(Eq(unitId), _)).WillOnce(Invoke(this, &SummonApplyTest::onUnitAdded));
- EXPECT_CALL(serverMock, apply(Matcher<BattleUnitsChanged &>(_))).Times(1);
- EffectTarget target;
- target.emplace_back(unitPosition);
- subject->apply(&serverMock, &mechanicsMock, target);
- EXPECT_EQ(unitAddInfo->count, unitAmount);
- EXPECT_EQ(unitAddInfo->id, unitId);
- EXPECT_EQ(unitAddInfo->position, unitPosition);
- EXPECT_EQ(unitAddInfo->side, mechanicsMock.casterSide);
- EXPECT_EQ(unitAddInfo->summoned, !permanent);
- EXPECT_EQ(unitAddInfo->type, toSummon);
- }
- TEST_P(SummonApplyTest, UpdatesOldUnit)
- {
- setDefaultExpectations();
- acquired = std::make_shared<battle::UnitFake>();
- acquired->addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHealth, BonusSourceID()));
- acquired->redirectBonusesToFake();
- acquired->expectAnyBonusSystemCall();
- auto & unit = unitsFake.add(BattleSide::ATTACKER);
- unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHealth, BonusSourceID()));
- {
- EXPECT_CALL(unit, acquire()).WillOnce(Return(acquired));
- EXPECT_CALL(*acquired, heal(Eq(unitTotalHealth), Eq(EHealLevel::OVERHEAL), Eq(permanent ? EHealPower::PERMANENT : EHealPower::ONE_BATTLE)));
- EXPECT_CALL(*acquired, save(_));
- EXPECT_CALL(*battleFake, setUnitState(Eq(unitId), _, _));
- }
- EXPECT_CALL(unit, unitId()).WillOnce(Return(unitId));
- EXPECT_CALL(serverMock, apply(Matcher<BattleUnitsChanged &>(_))).Times(1);
- unitsFake.setDefaultBonusExpectations();
- EffectTarget target;
- target.emplace_back(&unit, BattleHex());
- subject->apply(&serverMock, &mechanicsMock, target);
- }
- INSTANTIATE_TEST_SUITE_P
- (
- ByConfig,
- SummonApplyTest,
- Combine
- (
- Values(false, true),
- Values(false, true)
- )
- );
- }
|