diff options
author | Sam McCall <sam.mccall@gmail.com> | 2017-11-30 21:32:29 +0000 |
---|---|---|
committer | Sam McCall <sam.mccall@gmail.com> | 2017-11-30 21:32:29 +0000 |
commit | 9892c71e6829581c44f20b94d4ca34141c4de6cf (patch) | |
tree | 6af1459593b670b4212b5140ce53ec45f3b09726 /unittests | |
parent | 0285b529a005e2e300e3ca7148adc9bfeb131222 (diff) |
[clangd] New conventions for JSON-marshalling functions, centralize machinery
Summary:
- JSON<->Obj interface is now ADL functions, so they play nicely with enums
- recursive vector/map parsing and ObjectMapper moved to JSONExpr and tested
- renamed (un)parse to (de)serialize, since text -> JSON is called parse
- Protocol.cpp gets a bit shorter
Sorry for the giant patch, it's prety mechanical though
Reviewers: ilya-biryukov
Subscribers: klimek, cfe-commits
Differential Revision: https://reviews.llvm.org/D40596
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@319478 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests')
-rw-r--r-- | unittests/clangd/JSONExprTests.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/unittests/clangd/JSONExprTests.cpp b/unittests/clangd/JSONExprTests.cpp index b8fac58f..2c5cab29 100644 --- a/unittests/clangd/JSONExprTests.cpp +++ b/unittests/clangd/JSONExprTests.cpp @@ -229,6 +229,64 @@ TEST(JSONTest, Inspection) { } } +// Sample struct with typical JSON-mapping rules. +struct CustomStruct { + CustomStruct() : B(false) {} + CustomStruct(std::string S, llvm::Optional<int> I, bool B) + : S(S), I(I), B(B) {} + std::string S; + llvm::Optional<int> I; + bool B; +}; +inline bool operator==(const CustomStruct &L, const CustomStruct &R) { + return L.S == R.S && L.I == R.I && L.B == R.B; +} +inline std::ostream &operator<<(std::ostream &OS, const CustomStruct &S) { + return OS << "(" << S.S << ", " << (S.I ? std::to_string(*S.I) : "None") + << ", " << S.B << ")"; +} +bool fromJSON(const json::Expr &E, CustomStruct &R) { + ObjectMapper O(E); + if (!O || !O.map("str", R.S) || !O.map("int", R.I)) + return false; + O.map("bool", R.B); + return true; +} + +TEST(JSONTest, Deserialize) { + std::map<std::string, std::vector<CustomStruct>> R; + CustomStruct ExpectedStruct = {"foo", 42, true}; + std::map<std::string, std::vector<CustomStruct>> Expected; + Expr J = obj{{"foo", ary{ + obj{ + {"str", "foo"}, + {"int", 42}, + {"bool", true}, + {"unknown", "ignored"}, + }, + obj{{"str", "bar"}}, + obj{ + {"str", "baz"}, + {"bool", "string"}, // OK, deserialize ignores. + }, + }}}; + Expected["foo"] = { + CustomStruct("foo", 42, true), + CustomStruct("bar", llvm::None, false), + CustomStruct("baz", llvm::None, false), + }; + ASSERT_TRUE(fromJSON(J, R)); + EXPECT_EQ(R, Expected); + + CustomStruct V; + EXPECT_FALSE(fromJSON(nullptr, V)) << "Not an object " << V; + EXPECT_FALSE(fromJSON(obj{}, V)) << "Missing required field " << V; + EXPECT_FALSE(fromJSON(obj{{"str", 1}}, V)) << "Wrong type " << V; + // Optional<T> must parse as the correct type if present. + EXPECT_FALSE(fromJSON(obj{{"str", 1}, {"int", "string"}}, V)) + << "Wrong type for Optional<T> " << V; +} + } // namespace } // namespace json } // namespace clangd |