diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
commit | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch) | |
tree | 64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/libs/c-ares/test/ares-test-mock-ai.cc | |
parent | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff) | |
download | ydb-e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/c-ares/test/ares-test-mock-ai.cc')
-rw-r--r-- | contrib/libs/c-ares/test/ares-test-mock-ai.cc | 1446 |
1 files changed, 723 insertions, 723 deletions
diff --git a/contrib/libs/c-ares/test/ares-test-mock-ai.cc b/contrib/libs/c-ares/test/ares-test-mock-ai.cc index 700333b826..d0df867fef 100644 --- a/contrib/libs/c-ares/test/ares-test-mock-ai.cc +++ b/contrib/libs/c-ares/test/ares-test-mock-ai.cc @@ -1,723 +1,723 @@ -#include "ares-test-ai.h" -#include "dns-proto.h" - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif - -#include <sstream> -#include <vector> - -using testing::InvokeWithoutArgs; -using testing::DoAll; - -namespace ares { -namespace test { - -MATCHER_P(IncludesNumAddresses, n, "") { - if(!arg) - return false; - int cnt = 0; - for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) - cnt++; - return n == cnt; -} - -MATCHER_P(IncludesV4Address, address, "") { - if(!arg) - return false; - in_addr addressnum = {}; - if (!ares_inet_pton(AF_INET, address, &addressnum)) - return false; // wrong number format? - for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family != AF_INET) - continue; - if (reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_addr.s_addr == - addressnum.s_addr) - return true; // found - } - return false; -} - -MATCHER_P(IncludesV6Address, address, "") { - if(!arg) - return false; - in6_addr addressnum = {}; - if (!ares_inet_pton(AF_INET6, address, &addressnum)) { - return false; // wrong number format? - } - for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family != AF_INET6) - continue; - if (!memcmp( - reinterpret_cast<sockaddr_in6*>(ai->ai_addr)->sin6_addr.s6_addr, - addressnum.s6_addr, sizeof(addressnum.s6_addr))) - return true; // found - } - return false; -} - -// UDP only so mock server doesn't get confused by concatenated requests -TEST_P(MockUDPChannelTestAI, GetAddrInfoParallelLookups) { - DNSPacket rsp1; - rsp1.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)) - .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp1)); - DNSPacket rsp2; - rsp2.set_response().set_aa() - .add_question(new DNSQuestion("www.example.com", ns_t_a)) - .add_answer(new DNSARR("www.example.com", 100, {1, 2, 3, 4})); - ON_CALL(server_, OnRequest("www.example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp2)); - - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - AddrInfoResult result1; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result1); - AddrInfoResult result2; - ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result2); - AddrInfoResult result3; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result3); - Process(); - - EXPECT_TRUE(result1.done_); - EXPECT_EQ(result1.status_, ARES_SUCCESS); - EXPECT_THAT(result1.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result1.ai_, IncludesV4Address("2.3.4.5")); - - EXPECT_TRUE(result2.done_); - EXPECT_EQ(result2.status_, ARES_SUCCESS); - EXPECT_THAT(result2.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result2.ai_, IncludesV4Address("1.2.3.4")); - - EXPECT_TRUE(result3.done_); - EXPECT_EQ(result3.status_, ARES_SUCCESS); - EXPECT_THAT(result3.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result3.ai_, IncludesV4Address("2.3.4.5")); -} - -// UDP to TCP specific test -TEST_P(MockUDPChannelTestAI, TruncationRetry) { - DNSPacket rsptruncated; - rsptruncated.set_response().set_aa().set_tc() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - DNSPacket rspok; - rspok.set_response() - .add_question(new DNSQuestion("www.google.com", ns_t_a)) - .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4})); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsptruncated)) - .WillOnce(SetReply(&server_, &rspok)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(result.status_, ARES_SUCCESS); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4")); -} - -// TCP only to prevent retries -TEST_P(MockTCPChannelTestAI, MalformedResponse) { - std::vector<byte> one = {0x01}; - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReplyData(&server_, one)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ETIMEOUT, result.status_); -} - -TEST_P(MockTCPChannelTestAI, FormErrResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_formerr); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_EFORMERR, result.status_); -} - -TEST_P(MockTCPChannelTestAI, ServFailResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_servfail); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - // ARES_FLAG_NOCHECKRESP not set, so SERVFAIL consumed - EXPECT_EQ(ARES_ECONNREFUSED, result.status_); -} - -TEST_P(MockTCPChannelTestAI, NotImplResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_notimpl); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - // ARES_FLAG_NOCHECKRESP not set, so NOTIMPL consumed - EXPECT_EQ(ARES_ECONNREFUSED, result.status_); -} - -TEST_P(MockTCPChannelTestAI, RefusedResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_refused); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - // ARES_FLAG_NOCHECKRESP not set, so REFUSED consumed - EXPECT_EQ(ARES_ECONNREFUSED, result.status_); -} - -TEST_P(MockTCPChannelTestAI, YXDomainResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_yxdomain); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ENODATA, result.status_); -} - -class MockExtraOptsTestAI - : public MockChannelOptsTest, - public ::testing::WithParamInterface< std::pair<int, bool> > { - public: - MockExtraOptsTestAI() - : MockChannelOptsTest(1, GetParam().first, GetParam().second, - FillOptions(&opts_), - ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF) {} - static struct ares_options* FillOptions(struct ares_options * opts) { - memset(opts, 0, sizeof(struct ares_options)); - // Set a few options that affect socket communications - opts->socket_send_buffer_size = 514; - opts->socket_receive_buffer_size = 514; - return opts; - } - private: - struct ares_options opts_; -}; - -TEST_P(MockExtraOptsTestAI, SimpleQuery) { - ares_set_local_ip4(channel_, 0x7F000001); - byte addr6[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; - ares_set_local_ip6(channel_, addr6); - ares_set_local_dev(channel_, "dummy"); - - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)) - .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_SUCCESS, result.status_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); -} - -class MockFlagsChannelOptsTestAI - : public MockChannelOptsTest, - public ::testing::WithParamInterface< std::pair<int, bool> > { - public: - MockFlagsChannelOptsTestAI(int flags) - : MockChannelOptsTest(1, GetParam().first, GetParam().second, - FillOptions(&opts_, flags), ARES_OPT_FLAGS) {} - static struct ares_options* FillOptions(struct ares_options * opts, int flags) { - memset(opts, 0, sizeof(struct ares_options)); - opts->flags = flags; - return opts; - } - private: - struct ares_options opts_; -}; - -class MockNoCheckRespChannelTestAI : public MockFlagsChannelOptsTestAI { - public: - MockNoCheckRespChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_NOCHECKRESP) {} -}; - -TEST_P(MockNoCheckRespChannelTestAI, ServFailResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_servfail); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ESERVFAIL, result.status_); -} - -TEST_P(MockNoCheckRespChannelTestAI, NotImplResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_notimpl); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ENOTIMP, result.status_); -} - -TEST_P(MockNoCheckRespChannelTestAI, RefusedResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_refused); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_EREFUSED, result.status_); -} - -TEST_P(MockChannelTestAI, FamilyV6) { - DNSPacket rsp6; - rsp6.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_aaaa)) - .add_answer(new DNSAaaaRR("example.com", 100, - {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03})); - ON_CALL(server_, OnRequest("example.com", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &rsp6)); - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET6; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com.", NULL, &hints, - AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303")); -} - -TEST_P(MockChannelTestAI, FamilyV4) { - DNSPacket rsp4; - rsp4.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_a)) - .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp4)); - AddrInfoResult result = {}; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com.", NULL, &hints, - AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); -} - -TEST_P(MockChannelTestAI, FamilyV4_MultipleAddresses) { - DNSPacket rsp4; - rsp4.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_a)) - .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})) - .add_answer(new DNSARR("example.com", 100, {7, 8, 9, 0})); - ON_CALL(server_, OnRequest("example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp4)); - AddrInfoResult result = {}; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com.", NULL, &hints, - AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - std::stringstream ss; - ss << result.ai_; - EXPECT_EQ("{addr=[2.3.4.5], addr=[7.8.9.0]}", ss.str()); -} - -TEST_P(MockChannelTestAI, FamilyUnspecified) { - DNSPacket rsp6; - rsp6.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_aaaa)) - .add_answer(new DNSAaaaRR("example.com", 100, - {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03})); - ON_CALL(server_, OnRequest("example.com", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &rsp6)); - DNSPacket rsp4; - rsp4.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_a)) - .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp4)); - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_UNSPEC; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com.", NULL, &hints, - AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(2)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); - EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303")); -} - -class MockEDNSChannelTestAI : public MockFlagsChannelOptsTestAI { - public: - MockEDNSChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_EDNS) {} -}; - -TEST_P(MockEDNSChannelTestAI, RetryWithoutEDNS) { - DNSPacket rspfail; - rspfail.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - DNSPacket rspok; - rspok.set_response() - .add_question(new DNSQuestion("www.google.com", ns_t_a)) - .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4})); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rspfail)) - .WillOnce(SetReply(&server_, &rspok)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4")); -} - -TEST_P(MockChannelTestAI, SearchDomains) { - DNSPacket nofirst; - nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.first.com", ns_t_a)); - ON_CALL(server_, OnRequest("www.first.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &nofirst)); - DNSPacket nosecond; - nosecond.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.second.org", ns_t_a)); - ON_CALL(server_, OnRequest("www.second.org", ns_t_a)) - .WillByDefault(SetReply(&server_, &nosecond)); - DNSPacket yesthird; - yesthird.set_response().set_aa() - .add_question(new DNSQuestion("www.third.gov", ns_t_a)) - .add_answer(new DNSARR("www.third.gov", 0x0200, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("www.third.gov", ns_t_a)) - .WillByDefault(SetReply(&server_, &yesthird)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); -} - -TEST_P(MockChannelTestAI, SearchDomainsServFailOnAAAA) { - DNSPacket nofirst; - nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.first.com", ns_t_aaaa)); - ON_CALL(server_, OnRequest("www.first.com", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &nofirst)); - DNSPacket nofirst4; - nofirst4.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.first.com", ns_t_a)); - ON_CALL(server_, OnRequest("www.first.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &nofirst4)); - - DNSPacket nosecond; - nosecond.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.second.org", ns_t_aaaa)); - ON_CALL(server_, OnRequest("www.second.org", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &nosecond)); - DNSPacket yessecond4; - yessecond4.set_response().set_aa() - .add_question(new DNSQuestion("www.second.org", ns_t_a)) - .add_answer(new DNSARR("www.second.org", 0x0200, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("www.second.org", ns_t_a)) - .WillByDefault(SetReply(&server_, &yessecond4)); - - DNSPacket failthird; - failthird.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.third.gov", ns_t_aaaa)); - ON_CALL(server_, OnRequest("www.third.gov", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &failthird)); - DNSPacket failthird4; - failthird4.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.third.gov", ns_t_a)); - ON_CALL(server_, OnRequest("www.third.gov", ns_t_a)) - .WillByDefault(SetReply(&server_, &failthird4)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_UNSPEC; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); -} - -class MockMultiServerChannelTestAI - : public MockChannelOptsTest, - public ::testing::WithParamInterface< std::pair<int, bool> > { - public: - MockMultiServerChannelTestAI(bool rotate) - : MockChannelOptsTest(3, GetParam().first, GetParam().second, nullptr, rotate ? ARES_OPT_ROTATE : ARES_OPT_NOROTATE) {} - void CheckExample() { - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(result.status_, ARES_SUCCESS); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); - } -}; - -class RotateMultiMockTestAI : public MockMultiServerChannelTestAI { - public: - RotateMultiMockTestAI() : MockMultiServerChannelTestAI(true) {} -}; - -class NoRotateMultiMockTestAI : public MockMultiServerChannelTestAI { - public: - NoRotateMultiMockTestAI() : MockMultiServerChannelTestAI(false) {} -}; - - -TEST_P(RotateMultiMockTestAI, ThirdServer) { - struct ares_options opts = {0}; - int optmask = 0; - EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask)); - EXPECT_EQ(0, (optmask & ARES_OPT_NOROTATE)); - ares_destroy_options(&opts); - - DNSPacket servfailrsp; - servfailrsp.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.example.com", ns_t_a)); - DNSPacket notimplrsp; - notimplrsp.set_response().set_aa().set_rcode(ns_r_notimpl) - .add_question(new DNSQuestion("www.example.com", ns_t_a)); - DNSPacket okrsp; - okrsp.set_response().set_aa() - .add_question(new DNSQuestion("www.example.com", ns_t_a)) - .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5})); - - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &okrsp)); - CheckExample(); - - // Second time around, starts from server [1]. - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), &servfailrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), ¬implrsp)); - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &okrsp)); - CheckExample(); - - // Third time around, starts from server [2]. - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &servfailrsp)); - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), ¬implrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), &okrsp)); - CheckExample(); -} - -TEST_P(NoRotateMultiMockTestAI, ThirdServer) { - struct ares_options opts = {0}; - int optmask = 0; - EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask)); - EXPECT_EQ(ARES_OPT_NOROTATE, (optmask & ARES_OPT_NOROTATE)); - ares_destroy_options(&opts); - - DNSPacket servfailrsp; - servfailrsp.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.example.com", ns_t_a)); - DNSPacket notimplrsp; - notimplrsp.set_response().set_aa().set_rcode(ns_r_notimpl) - .add_question(new DNSQuestion("www.example.com", ns_t_a)); - DNSPacket okrsp; - okrsp.set_response().set_aa() - .add_question(new DNSQuestion("www.example.com", ns_t_a)) - .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5})); - - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &okrsp)); - CheckExample(); - - // Second time around, still starts from server [0]. - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &okrsp)); - CheckExample(); - - // Third time around, still starts from server [0]. - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &okrsp)); - CheckExample(); -} - -TEST_P(MockChannelTestAI, FamilyV4ServiceName) { - DNSPacket rsp4; - rsp4.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_a)) - .add_answer(new DNSARR("example.com", 100, {1, 1, 1, 1})) - .add_answer(new DNSARR("example.com", 100, {2, 2, 2, 2})); - ON_CALL(server_, OnRequest("example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp4)); - AddrInfoResult result = {}; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com", "http", &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - std::stringstream ss; - ss << result.ai_; - EXPECT_EQ("{addr=[1.1.1.1:80], addr=[2.2.2.2:80]}", ss.str()); -} - -// force-tcp does currently not work, possibly test DNS server swallows -// bytes from second query -//INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockChannelTestAI, -// ::testing::ValuesIn(ares::test::families_modes)); -//const std::vector<std::pair<int, bool>> both_families_udponly = { -// std::make_pair<int, bool>(AF_INET, false), -// std::make_pair<int, bool>(AF_INET6, false) -//}; -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockChannelTestAI, - ::testing::Values(std::make_pair<int, bool>(AF_INET, false))); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockUDPChannelTestAI, - ::testing::ValuesIn(ares::test::families)); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockTCPChannelTestAI, - ::testing::ValuesIn(ares::test::families)); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockExtraOptsTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockNoCheckRespChannelTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockEDNSChannelTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - -INSTANTIATE_TEST_CASE_P(TransportModesAI, RotateMultiMockTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - -INSTANTIATE_TEST_CASE_P(TransportModesAI, NoRotateMultiMockTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - - -} // namespace test -} // namespace ares +#include "ares-test-ai.h" +#include "dns-proto.h" + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#include <sstream> +#include <vector> + +using testing::InvokeWithoutArgs; +using testing::DoAll; + +namespace ares { +namespace test { + +MATCHER_P(IncludesNumAddresses, n, "") { + if(!arg) + return false; + int cnt = 0; + for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) + cnt++; + return n == cnt; +} + +MATCHER_P(IncludesV4Address, address, "") { + if(!arg) + return false; + in_addr addressnum = {}; + if (!ares_inet_pton(AF_INET, address, &addressnum)) + return false; // wrong number format? + for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) { + if (ai->ai_family != AF_INET) + continue; + if (reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_addr.s_addr == + addressnum.s_addr) + return true; // found + } + return false; +} + +MATCHER_P(IncludesV6Address, address, "") { + if(!arg) + return false; + in6_addr addressnum = {}; + if (!ares_inet_pton(AF_INET6, address, &addressnum)) { + return false; // wrong number format? + } + for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) { + if (ai->ai_family != AF_INET6) + continue; + if (!memcmp( + reinterpret_cast<sockaddr_in6*>(ai->ai_addr)->sin6_addr.s6_addr, + addressnum.s6_addr, sizeof(addressnum.s6_addr))) + return true; // found + } + return false; +} + +// UDP only so mock server doesn't get confused by concatenated requests +TEST_P(MockUDPChannelTestAI, GetAddrInfoParallelLookups) { + DNSPacket rsp1; + rsp1.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)) + .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp1)); + DNSPacket rsp2; + rsp2.set_response().set_aa() + .add_question(new DNSQuestion("www.example.com", ns_t_a)) + .add_answer(new DNSARR("www.example.com", 100, {1, 2, 3, 4})); + ON_CALL(server_, OnRequest("www.example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp2)); + + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + AddrInfoResult result1; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result1); + AddrInfoResult result2; + ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result2); + AddrInfoResult result3; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result3); + Process(); + + EXPECT_TRUE(result1.done_); + EXPECT_EQ(result1.status_, ARES_SUCCESS); + EXPECT_THAT(result1.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result1.ai_, IncludesV4Address("2.3.4.5")); + + EXPECT_TRUE(result2.done_); + EXPECT_EQ(result2.status_, ARES_SUCCESS); + EXPECT_THAT(result2.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result2.ai_, IncludesV4Address("1.2.3.4")); + + EXPECT_TRUE(result3.done_); + EXPECT_EQ(result3.status_, ARES_SUCCESS); + EXPECT_THAT(result3.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result3.ai_, IncludesV4Address("2.3.4.5")); +} + +// UDP to TCP specific test +TEST_P(MockUDPChannelTestAI, TruncationRetry) { + DNSPacket rsptruncated; + rsptruncated.set_response().set_aa().set_tc() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + DNSPacket rspok; + rspok.set_response() + .add_question(new DNSQuestion("www.google.com", ns_t_a)) + .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4})); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsptruncated)) + .WillOnce(SetReply(&server_, &rspok)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(result.status_, ARES_SUCCESS); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4")); +} + +// TCP only to prevent retries +TEST_P(MockTCPChannelTestAI, MalformedResponse) { + std::vector<byte> one = {0x01}; + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReplyData(&server_, one)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ETIMEOUT, result.status_); +} + +TEST_P(MockTCPChannelTestAI, FormErrResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_formerr); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_EFORMERR, result.status_); +} + +TEST_P(MockTCPChannelTestAI, ServFailResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_servfail); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + // ARES_FLAG_NOCHECKRESP not set, so SERVFAIL consumed + EXPECT_EQ(ARES_ECONNREFUSED, result.status_); +} + +TEST_P(MockTCPChannelTestAI, NotImplResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_notimpl); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + // ARES_FLAG_NOCHECKRESP not set, so NOTIMPL consumed + EXPECT_EQ(ARES_ECONNREFUSED, result.status_); +} + +TEST_P(MockTCPChannelTestAI, RefusedResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_refused); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + // ARES_FLAG_NOCHECKRESP not set, so REFUSED consumed + EXPECT_EQ(ARES_ECONNREFUSED, result.status_); +} + +TEST_P(MockTCPChannelTestAI, YXDomainResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_yxdomain); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ENODATA, result.status_); +} + +class MockExtraOptsTestAI + : public MockChannelOptsTest, + public ::testing::WithParamInterface< std::pair<int, bool> > { + public: + MockExtraOptsTestAI() + : MockChannelOptsTest(1, GetParam().first, GetParam().second, + FillOptions(&opts_), + ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF) {} + static struct ares_options* FillOptions(struct ares_options * opts) { + memset(opts, 0, sizeof(struct ares_options)); + // Set a few options that affect socket communications + opts->socket_send_buffer_size = 514; + opts->socket_receive_buffer_size = 514; + return opts; + } + private: + struct ares_options opts_; +}; + +TEST_P(MockExtraOptsTestAI, SimpleQuery) { + ares_set_local_ip4(channel_, 0x7F000001); + byte addr6[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + ares_set_local_ip6(channel_, addr6); + ares_set_local_dev(channel_, "dummy"); + + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)) + .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_SUCCESS, result.status_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); +} + +class MockFlagsChannelOptsTestAI + : public MockChannelOptsTest, + public ::testing::WithParamInterface< std::pair<int, bool> > { + public: + MockFlagsChannelOptsTestAI(int flags) + : MockChannelOptsTest(1, GetParam().first, GetParam().second, + FillOptions(&opts_, flags), ARES_OPT_FLAGS) {} + static struct ares_options* FillOptions(struct ares_options * opts, int flags) { + memset(opts, 0, sizeof(struct ares_options)); + opts->flags = flags; + return opts; + } + private: + struct ares_options opts_; +}; + +class MockNoCheckRespChannelTestAI : public MockFlagsChannelOptsTestAI { + public: + MockNoCheckRespChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_NOCHECKRESP) {} +}; + +TEST_P(MockNoCheckRespChannelTestAI, ServFailResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_servfail); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ESERVFAIL, result.status_); +} + +TEST_P(MockNoCheckRespChannelTestAI, NotImplResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_notimpl); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ENOTIMP, result.status_); +} + +TEST_P(MockNoCheckRespChannelTestAI, RefusedResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_refused); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_EREFUSED, result.status_); +} + +TEST_P(MockChannelTestAI, FamilyV6) { + DNSPacket rsp6; + rsp6.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_aaaa)) + .add_answer(new DNSAaaaRR("example.com", 100, + {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03})); + ON_CALL(server_, OnRequest("example.com", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &rsp6)); + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET6; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com.", NULL, &hints, + AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303")); +} + +TEST_P(MockChannelTestAI, FamilyV4) { + DNSPacket rsp4; + rsp4.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_a)) + .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp4)); + AddrInfoResult result = {}; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com.", NULL, &hints, + AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); +} + +TEST_P(MockChannelTestAI, FamilyV4_MultipleAddresses) { + DNSPacket rsp4; + rsp4.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_a)) + .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})) + .add_answer(new DNSARR("example.com", 100, {7, 8, 9, 0})); + ON_CALL(server_, OnRequest("example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp4)); + AddrInfoResult result = {}; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com.", NULL, &hints, + AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.ai_; + EXPECT_EQ("{addr=[2.3.4.5], addr=[7.8.9.0]}", ss.str()); +} + +TEST_P(MockChannelTestAI, FamilyUnspecified) { + DNSPacket rsp6; + rsp6.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_aaaa)) + .add_answer(new DNSAaaaRR("example.com", 100, + {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03})); + ON_CALL(server_, OnRequest("example.com", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &rsp6)); + DNSPacket rsp4; + rsp4.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_a)) + .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp4)); + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com.", NULL, &hints, + AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(2)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); + EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303")); +} + +class MockEDNSChannelTestAI : public MockFlagsChannelOptsTestAI { + public: + MockEDNSChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_EDNS) {} +}; + +TEST_P(MockEDNSChannelTestAI, RetryWithoutEDNS) { + DNSPacket rspfail; + rspfail.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + DNSPacket rspok; + rspok.set_response() + .add_question(new DNSQuestion("www.google.com", ns_t_a)) + .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4})); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rspfail)) + .WillOnce(SetReply(&server_, &rspok)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4")); +} + +TEST_P(MockChannelTestAI, SearchDomains) { + DNSPacket nofirst; + nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.first.com", ns_t_a)); + ON_CALL(server_, OnRequest("www.first.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &nofirst)); + DNSPacket nosecond; + nosecond.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.second.org", ns_t_a)); + ON_CALL(server_, OnRequest("www.second.org", ns_t_a)) + .WillByDefault(SetReply(&server_, &nosecond)); + DNSPacket yesthird; + yesthird.set_response().set_aa() + .add_question(new DNSQuestion("www.third.gov", ns_t_a)) + .add_answer(new DNSARR("www.third.gov", 0x0200, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("www.third.gov", ns_t_a)) + .WillByDefault(SetReply(&server_, &yesthird)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); +} + +TEST_P(MockChannelTestAI, SearchDomainsServFailOnAAAA) { + DNSPacket nofirst; + nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.first.com", ns_t_aaaa)); + ON_CALL(server_, OnRequest("www.first.com", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &nofirst)); + DNSPacket nofirst4; + nofirst4.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.first.com", ns_t_a)); + ON_CALL(server_, OnRequest("www.first.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &nofirst4)); + + DNSPacket nosecond; + nosecond.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.second.org", ns_t_aaaa)); + ON_CALL(server_, OnRequest("www.second.org", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &nosecond)); + DNSPacket yessecond4; + yessecond4.set_response().set_aa() + .add_question(new DNSQuestion("www.second.org", ns_t_a)) + .add_answer(new DNSARR("www.second.org", 0x0200, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("www.second.org", ns_t_a)) + .WillByDefault(SetReply(&server_, &yessecond4)); + + DNSPacket failthird; + failthird.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.third.gov", ns_t_aaaa)); + ON_CALL(server_, OnRequest("www.third.gov", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &failthird)); + DNSPacket failthird4; + failthird4.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.third.gov", ns_t_a)); + ON_CALL(server_, OnRequest("www.third.gov", ns_t_a)) + .WillByDefault(SetReply(&server_, &failthird4)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); +} + +class MockMultiServerChannelTestAI + : public MockChannelOptsTest, + public ::testing::WithParamInterface< std::pair<int, bool> > { + public: + MockMultiServerChannelTestAI(bool rotate) + : MockChannelOptsTest(3, GetParam().first, GetParam().second, nullptr, rotate ? ARES_OPT_ROTATE : ARES_OPT_NOROTATE) {} + void CheckExample() { + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(result.status_, ARES_SUCCESS); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); + } +}; + +class RotateMultiMockTestAI : public MockMultiServerChannelTestAI { + public: + RotateMultiMockTestAI() : MockMultiServerChannelTestAI(true) {} +}; + +class NoRotateMultiMockTestAI : public MockMultiServerChannelTestAI { + public: + NoRotateMultiMockTestAI() : MockMultiServerChannelTestAI(false) {} +}; + + +TEST_P(RotateMultiMockTestAI, ThirdServer) { + struct ares_options opts = {0}; + int optmask = 0; + EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask)); + EXPECT_EQ(0, (optmask & ARES_OPT_NOROTATE)); + ares_destroy_options(&opts); + + DNSPacket servfailrsp; + servfailrsp.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.example.com", ns_t_a)); + DNSPacket notimplrsp; + notimplrsp.set_response().set_aa().set_rcode(ns_r_notimpl) + .add_question(new DNSQuestion("www.example.com", ns_t_a)); + DNSPacket okrsp; + okrsp.set_response().set_aa() + .add_question(new DNSQuestion("www.example.com", ns_t_a)) + .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5})); + + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &okrsp)); + CheckExample(); + + // Second time around, starts from server [1]. + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), &servfailrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), ¬implrsp)); + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &okrsp)); + CheckExample(); + + // Third time around, starts from server [2]. + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &servfailrsp)); + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), ¬implrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), &okrsp)); + CheckExample(); +} + +TEST_P(NoRotateMultiMockTestAI, ThirdServer) { + struct ares_options opts = {0}; + int optmask = 0; + EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask)); + EXPECT_EQ(ARES_OPT_NOROTATE, (optmask & ARES_OPT_NOROTATE)); + ares_destroy_options(&opts); + + DNSPacket servfailrsp; + servfailrsp.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.example.com", ns_t_a)); + DNSPacket notimplrsp; + notimplrsp.set_response().set_aa().set_rcode(ns_r_notimpl) + .add_question(new DNSQuestion("www.example.com", ns_t_a)); + DNSPacket okrsp; + okrsp.set_response().set_aa() + .add_question(new DNSQuestion("www.example.com", ns_t_a)) + .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5})); + + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &okrsp)); + CheckExample(); + + // Second time around, still starts from server [0]. + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &okrsp)); + CheckExample(); + + // Third time around, still starts from server [0]. + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &okrsp)); + CheckExample(); +} + +TEST_P(MockChannelTestAI, FamilyV4ServiceName) { + DNSPacket rsp4; + rsp4.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_a)) + .add_answer(new DNSARR("example.com", 100, {1, 1, 1, 1})) + .add_answer(new DNSARR("example.com", 100, {2, 2, 2, 2})); + ON_CALL(server_, OnRequest("example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp4)); + AddrInfoResult result = {}; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com", "http", &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.ai_; + EXPECT_EQ("{addr=[1.1.1.1:80], addr=[2.2.2.2:80]}", ss.str()); +} + +// force-tcp does currently not work, possibly test DNS server swallows +// bytes from second query +//INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockChannelTestAI, +// ::testing::ValuesIn(ares::test::families_modes)); +//const std::vector<std::pair<int, bool>> both_families_udponly = { +// std::make_pair<int, bool>(AF_INET, false), +// std::make_pair<int, bool>(AF_INET6, false) +//}; +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockChannelTestAI, + ::testing::Values(std::make_pair<int, bool>(AF_INET, false))); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockUDPChannelTestAI, + ::testing::ValuesIn(ares::test::families)); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockTCPChannelTestAI, + ::testing::ValuesIn(ares::test::families)); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockExtraOptsTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockNoCheckRespChannelTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockEDNSChannelTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + +INSTANTIATE_TEST_CASE_P(TransportModesAI, RotateMultiMockTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + +INSTANTIATE_TEST_CASE_P(TransportModesAI, NoRotateMultiMockTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + + +} // namespace test +} // namespace ares |