From 814b989e7103cf62ead37ac7f41c277b6d5564c7 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Thu, 10 Sep 2015 20:21:30 -0700 Subject: [PATCH] Fix Build: IPv6: SocketAddressTest.SetFromStrings and AsyncSocketTest.ConnectTimeout failing Summary: [Folly] Fix Build: IPv6: `SocketAddressTest.SetFromStrings` and `AsyncSocketTest.ConnectTimeout` failing On IPv6-only machines, the `SocketAddressTest.SetFromStrings` example in `folly/test/SocketAddressTest.cpp` was failing because it tries to resolve `127.0.0.1` with `AI_ADDRCONFIG` set. Fix it by detecting which of IPv6 and IPv4 are enabled, and picking an appropriate loopback address. On IPv6-only machines, the `AsyncSocketTest.ConnectTimeout` example in `folly/io/async/test/AsyncSocketTest2.cpp` was failing because it tries to connect `8.8.8.8`, which is IPv4. Fix it by detecting which of IPv6 and IPv4 are enabled, and picking an approprate remote address. Reviewed By: @chipturner Differential Revision: D2429109 --- folly/io/async/test/AsyncSocketTest2.cpp | 9 +++- folly/test/SocketAddressTest.cpp | 15 +++++-- folly/test/SocketAddressTestHelper.cpp | 52 ++++++++++++++++++++++++ folly/test/SocketAddressTestHelper.h | 47 +++++++++++++++++++++ 4 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 folly/test/SocketAddressTestHelper.cpp create mode 100644 folly/test/SocketAddressTestHelper.h diff --git a/folly/io/async/test/AsyncSocketTest2.cpp b/folly/io/async/test/AsyncSocketTest2.cpp index 0cdf0876..66edf663 100644 --- a/folly/io/async/test/AsyncSocketTest2.cpp +++ b/folly/io/async/test/AsyncSocketTest2.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -130,7 +131,13 @@ TEST(AsyncSocketTest, ConnectTimeout) { // Hopefully this IP will be routable but unresponsive. // (Alternatively, we could try listening on a local raw socket, but that // normally requires root privileges.) - folly::SocketAddress addr("8.8.8.8", 65535); + auto host = + SocketAddressTestHelper::isIPv6Enabled() ? + SocketAddressTestHelper::kGooglePublicDnsAAddrIPv6 : + SocketAddressTestHelper::isIPv4Enabled() ? + SocketAddressTestHelper::kGooglePublicDnsAAddrIPv4 : + nullptr; + SocketAddress addr(host, 65535); ConnCallback cb; socket->connect(&cb, addr, 1); // also set a ridiculously small timeout diff --git a/folly/test/SocketAddressTest.cpp b/folly/test/SocketAddressTest.cpp index 5125cc37..8a831aa0 100644 --- a/folly/test/SocketAddressTest.cpp +++ b/folly/test/SocketAddressTest.cpp @@ -19,12 +19,14 @@ #include #include #include +#include using namespace boost; using std::string; using std::cerr; using std::endl; using folly::SocketAddress; +using folly::SocketAddressTestHelper; TEST(SocketAddress, Size) { SocketAddress addr; @@ -138,9 +140,16 @@ TEST(SocketAddress, SetFromStrings) { EXPECT_EQ(addr.getPort(), 80); // Call setFromLocalIpPort() with an IP and port. - addr.setFromLocalIpPort("127.0.0.1:4321"); - EXPECT_EQ(addr.getAddressStr(), "127.0.0.1"); - EXPECT_EQ(addr.getPort(), 4321); + if (SocketAddressTestHelper::isIPv4Enabled()) { + addr.setFromLocalIpPort("127.0.0.1:4321"); + EXPECT_EQ(addr.getAddressStr(), "127.0.0.1"); + EXPECT_EQ(addr.getPort(), 4321); + } + if (SocketAddressTestHelper::isIPv6Enabled()) { + addr.setFromLocalIpPort("::1:4321"); + EXPECT_EQ(addr.getAddressStr(), "::1"); + EXPECT_EQ(addr.getPort(), 4321); + } // setFromIpPort() without an address should fail EXPECT_THROW(addr.setFromIpPort("4321"), std::invalid_argument); diff --git a/folly/test/SocketAddressTestHelper.cpp b/folly/test/SocketAddressTestHelper.cpp new file mode 100644 index 00000000..d24eb0b6 --- /dev/null +++ b/folly/test/SocketAddressTestHelper.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2015 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +namespace folly { + +constexpr const char* SocketAddressTestHelper::kLoopbackAddrIPv4; +constexpr const char* SocketAddressTestHelper::kLoopbackAddrIPv6; +constexpr const char* SocketAddressTestHelper::kGooglePublicDnsAName; +constexpr const char* SocketAddressTestHelper::kGooglePublicDnsBName; +constexpr const char* SocketAddressTestHelper::kGooglePublicDnsAAddrIPv4; +constexpr const char* SocketAddressTestHelper::kGooglePublicDnsBAddrIPv4; +constexpr const char* SocketAddressTestHelper::kGooglePublicDnsAAddrIPv6; +constexpr const char* SocketAddressTestHelper::kGooglePublicDnsBAddrIPv6; + +bool SocketAddressTestHelper::isIPv4Enabled() { + return isFamilyOfAddrEnabled(kLoopbackAddrIPv4); +} + +bool SocketAddressTestHelper::isIPv6Enabled() { + return isFamilyOfAddrEnabled(kLoopbackAddrIPv6); +} + +bool SocketAddressTestHelper::isFamilyOfAddrEnabled(const char* addr) { + struct addrinfo hints {}; + hints.ai_flags = AI_ADDRCONFIG; + + struct addrinfo* resultsp = nullptr; + int err = getaddrinfo(addr, nullptr, &hints, &resultsp); + freeaddrinfo(resultsp); + return !err; +} + +} diff --git a/folly/test/SocketAddressTestHelper.h b/folly/test/SocketAddressTestHelper.h new file mode 100644 index 00000000..fd133e21 --- /dev/null +++ b/folly/test/SocketAddressTestHelper.h @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace folly { + +class SocketAddressTestHelper { + public: + + static constexpr const char* kLoopbackAddrIPv4 = "127.0.0.1"; + static constexpr const char* kLoopbackAddrIPv6 = "::1"; + + // https://developers.google.com/speed/public-dns/docs/using?hl=en + static constexpr const char* kGooglePublicDnsAName = + "google-public-dns-a.google.com"; + static constexpr const char* kGooglePublicDnsBName = + "google-public-dns-b.google.com"; + static constexpr const char* kGooglePublicDnsAAddrIPv4 = "8.8.8.8"; + static constexpr const char* kGooglePublicDnsBAddrIPv4 = "8.8.4.4"; + static constexpr const char* kGooglePublicDnsAAddrIPv6 = + "2001:4860:4860::8888"; + static constexpr const char* kGooglePublicDnsBAddrIPv6 = + "2001:4860:4860::8844"; + + static bool isIPv4Enabled(); + static bool isIPv6Enabled(); + + private: + + static bool isFamilyOfAddrEnabled(const char* addr); +}; + +} -- 2.34.1