11#include "gmock/gmock.h"
12#include "gtest/gtest.h"
21#if !(defined(_WIN32) || (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
22 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300))
25class JSONTransportTest :
public ::testing::Test {
26 std::string InBuf, OutBuf, MirrorBuf;
27 llvm::raw_string_ostream
Out, Mirror;
28 std::unique_ptr<FILE, int (*)(FILE *)> In;
31 JSONTransportTest() :
Out(OutBuf), Mirror(MirrorBuf), In(nullptr, nullptr) {}
33 template <
typename...
Args>
34 std::unique_ptr<Transport> transport(std::string InData,
bool Pretty,
36 InBuf = std::move(InData);
37 In = {fmemopen(&InBuf[0], InBuf.size(),
"r"), &fclose};
41 std::string input()
const {
return InBuf; }
42 std::string output() {
return Out.str(); }
43 std::string inputMirror() {
return Mirror.str(); }
51class Echo :
public Transport::MessageHandler {
54 llvm::raw_string_ostream Log;
57 Echo(Transport &Target) : Target(Target), Log(LogBuf) {}
59 std::string
log() {
return Log.str(); }
61 bool onNotify(llvm::StringRef
Method, llvm::json::Value Params)
override {
62 Log <<
"Notification " <<
Method <<
": " << Params <<
"\n";
64 Target.call(
"echo call", std::move(Params), 42);
68 bool onCall(llvm::StringRef
Method, llvm::json::Value Params,
69 llvm::json::Value
ID)
override {
70 Log <<
"Call " <<
Method <<
"(" <<
ID <<
"): " << Params <<
"\n";
73 ID, llvm::make_error<LSPError>(
"trouble at mill",
ErrorCode(88)));
74 else if (
Method ==
"invalidated")
75 Target.reply(
ID, llvm::make_error<CancelledError>(
78 Target.reply(
ID, std::move(Params));
82 bool onReply(llvm::json::Value
ID,
83 llvm::Expected<llvm::json::Value> Params)
override {
85 Log <<
"Reply(" <<
ID <<
"): " << *Params <<
"\n";
88 <<
"): error = " << llvm::toString(Params.takeError()) <<
"\n";
93std::string trim(llvm::StringRef S) {
return S.trim().str(); }
96TEST_F(JSONTransportTest, StandardDense) {
98 "Content-Length: 52\r\n\r\n"
99 R
"({"jsonrpc": "2.0", "method": "call", "params": 1234})"
100 "Content-Length: 46\r\n\r\n"
101 R
"({"jsonrpc": "2.0", "id": 1234, "result": 5678})"
102 "Content-Length: 67\r\n\r\n"
103 R
"({"jsonrpc": "2.0", "method": "foo", "id": "abcd", "params": "efgh"})"
104 "Content-Length: 73\r\n\r\n"
105 R
"({"jsonrpc": "2.0", "id": "xyz", "error": {"code": 99, "message": "bad!"}})"
106 "Content-Length: 68\r\n\r\n"
107 R
"({"jsonrpc": "2.0", "method": "err", "id": "wxyz", "params": "boom!"})"
108 "Content-Length: 36\r\n\r\n"
109 R
"({"jsonrpc": "2.0", "method": "exit"})",
112 auto Err =
T->loop(
E);
113 EXPECT_FALSE(
bool(Err)) <<
toString(std::move(Err));
115 const char *WantLog = R
"(
116Notification call: 1234
118Call foo("abcd"): "efgh"
119Reply("xyz"): error = 99: bad!
120Call err("wxyz"): "boom!"
121Notification exit: null
123 EXPECT_EQ(trim(E.log()), trim(WantLog));
124 const char *WantOutput =
125 "Content-Length: 60\r\n\r\n"
126 R
"({"id":42,"jsonrpc":"2.0","method":"echo call","params":1234})"
127 "Content-Length: 45\r\n\r\n"
128 R
"({"id":"abcd","jsonrpc":"2.0","result":"efgh"})"
129 "Content-Length: 77\r\n\r\n"
130 R
"({"error":{"code":88,"message":"trouble at mill"},"id":"wxyz","jsonrpc":"2.0"})";
131 EXPECT_EQ(output(), WantOutput);
132 EXPECT_EQ(trim(inputMirror()), trim(input()));
137TEST_F(JSONTransportTest, DelimitedPretty) {
138 auto T = transport(R
"jsonrpc(
139{"jsonrpc": "2.0", "method": "call", "params": 1234}
141{"jsonrpc": "2.0", "id": 1234, "result": 5678}
143{"jsonrpc": "2.0", "method": "foo", "id": "abcd", "params": "efgh"}
145{"jsonrpc": "2.0", "id": "xyz", "error": {"code": 99, "message": "bad!"}}
147{"jsonrpc": "2.0", "method": "invalidated", "id": "wxyz", "params": "boom!"}
149{"jsonrpc": "2.0", "method": "exit"}
153 auto Err =
T->loop(
E);
154 EXPECT_FALSE(
bool(Err)) <<
toString(std::move(Err));
156 const char *WantLog = R
"(
157Notification call: 1234
159Call foo("abcd"): "efgh"
160Reply("xyz"): error = 99: bad!
161Call invalidated("wxyz"): "boom!"
162Notification exit: null
164 EXPECT_EQ(trim(E.log()), trim(WantLog));
165 const char *WantOutput =
"Content-Length: 77\r\n\r\n"
169 "method": "echo call",
172 "Content-Length: 58\r\n\r\n"
178 "Content-Length: 145\r\n\r\n"
182 "message": "Request cancelled because the document was modified"
187 EXPECT_EQ(output(), WantOutput);
188 EXPECT_EQ(trim(inputMirror()), trim(input()));
193TEST_F(JSONTransportTest, EndOfFile) {
194 auto T = transport(
"Content-Length: 52\r\n\r\n"
195 R
"({"jsonrpc": "2.0", "method": "call", "params": 1234})",
198 auto Err =
T->loop(
E);
199 EXPECT_EQ(trim(
E.log()),
"Notification call: 1234");
200 EXPECT_TRUE(
bool(Err));
201 consumeError(std::move(Err));
202 EXPECT_EQ(trim(inputMirror()), trim(input()));
CompiledFragmentImpl & Out
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
static const char * toString(OffsetEncoding OE)
void log(const char *Fmt, Ts &&... Vals)
std::unique_ptr< Transport > newJSONTransport(std::FILE *In, llvm::raw_ostream &Out, llvm::raw_ostream *InMirror, bool Pretty, JSONStreamStyle Style)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//