MapComparer.cpp 7.7 KB

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