| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 | 
							- /*
 
-  * 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_INTEGER:
 
- 		return value.Integer() == 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(!condition)
 
- 	{
 
- 		if(strict)
 
- 		{
 
- 			GTEST_FAIL() << buildMessage(message);
 
- 		}
 
- 		else
 
- 		{
 
- 			ADD_FAILURE() << 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-8)
 
- 	{
 
- 		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();
 
- 	//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;
 
- 		}
 
- 	}
 
- 	else if(actual.isNumber() && expected.isNumber())
 
- 	{
 
- 		checkEqualFloat(actual.Float(),expected.Float());
 
- 	}
 
- 	else
 
- 	{
 
- 		check(false, "type mismatch. \n expected:\n"+expected.toJson(true)+"\n actual:\n" +actual.toJson(true));
 
- 	}
 
- }
 
- 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);
 
- }
 
 
  |