MapComparer.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * MapComparer.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 "MapComparer.h"
  12. #include "../lib/mapping/CMap.h"
  13. #include "../lib/mapObjects/CGObjectInstance.h"
  14. #include "../lib/mapObjects/ObjectTemplate.h"
  15. #define VCMI_CHECK_FIELD_EQUAL_P(field) EXPECT_EQ(actual->field, expected->field)
  16. #define VCMI_CHECK_FIELD_EQUAL(field) EXPECT_EQ(actual.field, expected.field)
  17. #define VCMI_REQUIRE_FIELD_EQUAL_P(field) ASSERT_EQ(actual->field, expected->field)
  18. #define VCMI_REQUIRE_FIELD_EQUAL(field) ASSERT_EQ(actual.field, expected.field)
  19. template <class T>
  20. void checkEqual(const T & actual, const T & expected)
  21. {
  22. EXPECT_EQ(actual, expected) ;
  23. }
  24. void checkEqual(const std::vector<bool> & actual, const std::vector<bool> & expected)
  25. {
  26. EXPECT_EQ(actual.size(), expected.size());
  27. for(auto actualIt = actual.begin(), expectedIt = expected.begin(); actualIt != actual.end() && expectedIt != expected.end(); actualIt++, expectedIt++)
  28. {
  29. checkEqual(*actualIt, *expectedIt);
  30. }
  31. }
  32. template <class Element>
  33. void checkEqual(const std::vector<Element> & actual, const std::vector<Element> & expected)
  34. {
  35. EXPECT_EQ(actual.size(), expected.size());
  36. for(auto actualIt = actual.begin(), expectedIt = expected.begin(); actualIt != actual.end() && expectedIt != expected.end(); actualIt++, expectedIt++)
  37. {
  38. checkEqual(*actualIt, *expectedIt);
  39. }
  40. }
  41. template <class Element>
  42. void checkEqual(const std::set<Element> & actual, const std::set<Element> & expected)
  43. {
  44. EXPECT_EQ(actual.size(), expected.size());
  45. for(auto elem : expected)
  46. {
  47. if(!vstd::contains(actual, elem))
  48. FAIL() << "Required element not found "+std::to_string(elem);
  49. }
  50. }
  51. void checkEqual(const SHeroName & actual, const SHeroName & expected)
  52. {
  53. VCMI_CHECK_FIELD_EQUAL(heroId);
  54. VCMI_CHECK_FIELD_EQUAL(heroName);
  55. }
  56. void checkEqual(const PlayerInfo & actual, const PlayerInfo & expected)
  57. {
  58. VCMI_CHECK_FIELD_EQUAL(canHumanPlay);
  59. VCMI_CHECK_FIELD_EQUAL(canComputerPlay);
  60. VCMI_CHECK_FIELD_EQUAL(aiTactic);
  61. checkEqual(actual.allowedFactions, expected.allowedFactions);
  62. VCMI_CHECK_FIELD_EQUAL(isFactionRandom);
  63. VCMI_CHECK_FIELD_EQUAL(mainCustomHeroPortrait);
  64. VCMI_CHECK_FIELD_EQUAL(mainCustomHeroNameTextId);
  65. VCMI_CHECK_FIELD_EQUAL(mainCustomHeroId);
  66. checkEqual(actual.heroesNames, expected.heroesNames);
  67. VCMI_CHECK_FIELD_EQUAL(hasMainTown);
  68. VCMI_CHECK_FIELD_EQUAL(generateHeroAtMainTown);
  69. VCMI_CHECK_FIELD_EQUAL(posOfMainTown);
  70. //VCMI_CHECK_FIELD_EQUAL(team); //TODO: smart team checking, for now team checking is useless, because random team is assigned for single-member teams
  71. VCMI_CHECK_FIELD_EQUAL(hasRandomHero);
  72. }
  73. void checkEqual(const EventExpression & actual, const EventExpression & expected)
  74. {
  75. //todo: checkEventExpression
  76. }
  77. void checkEqual(const TriggeredEvent & actual, const TriggeredEvent & expected)
  78. {
  79. VCMI_CHECK_FIELD_EQUAL(identifier);
  80. VCMI_CHECK_FIELD_EQUAL(description);
  81. VCMI_CHECK_FIELD_EQUAL(onFulfill);
  82. VCMI_CHECK_FIELD_EQUAL(effect.type);
  83. VCMI_CHECK_FIELD_EQUAL(effect.toOtherMessage);
  84. checkEqual(actual.trigger, expected.trigger);
  85. }
  86. void checkEqual(const Rumor & actual, const Rumor & expected)
  87. {
  88. VCMI_CHECK_FIELD_EQUAL(name);
  89. VCMI_CHECK_FIELD_EQUAL(text);
  90. }
  91. void checkEqual(const DisposedHero & actual, const DisposedHero & expected)
  92. {
  93. VCMI_CHECK_FIELD_EQUAL(heroId);
  94. VCMI_CHECK_FIELD_EQUAL(portrait);
  95. VCMI_CHECK_FIELD_EQUAL(name);
  96. VCMI_CHECK_FIELD_EQUAL(players);
  97. }
  98. void checkEqual(const ObjectTemplate & actual, const ObjectTemplate & expected)
  99. {
  100. VCMI_CHECK_FIELD_EQUAL(id);
  101. VCMI_CHECK_FIELD_EQUAL(subid);
  102. VCMI_CHECK_FIELD_EQUAL(printPriority);
  103. VCMI_CHECK_FIELD_EQUAL(animationFile);
  104. //VCMI_CHECK_FIELD_EQUAL(stringID);
  105. }
  106. void checkEqual(const TerrainTile & actual, const TerrainTile & expected)
  107. {
  108. //fatal fail here on any error
  109. VCMI_REQUIRE_FIELD_EQUAL(terrainType);
  110. VCMI_REQUIRE_FIELD_EQUAL(terView);
  111. VCMI_REQUIRE_FIELD_EQUAL(riverType);
  112. VCMI_REQUIRE_FIELD_EQUAL(riverDir);
  113. VCMI_REQUIRE_FIELD_EQUAL(roadType);
  114. VCMI_REQUIRE_FIELD_EQUAL(roadDir);
  115. VCMI_REQUIRE_FIELD_EQUAL(extTileFlags);
  116. ASSERT_EQ(actual.blockingObjects.size(), expected.blockingObjects.size());
  117. ASSERT_EQ(actual.visitableObjects.size(), expected.visitableObjects.size());
  118. }
  119. //MapComparer
  120. void MapComparer::compareHeader()
  121. {
  122. //map size parameters are vital for further checks
  123. VCMI_REQUIRE_FIELD_EQUAL_P(height);
  124. VCMI_REQUIRE_FIELD_EQUAL_P(width);
  125. VCMI_REQUIRE_FIELD_EQUAL_P(twoLevel);
  126. VCMI_CHECK_FIELD_EQUAL_P(name);
  127. VCMI_CHECK_FIELD_EQUAL_P(description);
  128. VCMI_CHECK_FIELD_EQUAL_P(difficulty);
  129. VCMI_CHECK_FIELD_EQUAL_P(levelLimit);
  130. VCMI_CHECK_FIELD_EQUAL_P(victoryMessage);
  131. VCMI_CHECK_FIELD_EQUAL_P(defeatMessage);
  132. VCMI_CHECK_FIELD_EQUAL_P(victoryIconIndex);
  133. VCMI_CHECK_FIELD_EQUAL_P(defeatIconIndex);
  134. VCMI_CHECK_FIELD_EQUAL_P(howManyTeams);
  135. checkEqual(actual->players, expected->players);
  136. checkEqual(actual->allowedHeroes, expected->allowedHeroes);
  137. std::vector<TriggeredEvent> actualEvents = actual->triggeredEvents;
  138. std::vector<TriggeredEvent> expectedEvents = expected->triggeredEvents;
  139. auto sortByIdentifier = [](const TriggeredEvent & lhs, const TriggeredEvent & rhs) -> bool
  140. {
  141. return lhs.identifier < rhs.identifier;
  142. };
  143. boost::sort (actualEvents, sortByIdentifier);
  144. boost::sort (expectedEvents, sortByIdentifier);
  145. checkEqual(actualEvents, expectedEvents);
  146. }
  147. void MapComparer::compareOptions()
  148. {
  149. checkEqual(actual->rumors, expected->rumors);
  150. checkEqual(actual->disposedHeroes, expected->disposedHeroes);
  151. //todo: compareOptions predefinedHeroes
  152. checkEqual(actual->allowedAbilities, expected->allowedAbilities);
  153. checkEqual(actual->allowedArtifact, expected->allowedArtifact);
  154. checkEqual(actual->allowedSpells, expected->allowedSpells);
  155. //todo: compareOptions events
  156. }
  157. void MapComparer::compareObject(const CGObjectInstance * actual, const CGObjectInstance * expected)
  158. {
  159. EXPECT_EQ(actual->instanceName, expected->instanceName);
  160. EXPECT_EQ(typeid(actual).name(), typeid(expected).name());//todo: remove and use just comparison
  161. std::string actualFullID = boost::str(boost::format("(%d)|(%d) %d") % actual->ID % actual->subID % actual->tempOwner);
  162. std::string expectedFullID = boost::str(boost::format("(%d)|(%d) %d") % expected->ID % expected->subID % expected->tempOwner);
  163. EXPECT_EQ(actualFullID, expectedFullID);
  164. VCMI_CHECK_FIELD_EQUAL_P(pos);
  165. checkEqual(*actual->appearance, *expected->appearance);
  166. }
  167. void MapComparer::compareObjects()
  168. {
  169. EXPECT_EQ(actual->objects.size(), expected->objects.size());
  170. for(size_t idx = 0; idx < expected->objects.size(); idx++)
  171. {
  172. auto expectedObject = expected->objects[idx];
  173. ASSERT_EQ(idx, expectedObject->id.getNum());
  174. {
  175. auto it = expected->instanceNames.find(expectedObject->instanceName);
  176. ASSERT_NE(it, expected->instanceNames.end());
  177. }
  178. {
  179. auto it = actual->instanceNames.find(expectedObject->instanceName);
  180. ASSERT_NE(it, actual->instanceNames.end());
  181. auto actualObject = it->second;
  182. compareObject(actualObject, expectedObject);
  183. }
  184. }
  185. }
  186. void MapComparer::compareTerrain()
  187. {
  188. //assume map dimensions check passed
  189. //todo: separate check for underground
  190. for(int x = 0; x < expected->width; x++)
  191. for(int y = 0; y < expected->height; y++)
  192. {
  193. int3 coord(x,y,0);
  194. SCOPED_TRACE(coord.toString());
  195. checkEqual(actual->getTile(coord), expected->getTile(coord));
  196. }
  197. }
  198. void MapComparer::compare()
  199. {
  200. ASSERT_NE((void *) actual, (void *) expected); //should not point to the same object
  201. ASSERT_TRUE(actual != nullptr) << "Actual map is not defined";
  202. ASSERT_TRUE(expected != nullptr) << "Expected map is not defined";
  203. compareHeader();
  204. compareOptions();
  205. compareObjects();
  206. compareTerrain();
  207. }
  208. void MapComparer::operator() (const std::unique_ptr<CMap>& actual, const std::unique_ptr<CMap>& expected)
  209. {
  210. this->actual = actual.get();
  211. this->expected = expected.get();
  212. compare();
  213. }