[Lldb-commits] [lldb] 18e96a3 - [lldb/unittests] Skip IPv6 test on systems which don't have IPv6 configured

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Mon Apr 27 08:33:30 PDT 2020


Author: Pavel Labath
Date: 2020-04-27T17:33:20+02:00
New Revision: 18e96a31fe0214eb435e131e6ff585a899694576

URL: https://github.com/llvm/llvm-project/commit/18e96a31fe0214eb435e131e6ff585a899694576
DIFF: https://github.com/llvm/llvm-project/commit/18e96a31fe0214eb435e131e6ff585a899694576.diff

LOG: [lldb/unittests] Skip IPv6 test on systems which don't have IPv6 configured

Sadly IPv6 is still not present anywhere. The test was attempting to
detect&skip such hosts, but the way it did that (essentially, by calling
getaddrinfo) meant that it only detected hosts which have IPv6 support
completely compiled out. It did not do anything about hosts which have
it compiled in, but lack runtime configuration even for the ::1 loopback
address.

This patch changes the detection logic to use a new method. It does it
by attempting to bind a socket to the appropriate loopback address. That
should ensure the hosts loopback interface is fully set up. In an effort
to avoid silently skipping the test on too many hosts, the test is
fairly strict about the kind of error it expects in these cases -- it
will only skip the test when receiving EADDRNOTAVAIL. If we find other
error codes that can be reasonably returned in these situations, we can
add more of them.

The (small) change in TCPSocket.cpp is to ensure that the code correctly
propagates the error received from the OS.

Added: 
    

Modified: 
    lldb/source/Host/common/TCPSocket.cpp
    lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
    lldb/unittests/Host/SocketTest.cpp
    lldb/unittests/Host/SocketTestUtilities.cpp
    lldb/unittests/Host/SocketTestUtilities.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp
index 821574e8d822..76ae7f2bd01c 100644
--- a/lldb/source/Host/common/TCPSocket.cpp
+++ b/lldb/source/Host/common/TCPSocket.cpp
@@ -42,6 +42,16 @@ typedef const void *set_socket_option_arg_type;
 using namespace lldb;
 using namespace lldb_private;
 
+static Status GetLastSocketError() {
+  std::error_code EC;
+#ifdef _WIN32
+  EC = llvm::mapWindowsError(WSAGetLastError());
+#else
+  EC = std::error_code(errno, std::generic_category());
+#endif
+  return EC;
+}
+
 namespace {
 const int kType = SOCK_STREAM;
 }
@@ -192,10 +202,8 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
   for (SocketAddress &address : addresses) {
     int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
                                   m_child_processes_inherit, error);
-    if (error.Fail()) {
-      error.Clear();
+    if (error.Fail())
       continue;
-    }
 
     // enable local address reuse
     int option_value = 1;
@@ -216,6 +224,7 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
       err = ::listen(fd, backlog);
 
     if (-1 == err) {
+      error = GetLastSocketError();
       CLOSE_SOCKET(fd);
       continue;
     }
@@ -228,9 +237,11 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
     m_listen_sockets[fd] = address;
   }
 
