mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
[tests] Moved JsonComparer to own file
This commit is contained in:
parent
079cd470c2
commit
b2faf30d0d
@ -16,6 +16,7 @@ set(test_SRCS
|
||||
main.cpp
|
||||
CMemoryBufferTest.cpp
|
||||
CVcmiTestConfig.cpp
|
||||
JsonComparer.cpp
|
||||
|
||||
battle/BattleHexTest.cpp
|
||||
battle/CBattleInfoCallbackTest.cpp
|
||||
@ -66,6 +67,8 @@ set(test_HEADERS
|
||||
StdInc.h
|
||||
|
||||
CVcmiTestConfig.h
|
||||
JsonComparer.h
|
||||
|
||||
map/MapComparer.h
|
||||
|
||||
spells/effects/EffectFixture.h
|
||||
|
180
test/JsonComparer.cpp
Normal file
180
test/JsonComparer.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* JsonComparer.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 "JsonComparer.h"
|
||||
|
||||
#include "../lib/ScopeGuard.h"
|
||||
|
||||
//JsonComparer
|
||||
JsonComparer::JsonComparer(bool strict_)
|
||||
: strict(strict_)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
vstd::ScopeGuard<JsonComparer::TScopeGuard> JsonComparer::pushName(const std::string & name)
|
||||
{
|
||||
namePath.push_back(name);
|
||||
return vstd::makeScopeGuard<TScopeGuard>([this](){namePath.pop_back();});
|
||||
}
|
||||
|
||||
std::string JsonComparer::buildMessage(const std::string & message)
|
||||
{
|
||||
std::stringstream buf;
|
||||
|
||||
for(auto & s : namePath)
|
||||
buf << s << "|";
|
||||
buf << " " << message;
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
bool JsonComparer::isEmpty(const JsonNode & value)
|
||||
{
|
||||
switch (value.getType())
|
||||
{
|
||||
case JsonNode::JsonType::DATA_NULL:
|
||||
return true;
|
||||
case JsonNode::JsonType::DATA_BOOL:
|
||||
return !value.Bool();
|
||||
case JsonNode::JsonType::DATA_FLOAT:
|
||||
return value.Float() == 0;
|
||||
case JsonNode::JsonType::DATA_STRING:
|
||||
return value.String() == "";
|
||||
case JsonNode::JsonType::DATA_VECTOR:
|
||||
return value.Vector().empty();
|
||||
case JsonNode::JsonType::DATA_STRUCT:
|
||||
return value.Struct().empty();
|
||||
break;
|
||||
default:
|
||||
EXPECT_TRUE(false) << "Unknown Json type";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void JsonComparer::check(const bool condition, const std::string & message)
|
||||
{
|
||||
if(strict)
|
||||
ASSERT_TRUE(condition) << buildMessage(message);
|
||||
else
|
||||
EXPECT_TRUE(condition) << buildMessage(message);
|
||||
}
|
||||
|
||||
void JsonComparer::checkEqualInteger(const si64 actual, const si64 expected)
|
||||
{
|
||||
if(actual != expected)
|
||||
{
|
||||
check(false, boost::str(boost::format("'%d' != '%d'") % actual % expected));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonComparer::checkEqualFloat(const double actual, const double expected)
|
||||
{
|
||||
if(std::abs(actual - expected) > 1e-6)
|
||||
{
|
||||
check(false, boost::str(boost::format("'%d' != '%d' (diff %d)") % actual % expected % (expected - actual)));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonComparer::checkEqualString(const std::string & actual, const std::string & expected)
|
||||
{
|
||||
if(actual != expected)
|
||||
{
|
||||
check(false, boost::str(boost::format("'%s' != '%s'") % actual % expected));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonComparer::checkEqualJson(const JsonMap & actual, const JsonMap & expected)
|
||||
{
|
||||
for(const auto & p : expected)
|
||||
checkStructField(actual, p.first, p.second);
|
||||
for(const auto & p : actual)
|
||||
checkExcessStructField(p.second, p.first, expected);
|
||||
}
|
||||
|
||||
void JsonComparer::checkEqualJson(const JsonVector & actual, const JsonVector & expected)
|
||||
{
|
||||
check(actual.size() == expected.size(), "size mismatch");
|
||||
|
||||
size_t sz = std::min(actual.size(), expected.size());
|
||||
|
||||
for(size_t idx = 0; idx < sz; idx ++)
|
||||
{
|
||||
auto guard = pushName(boost::to_string(idx));
|
||||
|
||||
checkEqualJson(actual.at(idx), expected.at(idx));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonComparer::checkEqualJson(const JsonNode & actual, const JsonNode & expected)
|
||||
{
|
||||
//name has been pushed before
|
||||
|
||||
const bool validType = actual.getType() == expected.getType();
|
||||
|
||||
check(validType, "type mismatch");
|
||||
|
||||
//do detail checks avoiding assertions in JsonNode
|
||||
if(validType)
|
||||
{
|
||||
switch (actual.getType())
|
||||
{
|
||||
case JsonNode::JsonType::DATA_NULL:
|
||||
break; //do nothing
|
||||
case JsonNode::JsonType::DATA_BOOL:
|
||||
check(actual.Bool() == expected.Bool(), "mismatch");
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_FLOAT:
|
||||
checkEqualFloat(actual.Float(),expected.Float());
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_STRING:
|
||||
checkEqualString(actual.String(),expected.String());
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_VECTOR:
|
||||
checkEqualJson(actual.Vector(), expected.Vector());
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_STRUCT:
|
||||
checkEqualJson(actual.Struct(), expected.Struct());
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_INTEGER:
|
||||
checkEqualInteger(actual.Integer(), expected.Integer());
|
||||
break;
|
||||
default:
|
||||
check(false, "Unknown Json type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonComparer::checkExcessStructField(const JsonNode & actualValue, const std::string & name, const JsonMap & expected)
|
||||
{
|
||||
auto guard = pushName(name);
|
||||
|
||||
if(!vstd::contains(expected, name))
|
||||
check(isEmpty(actualValue), "excess");
|
||||
}
|
||||
|
||||
void JsonComparer::checkStructField(const JsonMap & actual, const std::string & name, const JsonNode & expectedValue)
|
||||
{
|
||||
auto guard = pushName(name);
|
||||
|
||||
if(!vstd::contains(actual, name))
|
||||
check(isEmpty(expectedValue), "missing");
|
||||
else
|
||||
checkEqualJson(actual.at(name), expectedValue);
|
||||
}
|
||||
|
||||
void JsonComparer::compare(const std::string & name, const JsonNode & actual, const JsonNode & expected)
|
||||
{
|
||||
auto guard = pushName(name);
|
||||
checkEqualJson(actual, expected);
|
||||
}
|
||||
|
||||
|
52
test/JsonComparer.h
Normal file
52
test/JsonComparer.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* JsonComparer.h, 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../lib/JsonNode.h"
|
||||
|
||||
namespace vstd
|
||||
{
|
||||
template<typename T>
|
||||
class ScopeGuard;
|
||||
}
|
||||
|
||||
class JsonComparer
|
||||
{
|
||||
public:
|
||||
JsonComparer(bool strict_);
|
||||
|
||||
void compare(const std::string & name, const JsonNode & actual, const JsonNode & expected);
|
||||
|
||||
private:
|
||||
typedef std::function<void(void)> TScopeGuard;
|
||||
|
||||
bool strict;
|
||||
std::list<std::string> namePath;
|
||||
|
||||
vstd::ScopeGuard<TScopeGuard> pushName(const std::string & name);
|
||||
|
||||
std::string buildMessage(const std::string & message);
|
||||
|
||||
bool isEmpty(const JsonNode & value);
|
||||
|
||||
void check(const bool condition, const std::string & message);
|
||||
|
||||
void checkExcessStructField(const JsonNode & actualValue, const std::string & name, const JsonMap & expected);
|
||||
void checkStructField(const JsonMap & actual, const std::string & name, const JsonNode & expectedValue);
|
||||
|
||||
void checkEqualInteger(const si64 actual, const si64 expected);
|
||||
void checkEqualFloat(const double actual, const double expected);
|
||||
void checkEqualString(const std::string & actual, const std::string & expected);
|
||||
|
||||
void checkEqualJson(const JsonNode & actual, const JsonNode & expected);
|
||||
void checkEqualJson(const JsonMap & actual, const JsonMap & expected);
|
||||
void checkEqualJson(const JsonVector & actual, const JsonVector & expected);
|
||||
};
|
@ -72,6 +72,8 @@
|
||||
<Unit filename="CMemoryBufferTest.cpp" />
|
||||
<Unit filename="CVcmiTestConfig.cpp" />
|
||||
<Unit filename="CVcmiTestConfig.h" />
|
||||
<Unit filename="JsonComparer.cpp" />
|
||||
<Unit filename="JsonComparer.h" />
|
||||
<Unit filename="StdInc.cpp">
|
||||
<Option compile="0" />
|
||||
<Option link="0" />
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../lib/VCMIDirs.h"
|
||||
|
||||
#include "MapComparer.h"
|
||||
#include "../JsonComparer.h"
|
||||
|
||||
static const int TEST_RANDOM_SEED = 1337;
|
||||
|
||||
@ -166,13 +167,13 @@ TEST(MapFormat, Objects)
|
||||
saveTestMap(serializeBuffer, "test_object_property.vmap");
|
||||
|
||||
{
|
||||
JsonMapComparer c(false);
|
||||
c.compareHeader(actualHeader, expectedHeader);
|
||||
c.compareObjects(actualObjects, expectedObjects);
|
||||
JsonComparer c(false);
|
||||
c.compare("hdr", actualHeader, expectedHeader);
|
||||
c.compare("obj", actualObjects, expectedObjects);
|
||||
}
|
||||
|
||||
{
|
||||
JsonMapComparer c(true);
|
||||
JsonComparer c(true);
|
||||
c.compare("surface", actualSurface, expectedSurface);
|
||||
c.compare("underground", actualUnderground, expectedUnderground);
|
||||
}
|
||||
@ -202,13 +203,13 @@ TEST(MapFormat, Terrain)
|
||||
saveTestMap(serializeBuffer, "test_terrain.vmap");
|
||||
|
||||
{
|
||||
JsonMapComparer c(false);
|
||||
c.compareHeader(actualHeader, expectedHeader);
|
||||
c.compareObjects(actualObjects, expectedObjects);
|
||||
JsonComparer c(false);
|
||||
c.compare("hdr", actualHeader, expectedHeader);
|
||||
c.compare("obj", actualObjects, expectedObjects);
|
||||
}
|
||||
|
||||
{
|
||||
JsonMapComparer c(true);
|
||||
JsonComparer c(true);
|
||||
c.compare("surface", actualSurface, expectedSurface);
|
||||
c.compare("underground", actualUnderground, expectedUnderground);
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
#include "MapComparer.h"
|
||||
|
||||
#include "../lib/ScopeGuard.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
|
||||
#define VCMI_CHECK_FIELD_EQUAL_P(field) EXPECT_EQ(actual->field, expected->field)
|
||||
@ -272,188 +271,3 @@ void MapComparer::operator() (const std::unique_ptr<CMap>& actual, const std::un
|
||||
this->expected = expected.get();
|
||||
compare();
|
||||
}
|
||||
|
||||
//JsonMapComparer
|
||||
JsonMapComparer::JsonMapComparer(bool strict_)
|
||||
: strict(strict_)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
vstd::ScopeGuard<JsonMapComparer::TScopeGuard> JsonMapComparer::pushName(const std::string & name)
|
||||
{
|
||||
namePath.push_back(name);
|
||||
return vstd::makeScopeGuard<TScopeGuard>([this](){namePath.pop_back();});
|
||||
}
|
||||
|
||||
std::string JsonMapComparer::buildMessage(const std::string & message)
|
||||
{
|
||||
std::stringstream buf;
|
||||
|
||||
for(auto & s : namePath)
|
||||
buf << s << "|";
|
||||
buf << " " << message;
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
void JsonMapComparer::addError(const std::string & message)
|
||||
{
|
||||
FAIL()<<buildMessage(message);
|
||||
}
|
||||
|
||||
bool JsonMapComparer::isEmpty(const JsonNode & value)
|
||||
{
|
||||
switch (value.getType())
|
||||
{
|
||||
case JsonNode::JsonType::DATA_NULL:
|
||||
return true;
|
||||
case JsonNode::JsonType::DATA_BOOL:
|
||||
return !value.Bool();
|
||||
case JsonNode::JsonType::DATA_FLOAT:
|
||||
return value.Float() == 0;
|
||||
case JsonNode::JsonType::DATA_STRING:
|
||||
return value.String() == "";
|
||||
case JsonNode::JsonType::DATA_VECTOR:
|
||||
return value.Vector().empty();
|
||||
case JsonNode::JsonType::DATA_STRUCT:
|
||||
return value.Struct().empty();
|
||||
break;
|
||||
default:
|
||||
EXPECT_TRUE(false) << "Unknown Json type";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void JsonMapComparer::check(const bool condition, const std::string & message)
|
||||
{
|
||||
if(strict)
|
||||
ASSERT_TRUE(condition) << buildMessage(message);
|
||||
else
|
||||
EXPECT_TRUE(condition) << buildMessage(message);
|
||||
}
|
||||
|
||||
void JsonMapComparer::checkEqualInteger(const si64 actual, const si64 expected)
|
||||
{
|
||||
if(actual != expected)
|
||||
{
|
||||
check(false, boost::str(boost::format("'%d' != '%d'") % actual % expected));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonMapComparer::checkEqualFloat(const double actual, const double expected)
|
||||
{
|
||||
if(std::abs(actual - expected) > 1e-6)
|
||||
{
|
||||
check(false, boost::str(boost::format("'%d' != '%d' (diff %d)") % actual % expected % (expected - actual)));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonMapComparer::checkEqualString(const std::string & actual, const std::string & expected)
|
||||
{
|
||||
if(actual != expected)
|
||||
{
|
||||
check(false, boost::str(boost::format("'%s' != '%s'") % actual % expected));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonMapComparer::checkEqualJson(const JsonMap & actual, const JsonMap & expected)
|
||||
{
|
||||
for(const auto & p : expected)
|
||||
checkStructField(actual, p.first, p.second);
|
||||
for(const auto & p : actual)
|
||||
checkExcessStructField(p.second, p.first, expected);
|
||||
}
|
||||
|
||||
void JsonMapComparer::checkEqualJson(const JsonVector & actual, const JsonVector & expected)
|
||||
{
|
||||
check(actual.size() == expected.size(), "size mismatch");
|
||||
|
||||
size_t sz = std::min(actual.size(), expected.size());
|
||||
|
||||
for(size_t idx = 0; idx < sz; idx ++)
|
||||
{
|
||||
auto guard = pushName(boost::to_string(idx));
|
||||
|
||||
checkEqualJson(actual.at(idx), expected.at(idx));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonMapComparer::checkEqualJson(const JsonNode & actual, const JsonNode & expected)
|
||||
{
|
||||
//name has been pushed before
|
||||
|
||||
const bool validType = actual.getType() == expected.getType();
|
||||
|
||||
if(!validType)
|
||||
addError("type mismatch");
|
||||
|
||||
//do detail checks avoiding assertions in JsonNode
|
||||
if(validType)
|
||||
{
|
||||
switch (actual.getType())
|
||||
{
|
||||
case JsonNode::JsonType::DATA_NULL:
|
||||
break; //do nothing
|
||||
case JsonNode::JsonType::DATA_BOOL:
|
||||
check(actual.Bool() == expected.Bool(), "mismatch");
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_FLOAT:
|
||||
checkEqualFloat(actual.Float(),expected.Float());
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_STRING:
|
||||
checkEqualString(actual.String(),expected.String());
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_VECTOR:
|
||||
checkEqualJson(actual.Vector(), expected.Vector());
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_STRUCT:
|
||||
checkEqualJson(actual.Struct(), expected.Struct());
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_INTEGER:
|
||||
checkEqualInteger(actual.Integer(), expected.Integer());
|
||||
break;
|
||||
default:
|
||||
FAIL() << "Unknown Json type";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonMapComparer::checkExcessStructField(const JsonNode & actualValue, const std::string & name, const JsonMap & expected)
|
||||
{
|
||||
auto guard = pushName(name);
|
||||
|
||||
if(!vstd::contains(expected, name))
|
||||
{
|
||||
if(!isEmpty(actualValue))
|
||||
addError("excess");
|
||||
}
|
||||
}
|
||||
|
||||
void JsonMapComparer::checkStructField(const JsonMap & actual, const std::string & name, const JsonNode & expectedValue)
|
||||
{
|
||||
auto guard = pushName(name);
|
||||
if(!vstd::contains(actual, name))
|
||||
{
|
||||
if(!isEmpty(expectedValue))
|
||||
addError("missing");
|
||||
}
|
||||
else
|
||||
checkEqualJson(actual.at(name), expectedValue);
|
||||
}
|
||||
|
||||
void JsonMapComparer::compare(const std::string & name, const JsonNode & actual, const JsonNode & expected)
|
||||
{
|
||||
auto guard = pushName(name);
|
||||
checkEqualJson(actual, expected);
|
||||
}
|
||||
|
||||
void JsonMapComparer::compareHeader(const JsonNode & actual, const JsonNode & expected)
|
||||
{
|
||||
compare("hdr", actual, expected);
|
||||
}
|
||||
|
||||
void JsonMapComparer::compareObjects(const JsonNode & actual, const JsonNode & expected)
|
||||
{
|
||||
compare("obj", actual, expected);
|
||||
}
|
||||
|
@ -10,15 +10,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../lib/ScopeGuard.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
|
||||
namespace vstd
|
||||
{
|
||||
template<typename Func>
|
||||
class ScopeGuard;
|
||||
}
|
||||
|
||||
class CMap;
|
||||
class CGObjectInstance;
|
||||
|
||||
@ -38,40 +29,6 @@ struct MapComparer
|
||||
void operator() (const std::unique_ptr<CMap>& actual, const std::unique_ptr<CMap>& expected);
|
||||
};
|
||||
|
||||
struct JsonMapComparer
|
||||
{
|
||||
typedef std::function<void(void)> TScopeGuard;
|
||||
|
||||
bool strict;
|
||||
std::list<std::string> namePath;
|
||||
|
||||
JsonMapComparer(bool strict_);
|
||||
|
||||
vstd::ScopeGuard<TScopeGuard> pushName(const std::string & name);
|
||||
|
||||
std::string buildMessage(const std::string & message);
|
||||
|
||||
void addError(const std::string & message);
|
||||
|
||||
bool isEmpty(const JsonNode & value);
|
||||
|
||||
void check(const bool condition, const std::string & message);
|
||||
|
||||
void checkExcessStructField(const JsonNode & actualValue, const std::string & name, const JsonMap & expected);
|
||||
void checkStructField(const JsonMap & actual, const std::string & name, const JsonNode & expectedValue);
|
||||
|
||||
void checkEqualInteger(const si64 actual, const si64 expected);
|
||||
void checkEqualFloat(const double actual, const double expected);
|
||||
void checkEqualString(const std::string & actual, const std::string & expected);
|
||||
|
||||
void checkEqualJson(const JsonNode & actual, const JsonNode & expected);
|
||||
void checkEqualJson(const JsonMap & actual, const JsonMap & expected);
|
||||
void checkEqualJson(const JsonVector & actual, const JsonVector & expected);
|
||||
|
||||
void compare(const std::string & name, const JsonNode & actual, const JsonNode & expected);
|
||||
|
||||
void compareHeader(const JsonNode & actual, const JsonNode & expected);
|
||||
void compareObjects(const JsonNode & actual, const JsonNode & expected);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user