summaryrefslogtreecommitdiffstats
path: root/unittests
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2017-11-30 21:32:29 +0000
committerSam McCall <sam.mccall@gmail.com>2017-11-30 21:32:29 +0000
commit9892c71e6829581c44f20b94d4ca34141c4de6cf (patch)
tree6af1459593b670b4212b5140ce53ec45f3b09726 /unittests
parent0285b529a005e2e300e3ca7148adc9bfeb131222 (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.cpp58
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