From 6f7c28798ddda71f0591ab641b1c57e6e0adbc88 Mon Sep 17 00:00:00 2001 From: Daria Volvenkova Date: Fri, 2 Aug 2019 22:30:48 +0300 Subject: [PATCH] [coding] Tests for json serializer and deserialiser. --- coding/coding_tests/CMakeLists.txt | 2 + coding/coding_tests/serdes_json_test.cpp | 283 +++++++++++++++++++++++ coding/serdes_json.hpp | 2 + 3 files changed, 287 insertions(+) create mode 100644 coding/coding_tests/serdes_json_test.cpp diff --git a/coding/coding_tests/CMakeLists.txt b/coding/coding_tests/CMakeLists.txt index 9b203840a4..18cbd8127b 100644 --- a/coding/coding_tests/CMakeLists.txt +++ b/coding/coding_tests/CMakeLists.txt @@ -27,6 +27,7 @@ set( reader_test.cpp reader_test.hpp reader_writer_ops_test.cpp + serdes_json_test.cpp simple_dense_coding_test.cpp string_utf8_multilang_tests.cpp succinct_mapper_test.cpp @@ -55,6 +56,7 @@ omim_link_libraries( coding base geometry + jansson minizip succinct stats_client diff --git a/coding/coding_tests/serdes_json_test.cpp b/coding/coding_tests/serdes_json_test.cpp new file mode 100644 index 0000000000..42c976705a --- /dev/null +++ b/coding/coding_tests/serdes_json_test.cpp @@ -0,0 +1,283 @@ +#include "testing/testing.hpp" + +#include "coding/serdes_json.hpp" +#include "coding/writer.hpp" + +#include "base/string_utils.hpp" +#include "base/visitor.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace +{ +template +bool samePtrValue(PtrT const & lhs, PtrT const & rhs) +{ + return (!lhs && !rhs) || (lhs && rhs && *lhs == *rhs); +} + +template +bool TestSerDes(T const & value) +{ + std::string jsonStr; + { + using Sink = MemWriter; + Sink sink(jsonStr); + coding::SerializerJson ser(sink); + ser(value); + } + + T deserializedValue; + try + { + coding::DeserializerJson des(jsonStr); + des(deserializedValue); + } + catch (base::Json::Exception const & exception) + { + LOG(LWARNING, ("Exception while parsing json string, reason:", exception.what(), + "json:", jsonStr)); + return false; + } + return deserializedValue == value; +} + +enum class TestEnum +{ + Value0 = 0, + Value1, + Value2, + Count +}; + +struct ValueTypes +{ + DECLARE_VISITOR(visitor(m_boolValue, "boolValue"), + visitor(m_uint8_tValue, "uint8_tValue"), + visitor(m_uint32_tValue, "uint32_tValue"), + visitor(m_uint64_tValue, "uint64_tValue"), + visitor(m_int8_tValue, "int8_tValue"), + visitor(m_int32_tValue, "int32_tValue"), + visitor(m_int64_tValue, "int64_tValue"), + visitor(m_doubleValue, "doubleValue"), + visitor(m_stringValue, "stringValue"), + visitor(m_enumValue, "enumValue"), + visitor(m_time_pointValue, "time_pointValue")); + + ValueTypes() = default; + ValueTypes(uint32_t testCounter) + : m_boolValue(static_cast(testCounter % 2)) + , m_uint8_tValue(numeric_limits::max() - static_cast(testCounter)) + , m_uint32_tValue(numeric_limits::max() - testCounter) + , m_uint64_tValue(numeric_limits::max() - testCounter) + , m_int8_tValue(numeric_limits::min() + static_cast(testCounter)) + , m_int32_tValue(numeric_limits::min() + static_cast(testCounter)) + , m_int64_tValue(numeric_limits::min() + static_cast(testCounter)) + , m_doubleValue(numeric_limits::max() - testCounter) + , m_stringValue(strings::to_string(testCounter)) + , m_enumValue(static_cast(testCounter % static_cast(TestEnum::Count))) + , m_time_pointValue(chrono::system_clock::now()) + {} + + bool operator==(ValueTypes const & rhs) const + { + return m_boolValue == rhs.m_boolValue && m_uint8_tValue == rhs.m_uint8_tValue && + m_uint32_tValue == rhs.m_uint32_tValue && m_uint64_tValue == rhs.m_uint64_tValue && + m_int8_tValue == rhs.m_int8_tValue && m_int32_tValue == rhs.m_int32_tValue && + m_int64_tValue == rhs.m_int64_tValue && m_doubleValue == rhs.m_doubleValue && + m_stringValue == rhs.m_stringValue && m_enumValue == rhs.m_enumValue && + m_time_pointValue == rhs.m_time_pointValue; + } + + bool m_boolValue; + uint8_t m_uint8_tValue; + uint32_t m_uint32_tValue; + uint64_t m_uint64_tValue; + int8_t m_int8_tValue; + int32_t m_int32_tValue; + int64_t m_int64_tValue; + double m_doubleValue; + string m_stringValue; + TestEnum m_enumValue; + chrono::system_clock::time_point m_time_pointValue; +}; + +struct ObjectTypes +{ + DECLARE_VISITOR(visitor(m_pointValue, "pointValue"), + visitor(m_latLonValue, "latLonValue"), + visitor(m_pairValue, "pairValue")); + + ObjectTypes() = default; + ObjectTypes(uint32_t testCounter) + : m_pointValue(testCounter, testCounter) + , m_latLonValue(testCounter, testCounter) + , m_pairValue(testCounter, strings::to_string(testCounter)) + {} + + bool operator==(ObjectTypes const & rhs) const + { + return m_pointValue == rhs.m_pointValue && m_latLonValue == rhs.m_latLonValue && + m_pairValue == rhs.m_pairValue; + } + + m2::PointD m_pointValue; + ms::LatLon m_latLonValue; + pair m_pairValue; +}; + +struct PointerTypes +{ + DECLARE_VISITOR(visitor(m_unique_ptrValue, "unique_ptrValue"), + visitor(m_shared_ptrValue, "shared_ptrValue")); + + PointerTypes() = default; + PointerTypes(uint32_t testCounter) + { + m_unique_ptrValue = make_unique(testCounter); + m_shared_ptrValue = make_shared(testCounter); + } + + bool operator==(PointerTypes const & rhs) const + { + return samePtrValue(m_unique_ptrValue, rhs.m_unique_ptrValue) && + samePtrValue(m_shared_ptrValue, rhs.m_shared_ptrValue); + } + + unique_ptr m_unique_ptrValue; + shared_ptr m_shared_ptrValue; +}; + +struct ArrayTypes +{ + DECLARE_VISITOR(visitor(m_arrayValue, "arrayValue"), + visitor(m_dequeValue, "dequeValue"), + visitor(m_vectorValue, "vectorValue"), + visitor(m_mapValue, "mapValue"), + visitor(m_unordered_setValue, "unordered_setValue")); + + ArrayTypes() = default; + ArrayTypes(uint32_t testCounter) + : m_arrayValue({{testCounter, testCounter + 1, testCounter + 2}}) + , m_dequeValue({testCounter + 2, testCounter + 1, testCounter}) + , m_vectorValue({testCounter, testCounter + 2, testCounter + 1}) + , m_mapValue({{testCounter, testCounter}, {testCounter + 1, testCounter + 1}}) + , m_unordered_setValue({testCounter + 2, testCounter, testCounter + 1}) + {} + + bool operator==(ArrayTypes const & rhs) const + { + return m_arrayValue == rhs.m_arrayValue && m_dequeValue == rhs.m_dequeValue && + m_vectorValue == rhs.m_vectorValue && m_mapValue == rhs.m_mapValue && + m_unordered_setValue == rhs.m_unordered_setValue; + } + + array m_arrayValue; + deque m_dequeValue; + vector m_vectorValue; + map m_mapValue; + unordered_set m_unordered_setValue; +}; +} // namespace + +UNIT_TEST(SerdesJsonTest) +{ + { + ValueTypes valueTypes(0); + TEST(TestSerDes(valueTypes), ()); + + ObjectTypes objectTypes(0); + TEST(TestSerDes(objectTypes), ()); + + PointerTypes pointersTypes(0); + TEST(TestSerDes(pointersTypes), ()); + + ArrayTypes arrayTypes(0); + TEST(TestSerDes(arrayTypes), ()); + } + + { + pair testValue = {"test", m2::PointD(1.0, 2.0)}; + TEST(TestSerDes(testValue), ()); + } + + { + pair testValue = {m2::PointD(1.0, 2.0), m2::PointD(2.0, 3.0)}; + TEST(TestSerDes(testValue), ()); + } + + { + pair> testValue = {"test", {"test1", "test2"}}; + TEST(TestSerDes(testValue), ()); + } + + { + pair testValue = {"test", ValueTypes(0)}; + TEST(TestSerDes(testValue), ()); + } + + { + array testValue = {{ObjectTypes(0), ObjectTypes(1)}}; + TEST(TestSerDes(testValue), ()); + } + + { + struct Hasher + { + std::hash m_hasher; + + size_t operator()(pair const & item) const + { + return m_hasher(item.first + item.second); + } + }; + + unordered_set, Hasher> testValue = {{"ab", "ab"}, {"ef", "ef"}, + {"cd", "cd"}}; + TEST(TestSerDes(testValue), ()); + } + + { + vector> testValue; + for (uint32_t i = 0; i < 5; ++i) + testValue.push_back({i, i, i}); + TEST(TestSerDes(testValue), ()); + } + + { + vector valuesVector; + for (uint32_t i = 0; i < 5; ++i) + valuesVector.push_back(ValueTypes(i)); + TEST(TestSerDes(valuesVector), ()); + } + + { + map valuesMap; + for (uint32_t i = 0; i < 5; ++i) + valuesMap.insert(make_pair(i, ValueTypes(i))); + TEST(TestSerDes(valuesMap), ()); + } + + { + vector objectsVector; + for (uint32_t i = 0; i < 5; ++i) + objectsVector.push_back(ObjectTypes(i)); + TEST(TestSerDes(objectsVector), ()); + } + + { + map objectsMap; + for (uint32_t i = 0; i < 5; ++i) + objectsMap.insert(make_pair(i, ObjectTypes(i))); + TEST(TestSerDes(objectsMap), ()); + } +} diff --git a/coding/serdes_json.hpp b/coding/serdes_json.hpp index 36b46858c3..c5a482d251 100644 --- a/coding/serdes_json.hpp +++ b/coding/serdes_json.hpp @@ -107,6 +107,8 @@ public: void operator()(uint8_t const d, char const * name = nullptr) { ToJsonObjectOrValue(d, name); } void operator()(uint32_t const d, char const * name = nullptr) { ToJsonObjectOrValue(d, name); } void operator()(uint64_t const d, char const * name = nullptr) { ToJsonObjectOrValue(d, name); } + void operator()(int8_t const d, char const * name = nullptr) { ToJsonObjectOrValue(d, name); } + void operator()(int32_t const d, char const * name = nullptr) { ToJsonObjectOrValue(d, name); } void operator()(int64_t const d, char const * name = nullptr) { ToJsonObjectOrValue(d, name); } void operator()(double const d, char const * name = nullptr) { ToJsonObjectOrValue(d, name); } void operator()(std::string const & s, char const * name = nullptr) { ToJsonObjectOrValue(s, name); }