xref: /llvm-project/llvm/unittests/Support/raw_socket_stream_test.cpp (revision 76321b9f08ef31a2b8ca26f7522aee511a05f7a8)
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