Skip to content

Commit c270402

Browse files
committed
Adding a test with a zero-byte write and ensuring we only append to the buffer if we have data to append.
1 parent d6e44d7 commit c270402

File tree

4 files changed

+39
-19
lines changed

4 files changed

+39
-19
lines changed

lldb/include/lldb/Host/JSONTransport.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,20 +110,24 @@ class JSONTransport {
110110
return;
111111
}
112112

113-
m_buffer.append(std::string(buffer, len));
114-
115-
llvm::Expected<std::vector<std::string>> messages = Parse();
116-
if (llvm::Error error = messages.takeError()) {
117-
callback(loop, std::move(error));
118-
return;
113+
if (len)
114+
m_buffer.append(std::string(buffer, len));
115+
116+
// If the buffer has contents, try parsing any pending messages.
117+
if (!m_buffer.empty()) {
118+
llvm::Expected<std::vector<std::string>> messages = Parse();
119+
if (llvm::Error error = messages.takeError()) {
120+
callback(loop, std::move(error));
121+
return;
122+
}
123+
124+
for (const auto &message : *messages)
125+
if constexpr (std::is_same<T, std::string>::value)
126+
callback(loop, message);
127+
else
128+
callback(loop, llvm::json::parse<T>(message));
119129
}
120130

121-
for (const auto &message : *messages)
122-
if constexpr (std::is_same<T, std::string>::value)
123-
callback(loop, message);
124-
else
125-
callback(loop, llvm::json::parse<T>(message));
126-
127131
// On EOF, notify the callback after the remaining messages were
128132
// handled.
129133
if (len == 0) {

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,10 +1004,8 @@ Status DAP::TransportHandler() {
10041004
}
10051005
}
10061006

1007-
{
1008-
std::lock_guard<std::mutex> guard(m_queue_mutex);
1009-
m_queue.push_back(std::move(*message));
1010-
}
1007+
std::lock_guard<std::mutex> guard(m_queue_mutex);
1008+
m_queue.push_back(std::move(*message));
10111009
m_queue_cv.notify_one();
10121010
});
10131011
if (auto err = handle.takeError())

lldb/unittests/DAP/TestBase.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ class TransportBase : public PipePairTest {
2828
void SetUp() override;
2929

3030
template <typename P>
31-
void
32-
RunOnce(std::function<void(llvm::Expected<P>)> callback,
33-
std::chrono::milliseconds timeout = std::chrono::milliseconds(100)) {
31+
void RunOnce(std::function<void(llvm::Expected<P>)> callback,
32+
std::chrono::milliseconds timeout = std::chrono::seconds(1)) {
3433
auto handle = from_dap->RegisterReadObject<P>(
3534
loop, [&](lldb_private::MainLoopBase &loop, llvm::Expected<P> message) {
3635
callback(std::move(message));

lldb/unittests/Host/JSONTransportTest.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,25 @@ TEST_F(HTTPDelimitedJSONTransportTest, ReadPartialMessage) {
173173
HasValue(testing::FieldsAre(/*str=*/"foo")));
174174
}
175175

176+
TEST_F(HTTPDelimitedJSONTransportTest, ReadWithZeroByteWrites) {
177+
std::future<void> background_task = std::async(std::launch::async, [&]() {
178+
std::string json = R"({"str": "foo"})";
179+
std::string message =
180+
formatv("Content-Length: {0}\r\n\r\n{1}", json.size(), json).str();
181+
std::string part1 = message.substr(0, 28);
182+
std::string part2 = message.substr(28);
183+
184+
ASSERT_THAT_EXPECTED(input.Write(part1.data(), part1.size()), Succeeded());
185+
ASSERT_THAT_EXPECTED(input.Write(part1.data(), 0),
186+
Succeeded()); // zero-byte write.
187+
std::this_thread::sleep_for(std::chrono::milliseconds(10));
188+
ASSERT_THAT_EXPECTED(input.Write(part2.data(), part2.size()), Succeeded());
189+
});
190+
191+
ASSERT_THAT_EXPECTED(RunOnce<JSONTestType>(),
192+
HasValue(testing::FieldsAre(/*str=*/"foo")));
193+
}
194+
176195
TEST_F(HTTPDelimitedJSONTransportTest, ReadWithEOF) {
177196
input.CloseWriteFileDescriptor();
178197
ASSERT_THAT_EXPECTED(RunOnce<JSONTestType>(), Failed<TransportEOFError>());

0 commit comments

Comments
 (0)