diff --git a/test/ares-test-mock.cc b/test/ares-test-mock.cc index 81bcf281..36fcdadf 100644 --- a/test/ares-test-mock.cc +++ b/test/ares-test-mock.cc @@ -11,7 +11,7 @@ using testing::InvokeWithoutArgs; namespace ares { namespace test { -TEST_F(MockChannelTest, Basic) { +TEST_P(MockChannelTest, Basic) { std::vector reply = { 0x00, 0x00, // qid 0x84, // response + query + AA + not-TC + not-RD @@ -51,7 +51,7 @@ TEST_F(MockChannelTest, Basic) { EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str()); } -TEST_F(MockChannelTest, SearchDomains) { +TEST_P(MockChannelTest, SearchDomains) { DNSPacket nofirst; nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) .add_question(new DNSQuestion("www.first.com", ns_t_a)); @@ -78,7 +78,7 @@ TEST_F(MockChannelTest, SearchDomains) { EXPECT_EQ("{'www.third.gov' aliases=[] addrs=[2.3.4.5]}", ss.str()); } -TEST_F(MockChannelTest, SearchDomainsBare) { +TEST_P(MockChannelTest, SearchDomainsBare) { DNSPacket nofirst; nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) .add_question(new DNSQuestion("www.first.com", ns_t_a)); @@ -110,7 +110,7 @@ TEST_F(MockChannelTest, SearchDomainsBare) { EXPECT_EQ("{'www' aliases=[] addrs=[2.3.4.5]}", ss.str()); } -TEST_F(MockChannelTest, SearchNoDataThenSuccess) { +TEST_P(MockChannelTest, SearchNoDataThenSuccess) { // First two search domains recognize the name but have no A records. DNSPacket nofirst; nofirst.set_response().set_aa() @@ -138,7 +138,7 @@ TEST_F(MockChannelTest, SearchNoDataThenSuccess) { EXPECT_EQ("{'www.third.gov' aliases=[] addrs=[2.3.4.5]}", ss.str()); } -TEST_F(MockChannelTest, SearchNoDataThenFail) { +TEST_P(MockChannelTest, SearchNoDataThenFail) { // First two search domains recognize the name but have no A records. DNSPacket nofirst; nofirst.set_response().set_aa() @@ -168,7 +168,7 @@ TEST_F(MockChannelTest, SearchNoDataThenFail) { EXPECT_EQ(ARES_ENODATA, result.status_); } -TEST_F(MockChannelTest, SearchAllocFailure) { +TEST_P(MockChannelTest, SearchAllocFailure) { SearchResult result; SetAllocFail(1); ares_search(channel_, "fully.qualified.", ns_c_in, ns_t_a, SearchCallback, &result); @@ -177,7 +177,7 @@ TEST_F(MockChannelTest, SearchAllocFailure) { EXPECT_EQ(ARES_ENOMEM, result.status_); } -TEST_F(MockChannelTest, SearchHighNdots) { +TEST_P(MockChannelTest, SearchHighNdots) { DNSPacket nobare; nobare.set_response().set_aa().set_rcode(ns_r_nxdomain) .add_question(new DNSQuestion("a.b.c.w.w.w", ns_t_a)); @@ -202,7 +202,7 @@ TEST_F(MockChannelTest, SearchHighNdots) { ss.str()); } -TEST_F(MockChannelTest, UnspecifiedFamilyV6) { +TEST_P(MockChannelTest, UnspecifiedFamilyV6) { DNSPacket rsp6; rsp6.set_response().set_aa() .add_question(new DNSQuestion("example.com", ns_t_aaaa)) @@ -222,7 +222,7 @@ TEST_F(MockChannelTest, UnspecifiedFamilyV6) { EXPECT_EQ("{'example.com' aliases=[] addrs=[2121:0000:0000:0000:0000:0000:0000:0303]}", ss.str()); } -TEST_F(MockChannelTest, UnspecifiedFamilyV4) { +TEST_P(MockChannelTest, UnspecifiedFamilyV4) { DNSPacket rsp4; rsp4.set_response().set_aa() .add_question(new DNSQuestion("example.com", ns_t_a)) @@ -244,7 +244,7 @@ TEST_F(MockChannelTest, UnspecifiedFamilyV4) { EXPECT_EQ("{'example.com' aliases=[] addrs=[2.3.4.5]}", ss.str()); } -TEST_F(MockChannelTest, UnspecifiedFamilyNoData) { +TEST_P(MockChannelTest, UnspecifiedFamilyNoData) { DNSPacket rsp4; rsp4.set_response().set_aa() .add_question(new DNSQuestion("example.com", ns_t_a)); @@ -266,7 +266,7 @@ TEST_F(MockChannelTest, UnspecifiedFamilyNoData) { EXPECT_EQ("{'' aliases=[] addrs=[]}", ss.str()); } -TEST_F(MockChannelTest, ExplicitIP) { +TEST_P(MockChannelTest, ExplicitIP) { HostResult result; ares_gethostbyname(channel_, "1.2.3.4", AF_INET, HostCallback, &result); EXPECT_TRUE(result.done_); // Immediate return @@ -276,7 +276,7 @@ TEST_F(MockChannelTest, ExplicitIP) { EXPECT_EQ("{'1.2.3.4' aliases=[] addrs=[1.2.3.4]}", ss.str()); } -TEST_F(MockChannelTest, ExplicitIPAllocFail) { +TEST_P(MockChannelTest, ExplicitIPAllocFail) { HostResult result; SetAllocSizeFail(strlen("1.2.3.4") + 1); ares_gethostbyname(channel_, "1.2.3.4", AF_INET, HostCallback, &result); @@ -284,7 +284,7 @@ TEST_F(MockChannelTest, ExplicitIPAllocFail) { EXPECT_EQ(ARES_ENOMEM, result.status_); } -TEST_F(MockChannelTest, SortListV4) { +TEST_P(MockChannelTest, SortListV4) { DNSPacket rsp; rsp.set_response().set_aa() .add_question(new DNSQuestion("example.com", ns_t_a)) @@ -322,7 +322,7 @@ TEST_F(MockChannelTest, SortListV4) { ares_destroy_options(&options); } -TEST_F(MockChannelTest, SortListV6) { +TEST_P(MockChannelTest, SortListV6) { DNSPacket rsp; rsp.set_response().set_aa() .add_question(new DNSQuestion("example.com", ns_t_aaaa)) @@ -359,7 +359,7 @@ TEST_F(MockChannelTest, SortListV6) { } } -TEST_F(MockChannelTest, SearchDomainsAllocFail) { +TEST_P(MockChannelTest, SearchDomainsAllocFail) { DNSPacket nofirst; nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) .add_question(new DNSQuestion("www.first.com", ns_t_a)); @@ -403,7 +403,7 @@ TEST_F(MockChannelTest, SearchDomainsAllocFail) { channel_ = nullptr; } -TEST_F(MockChannelTest, Resend) { +TEST_P(MockChannelTest, Resend) { std::vector nothing; DNSPacket reply; reply.set_response().set_aa() @@ -425,7 +425,7 @@ TEST_F(MockChannelTest, Resend) { EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str()); } -TEST_F(MockChannelTest, CancelImmediate) { +TEST_P(MockChannelTest, CancelImmediate) { HostResult result; ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result); ares_cancel(channel_); @@ -434,7 +434,7 @@ TEST_F(MockChannelTest, CancelImmediate) { EXPECT_EQ(0, result.timeouts_); } -TEST_F(MockChannelTest, CancelLater) { +TEST_P(MockChannelTest, CancelLater) { std::vector nothing; // On second request, cancel the channel. @@ -450,7 +450,7 @@ TEST_F(MockChannelTest, CancelLater) { EXPECT_EQ(0, result.timeouts_); } -TEST_F(MockChannelTest, GetHostByNameDestroyAbsolute) { +TEST_P(MockChannelTest, GetHostByNameDestroyAbsolute) { HostResult result; ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result); @@ -462,7 +462,7 @@ TEST_F(MockChannelTest, GetHostByNameDestroyAbsolute) { EXPECT_EQ(0, result.timeouts_); } -TEST_F(MockChannelTest, GetHostByNameDestroyRelative) { +TEST_P(MockChannelTest, GetHostByNameDestroyRelative) { HostResult result; ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result); @@ -474,7 +474,7 @@ TEST_F(MockChannelTest, GetHostByNameDestroyRelative) { EXPECT_EQ(0, result.timeouts_); } -TEST_F(MockChannelTest, GetHostByAddrDestroy) { +TEST_P(MockChannelTest, GetHostByAddrDestroy) { unsigned char gdns_addr4[4] = {0x08, 0x08, 0x08, 0x08}; HostResult result; ares_gethostbyaddr(channel_, gdns_addr4, sizeof(gdns_addr4), AF_INET, HostCallback, &result); @@ -487,7 +487,7 @@ TEST_F(MockChannelTest, GetHostByAddrDestroy) { EXPECT_EQ(0, result.timeouts_); } -TEST_F(MockChannelTest, HostAlias) { +TEST_P(MockChannelTest, HostAlias) { DNSPacket reply; reply.set_response().set_aa() .add_question(new DNSQuestion("www.google.com", ns_t_a)) @@ -507,7 +507,7 @@ TEST_F(MockChannelTest, HostAlias) { EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str()); } -TEST_F(MockChannelTest, HostAliasMissing) { +TEST_P(MockChannelTest, HostAliasMissing) { DNSPacket yesfirst; yesfirst.set_response().set_aa() .add_question(new DNSQuestion("www.first.com", ns_t_a)) @@ -526,7 +526,7 @@ TEST_F(MockChannelTest, HostAliasMissing) { EXPECT_EQ("{'www.first.com' aliases=[] addrs=[2.3.4.5]}", ss.str()); } -TEST_F(MockChannelTest, HostAliasMissingFile) { +TEST_P(MockChannelTest, HostAliasMissingFile) { DNSPacket yesfirst; yesfirst.set_response().set_aa() .add_question(new DNSQuestion("www.first.com", ns_t_a)) @@ -544,7 +544,7 @@ TEST_F(MockChannelTest, HostAliasMissingFile) { EXPECT_EQ("{'www.first.com' aliases=[] addrs=[2.3.4.5]}", ss.str()); } -TEST_F(MockChannelTest, HostAliasUnreadable) { +TEST_P(MockChannelTest, HostAliasUnreadable) { TempFile aliases("www www.google.com\n"); chmod(aliases.filename(), 0); EnvValue with_env("HOSTALIASES", aliases.filename()); @@ -556,5 +556,8 @@ TEST_F(MockChannelTest, HostAliasUnreadable) { chmod(aliases.filename(), 0777); } +INSTANTIATE_TEST_CASE_P(AddressFamilies, MockChannelTest, + ::testing::Values(AF_INET, AF_INET6)); + } // namespace test } // namespace ares diff --git a/test/ares-test.cc b/test/ares-test.cc index 92cdb093..a2007ede 100644 --- a/test/ares-test.cc +++ b/test/ares-test.cc @@ -121,19 +121,30 @@ void DefaultChannelModeTest::Process() { ProcessWork(channel_, -1, nullptr); } -MockServer::MockServer(int port) : port_(port) { +MockServer::MockServer(int family, int port) : port_(port) { // Create a UDP socket to receive data on. - sockfd_ = socket(AF_INET, SOCK_DGRAM, 0); + sockfd_ = socket(family, SOCK_DGRAM, 0); EXPECT_NE(-1, sockfd_); // Bind it to the given port. - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(port_); - int rc = bind(sockfd_, (struct sockaddr*)&addr, sizeof(addr)); - EXPECT_EQ(0, rc) << "Failed to bind to port " << port_; + if (family == AF_INET) { + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port_); + int rc = bind(sockfd_, (struct sockaddr*)&addr, sizeof(addr)); + EXPECT_EQ(0, rc) << "Failed to bind AF_INET to port " << port_; + } else { + EXPECT_EQ(AF_INET6, family); + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr = in6addr_any; + addr.sin6_port = htons(port_); + int rc = bind(sockfd_, (struct sockaddr*)&addr, sizeof(addr)); + EXPECT_EQ(0, rc) << "Failed to bind AF_INET6 to port " << port_; + } } MockServer::~MockServer() { @@ -223,9 +234,10 @@ void MockServer::ProcessRequest(struct sockaddr_storage* addr, int addrlen, } } -MockChannelOptsTest::MockChannelOptsTest(struct ares_options* givenopts, +MockChannelOptsTest::MockChannelOptsTest(int family, + struct ares_options* givenopts, int optmask) - : server_(mock_port), channel_(nullptr) { + : server_(family, mock_port), channel_(nullptr) { // Set up channel options. struct ares_options opts; if (givenopts) { @@ -242,10 +254,12 @@ MockChannelOptsTest::MockChannelOptsTest(struct ares_options* givenopts, optmask |= ARES_OPT_TCP_PORT; opts.nservers = 1; struct in_addr server_addr; - memset(&server_addr, 0, sizeof(server_addr)); - server_addr.s_addr = htonl(0x7F000001); - opts.servers = &server_addr; - optmask |= ARES_OPT_SERVERS; + if (family == AF_INET) { + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.s_addr = htonl(0x7F000001); + opts.servers = &server_addr; + optmask |= ARES_OPT_SERVERS; + } // If not already overridden, set short timeouts. if (!(optmask & (ARES_OPT_TIMEOUTMS|ARES_OPT_TIMEOUT))) { @@ -267,6 +281,15 @@ MockChannelOptsTest::MockChannelOptsTest(struct ares_options* givenopts, EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel_, &opts, optmask)); EXPECT_NE(nullptr, channel_); + + // For IPv6 servers, have to set up after construction. + if (family == AF_INET6) { + struct ares_addr_node addr; + memset(&addr, 0, sizeof(addr)); + addr.family = AF_INET6; + addr.addr.addr6._S6_un._S6_u8[15] = 1; + EXPECT_EQ(ARES_SUCCESS, ares_set_servers(channel_, &addr)); + } } MockChannelOptsTest::~MockChannelOptsTest() { diff --git a/test/ares-test.h b/test/ares-test.h index f723c6c5..88f79614 100644 --- a/test/ares-test.h +++ b/test/ares-test.h @@ -110,7 +110,7 @@ class DefaultChannelModeTest // Mock DNS server to allow responses to be scripted by tests. class MockServer { public: - MockServer(int port); + MockServer(int family, int port); ~MockServer(); // Mock method indicating the processing of a particular @@ -140,7 +140,7 @@ class MockServer { // Test fixture that uses a mock DNS server. class MockChannelOptsTest : public LibraryTest { public: - MockChannelOptsTest(struct ares_options* givenopts, int optmask); + MockChannelOptsTest(int family, struct ares_options* givenopts, int optmask); ~MockChannelOptsTest(); // Process all pending work on ares-owned and mock-server-owned file descriptors. @@ -151,9 +151,11 @@ class MockChannelOptsTest : public LibraryTest { ares_channel channel_; }; -class MockChannelTest : public MockChannelOptsTest { +class MockChannelTest + : public MockChannelOptsTest, + public ::testing::WithParamInterface { public: - MockChannelTest() : MockChannelOptsTest(nullptr, 0) {} + MockChannelTest() : MockChannelOptsTest(GetParam(), nullptr, 0) {} }; // gMock action to set the reply for a mock server.