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 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits