From b2faf30d0d200cdb44a9daa227b64620caa8ff9a Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Mon, 5 Mar 2018 21:26:00 +0300 Subject: [PATCH] [tests] Moved JsonComparer to own file --- test/CMakeLists.txt | 3 + test/JsonComparer.cpp | 180 ++++++++++++++++++++++++++++++++++ test/JsonComparer.h | 52 ++++++++++ test/Test.cbp | 2 + test/map/CMapFormatTest.cpp | 17 ++-- test/map/MapComparer.cpp | 186 ------------------------------------ test/map/MapComparer.h | 45 +-------- 7 files changed, 247 insertions(+), 238 deletions(-) create mode 100644 test/JsonComparer.cpp create mode 100644 test/JsonComparer.h diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 25251f7c6..fda271eb4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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 diff --git a/test/JsonComparer.cpp b/test/JsonComparer.cpp new file mode 100644 index 000000000..911118a9f --- /dev/null +++ b/test/JsonComparer.cpp @@ -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::pushName(const std::string & name) +{ + namePath.push_back(name); + return vstd::makeScopeGuard([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); +} + + diff --git a/test/JsonComparer.h b/test/JsonComparer.h new file mode 100644 index 000000000..dd10b6950 --- /dev/null +++ b/test/JsonComparer.h @@ -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 + class ScopeGuard; +} + +class JsonComparer +{ +public: + JsonComparer(bool strict_); + + void compare(const std::string & name, const JsonNode & actual, const JsonNode & expected); + +private: + typedef std::function TScopeGuard; + + bool strict; + std::list namePath; + + vstd::ScopeGuard 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); +}; diff --git a/test/Test.cbp b/test/Test.cbp index c7121f107..2e112e3df 100644 --- a/test/Test.cbp +++ b/test/Test.cbp @@ -72,6 +72,8 @@ + +