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 <stdlib.h> 11 #include <thread> 12 13 #ifdef _WIN32 14 #include "llvm/Support/Windows/WindowsSupport.h" 15 #endif 16 17 using namespace llvm; 18 19 namespace { 20 21 bool hasUnixSocketSupport() { 22 #ifdef _WIN32 23 VersionTuple Ver = GetWindowsOSVersion(); 24 if (Ver < VersionTuple(10, 0, 0, 17063)) 25 return false; 26 #endif 27 return true; 28 } 29 30 TEST(raw_socket_streamTest, CLIENT_TO_SERVER_AND_SERVER_TO_CLIENT) { 31 if (!hasUnixSocketSupport()) 32 GTEST_SKIP(); 33 34 SmallString<100> SocketPath; 35 llvm::sys::fs::createUniquePath("client_server_comms.sock", SocketPath, true); 36 37 // Make sure socket file does not exist. May still be there from the last test 38 std::remove(SocketPath.c_str()); 39 40 Expected<ListeningSocket> MaybeServerListener = 41 ListeningSocket::createUnix(SocketPath); 42 ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded()); 43 44 ListeningSocket ServerListener = std::move(*MaybeServerListener); 45 46 Expected<std::unique_ptr<raw_socket_stream>> MaybeClient = 47 raw_socket_stream::createConnectedUnix(SocketPath); 48 ASSERT_THAT_EXPECTED(MaybeClient, llvm::Succeeded()); 49 50 raw_socket_stream &Client = **MaybeClient; 51 52 Expected<std::unique_ptr<raw_socket_stream>> MaybeServer = 53 ServerListener.accept(); 54 ASSERT_THAT_EXPECTED(MaybeServer, llvm::Succeeded()); 55 56 raw_socket_stream &Server = **MaybeServer; 57 58 Client << "01234567"; 59 Client.flush(); 60 61 char Bytes[8]; 62 ssize_t BytesRead = Server.read(Bytes, 8); 63 64 std::string string(Bytes, 8); 65 ASSERT_EQ(Server.has_error(), false); 66 67 ASSERT_EQ(8, BytesRead); 68 ASSERT_EQ("01234567", string); 69 } 70 71 TEST(raw_socket_streamTest, READ_WITH_TIMEOUT) { 72 if (!hasUnixSocketSupport()) 73 GTEST_SKIP(); 74 75 SmallString<100> SocketPath; 76 llvm::sys::fs::createUniquePath("read_with_timeout.sock", SocketPath, true); 77 78 // Make sure socket file does not exist. May still be there from the last test 79 std::remove(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 Expected<std::unique_ptr<raw_socket_stream>> MaybeClient = 87 raw_socket_stream::createConnectedUnix(SocketPath); 88 ASSERT_THAT_EXPECTED(MaybeClient, llvm::Succeeded()); 89 90 Expected<std::unique_ptr<raw_socket_stream>> MaybeServer = 91 ServerListener.accept(); 92 ASSERT_THAT_EXPECTED(MaybeServer, llvm::Succeeded()); 93 raw_socket_stream &Server = **MaybeServer; 94 95 char Bytes[8]; 96 ssize_t BytesRead = Server.read(Bytes, 8, std::chrono::milliseconds(100)); 97 ASSERT_EQ(BytesRead, -1); 98 ASSERT_EQ(Server.has_error(), true); 99 ASSERT_EQ(Server.error(), std::errc::timed_out); 100 Server.clear_error(); 101 } 102 103 TEST(raw_socket_streamTest, ACCEPT_WITH_TIMEOUT) { 104 if (!hasUnixSocketSupport()) 105 GTEST_SKIP(); 106 107 SmallString<100> SocketPath; 108 llvm::sys::fs::createUniquePath("accept_with_timeout.sock", SocketPath, true); 109 110 // Make sure socket file does not exist. May still be there from the last test 111 std::remove(SocketPath.c_str()); 112 113 Expected<ListeningSocket> MaybeServerListener = 114 ListeningSocket::createUnix(SocketPath); 115 ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded()); 116 ListeningSocket ServerListener = std::move(*MaybeServerListener); 117 118 Expected<std::unique_ptr<raw_socket_stream>> MaybeServer = 119 ServerListener.accept(std::chrono::milliseconds(100)); 120 ASSERT_EQ(llvm::errorToErrorCode(MaybeServer.takeError()), 121 std::errc::timed_out); 122 } 123 124 TEST(raw_socket_streamTest, ACCEPT_WITH_SHUTDOWN) { 125 if (!hasUnixSocketSupport()) 126 GTEST_SKIP(); 127 128 SmallString<100> SocketPath; 129 llvm::sys::fs::createUniquePath("accept_with_shutdown.sock", SocketPath, 130 true); 131 132 // Make sure socket file does not exist. May still be there from the last test 133 std::remove(SocketPath.c_str()); 134 135 Expected<ListeningSocket> MaybeServerListener = 136 ListeningSocket::createUnix(SocketPath); 137 ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded()); 138 ListeningSocket ServerListener = std::move(*MaybeServerListener); 139 140 // Create a separate thread to close the socket after a delay. Simulates a 141 // signal handler calling ServerListener::shutdown 142 std::thread CloseThread([&]() { 143 std::this_thread::sleep_for(std::chrono::milliseconds(500)); 144 ServerListener.shutdown(); 145 }); 146 147 Expected<std::unique_ptr<raw_socket_stream>> MaybeServer = 148 ServerListener.accept(); 149 150 // Wait for the CloseThread to finish 151 CloseThread.join(); 152 ASSERT_EQ(llvm::errorToErrorCode(MaybeServer.takeError()), 153 std::errc::operation_canceled); 154 } 155 } // namespace 156