diff options
author | Kyle Edwards <kyle.edwards@kitware.com> | 2020-09-06 17:24:27 (GMT) |
---|---|---|
committer | Kyle Edwards <kyle.edwards@kitware.com> | 2020-09-09 12:29:02 (GMT) |
commit | 3f3a30e1e06a3461c0e712b4a80b57a5bcb05eab (patch) | |
tree | 3cc5cd65a937e16df7b5c67d18a0342719a23e58 /Tests/CMakeLib | |
parent | e366977e62edc366e5b7ac38ed6c1c5cf729b428 (diff) | |
download | CMake-3f3a30e1e06a3461c0e712b4a80b57a5bcb05eab.zip CMake-3f3a30e1e06a3461c0e712b4a80b57a5bcb05eab.tar.gz CMake-3f3a30e1e06a3461c0e712b4a80b57a5bcb05eab.tar.bz2 |
JSON: Add helpers
Diffstat (limited to 'Tests/CMakeLib')
-rw-r--r-- | Tests/CMakeLib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/CMakeLib/testJSONHelpers.cxx | 493 |
2 files changed, 494 insertions, 0 deletions
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index 0b2c8f6..87925bd 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -13,6 +13,7 @@ set(CMakeLib_TESTS testCTestResourceGroups.cxx testGccDepfileReader.cxx testGeneratedFileStream.cxx + testJSONHelpers.cxx testRST.cxx testRange.cxx testOptional.cxx diff --git a/Tests/CMakeLib/testJSONHelpers.cxx b/Tests/CMakeLib/testJSONHelpers.cxx new file mode 100644 index 0000000..78eed5b --- /dev/null +++ b/Tests/CMakeLib/testJSONHelpers.cxx @@ -0,0 +1,493 @@ +#include <functional> +#include <iostream> +#include <map> +#include <string> +#include <vector> + +#include <cm/optional> +#include <cmext/string_view> + +#include <cm3p/json/value.h> + +#include "cmJSONHelpers.h" + +#define ASSERT_TRUE(x) \ + do { \ + if (!(x)) { \ + std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \ + return false; \ + } \ + } while (false) + +namespace { +struct ObjectStruct +{ + std::string Field1; + int Field2; +}; + +struct InheritedStruct : public ObjectStruct +{ + std::string Field3; +}; + +enum class ErrorCode +{ + Success, + InvalidInt, + InvalidBool, + InvalidString, + InvalidObject, + InvalidArray, + MissingRequired, +}; + +auto const IntHelper = + cmJSONIntHelper<ErrorCode>(ErrorCode::Success, ErrorCode::InvalidInt, 1); +auto const RequiredIntHelper = + cmJSONRequiredHelper<int, ErrorCode>(ErrorCode::MissingRequired, IntHelper); +auto const UIntHelper = + cmJSONUIntHelper<ErrorCode>(ErrorCode::Success, ErrorCode::InvalidInt, 1); +auto const BoolHelper = cmJSONBoolHelper<ErrorCode>( + ErrorCode::Success, ErrorCode::InvalidBool, false); +auto const StringHelper = cmJSONStringHelper<ErrorCode>( + ErrorCode::Success, ErrorCode::InvalidString, "default"); +auto const RequiredStringHelper = cmJSONRequiredHelper<std::string, ErrorCode>( + ErrorCode::MissingRequired, StringHelper); +auto const StringVectorHelper = cmJSONVectorHelper<std::string, ErrorCode>( + ErrorCode::Success, ErrorCode::InvalidArray, StringHelper); +auto const StringVectorFilterHelper = + cmJSONVectorFilterHelper<std::string, ErrorCode>( + ErrorCode::Success, ErrorCode::InvalidArray, StringHelper, + [](const std::string& value) { return value != "ignore"; }); +auto const StringMapHelper = cmJSONMapHelper<std::string, ErrorCode>( + ErrorCode::Success, ErrorCode::InvalidObject, StringHelper); +auto const StringMapFilterHelper = + cmJSONMapFilterHelper<std::string, ErrorCode>( + ErrorCode::Success, ErrorCode::InvalidObject, StringHelper, + [](const std::string& key) { return key != "ignore"; }); +auto const OptionalStringHelper = + cmJSONOptionalHelper<std::string>(ErrorCode::Success, StringHelper); + +bool testInt() +{ + Json::Value v(2); + int i = 0; + ASSERT_TRUE(IntHelper(i, &v) == ErrorCode::Success); + ASSERT_TRUE(i == 2); + + i = 0; + v = Json::nullValue; + ASSERT_TRUE(IntHelper(i, &v) == ErrorCode::InvalidInt); + + i = 0; + ASSERT_TRUE(IntHelper(i, nullptr) == ErrorCode::Success); + ASSERT_TRUE(i == 1); + + return true; +} + +bool testUInt() +{ + Json::Value v(2); + unsigned int i = 0; + ASSERT_TRUE(UIntHelper(i, &v) == ErrorCode::Success); + ASSERT_TRUE(i == 2); + + i = 0; + v = Json::nullValue; + ASSERT_TRUE(UIntHelper(i, &v) == ErrorCode::InvalidInt); + + i = 0; + ASSERT_TRUE(UIntHelper(i, nullptr) == ErrorCode::Success); + ASSERT_TRUE(i == 1); + + return true; +} + +bool testBool() +{ + Json::Value v(true); + bool b = false; + ASSERT_TRUE(BoolHelper(b, &v) == ErrorCode::Success); + ASSERT_TRUE(b); + + b = false; + v = false; + ASSERT_TRUE(BoolHelper(b, &v) == ErrorCode::Success); + ASSERT_TRUE(!b); + + b = false; + v = 4; + ASSERT_TRUE(BoolHelper(b, &v) == ErrorCode::InvalidBool); + + b = true; + ASSERT_TRUE(BoolHelper(b, nullptr) == ErrorCode::Success); + ASSERT_TRUE(!b); + + return true; +} + +bool testString() +{ + Json::Value v("str"); + std::string str = ""; + ASSERT_TRUE(StringHelper(str, &v) == ErrorCode::Success); + ASSERT_TRUE(str == "str"); + + str = ""; + v = Json::nullValue; + ASSERT_TRUE(StringHelper(str, &v) == ErrorCode::InvalidString); + + str = ""; + ASSERT_TRUE(StringHelper(str, nullptr) == ErrorCode::Success); + ASSERT_TRUE(str == "default"); + + return true; +} + +bool testObject() +{ + auto const helper = cmJSONObjectHelper<ObjectStruct, ErrorCode>( + ErrorCode::Success, ErrorCode::InvalidObject) + .Bind("field1"_s, &ObjectStruct::Field1, StringHelper) + .Bind("field2"_s, &ObjectStruct::Field2, IntHelper) + .Bind<std::string>("field3"_s, nullptr, StringHelper); + + Json::Value v(Json::objectValue); + v["field1"] = "Hello"; + v["field2"] = 2; + v["field3"] = "world!"; + v["extra"] = "extra"; + + ObjectStruct s1; + ASSERT_TRUE(helper(s1, &v) == ErrorCode::Success); + ASSERT_TRUE(s1.Field1 == "Hello"); + ASSERT_TRUE(s1.Field2 == 2); + + v["field2"] = "wrong"; + ObjectStruct s2; + ASSERT_TRUE(helper(s2, &v) == ErrorCode::InvalidInt); + + v.removeMember("field2"); + ObjectStruct s3; + ASSERT_TRUE(helper(s3, &v) == ErrorCode::InvalidObject); + + v["field2"] = 2; + v["field3"] = 3; + ObjectStruct s4; + ASSERT_TRUE(helper(s4, &v) == ErrorCode::InvalidString); + + v.removeMember("field3"); + ObjectStruct s5; + ASSERT_TRUE(helper(s5, &v) == ErrorCode::InvalidObject); + + v = "Hello"; + ObjectStruct s6; + ASSERT_TRUE(helper(s6, &v) == ErrorCode::InvalidObject); + + ObjectStruct s7; + ASSERT_TRUE(helper(s7, nullptr) == ErrorCode::InvalidObject); + + return true; +} + +bool testObjectInherited() +{ + auto const helper = + cmJSONObjectHelper<InheritedStruct, ErrorCode>(ErrorCode::Success, + ErrorCode::InvalidObject) + .Bind("field1"_s, &InheritedStruct::Field1, StringHelper) + .Bind("field2"_s, &InheritedStruct::Field2, IntHelper) + .Bind("field3"_s, &InheritedStruct::Field3, StringHelper); + + Json::Value v(Json::objectValue); + v["field1"] = "Hello"; + v["field2"] = 2; + v["field3"] = "world!"; + v["extra"] = "extra"; + + InheritedStruct s1; + ASSERT_TRUE(helper(s1, &v) == ErrorCode::Success); + ASSERT_TRUE(s1.Field1 == "Hello"); + ASSERT_TRUE(s1.Field2 == 2); + ASSERT_TRUE(s1.Field3 == "world!"); + + v["field2"] = "wrong"; + InheritedStruct s2; + ASSERT_TRUE(helper(s2, &v) == ErrorCode::InvalidInt); + + v.removeMember("field2"); + InheritedStruct s3; + ASSERT_TRUE(helper(s3, &v) == ErrorCode::InvalidObject); + + v["field2"] = 2; + v["field3"] = 3; + InheritedStruct s4; + ASSERT_TRUE(helper(s4, &v) == ErrorCode::InvalidString); + + v.removeMember("field3"); + InheritedStruct s5; + ASSERT_TRUE(helper(s5, &v) == ErrorCode::InvalidObject); + + v = "Hello"; + InheritedStruct s6; + ASSERT_TRUE(helper(s6, &v) == ErrorCode::InvalidObject); + + InheritedStruct s7; + ASSERT_TRUE(helper(s7, nullptr) == ErrorCode::InvalidObject); + + return true; +} + +bool testObjectNoExtra() +{ + auto const helper = cmJSONObjectHelper<ObjectStruct, ErrorCode>( + ErrorCode::Success, ErrorCode::InvalidObject, false) + .Bind("field1"_s, &ObjectStruct::Field1, StringHelper) + .Bind("field2"_s, &ObjectStruct::Field2, IntHelper); + + Json::Value v(Json::objectValue); + v["field1"] = "Hello"; + v["field2"] = 2; + + ObjectStruct s1; + ASSERT_TRUE(helper(s1, &v) == ErrorCode::Success); + ASSERT_TRUE(s1.Field1 == "Hello"); + ASSERT_TRUE(s1.Field2 == 2); + + v["extra"] = "world!"; + ObjectStruct s2; + ASSERT_TRUE(helper(s2, &v) == ErrorCode::InvalidObject); + + return true; +} + +bool testObjectOptional() +{ + auto const helper = + cmJSONObjectHelper<ObjectStruct, ErrorCode>(ErrorCode::Success, + ErrorCode::InvalidObject) + .Bind("field1"_s, &ObjectStruct::Field1, StringHelper, false) + .Bind("field2"_s, &ObjectStruct::Field2, IntHelper, false) + .Bind<std::string>("field3_s", nullptr, StringHelper, false); + + Json::Value v(Json::objectValue); + v["field1"] = "Hello"; + v["field2"] = 2; + v["field3"] = "world!"; + v["extra"] = "extra"; + + ObjectStruct s1; + ASSERT_TRUE(helper(s1, &v) == ErrorCode::Success); + ASSERT_TRUE(s1.Field1 == "Hello"); + ASSERT_TRUE(s1.Field2 == 2); + + v = Json::objectValue; + ObjectStruct s2; + ASSERT_TRUE(helper(s2, &v) == ErrorCode::Success); + ASSERT_TRUE(s2.Field1 == "default"); + ASSERT_TRUE(s2.Field2 == 1); + + ObjectStruct s3; + ASSERT_TRUE(helper(s3, nullptr) == ErrorCode::Success); + ASSERT_TRUE(s3.Field1 == "default"); + ASSERT_TRUE(s3.Field2 == 1); + + return true; +} + +bool testVector() +{ + Json::Value v(Json::arrayValue); + v.append("Hello"); + v.append("world!"); + v.append("ignore"); + + std::vector<std::string> l{ "default" }; + std::vector<std::string> expected{ "Hello", "world!", "ignore" }; + ASSERT_TRUE(StringVectorHelper(l, &v) == ErrorCode::Success); + ASSERT_TRUE(l == expected); + + v[1] = 2; + l = { "default" }; + ASSERT_TRUE(StringVectorHelper(l, &v) == ErrorCode::InvalidString); + + v = "Hello"; + l = { "default" }; + ASSERT_TRUE(StringVectorHelper(l, &v) == ErrorCode::InvalidArray); + + l = { "default" }; + ASSERT_TRUE(StringVectorHelper(l, nullptr) == ErrorCode::Success); + ASSERT_TRUE(l.empty()); + + return true; +} + +bool testVectorFilter() +{ + Json::Value v(Json::arrayValue); + v.append("Hello"); + v.append("world!"); + v.append("ignore"); + + std::vector<std::string> l{ "default" }; + std::vector<std::string> expected{ + "Hello", + "world!", + }; + ASSERT_TRUE(StringVectorFilterHelper(l, &v) == ErrorCode::Success); + ASSERT_TRUE(l == expected); + + v[1] = 2; + l = { "default" }; + ASSERT_TRUE(StringVectorFilterHelper(l, &v) == ErrorCode::InvalidString); + + v = "Hello"; + l = { "default" }; + ASSERT_TRUE(StringVectorFilterHelper(l, &v) == ErrorCode::InvalidArray); + + l = { "default" }; + ASSERT_TRUE(StringVectorFilterHelper(l, nullptr) == ErrorCode::Success); + ASSERT_TRUE(l.empty()); + + return true; +} + +bool testMap() +{ + Json::Value v(Json::objectValue); + v["field1"] = "Hello"; + v["field2"] = "world!"; + v["ignore"] = "ignore"; + + std::map<std::string, std::string> m{ { "key", "default" } }; + std::map<std::string, std::string> expected{ { "field1", "Hello" }, + { "field2", "world!" }, + { "ignore", "ignore" } }; + ASSERT_TRUE(StringMapHelper(m, &v) == ErrorCode::Success); + ASSERT_TRUE(m == expected); + + v = Json::arrayValue; + m = { { "key", "default" } }; + ASSERT_TRUE(StringMapHelper(m, &v) == ErrorCode::InvalidObject); + + m = { { "key", "default" } }; + ASSERT_TRUE(StringMapHelper(m, nullptr) == ErrorCode::Success); + ASSERT_TRUE(m.empty()); + + return true; +} + +bool testMapFilter() +{ + Json::Value v(Json::objectValue); + v["field1"] = "Hello"; + v["field2"] = "world!"; + v["ignore"] = "ignore"; + + std::map<std::string, std::string> m{ { "key", "default" } }; + std::map<std::string, std::string> expected{ { "field1", "Hello" }, + { "field2", "world!" } }; + ASSERT_TRUE(StringMapFilterHelper(m, &v) == ErrorCode::Success); + ASSERT_TRUE(m == expected); + + v = Json::arrayValue; + m = { { "key", "default" } }; + ASSERT_TRUE(StringMapFilterHelper(m, &v) == ErrorCode::InvalidObject); + + m = { { "key", "default" } }; + ASSERT_TRUE(StringMapFilterHelper(m, nullptr) == ErrorCode::Success); + ASSERT_TRUE(m.empty()); + + return true; +} + +bool testOptional() +{ + Json::Value v = "Hello"; + + cm::optional<std::string> str{ "default" }; + ASSERT_TRUE(OptionalStringHelper(str, &v) == ErrorCode::Success); + ASSERT_TRUE(str == "Hello"); + + str.emplace("default"); + ASSERT_TRUE(OptionalStringHelper(str, nullptr) == ErrorCode::Success); + ASSERT_TRUE(str == cm::nullopt); + + return true; +} + +bool testRequired() +{ + Json::Value v = "Hello"; + + std::string str = "default"; + int i = 1; + ASSERT_TRUE(RequiredStringHelper(str, &v) == ErrorCode::Success); + ASSERT_TRUE(str == "Hello"); + ASSERT_TRUE(RequiredIntHelper(i, &v) == ErrorCode::InvalidInt); + + v = 2; + str = "default"; + i = 1; + ASSERT_TRUE(RequiredStringHelper(str, &v) == ErrorCode::InvalidString); + ASSERT_TRUE(RequiredIntHelper(i, &v) == ErrorCode::Success); + ASSERT_TRUE(i == 2); + + str = "default"; + i = 1; + ASSERT_TRUE(RequiredStringHelper(str, nullptr) == + ErrorCode::MissingRequired); + ASSERT_TRUE(RequiredIntHelper(i, nullptr) == ErrorCode::MissingRequired); + + return true; +} +} + +int testJSONHelpers(int /*unused*/, char* /*unused*/ []) +{ + if (!testInt()) { + return 1; + } + if (!testUInt()) { + return 1; + } + if (!testBool()) { + return 1; + } + if (!testString()) { + return 1; + } + if (!testObject()) { + return 1; + } + if (!testObjectInherited()) { + return 1; + } + if (!testObjectNoExtra()) { + return 1; + } + if (!testObjectOptional()) { + return 1; + } + if (!testVector()) { + return 1; + } + if (!testVectorFilter()) { + return 1; + } + if (!testMap()) { + return 1; + } + if (!testMapFilter()) { + return 1; + } + if (!testOptional()) { + return 1; + } + if (!testRequired()) { + return 1; + } + return 0; +} |