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 (!IsAddressFamilySupported("127.0.0.1")) {
115     GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
116     return;
117   }
118   CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
119 
120   EXPECT_EQ(socket_a_up->GetLocalPortNumber(),
121             socket_b_up->GetRemotePortNumber());
122   EXPECT_EQ(socket_b_up->GetLocalPortNumber(),
123             socket_a_up->GetRemotePortNumber());
124   EXPECT_NE(socket_a_up->GetLocalPortNumber(),
125             socket_b_up->GetLocalPortNumber());
126   EXPECT_STREQ("127.0.0.1", socket_a_up->GetRemoteIPAddress().c_str());
127   EXPECT_STREQ("127.0.0.1", socket_b_up->GetRemoteIPAddress().c_str());
128 }
129 
130 TEST_F(SocketTest, UDPConnect) {
131   Socket *socket;
132 
133   bool child_processes_inherit = false;
134   auto error = UDPSocket::Connect("127.0.0.1:0", child_processes_inherit,
135                                   socket);
136 
137   std::unique_ptr<Socket> socket_up(socket);
138 
139   EXPECT_TRUE(error.Success());
140   EXPECT_TRUE(socket_up->IsValid());
141 }
142 
143 TEST_F(SocketTest, TCPListen0GetPort) {
144   Socket *server_socket;
145   Predicate<uint16_t> port_predicate;
146   port_predicate.SetValue(0, eBroadcastNever);
147   Status err =
148       Socket::TcpListen("10.10.12.3:0", false, server_socket, &port_predicate);
149   std::unique_ptr<TCPSocket> socket_up((TCPSocket*)server_socket);
150   EXPECT_TRUE(socket_up->IsValid());
151   EXPECT_NE(socket_up->GetLocalPortNumber(), 0);
152 }
153 
154 TEST_F(SocketTest, TCPGetConnectURI) {
155   std::unique_ptr<TCPSocket> socket_a_up;
156   std::unique_ptr<TCPSocket> socket_b_up;
157   if (!IsAddressFamilySupported("127.0.0.1")) {
158     GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
159     return;
160   }
161   CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
162 
163   llvm::StringRef scheme;
164   llvm::StringRef hostname;
165   int port;
166   llvm::StringRef path;
167   std::string uri(socket_a_up->GetRemoteConnectionURI());
168   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
169   EXPECT_EQ(scheme, "connect");
170   EXPECT_EQ(port, socket_a_up->GetRemotePortNumber());
171 }
172 
173 TEST_F(SocketTest, UDPGetConnectURI) {
174   if (!IsAddressFamilySupported("127.0.0.1")) {
175     GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
176     return;
177   }
178   Socket *socket;
179   bool child_processes_inherit = false;
180   auto error =
181       UDPSocket::Connect("127.0.0.1:0", child_processes_inherit, socket);
182 
183   llvm::StringRef scheme;
184   llvm::StringRef hostname;
185   int port;
186   llvm::StringRef path;
187   std::string uri(socket->GetRemoteConnectionURI());
188   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
189   EXPECT_EQ(scheme, "udp");
190 }
191 
192 #if LLDB_ENABLE_POSIX
193 TEST_F(SocketTest, DomainGetConnectURI) {
194   llvm::SmallString<64> domain_path;
195   std::error_code EC =
196       llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", domain_path);
197   ASSERT_FALSE(EC);
198   llvm::sys::path::append(domain_path, "test");
199 
200   // Skip the test if the $TMPDIR is too long to hold a domain socket.
201   if (domain_path.size() > 107u)
202     return;
203 
204   std::unique_ptr<DomainSocket> socket_a_up;
205   std::unique_ptr<DomainSocket> socket_b_up;
206   CreateDomainConnectedSockets(domain_path, &socket_a_up, &socket_b_up);
207 
208   llvm::StringRef scheme;
209   llvm::StringRef hostname;
210   int port;
211   llvm::StringRef path;
212   std::string uri(socket_a_up->GetRemoteConnectionURI());
213   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
214   EXPECT_EQ(scheme, "unix-connect");
215   EXPECT_EQ(path, domain_path);
216 }
217 #endif
218