xref: /llvm-project/lldb/unittests/debugserver/RNBSocketTest.cpp (revision 1c7e4074b1efe7c3c9110f1d116b16f50fce9c88)
1 //===-- RNBSocketTest.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 "gtest/gtest.h"
10 
11 #include <arpa/inet.h>
12 #include <sys/sysctl.h>
13 #include <unistd.h>
14 
15 #include "RNBDefs.h"
16 #include "RNBSocket.h"
17 #include "lldb/Host/Socket.h"
18 #include "lldb/Host/common/TCPSocket.h"
19 #include "llvm/Testing/Support/Error.h"
20 
21 using namespace lldb_private;
22 
23 std::string hello = "Hello, world!";
24 std::string goodbye = "Goodbye!";
25 
26 static void ServerCallbackv4(const void *baton, in_port_t port) {
27   auto child_pid = fork();
28   if (child_pid == 0) {
29     std::string addr_buffer =
30         llvm::formatv("{0}:{1}", (const char *)baton, port).str();
31     llvm::Expected<std::unique_ptr<Socket>> socket_or_err =
32         Socket::TcpConnect(addr_buffer);
33     ASSERT_THAT_EXPECTED(socket_or_err, llvm::Succeeded());
34     Socket *client_socket = socket_or_err->get();
35 
36     char buffer[32];
37     size_t read_size = 32;
38     Status err = client_socket->Read((void *)&buffer[0], read_size);
39     if (err.Fail())
40       abort();
41     std::string Recv(&buffer[0], read_size);
42     if (Recv != hello)
43       abort();
44     size_t write_size = goodbye.length();
45     err = client_socket->Write(goodbye.c_str(), write_size);
46     if (err.Fail())
47       abort();
48     if (write_size != goodbye.length())
49       abort();
50     delete client_socket;
51     exit(0);
52   }
53 }
54 
55 void TestSocketListen(const char *addr) {
56   // Skip IPv6 tests if there isn't a valid interafce
57   auto addresses = lldb_private::SocketAddress::GetAddressInfo(
58       addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
59   if (addresses.size() == 0)
60     return;
61 
62   const char *fmt = addresses.front().GetFamily() == AF_INET6 ? "[{0}]" : "{0}";
63   std::string addr_wrap = llvm::formatv(fmt, addr).str();
64 
65   RNBSocket server_socket;
66   auto result = server_socket.Listen(addr, 0, ServerCallbackv4,
67                                      (const void *)addr_wrap.c_str());
68   ASSERT_TRUE(result == rnb_success);
69   result = server_socket.Write(hello.c_str(), hello.length());
70   ASSERT_TRUE(result == rnb_success);
71   std::string bye;
72   result = server_socket.Read(bye);
73   ASSERT_TRUE(result == rnb_success);
74   ASSERT_EQ(bye, goodbye);
75 
76   int exit_status;
77   wait(&exit_status);
78   ASSERT_EQ(exit_status, 0);
79 }
80 
81 TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); }
82 
83 TEST(RNBSocket, LoopBackListenIPv6) { TestSocketListen("::1"); }
84 
85 TEST(RNBSocket, AnyListen) { TestSocketListen("*"); }
86 
87 void TestSocketConnect(const char *addr) {
88   // Skip IPv6 tests if there isn't a valid interafce
89   auto addresses = lldb_private::SocketAddress::GetAddressInfo(
90       addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
91   if (addresses.size() == 0)
92     return;
93 
94   const char *fmt =
95       addresses.front().GetFamily() == AF_INET6 ? "[{0}]:0" : "{0}:0";
96   std::string addr_wrap = llvm::formatv(fmt, addr).str();
97 
98   Socket *server_socket;
99   llvm::Expected<std::unique_ptr<Socket>> socket_or_err =
100       Socket::TcpListen(addr_wrap, false);
101   ASSERT_THAT_EXPECTED(socket_or_err, llvm::Succeeded());
102   server_socket = socket_or_err->get();
103 
104   auto port = ((TCPSocket *)server_socket)->GetLocalPortNumber();
105   auto child_pid = fork();
106   if (child_pid != 0) {
107     RNBSocket client_socket;
108     auto result = client_socket.Connect(addr, port);
109     ASSERT_TRUE(result == rnb_success);
110     result = client_socket.Write(hello.c_str(), hello.length());
111     ASSERT_TRUE(result == rnb_success);
112     std::string bye;
113     result = client_socket.Read(bye);
114     ASSERT_TRUE(result == rnb_success);
115     ASSERT_EQ(bye, goodbye);
116   } else {
117     Socket *connected_socket;
118     Status err =
119         server_socket->Accept(std::chrono::seconds(10), connected_socket);
120     if (err.Fail()) {
121       llvm::errs() << err.AsCString();
122       abort();
123     }
124     char buffer[32];
125     size_t read_size = 32;
126     err = connected_socket->Read((void *)&buffer[0], read_size);
127     if (err.Fail()) {
128       llvm::errs() << err.AsCString();
129       abort();
130     }
131     std::string Recv(&buffer[0], read_size);
132     if (Recv != hello) {
133       llvm::errs() << err.AsCString();
134       abort();
135     }
136     size_t write_size = goodbye.length();
137     err = connected_socket->Write(goodbye.c_str(), write_size);
138     if (err.Fail()) {
139       llvm::errs() << err.AsCString();
140       abort();
141     }
142     if (write_size != goodbye.length()) {
143       llvm::errs() << err.AsCString();
144       abort();
145     }
146     exit(0);
147   }
148   int exit_status;
149   wait(&exit_status);
150   ASSERT_EQ(exit_status, 0);
151 }
152 
153 TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); }
154 
155 TEST(RNBSocket, LoopBackConnectIPv6) { TestSocketConnect("::1"); }
156