10 #include "gmock/gmock.h" 11 #include "gtest/gtest.h" 20 #if !(defined(_WIN32) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \ 21 __MAC_OS_X_VERSION_MIN_REQUIRED < 101300)) 24 class JSONTransportTest :
public ::testing::Test {
25 std::string InBuf, OutBuf, MirrorBuf;
26 llvm::raw_string_ostream Out, Mirror;
27 std::unique_ptr<FILE, int (*)(FILE *)> In;
30 JSONTransportTest() : Out(OutBuf), Mirror(MirrorBuf), In(nullptr, nullptr) {}
32 template <
typename... Args>
33 std::unique_ptr<Transport> transport(std::string InData,
bool Pretty,
35 InBuf = std::move(InData);
36 In = {fmemopen(&InBuf[0], InBuf.size(),
"r"), &fclose};
40 std::string input()
const {
return InBuf; }
41 std::string output() {
return Out.str(); }
42 std::string input_mirror() {
return Mirror.str(); }
50 class Echo :
public Transport::MessageHandler {
53 llvm::raw_string_ostream
Log;
56 Echo(Transport &Target) : Target(Target), Log(LogBuf) {}
58 std::string
log() {
return Log.str(); }
60 bool onNotify(llvm::StringRef
Method, llvm::json::Value Params)
override {
61 Log <<
"Notification " << Method <<
": " << Params <<
"\n";
63 Target.call(
"echo call", std::move(Params), 42);
64 return Method !=
"exit";
67 bool onCall(llvm::StringRef Method, llvm::json::Value Params,
68 llvm::json::Value ID)
override {
69 Log <<
"Call " << Method <<
"(" << ID <<
"): " << Params <<
"\n";
72 ID, llvm::make_error<LSPError>(
"trouble at mill",
ErrorCode(88)));
74 Target.reply(ID, std::move(Params));
78 bool onReply(llvm::json::Value ID,
79 llvm::Expected<llvm::json::Value> Params)
override {
81 Log <<
"Reply(" << ID <<
"): " << *Params <<
"\n";
89 std::string trim(llvm::StringRef S) {
return S.trim().str(); }
92 TEST_F(JSONTransportTest, StandardDense) {
94 "Content-Length: 52\r\n\r\n" 95 R
"({"jsonrpc": "2.0", "method": "call", "params": 1234})" 96 "Content-Length: 46\r\n\r\n" 97 R
"({"jsonrpc": "2.0", "id": 1234, "result": 5678})" 98 "Content-Length: 67\r\n\r\n" 99 R
"({"jsonrpc": "2.0", "method": "foo", "id": "abcd", "params": "efgh"})" 100 "Content-Length: 73\r\n\r\n" 101 R
"({"jsonrpc": "2.0", "id": "xyz", "error": {"code": 99, "message": "bad!"}})" 102 "Content-Length: 68\r\n\r\n" 103 R
"({"jsonrpc": "2.0", "method": "err", "id": "wxyz", "params": "boom!"})" 104 "Content-Length: 36\r\n\r\n" 105 R
"({"jsonrpc": "2.0", "method": "exit"})", 108 auto Err = T->loop(
E);
109 EXPECT_FALSE(
bool(Err)) <<
toString(std::move(Err));
111 const char *WantLog = R
"( 112 Notification call: 1234 114 Call foo("abcd"): "efgh" 115 Reply("xyz"): error = 99: bad! 116 Call err("wxyz"): "boom!" 117 Notification exit: null 119 EXPECT_EQ(trim(E.log()), trim(WantLog)); 120 const char *WantOutput =
121 "Content-Length: 60\r\n\r\n" 122 R
"({"id":42,"jsonrpc":"2.0","method":"echo call","params":1234})" 123 "Content-Length: 45\r\n\r\n" 124 R
"({"id":"abcd","jsonrpc":"2.0","result":"efgh"})" 125 "Content-Length: 77\r\n\r\n" 126 R
"({"error":{"code":88,"message":"trouble at mill"},"id":"wxyz","jsonrpc":"2.0"})"; 127 EXPECT_EQ(output(), WantOutput); 128 EXPECT_EQ(trim(input_mirror()), trim(input())); 133 TEST_F(JSONTransportTest, DelimitedPretty) {
134 auto T = transport(R
"jsonrpc( 135 {"jsonrpc": "2.0", "method": "call", "params": 1234} 137 {"jsonrpc": "2.0", "id": 1234, "result": 5678} 139 {"jsonrpc": "2.0", "method": "foo", "id": "abcd", "params": "efgh"} 141 {"jsonrpc": "2.0", "id": "xyz", "error": {"code": 99, "message": "bad!"}} 143 {"jsonrpc": "2.0", "method": "err", "id": "wxyz", "params": "boom!"} 145 {"jsonrpc": "2.0", "method": "exit"} 149 auto Err = T->loop(
E);
150 EXPECT_FALSE(
bool(Err)) <<
toString(std::move(Err));
152 const char *WantLog = R
"( 153 Notification call: 1234 155 Call foo("abcd"): "efgh" 156 Reply("xyz"): error = 99: bad! 157 Call err("wxyz"): "boom!" 158 Notification exit: null 160 EXPECT_EQ(trim(E.log()), trim(WantLog)); 161 const char *WantOutput =
"Content-Length: 77\r\n\r\n" 165 "method": "echo call", 168 "Content-Length: 58\r\n\r\n" 174 "Content-Length: 105\r\n\r\n" 178 "message": "trouble at mill" 183 EXPECT_EQ(output(), WantOutput); 184 EXPECT_EQ(trim(input_mirror()), trim(input())); 189 TEST_F(JSONTransportTest, EndOfFile) {
190 auto T = transport(
"Content-Length: 52\r\n\r\n" 191 R
"({"jsonrpc": "2.0", "method": "call", "params": 1234})", 194 auto Err = T->loop(
E);
195 EXPECT_EQ(trim(
E.log()),
"Notification call: 1234");
196 EXPECT_TRUE(
bool(Err));
197 consumeError(std::move(Err));
198 EXPECT_EQ(trim(input_mirror()), trim(input()));
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
void log(const char *Fmt, Ts &&... Vals)
static const char * toString(OffsetEncoding OE)
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++ -*-===//