2015-08-08 18:16:33 +02:00
|
|
|
/*
|
|
|
|
* MapComparer.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 <boost/test/unit_test.hpp>
|
|
|
|
|
|
|
|
#include "MapComparer.h"
|
|
|
|
|
2015-08-09 13:04:26 +02:00
|
|
|
#define VCMI_CHECK_FIELD_EQUAL_P(field) BOOST_CHECK_EQUAL(actual->field, expected->field)
|
2015-08-08 20:04:07 +02:00
|
|
|
|
2015-08-09 13:04:26 +02:00
|
|
|
#define VCMI_CHECK_FIELD_EQUAL(field) BOOST_CHECK_EQUAL(actual.field, expected.field)
|
|
|
|
|
2015-08-16 00:29:21 +02:00
|
|
|
#define VCMI_REQUIRE_FIELD_EQUAL_P(field) BOOST_REQUIRE_EQUAL(actual->field, expected->field)
|
|
|
|
#define VCMI_REQUIRE_FIELD_EQUAL(field) BOOST_REQUIRE_EQUAL(actual.field, expected.field)
|
2015-08-09 13:04:26 +02:00
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
template <class T>
|
|
|
|
void checkEqual(const T & actual, const T & expected)
|
2015-08-08 20:04:07 +02:00
|
|
|
{
|
2015-08-15 19:25:40 +02:00
|
|
|
BOOST_CHECK_EQUAL(actual, expected) ;
|
2015-08-08 20:04:07 +02:00
|
|
|
}
|
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
template <class Element>
|
|
|
|
void checkEqual(const std::vector<Element> & actual, const std::vector<Element> & expected)
|
|
|
|
{
|
|
|
|
BOOST_CHECK_EQUAL(actual.size(), expected.size());
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
for(auto actualIt = actual.begin(), expectedIt = expected.begin(); actualIt != actual.end() && expectedIt != expected.end(); actualIt++, expectedIt++)
|
|
|
|
{
|
|
|
|
checkEqual(*actualIt, *expectedIt);
|
2015-08-18 01:21:35 +02:00
|
|
|
}
|
2015-08-15 19:25:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class Element>
|
|
|
|
void checkEqual(const std::set<Element> & actual, const std::set<Element> & expected)
|
|
|
|
{
|
|
|
|
BOOST_CHECK_EQUAL(actual.size(), expected.size());
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
for(auto elem : expected)
|
|
|
|
{
|
|
|
|
if(!vstd::contains(actual, elem))
|
|
|
|
BOOST_ERROR("Required element not found "+boost::to_string(elem));
|
2015-08-18 01:21:35 +02:00
|
|
|
}
|
2015-08-15 19:25:40 +02:00
|
|
|
}
|
2015-08-09 13:04:26 +02:00
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
void checkEqual(const PlayerInfo & actual, const PlayerInfo & expected)
|
2015-08-08 20:04:07 +02:00
|
|
|
{
|
2015-08-09 13:04:26 +02:00
|
|
|
VCMI_CHECK_FIELD_EQUAL(canHumanPlay);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(canComputerPlay);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(aiTactic);
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
checkEqual(actual.allowedFactions, expected.allowedFactions);
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
VCMI_CHECK_FIELD_EQUAL(isFactionRandom);
|
2015-08-18 01:21:35 +02:00
|
|
|
VCMI_CHECK_FIELD_EQUAL(mainCustomHeroPortrait);
|
2015-08-15 19:25:40 +02:00
|
|
|
VCMI_CHECK_FIELD_EQUAL(mainCustomHeroName);
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
VCMI_CHECK_FIELD_EQUAL(mainCustomHeroId);
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
//todo:heroesNames
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
VCMI_CHECK_FIELD_EQUAL(hasMainTown);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(generateHeroAtMainTown);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(posOfMainTown);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(team);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(hasRandomHero);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void checkEqual(const EventExpression & actual, const EventExpression & expected)
|
|
|
|
{
|
|
|
|
//todo: checkEventExpression
|
|
|
|
}
|
|
|
|
|
|
|
|
void checkEqual(const TriggeredEvent & actual, const TriggeredEvent & expected)
|
|
|
|
{
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(identifier);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(description);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(onFulfill);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL(effect.type);
|
2015-08-18 01:21:35 +02:00
|
|
|
VCMI_CHECK_FIELD_EQUAL(effect.toOtherMessage);
|
2015-08-15 19:25:40 +02:00
|
|
|
|
2015-08-18 01:21:35 +02:00
|
|
|
checkEqual(actual.trigger, expected.trigger);
|
2015-08-08 20:04:07 +02:00
|
|
|
}
|
|
|
|
|
2015-08-16 00:29:21 +02:00
|
|
|
void checkEqual(const TerrainTile & actual, const TerrainTile & expected)
|
|
|
|
{
|
|
|
|
//fatal fail here on any error
|
|
|
|
VCMI_REQUIRE_FIELD_EQUAL(terType);
|
|
|
|
VCMI_REQUIRE_FIELD_EQUAL(terView);
|
|
|
|
VCMI_REQUIRE_FIELD_EQUAL(riverType);
|
|
|
|
VCMI_REQUIRE_FIELD_EQUAL(riverDir);
|
|
|
|
VCMI_REQUIRE_FIELD_EQUAL(roadType);
|
|
|
|
VCMI_REQUIRE_FIELD_EQUAL(roadDir);
|
|
|
|
VCMI_REQUIRE_FIELD_EQUAL(extTileFlags);
|
|
|
|
}
|
|
|
|
|
2015-08-08 20:04:07 +02:00
|
|
|
void MapComparer::compareHeader()
|
|
|
|
{
|
2015-08-18 01:21:35 +02:00
|
|
|
//map size parameters are vital for further checks
|
2015-08-16 00:29:21 +02:00
|
|
|
VCMI_REQUIRE_FIELD_EQUAL_P(height);
|
|
|
|
VCMI_REQUIRE_FIELD_EQUAL_P(width);
|
|
|
|
VCMI_REQUIRE_FIELD_EQUAL_P(twoLevel);
|
2015-08-14 04:22:24 +02:00
|
|
|
|
2015-08-09 13:04:26 +02:00
|
|
|
VCMI_CHECK_FIELD_EQUAL_P(name);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL_P(description);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL_P(difficulty);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL_P(levelLimit);
|
|
|
|
|
|
|
|
VCMI_CHECK_FIELD_EQUAL_P(victoryMessage);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL_P(defeatMessage);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL_P(victoryIconIndex);
|
|
|
|
VCMI_CHECK_FIELD_EQUAL_P(defeatIconIndex);
|
2015-08-18 01:21:35 +02:00
|
|
|
|
|
|
|
checkEqual(actual->players, expected->players);
|
|
|
|
|
2015-08-15 19:25:40 +02:00
|
|
|
//todo: allowedHeroes, placeholdedHeroes
|
2015-08-18 01:21:35 +02:00
|
|
|
|
|
|
|
|
2015-08-16 00:46:58 +02:00
|
|
|
std::vector<TriggeredEvent> actualEvents = actual->triggeredEvents;
|
|
|
|
std::vector<TriggeredEvent> expectedEvents = expected->triggeredEvents;
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-16 00:46:58 +02:00
|
|
|
auto sortByIdentifier = [](const TriggeredEvent & lhs, const TriggeredEvent & rhs) -> bool
|
|
|
|
{
|
|
|
|
return lhs.identifier < rhs.identifier;
|
|
|
|
};
|
|
|
|
boost::sort (actualEvents, sortByIdentifier);
|
|
|
|
boost::sort (expectedEvents, sortByIdentifier);
|
2015-08-18 01:21:35 +02:00
|
|
|
|
|
|
|
checkEqual(actualEvents, expectedEvents);
|
2015-08-08 20:04:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void MapComparer::compareOptions()
|
|
|
|
{
|
2015-08-15 19:25:40 +02:00
|
|
|
//rumors
|
|
|
|
//disposedHeroes
|
|
|
|
//predefinedHeroes
|
|
|
|
//allowedSpell
|
|
|
|
//allowedArtifact
|
|
|
|
//allowedAbilities
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-16 00:29:21 +02:00
|
|
|
BOOST_ERROR("Not implemented compareOptions()");
|
2015-08-08 20:04:07 +02:00
|
|
|
}
|
|
|
|
|
2015-11-13 16:47:47 +02:00
|
|
|
void MapComparer::compareObject(const CGObjectInstance * actual, const CGObjectInstance * expected)
|
|
|
|
{
|
|
|
|
BOOST_CHECK_EQUAL(actual->getStringId(), expected->getStringId());
|
|
|
|
BOOST_CHECK_EQUAL(typeid(actual).name(), typeid(expected).name());//todo: remove and use just comparison
|
2015-11-14 15:50:29 +02:00
|
|
|
|
|
|
|
std::string actualFullID = boost::to_string(boost::format("%s(%d)|%s(%d)") % actual->typeName % actual->id % actual->subTypeName % actual->subID);
|
|
|
|
std::string expectedFullID = boost::to_string(boost::format("%s(%d)|%s(%d)") % expected->typeName % expected->id % expected->subTypeName % expected->subID);
|
|
|
|
|
|
|
|
BOOST_CHECK_EQUAL(actualFullID, expectedFullID);
|
|
|
|
BOOST_CHECK_EQUAL(actual->pos, expected->pos);
|
2015-11-15 17:07:15 +02:00
|
|
|
BOOST_CHECK_EQUAL(actual->tempOwner,expected->tempOwner);
|
2015-11-13 16:47:47 +02:00
|
|
|
}
|
|
|
|
|
2015-08-08 20:04:07 +02:00
|
|
|
void MapComparer::compareObjects()
|
|
|
|
{
|
2015-11-13 16:47:47 +02:00
|
|
|
BOOST_CHECK_EQUAL(actual->objects.size(), expected->objects.size());
|
|
|
|
|
|
|
|
for(size_t idx = 0; idx < std::min(actual->objects.size(), expected->objects.size()); idx++)
|
|
|
|
{
|
|
|
|
BOOST_REQUIRE_EQUAL(idx, expected->objects[idx]->id.getNum());
|
|
|
|
BOOST_CHECK_EQUAL(idx, actual->objects[idx]->id.getNum());
|
|
|
|
compareObject(actual->objects[idx], expected->objects[idx]);
|
|
|
|
}
|
2015-08-08 20:04:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void MapComparer::compareTerrain()
|
|
|
|
{
|
2015-08-16 00:29:21 +02:00
|
|
|
//assume map dimensions check passed
|
|
|
|
//todo: separate check for underground
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-16 00:29:21 +02:00
|
|
|
for(int x = 0; x < expected->width; x++)
|
|
|
|
for(int y = 0; y < expected->height; y++)
|
|
|
|
{
|
|
|
|
int3 coord(x,y,0);
|
|
|
|
BOOST_TEST_CHECKPOINT(coord);
|
2015-08-18 01:21:35 +02:00
|
|
|
|
2015-08-16 00:29:21 +02:00
|
|
|
checkEqual(actual->getTile(coord), expected->getTile(coord));
|
|
|
|
}
|
2015-08-08 20:04:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void MapComparer::compare()
|
|
|
|
{
|
|
|
|
BOOST_REQUIRE_NE((void *) actual, (void *) expected); //should not point to the same object
|
|
|
|
BOOST_REQUIRE_MESSAGE(actual != nullptr, "Actual map is not defined");
|
2015-08-13 23:16:31 +02:00
|
|
|
BOOST_REQUIRE_MESSAGE(expected != nullptr, "Expected map is not defined");
|
2015-08-08 20:04:07 +02:00
|
|
|
|
|
|
|
compareHeader();
|
|
|
|
compareOptions();
|
2015-08-09 13:04:26 +02:00
|
|
|
compareObjects();
|
2015-08-08 20:04:07 +02:00
|
|
|
compareTerrain();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MapComparer::operator() (const std::unique_ptr<CMap>& actual, const std::unique_ptr<CMap>& expected)
|
2015-08-08 18:16:33 +02:00
|
|
|
{
|
2015-08-08 20:04:07 +02:00
|
|
|
this->actual = actual.get();
|
|
|
|
this->expected = expected.get();
|
|
|
|
compare();
|
2015-08-08 18:16:33 +02:00
|
|
|
}
|