1a5ffabceScriis #include "llvm/ADT/SmallString.h" 2a5ffabceScriis #include "llvm/Config/llvm-config.h" 3a5ffabceScriis #include "llvm/Support/Casting.h" 4a5ffabceScriis #include "llvm/Support/FileSystem.h" 5a5ffabceScriis #include "llvm/Support/FileUtilities.h" 6c0d5d36dScriis #include "llvm/Support/raw_socket_stream.h" 7a5ffabceScriis #include "llvm/Testing/Support/Error.h" 8a5ffabceScriis #include "gtest/gtest.h" 9a5ffabceScriis #include <future> 10a5ffabceScriis #include <stdlib.h> 1187e6f87fSConnor Sughrue #include <thread> 12a5ffabceScriis 13d7aee330SMichael Spencer #ifdef _WIN32 14d7aee330SMichael Spencer #include "llvm/Support/Windows/WindowsSupport.h" 15d7aee330SMichael Spencer #endif 16d7aee330SMichael Spencer 17a5ffabceScriis using namespace llvm; 18a5ffabceScriis 19a5ffabceScriis namespace { 20a5ffabceScriis 21d7aee330SMichael Spencer bool hasUnixSocketSupport() { 22d7aee330SMichael Spencer #ifdef _WIN32 23d7aee330SMichael Spencer VersionTuple Ver = GetWindowsOSVersion(); 24d7aee330SMichael Spencer if (Ver < VersionTuple(10, 0, 0, 17063)) 25d7aee330SMichael Spencer return false; 26d7aee330SMichael Spencer #endif 27d7aee330SMichael Spencer return true; 28d7aee330SMichael Spencer } 29d7aee330SMichael Spencer 30a5ffabceScriis TEST(raw_socket_streamTest, CLIENT_TO_SERVER_AND_SERVER_TO_CLIENT) { 31d7aee330SMichael Spencer if (!hasUnixSocketSupport()) 32d7aee330SMichael Spencer GTEST_SKIP(); 33d7aee330SMichael Spencer 34a5ffabceScriis SmallString<100> SocketPath; 3587e6f87fSConnor Sughrue llvm::sys::fs::createUniquePath("client_server_comms.sock", SocketPath, true); 36a5ffabceScriis 3787e6f87fSConnor Sughrue // Make sure socket file does not exist. May still be there from the last test 3887e6f87fSConnor Sughrue std::remove(SocketPath.c_str()); 39a5ffabceScriis 40a5ffabceScriis Expected<ListeningSocket> MaybeServerListener = 41a5ffabceScriis ListeningSocket::createUnix(SocketPath); 42a5ffabceScriis ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded()); 43a5ffabceScriis 44a5ffabceScriis ListeningSocket ServerListener = std::move(*MaybeServerListener); 45a5ffabceScriis 46a5ffabceScriis Expected<std::unique_ptr<raw_socket_stream>> MaybeClient = 47a5ffabceScriis raw_socket_stream::createConnectedUnix(SocketPath); 48a5ffabceScriis ASSERT_THAT_EXPECTED(MaybeClient, llvm::Succeeded()); 49a5ffabceScriis 50a5ffabceScriis raw_socket_stream &Client = **MaybeClient; 51a5ffabceScriis 52a5ffabceScriis Expected<std::unique_ptr<raw_socket_stream>> MaybeServer = 53a5ffabceScriis ServerListener.accept(); 54a5ffabceScriis ASSERT_THAT_EXPECTED(MaybeServer, llvm::Succeeded()); 55a5ffabceScriis 56a5ffabceScriis raw_socket_stream &Server = **MaybeServer; 57a5ffabceScriis 58a5ffabceScriis Client << "01234567"; 59a5ffabceScriis Client.flush(); 60a5ffabceScriis 6187e6f87fSConnor Sughrue char Bytes[8]; 62a5ffabceScriis ssize_t BytesRead = Server.read(Bytes, 8); 63a5ffabceScriis 64a5ffabceScriis std::string string(Bytes, 8); 65*76321b9fSConnor Sughrue ASSERT_EQ(Server.has_error(), false); 66a5ffabceScriis 67a5ffabceScriis ASSERT_EQ(8, BytesRead); 68a5ffabceScriis ASSERT_EQ("01234567", string); 69a5ffabceScriis } 7087e6f87fSConnor Sughrue 71*76321b9fSConnor Sughrue TEST(raw_socket_streamTest, READ_WITH_TIMEOUT) { 7287e6f87fSConnor Sughrue if (!hasUnixSocketSupport()) 7387e6f87fSConnor Sughrue GTEST_SKIP(); 7487e6f87fSConnor Sughrue 7587e6f87fSConnor Sughrue SmallString<100> SocketPath; 76*76321b9fSConnor Sughrue llvm::sys::fs::createUniquePath("read_with_timeout.sock", SocketPath, true); 7787e6f87fSConnor Sughrue 7887e6f87fSConnor Sughrue // Make sure socket file does not exist. May still be there from the last test 7987e6f87fSConnor Sughrue std::remove(SocketPath.c_str()); 8087e6f87fSConnor Sughrue 8187e6f87fSConnor Sughrue Expected<ListeningSocket> MaybeServerListener = 8287e6f87fSConnor Sughrue ListeningSocket::createUnix(SocketPath); 8387e6f87fSConnor Sughrue ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded()); 8487e6f87fSConnor Sughrue ListeningSocket ServerListener = std::move(*MaybeServerListener); 8587e6f87fSConnor Sughrue 86*76321b9fSConnor Sughrue Expected<std::unique_ptr<raw_socket_stream>> MaybeClient = 87*76321b9fSConnor Sughrue raw_socket_stream::createConnectedUnix(SocketPath); 88*76321b9fSConnor Sughrue ASSERT_THAT_EXPECTED(MaybeClient, llvm::Succeeded()); 89*76321b9fSConnor Sughrue 9087e6f87fSConnor Sughrue Expected<std::unique_ptr<raw_socket_stream>> MaybeServer = 91*76321b9fSConnor Sughrue ServerListener.accept(); 92*76321b9fSConnor Sughrue ASSERT_THAT_EXPECTED(MaybeServer, llvm::Succeeded()); 93*76321b9fSConnor Sughrue raw_socket_stream &Server = **MaybeServer; 94*76321b9fSConnor Sughrue 95*76321b9fSConnor Sughrue char Bytes[8]; 96*76321b9fSConnor Sughrue ssize_t BytesRead = Server.read(Bytes, 8, std::chrono::milliseconds(100)); 97*76321b9fSConnor Sughrue ASSERT_EQ(BytesRead, -1); 98*76321b9fSConnor Sughrue ASSERT_EQ(Server.has_error(), true); 99*76321b9fSConnor Sughrue ASSERT_EQ(Server.error(), std::errc::timed_out); 100*76321b9fSConnor Sughrue Server.clear_error(); 10187e6f87fSConnor Sughrue } 10287e6f87fSConnor Sughrue 103*76321b9fSConnor Sughrue TEST(raw_socket_streamTest, ACCEPT_WITH_TIMEOUT) { 10487e6f87fSConnor Sughrue if (!hasUnixSocketSupport()) 10587e6f87fSConnor Sughrue GTEST_SKIP(); 10687e6f87fSConnor Sughrue 10787e6f87fSConnor Sughrue SmallString<100> SocketPath; 108*76321b9fSConnor Sughrue llvm::sys::fs::createUniquePath("accept_with_timeout.sock", SocketPath, true); 109*76321b9fSConnor Sughrue 110*76321b9fSConnor Sughrue // Make sure socket file does not exist. May still be there from the last test 111*76321b9fSConnor Sughrue std::remove(SocketPath.c_str()); 112*76321b9fSConnor Sughrue 113*76321b9fSConnor Sughrue Expected<ListeningSocket> MaybeServerListener = 114*76321b9fSConnor Sughrue ListeningSocket::createUnix(SocketPath); 115*76321b9fSConnor Sughrue ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded()); 116*76321b9fSConnor Sughrue ListeningSocket ServerListener = std::move(*MaybeServerListener); 117*76321b9fSConnor Sughrue 118*76321b9fSConnor Sughrue Expected<std::unique_ptr<raw_socket_stream>> MaybeServer = 119*76321b9fSConnor Sughrue ServerListener.accept(std::chrono::milliseconds(100)); 120*76321b9fSConnor Sughrue ASSERT_EQ(llvm::errorToErrorCode(MaybeServer.takeError()), 121*76321b9fSConnor Sughrue std::errc::timed_out); 122*76321b9fSConnor Sughrue } 123*76321b9fSConnor Sughrue 124*76321b9fSConnor Sughrue TEST(raw_socket_streamTest, ACCEPT_WITH_SHUTDOWN) { 125*76321b9fSConnor Sughrue if (!hasUnixSocketSupport()) 126*76321b9fSConnor Sughrue GTEST_SKIP(); 127*76321b9fSConnor Sughrue 128*76321b9fSConnor Sughrue SmallString<100> SocketPath; 129*76321b9fSConnor Sughrue llvm::sys::fs::createUniquePath("accept_with_shutdown.sock", SocketPath, 130*76321b9fSConnor Sughrue true); 13187e6f87fSConnor Sughrue 13287e6f87fSConnor Sughrue // Make sure socket file does not exist. May still be there from the last test 13387e6f87fSConnor Sughrue std::remove(SocketPath.c_str()); 13487e6f87fSConnor Sughrue 13587e6f87fSConnor Sughrue Expected<ListeningSocket> MaybeServerListener = 13687e6f87fSConnor Sughrue ListeningSocket::createUnix(SocketPath); 13787e6f87fSConnor Sughrue ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded()); 13887e6f87fSConnor Sughrue ListeningSocket ServerListener = std::move(*MaybeServerListener); 13987e6f87fSConnor Sughrue 14087e6f87fSConnor Sughrue // Create a separate thread to close the socket after a delay. Simulates a 14187e6f87fSConnor Sughrue // signal handler calling ServerListener::shutdown 14287e6f87fSConnor Sughrue std::thread CloseThread([&]() { 14387e6f87fSConnor Sughrue std::this_thread::sleep_for(std::chrono::milliseconds(500)); 14487e6f87fSConnor Sughrue ServerListener.shutdown(); 14587e6f87fSConnor Sughrue }); 14687e6f87fSConnor Sughrue 14787e6f87fSConnor Sughrue Expected<std::unique_ptr<raw_socket_stream>> MaybeServer = 14887e6f87fSConnor Sughrue ServerListener.accept(); 14987e6f87fSConnor Sughrue 15087e6f87fSConnor Sughrue // Wait for the CloseThread to finish 15187e6f87fSConnor Sughrue CloseThread.join(); 152203232ffSConnor Sughrue ASSERT_EQ(llvm::errorToErrorCode(MaybeServer.takeError()), 153203232ffSConnor Sughrue std::errc::operation_canceled); 15487e6f87fSConnor Sughrue } 155a5ffabceScriis } // namespace 156