[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / clang-tools-extra / clangd / unittests / LSPBinderTests.cpp
blob03f787035b3677d160bca144d122cc6589a5f637
1 //===-- LSPBinderTests.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "LSPBinder.h"
10 #include "llvm/Testing/Support/Error.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
13 #include <optional>
15 namespace clang {
16 namespace clangd {
17 namespace {
19 using testing::ElementsAre;
20 using testing::HasSubstr;
21 using testing::IsEmpty;
22 using testing::UnorderedElementsAre;
24 // JSON-serializable type for testing.
25 struct Foo {
26 int X;
27 friend bool operator==(Foo A, Foo B) { return A.X == B.X; }
29 bool fromJSON(const llvm::json::Value &V, Foo &F, llvm::json::Path P) {
30 return fromJSON(V, F.X, P.field("X"));
32 llvm::json::Value toJSON(const Foo &F) { return F.X; }
34 // Creates a Callback that writes its received value into an
35 // std::optional<Expected>.
36 template <typename T>
37 llvm::unique_function<void(llvm::Expected<T>)>
38 capture(std::optional<llvm::Expected<T>> &Out) {
39 Out.reset();
40 return [&Out](llvm::Expected<T> V) { Out.emplace(std::move(V)); };
43 struct OutgoingRecorder : public LSPBinder::RawOutgoing {
44 llvm::StringMap<std::vector<llvm::json::Value>> Received;
46 void callMethod(llvm::StringRef Method, llvm::json::Value Params,
47 Callback<llvm::json::Value> Reply) override {
48 Received[Method].push_back(Params);
49 if (Method == "fail")
50 return Reply(error("Params={0}", Params));
51 Reply(Params); // echo back the request
53 void notify(llvm::StringRef Method, llvm::json::Value Params) override {
54 Received[Method].push_back(std::move(Params));
57 std::vector<llvm::json::Value> take(llvm::StringRef Method) {
58 std::vector<llvm::json::Value> Result = Received.lookup(Method);
59 Received.erase(Method);
60 return Result;
64 TEST(LSPBinderTest, IncomingCalls) {
65 LSPBinder::RawHandlers RawHandlers;
66 OutgoingRecorder RawOutgoing;
67 LSPBinder Binder{RawHandlers, RawOutgoing};
68 struct Handler {
69 void plusOne(const Foo &Params, Callback<Foo> Reply) {
70 Reply(Foo{Params.X + 1});
72 void fail(const Foo &Params, Callback<Foo> Reply) {
73 Reply(error("X={0}", Params.X));
75 void notify(const Foo &Params) {
76 LastNotify = Params.X;
77 ++NotifyCount;
79 int LastNotify = -1;
80 int NotifyCount = 0;
83 Handler H;
84 Binder.method("plusOne", &H, &Handler::plusOne);
85 Binder.method("fail", &H, &Handler::fail);
86 Binder.notification("notify", &H, &Handler::notify);
87 Binder.command("cmdPlusOne", &H, &Handler::plusOne);
88 ASSERT_THAT(RawHandlers.MethodHandlers.keys(),
89 UnorderedElementsAre("plusOne", "fail"));
90 ASSERT_THAT(RawHandlers.NotificationHandlers.keys(),
91 UnorderedElementsAre("notify"));
92 ASSERT_THAT(RawHandlers.CommandHandlers.keys(),
93 UnorderedElementsAre("cmdPlusOne"));
94 std::optional<llvm::Expected<llvm::json::Value>> Reply;
96 auto &RawPlusOne = RawHandlers.MethodHandlers["plusOne"];
97 RawPlusOne(1, capture(Reply));
98 ASSERT_TRUE(Reply.has_value());
99 EXPECT_THAT_EXPECTED(*Reply, llvm::HasValue(2));
100 RawPlusOne("foo", capture(Reply));
101 ASSERT_TRUE(Reply.has_value());
102 EXPECT_THAT_EXPECTED(
103 *Reply, llvm::FailedWithMessage(HasSubstr(
104 "failed to decode plusOne request: expected integer")));
106 auto &RawFail = RawHandlers.MethodHandlers["fail"];
107 RawFail(2, capture(Reply));
108 ASSERT_TRUE(Reply.has_value());
109 EXPECT_THAT_EXPECTED(*Reply, llvm::FailedWithMessage("X=2"));
111 auto &RawNotify = RawHandlers.NotificationHandlers["notify"];
112 RawNotify(42);
113 EXPECT_EQ(H.LastNotify, 42);
114 EXPECT_EQ(H.NotifyCount, 1);
115 RawNotify("hi"); // invalid, will be logged
116 EXPECT_EQ(H.LastNotify, 42);
117 EXPECT_EQ(H.NotifyCount, 1);
119 auto &RawCmdPlusOne = RawHandlers.CommandHandlers["cmdPlusOne"];
120 RawCmdPlusOne(1, capture(Reply));
121 ASSERT_TRUE(Reply.has_value());
122 EXPECT_THAT_EXPECTED(*Reply, llvm::HasValue(2));
124 // None of this generated any outgoing traffic.
125 EXPECT_THAT(RawOutgoing.Received, IsEmpty());
128 TEST(LSPBinderTest, OutgoingCalls) {
129 LSPBinder::RawHandlers RawHandlers;
130 OutgoingRecorder RawOutgoing;
131 LSPBinder Binder{RawHandlers, RawOutgoing};
133 LSPBinder::OutgoingMethod<Foo, Foo> Echo;
134 Echo = Binder.outgoingMethod("echo");
135 LSPBinder::OutgoingMethod<Foo, std::string> WrongSignature;
136 WrongSignature = Binder.outgoingMethod("wrongSignature");
137 LSPBinder::OutgoingMethod<Foo, Foo> Fail;
138 Fail = Binder.outgoingMethod("fail");
140 std::optional<llvm::Expected<Foo>> Reply;
141 Echo(Foo{2}, capture(Reply));
142 EXPECT_THAT(RawOutgoing.take("echo"), ElementsAre(llvm::json::Value(2)));
143 ASSERT_TRUE(Reply.has_value());
144 EXPECT_THAT_EXPECTED(*Reply, llvm::HasValue(Foo{2}));
146 // JSON response is integer, can't be parsed as string.
147 std::optional<llvm::Expected<std::string>> WrongTypeReply;
148 WrongSignature(Foo{2}, capture(WrongTypeReply));
149 EXPECT_THAT(RawOutgoing.take("wrongSignature"),
150 ElementsAre(llvm::json::Value(2)));
151 ASSERT_TRUE(Reply.has_value());
152 EXPECT_THAT_EXPECTED(*WrongTypeReply,
153 llvm::FailedWithMessage(
154 HasSubstr("failed to decode wrongSignature reply")));
156 Fail(Foo{2}, capture(Reply));
157 EXPECT_THAT(RawOutgoing.take("fail"), ElementsAre(llvm::json::Value(2)));
158 ASSERT_TRUE(Reply.has_value());
159 EXPECT_THAT_EXPECTED(*Reply, llvm::FailedWithMessage("Params=2"));
162 } // namespace
163 } // namespace clangd
164 } // namespace clang