1 //===-- SocketTest.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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "SocketTestUtilities.h"
10 #include "TestingSupport/SubsystemRAII.h"
11 #include "lldb/Host/Config.h"
12 #include "lldb/Utility/UriParser.h"
13 #include "gtest/gtest.h"
14 
15 using namespace lldb_private;
16 
17 class SocketTest : public testing::Test {
18 public:
19   SubsystemRAII<Socket> subsystems;
20 };
21 
22 TEST_F(SocketTest, DecodeHostAndPort) {
23   std::string host_str;
24   std::string port_str;
25   int32_t port;
26   Status error;
27   EXPECT_TRUE(Socket::DecodeHostAndPort("localhost:1138", host_str, port_str,
28                                         port, &error));
29   EXPECT_STREQ("localhost", host_str.c_str());
30   EXPECT_STREQ("1138", port_str.c_str());
31   EXPECT_EQ(1138, port);
32   EXPECT_TRUE(error.Success());
33 
34   EXPECT_FALSE(Socket::DecodeHostAndPort("google.com:65536", host_str, port_str,
35                                          port, &error));
36   EXPECT_TRUE(error.Fail());
37   EXPECT_STREQ("invalid host:port specification: 'google.com:65536'",
38                error.AsCString());
39 
40   EXPECT_FALSE(Socket::DecodeHostAndPort("google.com:-1138", host_str, port_str,
41                                          port, &error));
42   EXPECT_TRUE(error.Fail());
43   EXPECT_STREQ("invalid host:port specification: 'google.com:-1138'",
44                error.AsCString());
45 
46   EXPECT_FALSE(Socket::DecodeHostAndPort("google.com:65536", host_str, port_str,
47                                          port, &error));
48   EXPECT_TRUE(error.Fail());
49   EXPECT_STREQ("invalid host:port specification: 'google.com:65536'",
50                error.AsCString());
51 
52   EXPECT_TRUE(
53       Socket::DecodeHostAndPort("12345", host_str, port_str, port, &error));
54   EXPECT_STREQ("", host_str.c_str());
55   EXPECT_STREQ("12345", port_str.c_str());
56   EXPECT_EQ(12345, port);
57   EXPECT_TRUE(error.Success());
58 
59   EXPECT_TRUE(
60       Socket::DecodeHostAndPort("*:0", host_str, port_str, port, &error));
61   EXPECT_STREQ("*", host_str.c_str());
62   EXPECT_STREQ("0", port_str.c_str());
63   EXPECT_EQ(0, port);
64   EXPECT_TRUE(error.Success());
65 
66   EXPECT_TRUE(
67       Socket::DecodeHostAndPort("*:65535", host_str, port_str, port, &error));
68   EXPECT_STREQ("*", host_str.c_str());
69   EXPECT_STREQ("65535", port_str.c_str());
70   EXPECT_EQ(65535, port);
71   EXPECT_TRUE(error.Success());
72 
73   EXPECT_TRUE(
74       Socket::DecodeHostAndPort("[::1]:12345", host_str, port_str, port, &error));
75   EXPECT_STREQ("::1", host_str.c_str());
76   EXPECT_STREQ("12345", port_str.c_str());
77   EXPECT_EQ(12345, port);
78   EXPECT_TRUE(error.Success());
79 
80   EXPECT_TRUE(
81       Socket::DecodeHostAndPort("[abcd:12fg:AF58::1]:12345", host_str, port_str, port, &error));
82   EXPECT_STREQ("abcd:12fg:AF58::1", host_str.c_str());
83   EXPECT_STREQ("12345", port_str.c_str());
84   EXPECT_EQ(12345, port);
85   EXPECT_TRUE(error.Success());
86 }
87 
88 #if LLDB_ENABLE_POSIX
89 TEST_F(SocketTest, DomainListenConnectAccept) {
90   llvm::SmallString<64> Path;
91   std::error_code EC = llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
92   ASSERT_FALSE(EC);
93   llvm::sys::path::append(Path, "test");
94 
95   // Skip the test if the $TMPDIR is too long to hold a domain socket.
96   if (Path.size() > 107u)
97     return;
98 
99   std::unique_ptr<DomainSocket> socket_a_up;
100   std::unique_ptr<DomainSocket> socket_b_up;
101   CreateDomainConnectedSockets(Path, &socket_a_up, &socket_b_up);
102 }
103 #endif
104 
105 TEST_F(SocketTest, TCPListen0ConnectAccept) {
106   std::unique_ptr<TCPSocket> socket_a_up;
107   std::unique_ptr<TCPSocket> socket_b_up;
108   CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
109 }
110 
111 TEST_F(SocketTest, TCPGetAddress) {
112   std::unique_ptr<TCPSocket> socket_a_up;
113   std::unique_ptr<TCPSocket> socket_b_up;
114   if (!HostSupportsIPv4())
115     return;
116   CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
117 
118   EXPECT_EQ(socket_a_up->GetLocalPortNumber(),
119             socket_b_up->GetRemotePortNumber());
120   EXPECT_EQ(socket_b_up->GetLocalPortNumber(),
121             socket_a_up->GetRemotePortNumber());
122   EXPECT_NE(socket_a_up->GetLocalPortNumber(),
123             socket_b_up->GetLocalPortNumber());
124   EXPECT_STREQ("127.0.0.1", socket_a_up->GetRemoteIPAddress().c_str());
125   EXPECT_STREQ("127.0.0.1", socket_b_up->GetRemoteIPAddress().c_str());
126 }
127 
128 TEST_F(SocketTest, UDPConnect) {
129   llvm::Expected<std::unique_ptr<UDPSocket>> socket =
130       UDPSocket::Connect("127.0.0.1:0", /*child_processes_inherit=*/false);
131 
132   ASSERT_THAT_EXPECTED(socket, llvm::Succeeded());
133   EXPECT_TRUE(socket.get()->IsValid());
134 }
135 
136 TEST_F(SocketTest, TCPListen0GetPort) {
137   Predicate<uint16_t> port_predicate;
138   port_predicate.SetValue(0, eBroadcastNever);
139   llvm::Expected<std::unique_ptr<TCPSocket>> sock =
140       Socket::TcpListen("10.10.12.3:0", false, &port_predicate);
141   ASSERT_THAT_EXPECTED(sock, llvm::Succeeded());
142   ASSERT_TRUE(sock.get()->IsValid());
143   EXPECT_NE(sock.get()->GetLocalPortNumber(), 0);
144 }
145 
146 TEST_F(SocketTest, TCPGetConnectURI) {
147   std::unique_ptr<TCPSocket> socket_a_up;
148   std::unique_ptr<TCPSocket> socket_b_up;
149   if (!HostSupportsIPv4())
150     return;
151   CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
152 
153   llvm::StringRef scheme;
154   llvm::StringRef hostname;
155   int port;
156   llvm::StringRef path;
157   std::string uri(socket_a_up->GetRemoteConnectionURI());
158   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
159   EXPECT_EQ(scheme, "connect");
160   EXPECT_EQ(port, socket_a_up->GetRemotePortNumber());
161 }
162 
163 TEST_F(SocketTest, UDPGetConnectURI) {
164   if (!HostSupportsIPv4())
165     return;
166   llvm::Expected<std::unique_ptr<UDPSocket>> socket =
167       UDPSocket::Connect("127.0.0.1:0", /*child_processes_inherit=*/false);
168   ASSERT_THAT_EXPECTED(socket, llvm::Succeeded());
169 
170   llvm::StringRef scheme;
171   llvm::StringRef hostname;
172   int port;
173   llvm::StringRef path;
174   std::string uri = socket.get()->GetRemoteConnectionURI();
175   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
176   EXPECT_EQ(scheme, "udp");
177 }
178 
179 #if LLDB_ENABLE_POSIX
180 TEST_F(SocketTest, DomainGetConnectURI) {
181   llvm::SmallString<64> domain_path;
182   std::error_code EC =
183       llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", domain_path);
184   ASSERT_FALSE(EC);
185   llvm::sys::path::append(domain_path, "test");
186 
187   // Skip the test if the $TMPDIR is too long to hold a domain socket.
188   if (domain_path.size() > 107u)
189     return;
190 
191   std::unique_ptr<DomainSocket> socket_a_up;
192   std::unique_ptr<DomainSocket> socket_b_up;
193   CreateDomainConnectedSockets(domain_path, &socket_a_up, &socket_b_up);
194 
195   llvm::StringRef scheme;
196   llvm::StringRef hostname;
197   int port;
198   llvm::StringRef path;
199   std::string uri(socket_a_up->GetRemoteConnectionURI());
200   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
201   EXPECT_EQ(scheme, "unix-connect");
202   EXPECT_EQ(path, domain_path);
203 }
204 #endif
205