[Lldb-commits] [lldb] c3193e4 - [lldb/ipv6] Support running lldb tests in an ipv6-only environment.
Jordan Rupprecht via lldb-commits
lldb-commits at lists.llvm.org
Wed Sep 30 11:11:13 PDT 2020
Author: Jordan Rupprecht
Date: 2020-09-30T11:08:41-07:00
New Revision: c3193e464cbd5e8b7cade103032c222bf8bc0e27
URL: https://github.com/llvm/llvm-project/commit/c3193e464cbd5e8b7cade103032c222bf8bc0e27
DIFF: https://github.com/llvm/llvm-project/commit/c3193e464cbd5e8b7cade103032c222bf8bc0e27.diff
LOG: [lldb/ipv6] Support running lldb tests in an ipv6-only environment.
When running in an ipv6-only environment where `AF_INET` sockets are not available, many lldb tests (mostly gdb remote tests) fail because things like `127.0.0.1` don't work there.
Use `localhost` instead of `127.0.0.1` whenever possible, or include a fallback of creating `AF_INET6` sockets when `AF_INET` fails.
Reviewed By: labath
Differential Revision: https://reviews.llvm.org/D87333
Added:
Modified:
lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py
lldb/tools/lldb-server/lldb-gdbserver.cpp
lldb/unittests/Host/SocketTest.cpp
lldb/unittests/Host/SocketTestUtilities.cpp
Removed:
################################################################################
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
index 253fd35d461e..7d7b61c8610d 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
@@ -318,7 +318,13 @@ def _verify_socket(self, sock):
raise _ConnectionRefused() # Got EOF, connection dropped.
def create_socket(self):
- sock = socket.socket()
+ try:
+ sock = socket.socket(family=socket.AF_INET)
+ except OSError as e:
+ if e.errno != errno.EAFNOSUPPORT:
+ raise
+ sock = socket.socket(family=socket.AF_INET6)
+
logger = self.logger
triple = self.dbg.GetSelectedPlatform().GetTriple()
@@ -379,7 +385,7 @@ def get_debug_monitor_command_line_args(self, attach_pid=None):
["*:{}".format(self.port)]
else:
commandline_args = self.debug_monitor_extra_args + \
- ["127.0.0.1:{}".format(self.port)]
+ ["localhost:{}".format(self.port)]
if attach_pid:
commandline_args += ["--attach=%d" % attach_pid]
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 832760f7f0dc..4981345d6a18 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -1234,7 +1234,7 @@ GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client,
const int backlog = 5;
TCPSocket listen_socket(true, child_processes_inherit);
if (llvm::Error error =
- listen_socket.Listen("127.0.0.1:0", backlog).ToError())
+ listen_socket.Listen("localhost:0", backlog).ToError())
return error;
Socket *accept_socket;
@@ -1243,7 +1243,7 @@ GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client,
llvm::SmallString<32> remote_addr;
llvm::raw_svector_ostream(remote_addr)
- << "connect://127.0.0.1:" << listen_socket.GetLocalPortNumber();
+ << "connect://localhost:" << listen_socket.GetLocalPortNumber();
std::unique_ptr<ConnectionFileDescriptor> conn_up(
new ConnectionFileDescriptor());
diff --git a/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py b/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
index eb789e861d9c..dabe9423434d 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
@@ -1,3 +1,4 @@
+import errno
import os
import os.path
import threading
@@ -317,12 +318,20 @@ class MockGDBServer:
def __init__(self, port = 0):
self.responder = MockGDBServerResponder()
self.port = port
- self._socket = socket.socket()
+ try:
+ self._socket = socket.socket(family=socket.AF_INET)
+ except OSError as e:
+ if e.errno != errno.EAFNOSUPPORT:
+ raise
+ self._socket = socket.socket(family=socket.AF_INET6)
def start(self):
# Block until the socket is up, so self.port is available immediately.
# Then start a thread that waits for a client connection.
- addr = ("127.0.0.1", self.port)
+ if self._socket.family == socket.AF_INET:
+ addr = ("127.0.0.1", self.port)
+ elif self._socket.family == socket.AF_INET6:
+ addr = ("::1", self.port)
self._socket.bind(addr)
self.port = self._socket.getsockname()[1]
self._socket.listen(1)
diff --git a/lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py b/lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py
index a3250ab4f1bf..4306f8dcc22d 100644
--- a/lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py
+++ b/lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py
@@ -1,5 +1,6 @@
from __future__ import print_function
+import errno
import gdbremote_testcase
import lldbgdbserverutils
import re
@@ -24,11 +25,20 @@ def setUp(self):
self.listener_port = self.listener_socket.getsockname()[1]
def create_listener_socket(self):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ except OSError as e:
+ if e.errno != errno.EAFNOSUPPORT:
+ raise
+ sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
self.assertIsNotNone(sock)
sock.settimeout(self.DEFAULT_TIMEOUT)
- sock.bind(("127.0.0.1", 0))
+ if sock.family == socket.AF_INET:
+ bind_addr = ("127.0.0.1", 0)
+ elif sock.family == socket.AF_INET6:
+ bind_addr = ("::1", 0)
+ sock.bind(bind_addr)
sock.listen(1)
def tear_down_listener():
diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp
index 5f06503d6424..7f53756424c6 100644
--- a/lldb/tools/lldb-server/lldb-gdbserver.cpp
+++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp
@@ -267,7 +267,8 @@ void ConnectToRemote(MainLoop &mainloop,
final_host_and_port.append("localhost");
final_host_and_port.append(host_and_port);
- const std::string::size_type colon_pos = final_host_and_port.find(':');
+ // Note: use rfind, because the host/port may look like "[::1]:12345".
+ const std::string::size_type colon_pos = final_host_and_port.rfind(':');
if (colon_pos != std::string::npos) {
connection_host = final_host_and_port.substr(0, colon_pos);
connection_port = final_host_and_port.substr(colon_pos + 1);
diff --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp
index c53d2660f0c8..901f878d2e46 100644
--- a/lldb/unittests/Host/SocketTest.cpp
+++ b/lldb/unittests/Host/SocketTest.cpp
@@ -14,12 +14,24 @@
using namespace lldb_private;
-class SocketTest : public testing::Test {
+struct SocketTestParams {
+ bool is_ipv6;
+ std::string localhost_ip;
+};
+
+class SocketTest : public testing::TestWithParam<SocketTestParams> {
public:
SubsystemRAII<Socket> subsystems;
+
+protected:
+ bool HostSupportsProtocol() const {
+ if (GetParam().is_ipv6)
+ return HostSupportsIPv6();
+ return HostSupportsIPv4();
+ }
};
-TEST_F(SocketTest, DecodeHostAndPort) {
+TEST_P(SocketTest, DecodeHostAndPort) {
std::string host_str;
std::string port_str;
int32_t port;
@@ -86,7 +98,7 @@ TEST_F(SocketTest, DecodeHostAndPort) {
}
#if LLDB_ENABLE_POSIX
-TEST_F(SocketTest, DomainListenConnectAccept) {
+TEST_P(SocketTest, DomainListenConnectAccept) {
llvm::SmallString<64> Path;
std::error_code EC = llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
ASSERT_FALSE(EC);
@@ -102,18 +114,22 @@ TEST_F(SocketTest, DomainListenConnectAccept) {
}
#endif
-TEST_F(SocketTest, TCPListen0ConnectAccept) {
+TEST_P(SocketTest, TCPListen0ConnectAccept) {
+ if (!HostSupportsProtocol())
+ return;
std::unique_ptr<TCPSocket> socket_a_up;
std::unique_ptr<TCPSocket> socket_b_up;
- CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
+ CreateTCPConnectedSockets(GetParam().localhost_ip, &socket_a_up,
+ &socket_b_up);
}
-TEST_F(SocketTest, TCPGetAddress) {
+TEST_P(SocketTest, TCPGetAddress) {
std::unique_ptr<TCPSocket> socket_a_up;
std::unique_ptr<TCPSocket> socket_b_up;
- if (!HostSupportsIPv4())
+ if (!HostSupportsProtocol())
return;
- CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
+ CreateTCPConnectedSockets(GetParam().localhost_ip, &socket_a_up,
+ &socket_b_up);
EXPECT_EQ(socket_a_up->GetLocalPortNumber(),
socket_b_up->GetRemotePortNumber());
@@ -121,11 +137,16 @@ TEST_F(SocketTest, TCPGetAddress) {
socket_a_up->GetRemotePortNumber());
EXPECT_NE(socket_a_up->GetLocalPortNumber(),
socket_b_up->GetLocalPortNumber());
- EXPECT_STREQ("127.0.0.1", socket_a_up->GetRemoteIPAddress().c_str());
- EXPECT_STREQ("127.0.0.1", socket_b_up->GetRemoteIPAddress().c_str());
+ EXPECT_STREQ(GetParam().localhost_ip.c_str(),
+ socket_a_up->GetRemoteIPAddress().c_str());
+ EXPECT_STREQ(GetParam().localhost_ip.c_str(),
+ socket_b_up->GetRemoteIPAddress().c_str());
}
-TEST_F(SocketTest, UDPConnect) {
+TEST_P(SocketTest, UDPConnect) {
+ // UDPSocket::Connect() creates sockets with AF_INET (IPv4).
+ if (!HostSupportsIPv4())
+ return;
llvm::Expected<std::unique_ptr<UDPSocket>> socket =
UDPSocket::Connect("127.0.0.1:0", /*child_processes_inherit=*/false);
@@ -133,7 +154,9 @@ TEST_F(SocketTest, UDPConnect) {
EXPECT_TRUE(socket.get()->IsValid());
}
-TEST_F(SocketTest, TCPListen0GetPort) {
+TEST_P(SocketTest, TCPListen0GetPort) {
+ if (!HostSupportsIPv4())
+ return;
Predicate<uint16_t> port_predicate;
port_predicate.SetValue(0, eBroadcastNever);
llvm::Expected<std::unique_ptr<TCPSocket>> sock =
@@ -143,12 +166,13 @@ TEST_F(SocketTest, TCPListen0GetPort) {
EXPECT_NE(sock.get()->GetLocalPortNumber(), 0);
}
-TEST_F(SocketTest, TCPGetConnectURI) {
+TEST_P(SocketTest, TCPGetConnectURI) {
std::unique_ptr<TCPSocket> socket_a_up;
std::unique_ptr<TCPSocket> socket_b_up;
- if (!HostSupportsIPv4())
+ if (!HostSupportsProtocol())
return;
- CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
+ CreateTCPConnectedSockets(GetParam().localhost_ip, &socket_a_up,
+ &socket_b_up);
llvm::StringRef scheme;
llvm::StringRef hostname;
@@ -160,7 +184,8 @@ TEST_F(SocketTest, TCPGetConnectURI) {
EXPECT_EQ(port, socket_a_up->GetRemotePortNumber());
}
-TEST_F(SocketTest, UDPGetConnectURI) {
+TEST_P(SocketTest, UDPGetConnectURI) {
+ // UDPSocket::Connect() creates sockets with AF_INET (IPv4).
if (!HostSupportsIPv4())
return;
llvm::Expected<std::unique_ptr<UDPSocket>> socket =
@@ -177,7 +202,7 @@ TEST_F(SocketTest, UDPGetConnectURI) {
}
#if LLDB_ENABLE_POSIX
-TEST_F(SocketTest, DomainGetConnectURI) {
+TEST_P(SocketTest, DomainGetConnectURI) {
llvm::SmallString<64> domain_path;
std::error_code EC =
llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", domain_path);
@@ -202,3 +227,13 @@ TEST_F(SocketTest, DomainGetConnectURI) {
EXPECT_EQ(path, domain_path);
}
#endif
+
+INSTANTIATE_TEST_CASE_P(
+ SocketTests, SocketTest,
+ testing::Values(SocketTestParams{/*is_ipv6=*/false,
+ /*localhost_ip=*/"127.0.0.1"},
+ SocketTestParams{/*is_ipv6=*/true, /*localhost_ip=*/"::1"}),
+ // Prints "SocketTests/SocketTest.DecodeHostAndPort/ipv4" etc. in test logs.
+ [](const testing::TestParamInfo<SocketTestParams> &info) {
+ return info.param.is_ipv6 ? "ipv6" : "ipv4";
+ });
diff --git a/lldb/unittests/Host/SocketTestUtilities.cpp b/lldb/unittests/Host/SocketTestUtilities.cpp
index e2006b85115d..3b52a66a09eb 100644
--- a/lldb/unittests/Host/SocketTestUtilities.cpp
+++ b/lldb/unittests/Host/SocketTestUtilities.cpp
@@ -101,13 +101,14 @@ static bool CheckIPSupport(llvm::StringRef Proto, llvm::StringRef Addr) {
"Creating a canary {0} TCP socket failed: {1}.",
Proto, Err)
.str();
- bool HasAddrNotAvail = false;
+ bool HasProtocolError = false;
handleAllErrors(std::move(Err), [&](std::unique_ptr<llvm::ECError> ECErr) {
- if (ECErr->convertToErrorCode() ==
- std::make_error_code(std::errc::address_not_available))
- HasAddrNotAvail = true;
+ std::error_code ec = ECErr->convertToErrorCode();
+ if (ec == std::make_error_code(std::errc::address_family_not_supported) ||
+ ec == std::make_error_code(std::errc::address_not_available))
+ HasProtocolError = true;
});
- if (HasAddrNotAvail) {
+ if (HasProtocolError) {
GTEST_LOG_(WARNING)
<< llvm::formatv(
"Assuming the host does not support {0}. Skipping test.", Proto)
More information about the lldb-commits
mailing list