ERM_MA.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * ERM_MA.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "../scripting/ScriptFixture.h"
  12. #include "../../lib/NetPacks.h"
  13. #include "../../lib/serializer/Cast.h"
  14. #include "../mock/mock_CreatureService.h"
  15. #include "../mock/mock_Creature.h"
  16. namespace test
  17. {
  18. namespace scripting
  19. {
  20. using namespace ::testing;
  21. class ERM_MA : public Test, public ScriptFixture
  22. {
  23. public:
  24. CreatureServiceMock creatureService;
  25. CreatureMock oldCreature;
  26. BonusBearerMock creatureBonuses;
  27. std::vector<EntityChanges> actualChanges;
  28. void onCommit(CPackForClient * pack)
  29. {
  30. EntitiesChanged * ec = dynamic_ptr_cast<EntitiesChanged>(pack);
  31. if(ec)
  32. onEntitiesChanged(ec);
  33. else
  34. GTEST_FAIL() << "Invalid NetPack";
  35. }
  36. void onEntitiesChanged(EntitiesChanged * pack)
  37. {
  38. vstd::concatenate(actualChanges, pack->changes);
  39. }
  40. protected:
  41. void SetUp() override
  42. {
  43. ScriptFixture::setUp();
  44. EXPECT_CALL(servicesMock, creatures()).WillRepeatedly(Return(&creatureService));
  45. EXPECT_CALL(creatureService, getByIndex(Eq(68))).WillRepeatedly(Return(&oldCreature));
  46. }
  47. };
  48. TEST_F(ERM_MA, Example)
  49. {
  50. const int32_t COST = 876;
  51. const int32_t ATTACK = 19;
  52. const int32_t DEFENSE = 17;
  53. const int32_t HIT_POINTS = 55;
  54. const int32_t SPEED = 10;
  55. const int32_t DAMAGE_MIN = 13;
  56. const int32_t DAMAGE_MAX = 21;
  57. const int32_t SHOTS = 1;
  58. const int32_t CASTS = 3;
  59. const int32_t GROWTH = 10;
  60. const int32_t HORDE = 9;
  61. const int32_t AI_VALUE = 3300;
  62. const int32_t FIGHT_VALUE = 2400;
  63. const int32_t LEVEL = 7;
  64. const int32_t FACTION = 35;
  65. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::DESTRUCTION, BonusSource::CREATURE_ABILITY, 0, 0));
  66. const int32_t FLAG_MASK = 394370;
  67. const int32_t FLAG_MASK_NEW = 397443;
  68. static_assert(FLAG_MASK == (1 << 1 | 1 << 7 | 1 << 10 | 1 << 17 | 1 << 18), "Wrong flag mask meaning");
  69. static_assert(FLAG_MASK_NEW == (1 << 0 | 1 << 1 | 1 << 7 | 1 << 12 | 1 << 17 | 1 << 18), "Wrong flag mask meaning");
  70. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::FLYING, BonusSource::CREATURE_ABILITY, 0, 0));
  71. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::KING, BonusSource::CREATURE_ABILITY, 0, 0));
  72. auto removed = std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::MIND_IMMUNITY, BonusSource::CREATURE_ABILITY, 0, 0);
  73. creatureBonuses.addNewBonus(removed);
  74. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::NO_MORALE, BonusSource::CREATURE_ABILITY, 0, 0));
  75. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::UNDEAD, BonusSource::CREATURE_ABILITY, 0, 0));
  76. auto added = std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::NO_MELEE_PENALTY, BonusSource::CREATURE_ABILITY, 0, 0);
  77. EXPECT_CALL(oldCreature, getRecruitCost(Eq(6))).WillOnce(Return(COST));
  78. EXPECT_CALL(oldCreature, getBaseAttack()).WillOnce(Return(ATTACK));
  79. EXPECT_CALL(oldCreature, getBaseDefense()).WillOnce(Return(DEFENSE));
  80. EXPECT_CALL(oldCreature, getBaseHitPoints()).WillOnce(Return(HIT_POINTS));
  81. EXPECT_CALL(oldCreature, getBaseSpeed()).WillOnce(Return(SPEED));
  82. EXPECT_CALL(oldCreature, getBaseDamageMin()).WillOnce(Return(DAMAGE_MIN));
  83. EXPECT_CALL(oldCreature, getBaseDamageMax()).WillOnce(Return(DAMAGE_MAX));
  84. EXPECT_CALL(oldCreature, getBaseShots()).WillOnce(Return(SHOTS));
  85. EXPECT_CALL(oldCreature, getGrowth()).WillOnce(Return(GROWTH));
  86. EXPECT_CALL(oldCreature, getBaseSpellPoints()).WillOnce(Return(CASTS));
  87. EXPECT_CALL(oldCreature, getHorde()).WillOnce(Return(HORDE));
  88. EXPECT_CALL(oldCreature, getAIValue()).WillOnce(Return(AI_VALUE));
  89. EXPECT_CALL(oldCreature, getFightValue()).WillOnce(Return(FIGHT_VALUE));
  90. EXPECT_CALL(oldCreature, getLevel()).WillOnce(Return(LEVEL));
  91. EXPECT_CALL(oldCreature, getFaction()).WillOnce(Return(FACTION));
  92. EXPECT_CALL(oldCreature, isDoubleWide()).WillRepeatedly(Return(false));
  93. EXPECT_CALL(oldCreature, getBonusBearer()).Times(AtLeast(1)).WillRepeatedly(Return(&creatureBonuses));
  94. EXPECT_CALL(serverMock, apply(Matcher<CPackForClient *>(_))).Times(AtLeast(1)).WillRepeatedly(Invoke(this, &ERM_MA::onCommit));
  95. std::stringstream source;
  96. source << "VERM" << std::endl;
  97. source << "!#MA:C68/6/?v1 A68/?v2 D68/?v3 P68/?v4 S68/?v5 M68/?v6 E68/?v7 N68/?v8 G68/?v9 B68/?v10 R68/?v11 I68/?v12 F68/?v13 L68/?v14 O68/?v15 X68/?v16;" << std::endl;
  98. source << "!#MA:C68/6/750 A68/17 D68/15 P68/50 S68/9 M68/12 E68/20 N68/0 G68/1 B68/2 R68/0 I68/3388 F68/2420 L68/6 O68/4 X68/397443;" << std::endl;
  99. loadScript(VLC->scriptHandler->erm, source.str());
  100. SCOPED_TRACE("\n" + subject->code);
  101. JsonNode actualState = runServer();
  102. const JsonNode & v = actualState["ERM"]["v"];
  103. EXPECT_EQ(v["1"].Integer(), COST);
  104. EXPECT_EQ(v["2"].Integer(), ATTACK);
  105. EXPECT_EQ(v["3"].Integer(), DEFENSE);
  106. EXPECT_EQ(v["4"].Integer(), HIT_POINTS);
  107. EXPECT_EQ(v["5"].Integer(), SPEED);
  108. EXPECT_EQ(v["6"].Integer(), DAMAGE_MIN);
  109. EXPECT_EQ(v["7"].Integer(), DAMAGE_MAX);
  110. EXPECT_EQ(v["8"].Integer(), SHOTS);
  111. EXPECT_EQ(v["9"].Integer(), GROWTH);
  112. EXPECT_EQ(v["10"].Integer(), CASTS);
  113. EXPECT_EQ(v["11"].Integer(), HORDE);
  114. EXPECT_EQ(v["12"].Integer(), AI_VALUE);
  115. EXPECT_EQ(v["13"].Integer(), FIGHT_VALUE);
  116. EXPECT_EQ(v["14"].Integer(), LEVEL);
  117. EXPECT_EQ(v["15"].Integer(), FACTION);
  118. EXPECT_EQ(v["16"].Integer(), FLAG_MASK);
  119. JsonNode merged(JsonNode::JsonType::DATA_STRUCT);
  120. for(EntityChanges & change : actualChanges)
  121. {
  122. EXPECT_EQ(change.metatype, Metatype::CREATURE);
  123. EXPECT_EQ(change.entityIndex,68);
  124. JsonUtils::merge(merged, change.data);
  125. }
  126. JsonNode expectedMerged(JsonNode::JsonType::DATA_STRUCT);
  127. JsonNode & config = expectedMerged["config"];
  128. config["cost"]["gold"].Integer() = 750;
  129. config["attack"].Integer() = 17;
  130. config["defense"].Integer() = 15;
  131. config["hitPoints"].Integer() = 50;
  132. config["speed"].Integer() = 9;
  133. config["damage"]["min"].Integer() = 12;
  134. config["damage"]["max"].Integer() = 20;
  135. config["shots"].Integer() = 0;
  136. config["growth"].Integer() = 1;
  137. config["spellPoints"].Integer() = 2;
  138. config["horde"].Integer() = 0;
  139. config["aiValue"].Integer() = 3388;
  140. config["fightValue"].Integer() = 2420;
  141. config["level"].Integer() = 6;
  142. config["faction"].Integer() = 4;
  143. config["doubleWide"].Bool() = true;
  144. JsonNode & toAdd = expectedMerged["bonuses"]["toAdd"];
  145. toAdd.Vector().push_back(added->toJsonNode());
  146. JsonNode & toRemove = expectedMerged["bonuses"]["toRemove"];
  147. toRemove.Vector().push_back(removed->toJsonNode());
  148. {
  149. JsonComparer c(false);
  150. c.compare("updateData", merged, expectedMerged);
  151. }
  152. }
  153. TEST_F(ERM_MA, Bonuses)
  154. {
  155. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::DESTRUCTION, BonusSource::CREATURE_ABILITY, 0, 0));
  156. const int32_t FLAG_MASK = 394370;
  157. const int32_t FLAG_MASK_NEW = 397442;
  158. static_assert(FLAG_MASK == (1 << 1 | 1 << 7 | 1 << 10 | 1 << 17 | 1 << 18), "Wrong flag mask meaning");
  159. static_assert(FLAG_MASK_NEW == ( 1 << 1 | 1 << 7 | 1 << 12 | 1 << 17 | 1 << 18), "Wrong flag mask meaning");
  160. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::FLYING, BonusSource::CREATURE_ABILITY, 0, 0));
  161. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::KING, BonusSource::CREATURE_ABILITY, 0, 0));
  162. auto removed = std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::MIND_IMMUNITY, BonusSource::CREATURE_ABILITY, 0, 0);
  163. creatureBonuses.addNewBonus(removed);
  164. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::NO_MORALE, BonusSource::CREATURE_ABILITY, 0, 0));
  165. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::UNDEAD, BonusSource::CREATURE_ABILITY, 0, 0));
  166. auto added = std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::NO_MELEE_PENALTY, BonusSource::CREATURE_ABILITY, 0, 0);
  167. EXPECT_CALL(oldCreature, isDoubleWide()).WillRepeatedly(Return(false));
  168. EXPECT_CALL(oldCreature, getBonusBearer()).Times(AtLeast(1)).WillRepeatedly(Return(&creatureBonuses));
  169. EXPECT_CALL(serverMock, apply(Matcher<CPackForClient *>(_))).WillOnce(Invoke(this, &ERM_MA::onCommit));
  170. std::stringstream source;
  171. source << "VERM" << std::endl;
  172. source << "!#MA:X68/?v16;" << std::endl;
  173. source << "!#MA:X68/397442;" << std::endl;
  174. loadScript(VLC->scriptHandler->erm, source.str());
  175. SCOPED_TRACE("\n" + subject->code);
  176. JsonNode actualState = runServer();
  177. const JsonNode & v = actualState["ERM"]["v"];
  178. EXPECT_EQ(v["16"].Integer(), FLAG_MASK);
  179. JsonNode merged(JsonNode::JsonType::DATA_STRUCT);
  180. for(EntityChanges & change : actualChanges)
  181. {
  182. EXPECT_EQ(change.metatype, Metatype::CREATURE);
  183. EXPECT_EQ(change.entityIndex, 68);
  184. JsonUtils::merge(merged, change.data);
  185. }
  186. JsonNode expectedMerged(JsonNode::JsonType::DATA_STRUCT);
  187. JsonNode & toAdd = expectedMerged["bonuses"]["toAdd"];
  188. toAdd.Vector().push_back(added->toJsonNode());
  189. JsonNode & toRemove = expectedMerged["bonuses"]["toRemove"];
  190. toRemove.Vector().push_back(removed->toJsonNode());
  191. {
  192. JsonComparer c(false);
  193. c.compare("updateData", merged, expectedMerged);
  194. }
  195. }
  196. TEST_F(ERM_MA, BonusesNoChanges)
  197. {
  198. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::DESTRUCTION, BonusSource::CREATURE_ABILITY, 0, 0));
  199. const int32_t FLAG_MASK = 394370;
  200. static_assert(FLAG_MASK == (1 << 1 | 1 << 7 | 1 << 10 | 1 << 17 | 1 << 18), "Wrong flag mask meaning");
  201. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::FLYING, BonusSource::CREATURE_ABILITY, 0, 0));
  202. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::KING, BonusSource::CREATURE_ABILITY, 0, 0));
  203. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::MIND_IMMUNITY, BonusSource::CREATURE_ABILITY, 0, 0));
  204. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, Bonus::NO_MORALE, BonusSource::CREATURE_ABILITY, 0, 0));
  205. creatureBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::UNDEAD, BonusSource::CREATURE_ABILITY, 0, 0));
  206. EXPECT_CALL(oldCreature, isDoubleWide()).WillRepeatedly(Return(false));
  207. EXPECT_CALL(oldCreature, getBonusBearer()).Times(AtLeast(1)).WillRepeatedly(Return(&creatureBonuses));
  208. EXPECT_CALL(serverMock, apply(Matcher<CPackForClient *>(_))).Times(0);
  209. std::stringstream source;
  210. source << "VERM" << std::endl;
  211. source << "!#MA:X68/?v16;" << std::endl;
  212. source << "!#MA:X68/394370;" << std::endl;
  213. source << "!#MA:X68/v16;" << std::endl;
  214. loadScript(VLC->scriptHandler->erm, source.str());
  215. SCOPED_TRACE("\n" + subject->code);
  216. JsonNode actualState = runServer();
  217. const JsonNode & v = actualState["ERM"]["v"];
  218. EXPECT_EQ(v["16"].Integer(), FLAG_MASK);
  219. }
  220. }
  221. }