Skip to content

Commit 4436e9f

Browse files
JDevliegheretomtor
authored andcommitted
[lldb] Implement JSON RPC (newline delimited) Transport (llvm#143946)
This PR implements JSON RPC-style (i.e. newline delimited) JSON transport. I moved the existing transport tests from DAP to Host and moved the PipeTest base class into TestingSupport so it can be shared by both.
1 parent 41c05bf commit 4436e9f

File tree

9 files changed

+260
-124
lines changed

9 files changed

+260
-124
lines changed

lldb/include/lldb/Host/JSONTransport.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,17 @@ class TransportTimeoutError : public llvm::ErrorInfo<TransportTimeoutError> {
5151
}
5252
};
5353

54-
class TransportClosedError : public llvm::ErrorInfo<TransportClosedError> {
54+
class TransportInvalidError : public llvm::ErrorInfo<TransportInvalidError> {
5555
public:
5656
static char ID;
5757

58-
TransportClosedError() = default;
58+
TransportInvalidError() = default;
5959

6060
void log(llvm::raw_ostream &OS) const override {
61-
OS << "transport is closed";
61+
OS << "transport IO object invalid";
6262
}
6363
std::error_code convertToErrorCode() const override {
64-
return llvm::inconvertibleErrorCode();
64+
return std::make_error_code(std::errc::not_connected);
6565
}
6666
};
6767

@@ -121,6 +121,21 @@ class HTTPDelimitedJSONTransport : public JSONTransport {
121121
static constexpr llvm::StringLiteral kHeaderSeparator = "\r\n\r\n";
122122
};
123123

124+
/// A transport class for JSON RPC.
125+
class JSONRPCTransport : public JSONTransport {
126+
public:
127+
JSONRPCTransport(lldb::IOObjectSP input, lldb::IOObjectSP output)
128+
: JSONTransport(input, output) {}
129+
virtual ~JSONRPCTransport() = default;
130+
131+
protected:
132+
virtual llvm::Error WriteImpl(const std::string &message) override;
133+
virtual llvm::Expected<std::string>
134+
ReadImpl(const std::chrono::microseconds &timeout) override;
135+
136+
static constexpr llvm::StringLiteral kMessageSeparator = "\n";
137+
};
138+
124139
} // namespace lldb_private
125140

126141
#endif

