1//===-- TransportTest.cpp -------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Transport.h"
10#include "Protocol/ProtocolBase.h"
11#include "TestBase.h"
12#include "lldb/Host/File.h"
13#include "lldb/Host/Pipe.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/Testing/Support/Error.h"
16#include "gtest/gtest.h"
17#include <chrono>
18#include <memory>
19#include <optional>
20
21using namespace llvm;
22using namespace lldb;
23using namespace lldb_dap;
24using namespace lldb_dap_tests;
25using namespace lldb_dap::protocol;
26using lldb_private::File;
27using lldb_private::NativeFile;
28using lldb_private::Pipe;
29
30class TransportTest : public PipeBase {
31protected:
32 std::unique_ptr<Transport> transport;
33
34 void SetUp() override {
35 PipeBase::SetUp();
36 transport = std::make_unique<Transport>(
37 args: "stdio", args: nullptr,
38 args: std::make_shared<NativeFile>(args: input.GetReadFileDescriptor(),
39 args: File::eOpenOptionReadOnly,
40 args: NativeFile::Unowned),
41 args: std::make_shared<NativeFile>(args: output.GetWriteFileDescriptor(),
42 args: File::eOpenOptionWriteOnly,
43 args: NativeFile::Unowned));
44 }
45};
46
47TEST_F(TransportTest, MalformedRequests) {
48 std::string malformed_header = "COnTent-LenGth: -1{}\r\n\r\nnotjosn";
49 ASSERT_THAT_EXPECTED(
50 input.Write(malformed_header.data(), malformed_header.size()),
51 Succeeded());
52 ASSERT_THAT_EXPECTED(
53 transport->Read(std::chrono::milliseconds(1)),
54 FailedWithMessage(
55 "expected 'Content-Length: ' and got 'COnTent-LenGth: '"));
56}
57
58TEST_F(TransportTest, Read) {
59 std::string json =
60 R"json({"seq": 1, "type": "request", "command": "abc"})json";
61 std::string message =
62 formatv(Fmt: "Content-Length: {0}\r\n\r\n{1}", Vals: json.size(), Vals&: json).str();
63 ASSERT_THAT_EXPECTED(input.Write(message.data(), message.size()),
64 Succeeded());
65 ASSERT_THAT_EXPECTED(
66 transport->Read(std::chrono::milliseconds(1)),
67 HasValue(testing::VariantWith<Request>(testing::FieldsAre(
68 /*seq=*/1, /*command=*/"abc", /*arguments=*/std::nullopt))));
69}
70
71TEST_F(TransportTest, ReadWithTimeout) {
72 ASSERT_THAT_EXPECTED(transport->Read(std::chrono::milliseconds(1)),
73 Failed<TimeoutError>());
74}
75
76TEST_F(TransportTest, ReadWithEOF) {
77 input.CloseWriteFileDescriptor();
78 ASSERT_THAT_EXPECTED(transport->Read(std::chrono::milliseconds(1)),
79 Failed<EndOfFileError>());
80}
81
82TEST_F(TransportTest, Write) {
83 ASSERT_THAT_ERROR(transport->Write(Event{"my-event", std::nullopt}),
84 Succeeded());
85 output.CloseWriteFileDescriptor();
86 char buf[1024];
87 Expected<size_t> bytes_read =
88 output.Read(buf, size: sizeof(buf), timeout: std::chrono::milliseconds(1));
89 ASSERT_THAT_EXPECTED(bytes_read, Succeeded());
90 ASSERT_EQ(
91 StringRef(buf, *bytes_read),
92 StringRef("Content-Length: 43\r\n\r\n"
93 R"json({"event":"my-event","seq":0,"type":"event"})json"));
94}
95

source code of lldb/unittests/DAP/TransportTest.cpp