1#include "llvm/ADT/SmallString.h"
2#include "llvm/Config/llvm-config.h"
3#include "llvm/Support/Casting.h"
4#include "llvm/Support/FileSystem.h"
5#include "llvm/Support/FileUtilities.h"
6#include "llvm/Support/raw_socket_stream.h"
7#include "llvm/Testing/Support/Error.h"
8#include "gtest/gtest.h"
9#include <future>
10#include <iostream>
11#include <stdlib.h>
12#include <thread>
13
14#ifdef _WIN32
15#include "llvm/Support/Windows/WindowsSupport.h"
16#endif
17
18using namespace llvm;
19
20namespace {
21
22bool hasUnixSocketSupport() {
23#ifdef _WIN32
24 VersionTuple Ver = GetWindowsOSVersion();
25 if (Ver < VersionTuple(10, 0, 0, 17063))
26 return false;
27#endif
28 return true;
29}
30
31TEST(raw_socket_streamTest, CLIENT_TO_SERVER_AND_SERVER_TO_CLIENT) {
32 if (!hasUnixSocketSupport())
33 GTEST_SKIP();
34
35 SmallString<100> SocketPath;
36 llvm::sys::fs::createUniquePath(Model: "client_server_comms.sock", ResultPath&: SocketPath, MakeAbsolute: true);
37
38 // Make sure socket file does not exist. May still be there from the last test
39 std::remove(filename: SocketPath.c_str());
40
41 Expected<ListeningSocket> MaybeServerListener =
42 ListeningSocket::createUnix(SocketPath);
43 ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded());
44
45 ListeningSocket ServerListener = std::move(*MaybeServerListener);
46
47 Expected<std::unique_ptr<raw_socket_stream>> MaybeClient =
48 raw_socket_stream::createConnectedUnix(SocketPath);
49 ASSERT_THAT_EXPECTED(MaybeClient, llvm::Succeeded());
50
51 raw_socket_stream &Client = **MaybeClient;
52
53 Expected<std::unique_ptr<raw_socket_stream>> MaybeServer =
54 ServerListener.accept();
55 ASSERT_THAT_EXPECTED(MaybeServer, llvm::Succeeded());
56
57 raw_socket_stream &Server = **MaybeServer;
58
59 Client << "01234567";
60 Client.flush();
61
62 char Bytes[8];
63 ssize_t BytesRead = Server.read(Ptr: Bytes, Size: 8);
64
65 std::string string(Bytes, 8);
66
67 ASSERT_EQ(8, BytesRead);
68 ASSERT_EQ("01234567", string);
69}
70
71TEST(raw_socket_streamTest, TIMEOUT_PROVIDED) {
72 if (!hasUnixSocketSupport())
73 GTEST_SKIP();
74
75 SmallString<100> SocketPath;
76 llvm::sys::fs::createUniquePath(Model: "timout_provided.sock", ResultPath&: SocketPath, MakeAbsolute: true);
77
78 // Make sure socket file does not exist. May still be there from the last test
79 std::remove(filename: SocketPath.c_str());
80
81 Expected<ListeningSocket> MaybeServerListener =
82 ListeningSocket::createUnix(SocketPath);
83 ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded());
84 ListeningSocket ServerListener = std::move(*MaybeServerListener);
85
86 std::chrono::milliseconds Timeout = std::chrono::milliseconds(100);
87 Expected<std::unique_ptr<raw_socket_stream>> MaybeServer =
88 ServerListener.accept(Timeout);
89
90 ASSERT_THAT_EXPECTED(MaybeServer, Failed());
91 llvm::Error Err = MaybeServer.takeError();
92 llvm::handleAllErrors(E: std::move(Err), Handlers: [&](const llvm::StringError &SE) {
93 std::error_code EC = SE.convertToErrorCode();
94 ASSERT_EQ(EC, std::errc::timed_out);
95 });
96}
97
98TEST(raw_socket_streamTest, FILE_DESCRIPTOR_CLOSED) {
99 if (!hasUnixSocketSupport())
100 GTEST_SKIP();
101
102 SmallString<100> SocketPath;
103 llvm::sys::fs::createUniquePath(Model: "fd_closed.sock", ResultPath&: SocketPath, MakeAbsolute: true);
104
105 // Make sure socket file does not exist. May still be there from the last test
106 std::remove(filename: SocketPath.c_str());
107
108 Expected<ListeningSocket> MaybeServerListener =
109 ListeningSocket::createUnix(SocketPath);
110 ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded());
111 ListeningSocket ServerListener = std::move(*MaybeServerListener);
112
113 // Create a separate thread to close the socket after a delay. Simulates a
114 // signal handler calling ServerListener::shutdown
115 std::thread CloseThread([&]() {
116 std::this_thread::sleep_for(rtime: std::chrono::milliseconds(500));
117 ServerListener.shutdown();
118 });
119
120 Expected<std::unique_ptr<raw_socket_stream>> MaybeServer =
121 ServerListener.accept();
122
123 // Wait for the CloseThread to finish
124 CloseThread.join();
125
126 ASSERT_THAT_EXPECTED(MaybeServer, Failed());
127 llvm::Error Err = MaybeServer.takeError();
128 llvm::handleAllErrors(E: std::move(Err), Handlers: [&](const llvm::StringError &SE) {
129 std::error_code EC = SE.convertToErrorCode();
130 ASSERT_EQ(EC, std::errc::operation_canceled);
131 });
132}
133} // namespace
134

source code of llvm/unittests/Support/raw_socket_stream_test.cpp