lldb/source/Host/common/JSONTransport.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ static Expected<std::string>
3131
ReadFull(IOObject &descriptor, size_t length,
3232
std::optional<std::chrono::microseconds> timeout = std::nullopt) {
3333
if (!descriptor.IsValid())
34-
return llvm::make_error<TransportClosedError>();
34+
return llvm::make_error<TransportInvalidError>();
3535

3636
bool timeout_supported = true;
3737
// FIXME: SelectHelper does not work with NativeFile on Win32.
@@ -92,7 +92,7 @@ void JSONTransport::Log(llvm::StringRef message) {
9292
Expected<std::string>
9393
HTTPDelimitedJSONTransport::ReadImpl(const std::chrono::microseconds &timeout) {
9494
if (!m_input || !m_input->IsValid())
95-
return createStringError("transport output is closed");
95+
return llvm::make_error<TransportInvalidError>();
9696

9797
IOObject *input = m_input.get();
9898
Expected<std::string> message_header =
@@ -131,7 +131,7 @@ HTTPDelimitedJSONTransport::ReadImpl(const std::chrono::microseconds &timeout) {
131131

132132
Error HTTPDelimitedJSONTransport::WriteImpl(const std::string &message) {
133133
if (!m_output || !m_output->IsValid())
134-
return llvm::make_error<TransportClosedError>();
134+
return llvm::make_error<TransportInvalidError>();
135135

136136
Log(llvm::formatv("<-- {0}", message).str());
137137

@@ -142,6 +142,35 @@ Error HTTPDelimitedJSONTransport::WriteImpl(const std::string &message) {
142142
return m_output->Write(Output.data(), num_bytes).takeError();
143143
}
144144

145+
Expected<std::string>
146+
JSONRPCTransport::ReadImpl(const std::chrono::microseconds &timeout) {
147+
if (!m_input || !m_input->IsValid())
148+
return make_error<TransportInvalidError>();
149+
150+
IOObject *input = m_input.get();
151+
Expected<std::string> raw_json =
152+
ReadUntil(*input, kMessageSeparator, timeout);
153+
if (!raw_json)
154+
return raw_json.takeError();
155+
156+
Log(llvm::formatv("--> {0}", *raw_json).str());
157+
158+
return *raw_json;
159+
}
160+
161+
Error JSONRPCTransport::WriteImpl(const std::string &message) {
162+
if (!m_output || !m_output->IsValid())
163+
return llvm::make_error<TransportInvalidError>();
164+
165+
Log(llvm::formatv("<-- {0}", message).str());
166+
167+
std::string Output;
168+
llvm::raw_string_ostream OS(Output);
169+
OS << message << kMessageSeparator;
170+
size_t num_bytes = Output.size();
171+
return m_output->Write(Output.data(), num_bytes).takeError();
172+
}
173+
145174
char TransportEOFError::ID;
146175
char TransportTimeoutError::ID;
147-
char TransportClosedError::ID;
176+
char TransportInvalidError::ID;

lldb/unittests/DAP/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ add_lldb_unittest(DAPTests
77
LLDBUtilsTest.cpp
88
ProtocolTypesTest.cpp
99
TestBase.cpp
10-
TransportTest.cpp
1110
VariablesTest.cpp
1211

1312
LINK_COMPONENTS

lldb/unittests/DAP/TestBase.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,8 @@ using lldb_private::File;
2828
using lldb_private::NativeFile;
2929
using lldb_private::Pipe;
3030

31-
void PipeBase::SetUp() {
32-
ASSERT_THAT_ERROR(input.CreateNew(false).ToError(), Succeeded());
33-
ASSERT_THAT_ERROR(output.CreateNew(false).ToError(), Succeeded());
34-
}
35-
3631
void TransportBase::SetUp() {
37-
PipeBase::SetUp();
32+
PipeTest::SetUp();
3833
to_dap = std::make_unique<Transport>(
3934
"to_dap", nullptr,
4035
std::make_shared<NativeFile>(input.GetReadFileDescriptor(),

lldb/unittests/DAP/TestBase.h

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,17 @@
88

99
#include "DAP.h"
1010
#include "Protocol/ProtocolBase.h"
11+
#include "TestingSupport/Host/PipeTestUtilities.h"
1112
#include "Transport.h"
12-
#include "lldb/Host/Pipe.h"
1313
#include "llvm/ADT/StringRef.h"
1414
#include "gmock/gmock.h"
1515
#include "gtest/gtest.h"
1616

1717
namespace lldb_dap_tests {
1818

19-
/// A base class for tests that need a pair of pipes for communication.
20-
class PipeBase : public testing::Test {
21-
protected:
22-
lldb_private::Pipe input;
23-
lldb_private::Pipe output;
24-
25-
void SetUp() override;
26-
};
27-
2819
/// A base class for tests that need transport configured for communicating DAP
2920
/// messages.
30-
class TransportBase : public PipeBase {
21+
class TransportBase : public PipeTest {
3122
protected:
3223
std::unique_ptr<lldb_dap::Transport> to_dap;
3324
std::unique_ptr<lldb_dap::Transport> from_dap;

lldb/unittests/DAP/TransportTest.cpp

Lines changed: 0 additions & 98 deletions
This file was deleted.

lldb/unittests/Host/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set (FILES
66
HostInfoTest.cpp
77
HostTest.cpp
88
MainLoopTest.cpp
9+
JSONTransportTest.cpp
910
NativeProcessProtocolTest.cpp
1011
PipeTest.cpp
1112
ProcessLaunchInfoTest.cpp

0 commit comments

Comments
 (0)