-  if (m_listen_sockets.size() == 0)
-    error.SetErrorString("Failed to connect port");
-  return error;
+  if (m_listen_sockets.size() == 0) {
+    assert(error.Fail());
+    return error;
+  }
+  return Status();
 }
 
 void TCPSocket::CloseListenSockets() {

diff  --git a/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp b/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
index 655febc11d14..76c54a96b22e 100644
--- a/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
+++ b/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
@@ -22,11 +22,6 @@ class ConnectionFileDescriptorTest : public testing::Test {
   void TestGetURI(std::string ip) {
     std::unique_ptr<TCPSocket> socket_a_up;
     std::unique_ptr<TCPSocket> socket_b_up;
-    if (!IsAddressFamilySupported(ip)) {
-      GTEST_LOG_(WARNING) << "Skipping test due to missing IPv"
-                          << (IsIPv4(ip) ? "4" : "6") << " support.";
-      return;
-    }
     CreateTCPConnectedSockets(ip, &socket_a_up, &socket_b_up);
     auto socket = socket_a_up.release();
     ConnectionFileDescriptor connection_file_descriptor(socket);
@@ -42,6 +37,14 @@ class ConnectionFileDescriptorTest : public testing::Test {
   }
 };
 
-TEST_F(ConnectionFileDescriptorTest, TCPGetURIv4) { TestGetURI("127.0.0.1"); }
-
-TEST_F(ConnectionFileDescriptorTest, TCPGetURIv6) { TestGetURI("::1"); }
+TEST_F(ConnectionFileDescriptorTest, TCPGetURIv4) {
+  if (!HostSupportsIPv4())
+    return;
+  TestGetURI("127.0.0.1");
+}
+
+TEST_F(ConnectionFileDescriptorTest, TCPGetURIv6) {
+  if (!HostSupportsIPv6())
+    return;
+  TestGetURI("::1");
+}

diff  --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp
index 54548d36956c..c53d2660f0c8 100644
--- a/lldb/unittests/Host/SocketTest.cpp
+++ b/lldb/unittests/Host/SocketTest.cpp
@@ -111,10 +111,8 @@ TEST_F(SocketTest, TCPListen0ConnectAccept) {
 TEST_F(SocketTest, TCPGetAddress) {
   std::unique_ptr<TCPSocket> socket_a_up;
   std::unique_ptr<TCPSocket> socket_b_up;
-  if (!IsAddressFamilySupported("127.0.0.1")) {
-    GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
+  if (!HostSupportsIPv4())
     return;
-  }
   CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
 
   EXPECT_EQ(socket_a_up->GetLocalPortNumber(),
@@ -148,10 +146,8 @@ TEST_F(SocketTest, TCPListen0GetPort) {
 TEST_F(SocketTest, TCPGetConnectURI) {
   std::unique_ptr<TCPSocket> socket_a_up;
   std::unique_ptr<TCPSocket> socket_b_up;
-  if (!IsAddressFamilySupported("127.0.0.1")) {
-    GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
+  if (!HostSupportsIPv4())
     return;
-  }
   CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
 
   llvm::StringRef scheme;
@@ -165,10 +161,8 @@ TEST_F(SocketTest, TCPGetConnectURI) {
 }
 
 TEST_F(SocketTest, UDPGetConnectURI) {
-  if (!IsAddressFamilySupported("127.0.0.1")) {
-    GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
+  if (!HostSupportsIPv4())
     return;
-  }
   llvm::Expected<std::unique_ptr<UDPSocket>> socket =
       UDPSocket::Connect("127.0.0.1:0", /*child_processes_inherit=*/false);
   ASSERT_THAT_EXPECTED(socket, llvm::Succeeded());

diff  --git a/lldb/unittests/Host/SocketTestUtilities.cpp b/lldb/unittests/Host/SocketTestUtilities.cpp
index ab883531bdf2..c56b5f7a7809 100644
--- a/lldb/unittests/Host/SocketTestUtilities.cpp
+++ b/lldb/unittests/Host/SocketTestUtilities.cpp
@@ -91,13 +91,34 @@ void lldb_private::CreateDomainConnectedSockets(
 }
 #endif
 
-bool lldb_private::IsAddressFamilySupported(std::string ip) {
-  auto addresses = lldb_private::SocketAddress::GetAddressInfo(
-      ip.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
-  return addresses.size() > 0;
+static bool CheckIPSupport(llvm::StringRef Proto, llvm::StringRef Addr) {
+  llvm::Expected<std::unique_ptr<TCPSocket>> Sock = Socket::TcpListen(
+      Addr, /*child_processes_inherit=*/false, /*predicate=*/nullptr);
+  if (Sock)
+    return true;
+  llvm::Error Err = Sock.takeError();
+  GTEST_LOG_(WARNING) << llvm::formatv(
+                             "Creating a canary {0} TCP socket failed: {1}.",
+                             Proto, Err)
+                             .str();
+  if (Err.isA<llvm::ECError>() &&
+      errorToErrorCode(std::move(Err)) ==
+          std::make_error_code(std::errc::address_not_available)) {
+    GTEST_LOG_(WARNING)
+        << llvm::formatv(
+               "Assuming the host does not support {0}. Skipping test.", Proto)
+               .str();
+    return false;
+  }
+  consumeError(std::move(Err));
+  GTEST_LOG_(WARNING) << "Continuing anyway. The test will probably fail.";
+  return true;
+}
+
+bool lldb_private::HostSupportsIPv4() {
+  return CheckIPSupport("IPv4", "127.0.0.1:0");
 }
 
-bool lldb_private::IsIPv4(std::string ip) {
-  struct sockaddr_in sock_addr;
-  return inet_pton(AF_INET, ip.c_str(), &(sock_addr.sin_addr)) != 0;
+bool lldb_private::HostSupportsIPv6() {
+  return CheckIPSupport("IPv6", "[::1]:0");
 }

diff  --git a/lldb/unittests/Host/SocketTestUtilities.h b/lldb/unittests/Host/SocketTestUtilities.h
index 356278247541..943d98a96be0 100644
--- a/lldb/unittests/Host/SocketTestUtilities.h
+++ b/lldb/unittests/Host/SocketTestUtilities.h
@@ -40,8 +40,8 @@ void CreateDomainConnectedSockets(llvm::StringRef path,
                                   std::unique_ptr<DomainSocket> *b_up);
 #endif
 
-bool IsAddressFamilySupported(std::string ip);
-bool IsIPv4(std::string ip);
+bool HostSupportsIPv6();
+bool HostSupportsIPv4();
 } // namespace lldb_private
 
-#endif
\ No newline at end of file
+#endif


        


More information about the lldb-commits mailing list