brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · f8c584a Raw
184 lines · cpp
1//===-- CommunicationTest.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Core/Communication.h"10#include "TestingSupport/SubsystemRAII.h"11#include "lldb/Core/ThreadedCommunication.h"12#include "lldb/Host/Config.h"13#include "lldb/Host/ConnectionFileDescriptor.h"14#include "lldb/Host/Pipe.h"15#include "lldb/Host/Socket.h"16#include "llvm/Testing/Support/Error.h"17#include "gtest/gtest.h"18 19#include <chrono>20#include <thread>21 22#if LLDB_ENABLE_POSIX23#include <fcntl.h>24#endif25 26using namespace lldb_private;27 28class CommunicationTest : public testing::Test {29private:30  SubsystemRAII<Socket> m_subsystems;31};32 33static void CommunicationReadTest(bool use_read_thread) {34  llvm::Expected<Socket::Pair> pair = Socket::CreatePair();35  ASSERT_THAT_EXPECTED(pair, llvm::Succeeded());36  Socket &a = *pair->first;37 38  size_t num_bytes = 4;39  ASSERT_THAT_ERROR(a.Write("test", num_bytes).ToError(), llvm::Succeeded());40  ASSERT_EQ(num_bytes, 4U);41 42  ThreadedCommunication comm("test");43  comm.SetConnection(44      std::make_unique<ConnectionFileDescriptor>(std::move(pair->second)));45  comm.SetCloseOnEOF(true);46 47  if (use_read_thread) {48    ASSERT_TRUE(comm.StartReadThread());49  }50 51  // This read should wait for the data to become available and return it.52  lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;53  char buf[16];54  Status error;55  EXPECT_EQ(56      comm.Read(buf, sizeof(buf), std::chrono::seconds(5), status, &error), 4U);57  EXPECT_EQ(status, lldb::eConnectionStatusSuccess);58  EXPECT_THAT_ERROR(error.ToError(), llvm::Succeeded());59  buf[4] = 0;60  EXPECT_STREQ(buf, "test");61 62  // These reads should time out as there is no more data.63  error.Clear();64  EXPECT_EQ(comm.Read(buf, sizeof(buf), std::chrono::microseconds(10), status,65                      &error),66            0U);67  EXPECT_EQ(status, lldb::eConnectionStatusTimedOut);68  EXPECT_THAT_ERROR(error.ToError(), llvm::Failed());69 70  // 0 is special-cased, so we test it separately.71  error.Clear();72  EXPECT_EQ(73      comm.Read(buf, sizeof(buf), std::chrono::seconds(0), status, &error), 0U);74  EXPECT_EQ(status, lldb::eConnectionStatusTimedOut);75  EXPECT_THAT_ERROR(error.ToError(), llvm::Failed());76 77  // This read should return EOF.78  ASSERT_THAT_ERROR(a.Close().ToError(), llvm::Succeeded());79  error.Clear();80  EXPECT_EQ(81      comm.Read(buf, sizeof(buf), std::chrono::seconds(5), status, &error), 0U);82  EXPECT_EQ(status, lldb::eConnectionStatusEndOfFile);83  EXPECT_THAT_ERROR(error.ToError(), llvm::Succeeded());84 85  // JoinReadThread() should just return immediately if there was no read86  // thread started.87  EXPECT_TRUE(comm.JoinReadThread());88 89  // Test using Communication that is disconnected.90  ASSERT_EQ(comm.Disconnect(), lldb::eConnectionStatusSuccess);91  if (use_read_thread) {92    ASSERT_TRUE(comm.StartReadThread());93  }94  error.Clear();95  EXPECT_EQ(96      comm.Read(buf, sizeof(buf), std::chrono::seconds(5), status, &error), 0U);97  EXPECT_EQ(status, lldb::eConnectionStatusLostConnection);98  EXPECT_THAT_ERROR(error.ToError(), llvm::Failed());99  EXPECT_TRUE(comm.JoinReadThread());100 101  // Test using Communication without a connection.102  comm.SetConnection(nullptr);103  if (use_read_thread) {104    ASSERT_TRUE(comm.StartReadThread());105  }106  error.Clear();107  EXPECT_EQ(108      comm.Read(buf, sizeof(buf), std::chrono::seconds(5), status, &error), 0U);109  EXPECT_EQ(status, lldb::eConnectionStatusNoConnection);110  EXPECT_THAT_ERROR(error.ToError(), llvm::Failed());111  EXPECT_TRUE(comm.JoinReadThread());112}113 114TEST_F(CommunicationTest, Read) {115  CommunicationReadTest(/*use_thread=*/false);116}117 118TEST_F(CommunicationTest, ReadThread) {119  CommunicationReadTest(/*use_thread=*/true);120}121 122TEST_F(CommunicationTest, SynchronizeWhileClosing) {123  llvm::Expected<Socket::Pair> pair = Socket::CreatePair();124  ASSERT_THAT_EXPECTED(pair, llvm::Succeeded());125  Socket &a = *pair->first;126 127  ThreadedCommunication comm("test");128  comm.SetConnection(129      std::make_unique<ConnectionFileDescriptor>(std::move(pair->second)));130  comm.SetCloseOnEOF(true);131  ASSERT_TRUE(comm.StartReadThread());132 133  // Ensure that we can safely synchronize with the read thread while it is134  // closing the read end (in response to us closing the write end).135  ASSERT_THAT_ERROR(a.Close().ToError(), llvm::Succeeded());136  comm.SynchronizeWithReadThread();137 138  ASSERT_TRUE(comm.StopReadThread());139}140 141#if LLDB_ENABLE_POSIX142TEST_F(CommunicationTest, WriteAll) {143  Pipe pipe;144  ASSERT_THAT_ERROR(pipe.CreateNew().ToError(), llvm::Succeeded());145 146  // Make the write end non-blocking in order to easily reproduce a partial147  // write.148  int write_fd = pipe.ReleaseWriteFileDescriptor();149  int flags = fcntl(write_fd, F_GETFL);150  ASSERT_NE(flags, -1);151  ASSERT_NE(fcntl(write_fd, F_SETFL, flags | O_NONBLOCK), -1);152 153  ConnectionFileDescriptor read_conn{pipe.ReleaseReadFileDescriptor(),154                                     /*owns_fd=*/true};155  Communication write_comm;156  write_comm.SetConnection(157      std::make_unique<ConnectionFileDescriptor>(write_fd, /*owns_fd=*/true));158 159  std::thread read_thread{[&read_conn]() {160    // Read using a smaller buffer to increase chances of partial write.161    char buf[128 * 1024];162    lldb::ConnectionStatus conn_status;163 164    do {165      read_conn.Read(buf, sizeof(buf), std::chrono::seconds(1), conn_status,166                     nullptr);167    } while (conn_status != lldb::eConnectionStatusEndOfFile);168  }};169 170  // Write 1 MiB of data into the pipe.171  lldb::ConnectionStatus conn_status;172  Status error;173  std::vector<uint8_t> data(1024 * 1024, 0x80);174  EXPECT_EQ(write_comm.WriteAll(data.data(), data.size(), conn_status, &error),175            data.size());176  EXPECT_EQ(conn_status, lldb::eConnectionStatusSuccess);177  EXPECT_FALSE(error.Fail());178 179  // Close the write end in order to trigger EOF.180  write_comm.Disconnect();181  read_thread.join();182}183#endif184