10#include "llvm/Testing/Support/Error.h"
11#include "gmock/gmock.h"
12#include "gtest/gtest.h"
19using testing::ElementsAre;
20using testing::HasSubstr;
21using testing::IsEmpty;
22using testing::UnorderedElementsAre;
27 friend bool operator==(Foo A, Foo B) {
return A.X ==
B.X; }
29bool fromJSON(
const llvm::json::Value &V, Foo &F, llvm::json::Path P) {
32llvm::json::Value
toJSON(
const Foo &F) {
return F.X; }
37llvm::unique_function<void(llvm::Expected<T>)>
38capture(std::optional<llvm::Expected<T>> &Out) {
40 return [&Out](llvm::Expected<T> V) { Out.emplace(std::move(V)); };
44 llvm::StringMap<std::vector<llvm::json::Value>> Received;
46 void callMethod(llvm::StringRef
Method, llvm::json::Value Params,
48 Received[
Method].push_back(Params);
50 return Reply(
error(
"Params={0}", Params));
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);
64TEST(LSPBinderTest, IncomingCalls) {
66 OutgoingRecorder RawOutgoing;
67 LSPBinder Binder{RawHandlers, RawOutgoing};
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;
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"];
113 EXPECT_EQ(H.LastNotify, 42);
114 EXPECT_EQ(H.NotifyCount, 1);
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));
125 EXPECT_THAT(RawOutgoing.Received, IsEmpty());
128TEST(LSPBinderTest, OutgoingCalls) {
130 OutgoingRecorder RawOutgoing;
131 LSPBinder Binder{RawHandlers, RawOutgoing};
134 Echo = Binder.outgoingMethod(
"echo");
136 WrongSignature = Binder.outgoingMethod(
"wrongSignature");
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}));
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"));
LSPBinder collects a table of functions that handle LSP calls.
llvm::unique_function< void(const P &, Callback< R >)> OutgoingMethod
llvm::Error error(std::error_code, std::string &&)
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
bool operator==(const Inclusion &LHS, const Inclusion &RHS)
llvm::json::Value toJSON(const FuzzyFindRequest &Request)
TEST(BackgroundQueueTest, Priority)
bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request, llvm::json::Path P)
cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccess P
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//