1 //===-- SocketTest.cpp ------------------------------------------*- C++ -*-===//
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 "lldb/Utility/UriParser.h"
11 #include "gtest/gtest.h"
12 
13 using namespace lldb_private;
14 
15 class SocketTest : public testing::Test {
16 public:
17   void SetUp() override {
18     ASSERT_THAT_ERROR(Socket::Initialize(), llvm::Succeeded());
19   }
20 
21   void TearDown() override { Socket::Terminate(); }
22 };
23 
24 TEST_F(SocketTest, DecodeHostAndPort) {
25   std::string host_str;
26   std::string port_str;
27   int32_t port;
28   Status error;
29   EXPECT_TRUE(Socket::DecodeHostAndPort("localhost:1138", host_str, port_str,
30                                         port, &error));
31   EXPECT_STREQ("localhost", host_str.c_str());
32   EXPECT_STREQ("1138", port_str.c_str());
33   EXPECT_EQ(1138, port);
34   EXPECT_TRUE(error.Success());
35 
36   EXPECT_FALSE(Socket::DecodeHostAndPort("google.com:65536", host_str, port_str,
37                                          port, &error));
38   EXPECT_TRUE(error.Fail());
39   EXPECT_STREQ("invalid host:port specification: 'google.com:65536'",
40                error.AsCString());
41 
42   EXPECT_FALSE(Socket::DecodeHostAndPort("google.com:-1138", host_str, port_str,
43                                          port, &error));
44   EXPECT_TRUE(error.Fail());
45   EXPECT_STREQ("invalid host:port specification: 'google.com:-1138'",
46                error.AsCString());
47 
48   EXPECT_FALSE(Socket::DecodeHostAndPort("google.com:65536", host_str, port_str,
49                                          port, &error));
50   EXPECT_TRUE(error.Fail());
51   EXPECT_STREQ("invalid host:port specification: 'google.com:65536'",
52                error.AsCString());
53 
54   EXPECT_TRUE(
55       Socket::DecodeHostAndPort("12345", host_str, port_str, port, &error));
56   EXPECT_STREQ("", host_str.c_str());
57   EXPECT_STREQ("12345", port_str.c_str());
58   EXPECT_EQ(12345, port);
59   EXPECT_TRUE(error.Success());
60 
61   EXPECT_TRUE(
62       Socket::DecodeHostAndPort("*:0", host_str, port_str, port, &error));
63   EXPECT_STREQ("*", host_str.c_str());
64   EXPECT_STREQ("0", port_str.c_str());
65   EXPECT_EQ(0, port);
66   EXPECT_TRUE(error.Success());
67 
68   EXPECT_TRUE(
69       Socket::DecodeHostAndPort("*:65535", host_str, port_str, port, &error));
70   EXPECT_STREQ("*", host_str.c_str());
71   EXPECT_STREQ("65535", port_str.c_str());
72   EXPECT_EQ(65535, port);
73   EXPECT_TRUE(error.Success());
74 
75   EXPECT_TRUE(
76       Socket::DecodeHostAndPort("[::1]:12345", host_str, port_str, port, &error));
77   EXPECT_STREQ("::1", host_str.c_str());
78   EXPECT_STREQ("12345", port_str.c_str());
79   EXPECT_EQ(12345, port);
80   EXPECT_TRUE(error.Success());
81 
82   EXPECT_TRUE(
83       Socket::DecodeHostAndPort("[abcd:12fg:AF58::1]:12345", host_str, port_str, port, &error));
84   EXPECT_STREQ("abcd:12fg:AF58::1", host_str.c_str());
85   EXPECT_STREQ("12345", port_str.c_str());
86   EXPECT_EQ(12345, port);
87   EXPECT_TRUE(error.Success());
88 }
89 
90 #ifndef LLDB_DISABLE_POSIX
91 TEST_F(SocketTest, DomainListenConnectAccept) {
92   llvm::SmallString<64> Path;
93   std::error_code EC = llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
94   ASSERT_FALSE(EC);
95   llvm::sys::path::append(Path, "test");
96   // If this fails, $TMPDIR is too long to hold a domain socket.
97   EXPECT_LE(Path.size(), 107u);
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 #ifndef LLDB_DISABLE_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   // If this fails, $TMPDIR is too long to hold a domain socket.
200   EXPECT_LE(domain_path.size(), 107u);
201 
202   std::unique_ptr<DomainSocket> socket_a_up;
203   std::unique_ptr<DomainSocket> socket_b_up;
204   CreateDomainConnectedSockets(domain_path, &socket_a_up, &socket_b_up);
205 
206   llvm::StringRef scheme;
207   llvm::StringRef hostname;
208   int port;
209   llvm::StringRef path;
210   std::string uri(socket_a_up->GetRemoteConnectionURI());
211   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
212   EXPECT_EQ(scheme, "unix-connect");
213   EXPECT_EQ(path, domain_path);
214 }
215 #endif
216