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 
97   std::unique_ptr<DomainSocket> socket_a_up;
98   std::unique_ptr<DomainSocket> socket_b_up;
99   CreateDomainConnectedSockets(Path, &socket_a_up, &socket_b_up);
100 }
101 #endif
102 
103 TEST_F(SocketTest, TCPListen0ConnectAccept) {
104   std::unique_ptr<TCPSocket> socket_a_up;
105   std::unique_ptr<TCPSocket> socket_b_up;
106   CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
107 }
108 
109 TEST_F(SocketTest, TCPGetAddress) {
110   std::unique_ptr<TCPSocket> socket_a_up;
111   std::unique_ptr<TCPSocket> socket_b_up;
112   if (!IsAddressFamilySupported("127.0.0.1")) {
113     GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
114     return;
115   }
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   Socket *socket;
130 
131   bool child_processes_inherit = false;
132   auto error = UDPSocket::Connect("127.0.0.1:0", child_processes_inherit,
133                                   socket);
134 
135   std::unique_ptr<Socket> socket_up(socket);
136 
137   EXPECT_TRUE(error.Success());
138   EXPECT_TRUE(socket_up->IsValid());
139 }
140 
141 TEST_F(SocketTest, TCPListen0GetPort) {
142   Socket *server_socket;
143   Predicate<uint16_t> port_predicate;
144   port_predicate.SetValue(0, eBroadcastNever);
145   Status err =
146       Socket::TcpListen("10.10.12.3:0", false, server_socket, &port_predicate);
147   std::unique_ptr<TCPSocket> socket_up((TCPSocket*)server_socket);
148   EXPECT_TRUE(socket_up->IsValid());
149   EXPECT_NE(socket_up->GetLocalPortNumber(), 0);
150 }
151 
152 TEST_F(SocketTest, TCPGetConnectURI) {
153   std::unique_ptr<TCPSocket> socket_a_up;
154   std::unique_ptr<TCPSocket> socket_b_up;
155   if (!IsAddressFamilySupported("127.0.0.1")) {
156     GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
157     return;
158   }
159   CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
160 
161   llvm::StringRef scheme;
162   llvm::StringRef hostname;
163   int port;
164   llvm::StringRef path;
165   std::string uri(socket_a_up->GetRemoteConnectionURI());
166   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
167   EXPECT_EQ(scheme, "connect");
168   EXPECT_EQ(port, socket_a_up->GetRemotePortNumber());
169 }
170 
171 TEST_F(SocketTest, UDPGetConnectURI) {
172   if (!IsAddressFamilySupported("127.0.0.1")) {
173     GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
174     return;
175   }
176   Socket *socket;
177   bool child_processes_inherit = false;
178   auto error =
179       UDPSocket::Connect("127.0.0.1:0", child_processes_inherit, socket);
180 
181   llvm::StringRef scheme;
182   llvm::StringRef hostname;
183   int port;
184   llvm::StringRef path;
185   std::string uri(socket->GetRemoteConnectionURI());
186   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
187   EXPECT_EQ(scheme, "udp");
188 }
189 
190 #ifndef LLDB_DISABLE_POSIX
191 TEST_F(SocketTest, DomainGetConnectURI) {
192   llvm::SmallString<64> domain_path;
193   std::error_code EC =
194       llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", domain_path);
195   ASSERT_FALSE(EC);
196   llvm::sys::path::append(domain_path, "test");
197 
198   std::unique_ptr<DomainSocket> socket_a_up;
199   std::unique_ptr<DomainSocket> socket_b_up;
200   CreateDomainConnectedSockets(domain_path, &socket_a_up, &socket_b_up);
201 
202   llvm::StringRef scheme;
203   llvm::StringRef hostname;
204   int port;
205   llvm::StringRef path;
206   std::string uri(socket_a_up->GetRemoteConnectionURI());
207   EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
208   EXPECT_EQ(scheme, "unix-connect");
209   EXPECT_EQ(path, domain_path);
210 }
211 #endif