diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index a527b093..10e43e8d 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -29,7 +29,7 @@ jobs: - name: "CMake: build and test c-ares" env: BUILD_TYPE: CMAKE - CMAKE_TEST_FLAGS: "-DCARES_BUILD_TESTS=ON" + CMAKE_TEST_FLAGS: "-DCARES_BUILD_CONTAINER_TESTS=ON" TEST_DEBUGGER: gdb run: | ./ci/build.sh @@ -46,7 +46,7 @@ jobs: env: BUILD_TYPE: CMAKE CMAKE_FLAGS: "-DCMAKE_BUILD_TYPE=DEBUG -DCARES_STATIC=ON -DCARES_STATIC_PIC=ON -DCARES_THREADS=OFF -G Ninja" - CMAKE_TEST_FLAGS: "-DCARES_BUILD_TESTS=ON" + CMAKE_TEST_FLAGS: "-DCARES_BUILD_CONTAINER_TESTS=ON" TEST_DEBUGGER: gdb run: | ./ci/build.sh @@ -55,7 +55,7 @@ jobs: env: BUILD_TYPE: CMAKE CMAKE_FLAGS: "-DCMAKE_BUILD_TYPE=DEBUG -DCARES_STATIC=OFF -DCARES_SYMBOL_HIDING=ON -G Ninja" - CMAKE_TEST_FLAGS: "-DCARES_BUILD_TESTS=ON" + CMAKE_TEST_FLAGS: "-DCARES_BUILD_CONTAINER_TESTS=ON" TEST_DEBUGGER: gdb run: | ./ci/build.sh @@ -64,7 +64,8 @@ jobs: env: BUILD_TYPE: "ubsan" CC: "clang" - CMAKE_TEST_FLAGS: "-DCARES_BUILD_TESTS=ON" + CXX: "clang++" + CMAKE_TEST_FLAGS: "-DCARES_BUILD_CONTAINER_TESTS=ON" CFLAGS: "-fsanitize=undefined -fno-sanitize-recover" CXXFLAGS: "-fsanitize=undefined -fno-sanitize-recover" LDFLAGS: "-fsanitize=undefined" @@ -76,7 +77,8 @@ jobs: env: BUILD_TYPE: "asan" CC: "clang" - CMAKE_TEST_FLAGS: "-DCARES_BUILD_TESTS=ON" + CXX: "clang++" + CMAKE_TEST_FLAGS: "-DCARES_BUILD_CONTAINER_TESTS=ON" CFLAGS: "-fsanitize=address" CXXFLAGS: "-fsanitize=address" LDFLAGS: "-fsanitize=address" diff --git a/configure.ac b/configure.ac index 14eee048..4a652342 100644 --- a/configure.ac +++ b/configure.ac @@ -153,8 +153,6 @@ _EOF ]) AX_CODE_COVERAGE -AX_CHECK_USER_NAMESPACE -AX_CHECK_UTS_NAMESPACE AC_SYS_LARGEFILE case $host_os in @@ -838,6 +836,12 @@ if test "x$build_tests" != "xno" ; then else AC_MSG_ERROR([tests require gmock]) fi + else + PKG_CHECK_MODULES([GMOCK112], [gmock >= 1.12.0], [ have_gmock_v112=yes ], [ have_gmock_v112=no ]) + if test "x$have_gmock_v112" = "xyes" ; then + AX_CHECK_USER_NAMESPACE + AX_CHECK_UTS_NAMESPACE + fi fi fi if test "x$build_tests" != "xno" ; then diff --git a/src/lib/ares_sysconfig.c b/src/lib/ares_sysconfig.c index 32f8b7f8..4f17b1d4 100644 --- a/src/lib/ares_sysconfig.c +++ b/src/lib/ares_sysconfig.c @@ -1068,6 +1068,7 @@ ares_status_t ares__init_by_sysconfig(ares_channel_t *channel) ares_sysconfig_t sysconfig; memset(&sysconfig, 0, sizeof(sysconfig)); + sysconfig.ndots = 1; /* Default value if not otherwise set */ #if defined(USE_WINSOCK) status = ares__init_sysconfig_windows(&sysconfig); diff --git a/test/ares-test-ai.h b/test/ares-test-ai.h index 95eeb885..f127fae7 100644 --- a/test/ares-test-ai.h +++ b/test/ares-test-ai.h @@ -39,7 +39,7 @@ class MockChannelTestAI public ::testing::WithParamInterface> { public: MockChannelTestAI() - : MockChannelOptsTest(1, GetParam().first, GetParam().second, nullptr, 0) + : MockChannelOptsTest(1, GetParam().first, GetParam().second, false, nullptr, 0) { } }; @@ -47,7 +47,7 @@ public: class MockUDPChannelTestAI : public MockChannelOptsTest, public ::testing::WithParamInterface { public: - MockUDPChannelTestAI() : MockChannelOptsTest(1, GetParam(), false, nullptr, 0) + MockUDPChannelTestAI() : MockChannelOptsTest(1, GetParam(), false, false, nullptr, 0) { } }; @@ -55,7 +55,7 @@ public: class MockTCPChannelTestAI : public MockChannelOptsTest, public ::testing::WithParamInterface { public: - MockTCPChannelTestAI() : MockChannelOptsTest(1, GetParam(), true, nullptr, 0) + MockTCPChannelTestAI() : MockChannelOptsTest(1, GetParam(), true, false, nullptr, 0) { } }; diff --git a/test/ares-test-init.cc b/test/ares-test-init.cc index 4fd5cff6..453848f3 100644 --- a/test/ares-test-init.cc +++ b/test/ares-test-init.cc @@ -417,7 +417,8 @@ CONTAINED_TEST_F(LibraryTest, ContainerChannelInit, CONTAINED_TEST_F(LibraryTest, ContainerSortlistOptionInit, "myhostname", "mydomainname.org", filelist) { ares_channel_t *channel = nullptr; - struct ares_options opts = {0}; + struct ares_options opts; + memset(&opts, 0, sizeof(opts)); int optmask = 0; optmask |= ARES_OPT_SORTLIST; opts.nsort = 0; @@ -461,7 +462,8 @@ CONTAINED_TEST_F(LibraryTest, ContainerMyResolvConfInit, "myhostname", "mydomain.org", myresolvconf) { char filename[] = "/tmp/myresolv.cnf"; ares_channel_t *channel = nullptr; - struct ares_options options = {0}; + struct ares_options options; + memset(&options, 0, sizeof(options)); options.resolvconf_path = strdup(filename); int optmask = ARES_OPT_RESOLVCONF; EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &options, optmask)); @@ -487,11 +489,12 @@ CONTAINED_TEST_F(LibraryTest, ContainerMyHostsInit, "myhostname", "mydomain.org", myhosts) { char filename[] = "/tmp/hosts"; ares_channel_t *channel = nullptr; - struct ares_options options = {0}; + struct ares_options options; + options.hosts_path = strdup(filename); int optmask = ARES_OPT_HOSTS_FILE; EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &options, optmask)); - + memset(&options, 0, sizeof(options)); optmask = 0; free(options.hosts_path); options.hosts_path = NULL; @@ -595,7 +598,8 @@ CONTAINED_TEST_F(LibraryTest, ContainerRotateInit, CONTAINED_TEST_F(LibraryTest, ContainerRotateOverride, "myhostname", "mydomainname.org", rotateenv) { ares_channel_t *channel = nullptr; - struct ares_options opts = {0}; + struct ares_options opts; + memset(&opts, 0, sizeof(opts)); int optmask = ARES_OPT_NOROTATE; EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask)); optmask = 0; @@ -687,7 +691,8 @@ CONTAINED_TEST_F(LibraryTest, ContainerEmptyInit, CONTAINED_TEST_F(LibraryTest, ContainerNoDfltSvrEmptyInit, "myhostname", "mydomainname.org", empty) { ares_channel_t *channel = nullptr; - struct ares_options opts = {0}; + struct ares_options opts; + memset(&opts, 0, sizeof(opts)); int optmask = ARES_OPT_FLAGS; opts.flags = ARES_FLAG_NO_DFLT_SVR; EXPECT_EQ(ARES_ENOSERVER, ares_init_options(&channel, &opts, optmask)); @@ -700,7 +705,8 @@ CONTAINED_TEST_F(LibraryTest, ContainerNoDfltSvrEmptyInit, CONTAINED_TEST_F(LibraryTest, ContainerNoDfltSvrFullInit, "myhostname", "mydomainname.org", filelist) { ares_channel_t *channel = nullptr; - struct ares_options opts = {0}; + struct ares_options opts; + memset(&opts, 0, sizeof(opts)); int optmask = ARES_OPT_FLAGS; opts.flags = ARES_FLAG_NO_DFLT_SVR; EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask)); diff --git a/test/ares-test-mock-ai.cc b/test/ares-test-mock-ai.cc index c9100e51..3cbdd6fa 100644 --- a/test/ares-test-mock-ai.cc +++ b/test/ares-test-mock-ai.cc @@ -263,7 +263,7 @@ class MockExtraOptsTestAI public ::testing::WithParamInterface< std::pair > { public: MockExtraOptsTestAI() - : MockChannelOptsTest(1, GetParam().first, GetParam().second, + : MockChannelOptsTest(1, GetParam().first, GetParam().second, false, FillOptions(&opts_), ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF) {} static struct ares_options* FillOptions(struct ares_options * opts) { @@ -308,7 +308,7 @@ class MockExtraOptsNDotsTestAI public ::testing::WithParamInterface< std::pair > { public: MockExtraOptsNDotsTestAI(int ndots) - : MockChannelOptsTest(1, GetParam().first, GetParam().second, + : MockChannelOptsTest(1, GetParam().first, GetParam().second, false, FillOptions(&opts_, ndots), ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF|ARES_OPT_NDOTS) {} static struct ares_options* FillOptions(struct ares_options * opts, int ndots) { @@ -406,7 +406,7 @@ class MockFlagsChannelOptsTestAI public ::testing::WithParamInterface< std::pair > { public: MockFlagsChannelOptsTestAI(int flags) - : MockChannelOptsTest(1, GetParam().first, GetParam().second, + : MockChannelOptsTest(1, GetParam().first, GetParam().second, false, FillOptions(&opts_, flags), ARES_OPT_FLAGS) {} static struct ares_options* FillOptions(struct ares_options * opts, int flags) { memset(opts, 0, sizeof(struct ares_options)); @@ -701,7 +701,7 @@ class MockMultiServerChannelTestAI public ::testing::WithParamInterface< std::pair > { public: MockMultiServerChannelTestAI(ares_options *opts, int optmask) - : MockChannelOptsTest(3, GetParam().first, GetParam().second, opts, optmask) {} + : MockChannelOptsTest(3, GetParam().first, GetParam().second, false, opts, optmask) {} void CheckExample() { AddrInfoResult result; struct ares_addrinfo_hints hints = {}; diff --git a/test/ares-test-mock.cc b/test/ares-test-mock.cc index 4ef6c29e..ce451ad3 100644 --- a/test/ares-test-mock.cc +++ b/test/ares-test-mock.cc @@ -391,7 +391,7 @@ class MockUDPMaxQueriesTest public ::testing::WithParamInterface { public: MockUDPMaxQueriesTest() - : MockChannelOptsTest(1, GetParam(), false, + : MockChannelOptsTest(1, GetParam(), false, false, FillOptions(&opts_), ARES_OPT_UDP_MAX_QUERIES) {} static struct ares_options* FillOptions(struct ares_options * opts) { @@ -438,7 +438,7 @@ class CacheQueriesTest public ::testing::WithParamInterface { public: CacheQueriesTest() - : MockChannelOptsTest(1, GetParam(), false, + : MockChannelOptsTest(1, GetParam(), false, false, FillOptions(&opts_), ARES_OPT_QUERY_CACHE) {} static struct ares_options* FillOptions(struct ares_options * opts) { @@ -603,7 +603,7 @@ class MockExtraOptsTest public ::testing::WithParamInterface< std::pair > { public: MockExtraOptsTest() - : MockChannelOptsTest(1, GetParam().first, GetParam().second, + : MockChannelOptsTest(1, GetParam().first, GetParam().second, false, FillOptions(&opts_), ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF) {} static struct ares_options* FillOptions(struct ares_options * opts) { @@ -645,7 +645,7 @@ class MockFlagsChannelOptsTest public ::testing::WithParamInterface< std::pair > { public: MockFlagsChannelOptsTest(int flags) - : MockChannelOptsTest(1, GetParam().first, GetParam().second, + : MockChannelOptsTest(1, GetParam().first, GetParam().second, false, FillOptions(&opts_, flags), ARES_OPT_FLAGS) {} static struct ares_options* FillOptions(struct ares_options * opts, int flags) { memset(opts, 0, sizeof(struct ares_options)); @@ -755,6 +755,67 @@ TEST_P(MockChannelTest, SearchDomains) { EXPECT_EQ("{'www.third.gov' aliases=[] addrs=[2.3.4.5]}", ss.str()); } +#ifdef HAVE_CONTAINER +// Issue #852 +class ContainedMockChannelSysConfig + : public MockChannelOptsTest, + public ::testing::WithParamInterface> { + public: + ContainedMockChannelSysConfig() + : MockChannelOptsTest(1, GetParam().first, GetParam().second, true, nullptr, 0) {} +}; + +NameContentList files_no_ndots = { + {"/etc/resolv.conf", "nameserver 1.2.3.4\n" // Will be replaced + "search example.com example.org\n" + "options edns0 trust-ad\n"}, // ndots:1 is default + {"/etc/hosts", "3.4.5.6 ahostname.com\n"}, + {"/etc/nsswitch.conf", "hosts: files dns\n"}}; +CONTAINED_TEST_P(ContainedMockChannelSysConfig, SysConfigNdotsDefault, + "myhostname", "mydomainname.org", files_no_ndots) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.example.com", T_A)) + .add_answer(new DNSARR("www.example.com", 0x0200, {2, 3, 4, 5})); + EXPECT_CALL(server_, OnRequest("www.example.com", T_A)) + .WillOnce(SetReply(&server_, &rsp)); + + HostResult result; + ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.host_; + EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss.str()); + return HasFailure(); +} + +NameContentList files_ndots0 = { + {"/etc/resolv.conf", "nameserver 1.2.3.4\n" // Will be replaced + "search example.com example.org\n" + "options edns0 trust-ad ndots:0\n"}, // ndots:1 is default + {"/etc/hosts", "3.4.5.6 ahostname.com\n"}, + {"/etc/nsswitch.conf", "hosts: files dns\n"}}; +CONTAINED_TEST_P(ContainedMockChannelSysConfig, SysConfigNdots0, + "myhostname", "mydomainname.org", files_ndots0) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www", T_A)) + .add_answer(new DNSARR("www", 0x0200, {1, 2, 3, 4})); + EXPECT_CALL(server_, OnRequest("www", T_A)) + .WillOnce(SetReply(&server_, &rsp)); + + HostResult result; + ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.host_; + EXPECT_EQ("{'www' aliases=[] addrs=[1.2.3.4]}", ss.str()); + return HasFailure(); +} +#endif + // Issue #858 TEST_P(CacheQueriesTest, BlankName) { DNSPacket rsp; @@ -1562,7 +1623,7 @@ class MockMultiServerChannelTest public ::testing::WithParamInterface< std::pair > { public: MockMultiServerChannelTest(ares_options *opts, int optmask) - : MockChannelOptsTest(3, GetParam().first, GetParam().second, opts, optmask) {} + : MockChannelOptsTest(3, GetParam().first, GetParam().second, false, opts, optmask) {} void CheckExample() { HostResult result; ares_gethostbyname(channel_, "www.example.com.", AF_INET, HostCallback, &result); @@ -1885,6 +1946,10 @@ std::string PrintFamily(const testing::TestParamInfo &info) INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockChannelTest, ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode); +#ifdef HAVE_CONTAINER +INSTANTIATE_TEST_SUITE_P(AddressFamilies, ContainedMockChannelSysConfig, ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode); +#endif + INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockUDPChannelTest, ::testing::ValuesIn(ares::test::families), PrintFamily); INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockUDPMaxQueriesTest, ::testing::ValuesIn(ares::test::families), PrintFamily); diff --git a/test/ares-test-ns.cc b/test/ares-test-ns.cc index 748c5f40..879a7cea 100644 --- a/test/ares-test-ns.cc +++ b/test/ares-test-ns.cc @@ -155,8 +155,8 @@ int RunInContainer(ContainerFilesystem* fs, const std::string& hostname, std::stringstream contentss; contentss << "0 " << getuid() << " 1" << std::endl; std::string content = contentss.str(); - int rc = write(fd, content.c_str(), content.size()); - if (rc != (int)content.size()) { + ssize_t rc = write(fd, content.c_str(), content.size()); + if (rc != (ssize_t)content.size()) { std::cerr << "Failed to write uid map to '" << mapfile << "'" << std::endl; } close(fd); @@ -181,8 +181,13 @@ ContainerFilesystem::ContainerFilesystem(NameContentList files, const std::strin dirs_.push_front(rootdir_); for (const auto& nc : files) { std::string fullpath = rootdir_ + nc.first; - int idx = fullpath.rfind('/'); - std::string dir = fullpath.substr(0, idx); + size_t idx = fullpath.rfind('/'); + std::string dir; + if (idx != SIZE_MAX) { + dir = fullpath.substr(0, idx); + } else { + dir = fullpath; + } EnsureDirExists(dir); files_.push_back(std::unique_ptr( new TransientFile(fullpath, nc.second))); diff --git a/test/ares-test.cc b/test/ares-test.cc index ce11f0e2..69701694 100644 --- a/test/ares-test.cc +++ b/test/ares-test.cc @@ -730,11 +730,13 @@ MockChannelOptsTest::NiceMockServers MockChannelOptsTest::BuildServers(int count MockChannelOptsTest::MockChannelOptsTest(int count, int family, bool force_tcp, + bool honor_sysconfig, struct ares_options* givenopts, int optmask) : servers_(BuildServers(count, family, mock_port)), server_(*servers_[0].get()), channel_(nullptr) { // Set up channel options. + const char *domains[3] = {"first.com", "second.org", "third.gov"}; struct ares_options opts; if (givenopts) { memcpy(&opts, givenopts, sizeof(opts)); @@ -742,41 +744,39 @@ MockChannelOptsTest::MockChannelOptsTest(int count, memset(&opts, 0, sizeof(opts)); } - // Point the library at the first mock server by default (overridden below). - opts.udp_port = server_.udpport(); - optmask |= ARES_OPT_UDP_PORT; - opts.tcp_port = server_.tcpport(); - optmask |= ARES_OPT_TCP_PORT; + /* Honor items from resolv.conf except the dns server itself */ + if (!honor_sysconfig) { + if (!(optmask & (ARES_OPT_TIMEOUTMS|ARES_OPT_TIMEOUT))) { + // Reduce timeouts significantly to shorten test times. + opts.timeout = 250; + optmask |= ARES_OPT_TIMEOUTMS; + } + // If not already overridden, set 3 retries. + if (!(optmask & ARES_OPT_TRIES)) { + opts.tries = 3; + optmask |= ARES_OPT_TRIES; + } - if (!(optmask & (ARES_OPT_TIMEOUTMS|ARES_OPT_TIMEOUT))) { - // Reduce timeouts significantly to shorten test times. - opts.timeout = 250; - optmask |= ARES_OPT_TIMEOUTMS; - } - // If not already overridden, set 3 retries. - if (!(optmask & ARES_OPT_TRIES)) { - opts.tries = 3; - optmask |= ARES_OPT_TRIES; - } - // If not already overridden, set search domains. - const char *domains[3] = {"first.com", "second.org", "third.gov"}; - if (!(optmask & ARES_OPT_DOMAINS)) { - opts.ndomains = 3; - opts.domains = (char**)domains; - optmask |= ARES_OPT_DOMAINS; + // If not already overridden, set search domains. + if (!(optmask & ARES_OPT_DOMAINS)) { + opts.ndomains = 3; + opts.domains = (char**)domains; + optmask |= ARES_OPT_DOMAINS; + } + + /* Tests expect ndots=1 in general, the system config may not default to this + * so we don't want to inherit that. */ + if (!(optmask & ARES_OPT_NDOTS)) { + opts.ndots = 1; + optmask |= ARES_OPT_NDOTS; + } } + if (force_tcp) { opts.flags |= ARES_FLAG_USEVC; optmask |= ARES_OPT_FLAGS; } - /* Tests expect ndots=1 in general, the system config may not default to this - * so we don't want to inherit that. */ - if (!(optmask & ARES_OPT_NDOTS)) { - opts.ndots = 1; - optmask |= ARES_OPT_NDOTS; - } - /* Disable the query cache for tests unless explicitly enabled. As of * c-ares 1.31.0, the query cache is enabled by default so we have to set * the option and set the TTL to 0 to effectively disable it. */ diff --git a/test/ares-test.h b/test/ares-test.h index 16d95902..d3be5fe9 100644 --- a/test/ares-test.h +++ b/test/ares-test.h @@ -309,7 +309,7 @@ private: // Test fixture that uses a mock DNS server. class MockChannelOptsTest : public LibraryTest { public: - MockChannelOptsTest(int count, int family, bool force_tcp, + MockChannelOptsTest(int count, int family, bool force_tcp, bool honor_sysconfig, struct ares_options *givenopts, int optmask); ~MockChannelOptsTest(); @@ -339,7 +339,7 @@ class MockChannelTest public ::testing::WithParamInterface> { public: MockChannelTest() - : MockChannelOptsTest(1, GetParam().first, GetParam().second, nullptr, 0) + : MockChannelOptsTest(1, GetParam().first, GetParam().second, false, nullptr, 0) { } }; @@ -347,7 +347,7 @@ public: class MockUDPChannelTest : public MockChannelOptsTest, public ::testing::WithParamInterface { public: - MockUDPChannelTest() : MockChannelOptsTest(1, GetParam(), false, nullptr, 0) + MockUDPChannelTest() : MockChannelOptsTest(1, GetParam(), false, false, nullptr, 0) { } }; @@ -355,7 +355,7 @@ public: class MockTCPChannelTest : public MockChannelOptsTest, public ::testing::WithParamInterface { public: - MockTCPChannelTest() : MockChannelOptsTest(1, GetParam(), true, nullptr, 0) + MockTCPChannelTest() : MockChannelOptsTest(1, GetParam(), true, false, nullptr, 0) { } }; @@ -365,7 +365,7 @@ public: MockEventThreadOptsTest(int count, ares_evsys_t evsys, int family, bool force_tcp, struct ares_options *givenopts, int optmask) - : MockChannelOptsTest(count, family, force_tcp, + : MockChannelOptsTest(count, family, force_tcp, false, FillOptionsET(&evopts_, givenopts, evsys), optmask | ARES_OPT_EVENT_THREAD) { @@ -761,6 +761,50 @@ int RunInContainer(ContainerFilesystem *fs, const std::string &hostname, } \ int ICLASS_NAME(casename, testname)::InnerTestBody() +#define CONTAINED_TEST_P(test_suite_name, test_name, hostname, domainname, files) \ + class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ + : public test_suite_name { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ + int InnerTestBody(); \ + void TestBody() \ + { \ + ContainerFilesystem chroot(files, ".."); \ + VoidToIntFn fn = \ + [this](void) -> int { \ + ares_reinit(this->channel_); \ + ares_sleep_time(100); \ + return this->InnerTestBody(); \ + }; \ + EXPECT_EQ(0, RunInContainer(&chroot, hostname, domainname, fn)); \ + } \ + \ + private: \ + static int AddToRegistry() { \ + ::testing::UnitTest::GetInstance() \ + ->parameterized_test_registry() \ + .GetTestSuitePatternHolder( \ + GTEST_STRINGIFY_(test_suite_name), \ + ::testing::internal::CodeLocation(__FILE__, __LINE__)) \ + ->AddTestPattern( \ + GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name), \ + new ::testing::internal::TestMetaFactory(), \ + ::testing::internal::CodeLocation(__FILE__, __LINE__)); \ + return 0; \ + } \ + static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \ + GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ + (const GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) &) = delete; \ + GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) & operator=( \ + const GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name) &) = delete; /* NOLINT */ \ + }; \ + int GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name)::gtest_registering_dummy_ = \ + GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::AddToRegistry(); \ + int GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::InnerTestBody() + #endif /* Assigns virtual IO functions to a channel. These functions simply call