test: Add various additional tests

pull/34/head
David Drysdale 9 years ago
parent 5da3201a05
commit 79dc327a2d
  1. 201
      test/ares-test-live.cc
  2. 90
      test/ares-test-misc.cc
  3. 297
      test/ares-test-parse.cc
  4. 4
      test/ares-test.cc
  5. 26
      test/ares-test.h
  6. 7
      test/dns-proto.cc
  7. 3
      test/dns-proto.h

@ -1,5 +1,7 @@
// This file includes tests that attempt to do real lookups
// of DNS names using the local machine's live infrastructure.
// As a result, we don't check the results very closely, to allow
// for varying local configurations.
#include "ares-test.h"
@ -8,6 +10,12 @@
namespace ares {
namespace test {
// Use the address of Google's public DNS servers as example addresses that are
// likely to be accessible everywhere/everywhen.
unsigned char gdns_addr4[4] = {0x08, 0x08, 0x08, 0x08};
unsigned char gdns_addr6[16] = {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88};
TEST_F(DefaultChannelTest, LiveGetHostByNameV4) {
HostResult result;
ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
@ -30,8 +38,7 @@ TEST_F(DefaultChannelTest, LiveGetHostByNameV6) {
TEST_F(DefaultChannelTest, LiveGetHostByAddrV4) {
HostResult result;
unsigned char addr[4] = {8, 8, 8, 8};
ares_gethostbyaddr(channel_, addr, sizeof(addr), AF_INET, HostCallback, &result);
ares_gethostbyaddr(channel_, gdns_addr4, sizeof(gdns_addr4), AF_INET, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_SUCCESS, result.status_);
@ -41,9 +48,7 @@ TEST_F(DefaultChannelTest, LiveGetHostByAddrV4) {
TEST_F(DefaultChannelTest, LiveGetHostByAddrV6) {
HostResult result;
unsigned char addr[16] = {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88};
ares_gethostbyaddr(channel_, addr, sizeof(addr), AF_INET6, HostCallback, &result);
ares_gethostbyaddr(channel_, gdns_addr6, sizeof(gdns_addr6), AF_INET6, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_SUCCESS, result.status_);
@ -51,7 +56,101 @@ TEST_F(DefaultChannelTest, LiveGetHostByAddrV6) {
EXPECT_EQ(AF_INET6, result.host_.addrtype_);
}
TEST_F(DefaultChannelTest, LiveGetHostByAddrFailFamily) {
TEST_P(DefaultChannelModeTest, LiveGetLocalhostByNameV4) {
HostResult result;
ares_gethostbyname(channel_, "localhost", AF_INET, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
if (result.status_ != ARES_ENOTFOUND) {
EXPECT_EQ(ARES_SUCCESS, result.status_);
EXPECT_EQ(1, (int)result.host_.addrs_.size());
EXPECT_EQ(AF_INET, result.host_.addrtype_);
EXPECT_NE(std::string::npos, result.host_.name_.find("localhost"));
}
}
TEST_P(DefaultChannelModeTest, LiveGetLocalhostByNameV6) {
HostResult result;
ares_gethostbyname(channel_, "localhost", AF_INET6, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
if (result.status_ == ARES_SUCCESS) {
EXPECT_EQ(1, (int)result.host_.addrs_.size());
EXPECT_EQ(AF_INET6, result.host_.addrtype_);
std::stringstream ss;
ss << HostEnt(result.host_);
EXPECT_NE(std::string::npos, result.host_.name_.find("localhost"));
}
}
TEST_P(DefaultChannelModeTest, LiveGetLocalhostByNameIPV4) {
HostResult result;
ares_gethostbyname(channel_, "127.0.0.1", AF_INET, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_SUCCESS, result.status_);
EXPECT_EQ(1, (int)result.host_.addrs_.size());
EXPECT_EQ(AF_INET, result.host_.addrtype_);
std::stringstream ss;
ss << HostEnt(result.host_);
EXPECT_EQ("{'127.0.0.1' aliases=[] addrs=[127.0.0.1]}", ss.str());
}
TEST_P(DefaultChannelModeTest, LiveGetLocalhostByNameIPV6) {
HostResult result;
ares_gethostbyname(channel_, "::1", AF_INET6, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
if (result.status_ != ARES_ENOTFOUND) {
EXPECT_EQ(ARES_SUCCESS, result.status_);
EXPECT_EQ(1, (int)result.host_.addrs_.size());
EXPECT_EQ(AF_INET6, result.host_.addrtype_);
std::stringstream ss;
ss << HostEnt(result.host_);
EXPECT_EQ("{'::1' aliases=[] addrs=[0000:0000:0000:0000:0000:0000:0000:0001]}", ss.str());
}
}
TEST_P(DefaultChannelModeTest, LiveGetLocalhostFailFamily) {
HostResult result;
ares_gethostbyname(channel_, "127.0.0.1", AF_INET+AF_INET6, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_ENOTIMP, result.status_);
}
TEST_P(DefaultChannelModeTest, LiveGetLocalhostByAddrV4) {
HostResult result;
struct in_addr addr;
addr.s_addr = htonl(INADDR_LOOPBACK);
ares_gethostbyaddr(channel_, &addr, sizeof(addr), AF_INET, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
if (result.status_ != ARES_ENOTFOUND) {
EXPECT_EQ(ARES_SUCCESS, result.status_);
EXPECT_LT(0, (int)result.host_.addrs_.size());
EXPECT_EQ(AF_INET, result.host_.addrtype_);
EXPECT_NE(std::string::npos,
result.host_.name_.find("localhost"));
}
}
TEST_P(DefaultChannelModeTest, LiveGetLocalhostByAddrV6) {
HostResult result;
struct in6_addr addr = in6addr_loopback;
ares_gethostbyaddr(channel_, &addr, sizeof(addr), AF_INET6, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
if (result.status_ != ARES_ENOTFOUND) {
EXPECT_EQ(ARES_SUCCESS, result.status_);
EXPECT_LT(0, (int)result.host_.addrs_.size());
EXPECT_EQ(AF_INET6, result.host_.addrtype_);
EXPECT_NE(std::string::npos,
result.host_.name_.find("localhost"));
}
}
TEST_P(DefaultChannelModeTest, LiveGetHostByAddrFailFamily) {
HostResult result;
unsigned char addr[4] = {8, 8, 8, 8};
ares_gethostbyaddr(channel_, addr, sizeof(addr), AF_INET6+AF_INET,
@ -60,7 +159,7 @@ TEST_F(DefaultChannelTest, LiveGetHostByAddrFailFamily) {
EXPECT_EQ(ARES_ENOTIMP, result.status_);
}
TEST_F(DefaultChannelTest, LiveGetHostByAddrFailAddrSize) {
TEST_P(DefaultChannelModeTest, LiveGetHostByAddrFailAddrSize) {
HostResult result;
unsigned char addr[4] = {8, 8, 8, 8};
ares_gethostbyaddr(channel_, addr, sizeof(addr) - 1, AF_INET,
@ -69,7 +168,7 @@ TEST_F(DefaultChannelTest, LiveGetHostByAddrFailAddrSize) {
EXPECT_EQ(ARES_ENOTIMP, result.status_);
}
TEST_F(DefaultChannelTest, LiveGetHostByAddrFailAlloc) {
TEST_P(DefaultChannelModeTest, LiveGetHostByAddrFailAlloc) {
HostResult result;
unsigned char addr[4] = {8, 8, 8, 8};
SetAllocFail(1);
@ -79,6 +178,9 @@ TEST_F(DefaultChannelTest, LiveGetHostByAddrFailAlloc) {
EXPECT_EQ(ARES_ENOMEM, result.status_);
}
INSTANTIATE_TEST_CASE_P(Modes, DefaultChannelModeTest,
::testing::Values("f", "b", "fb", "bf"));
TEST_F(DefaultChannelTest, LiveSearchA) {
SearchResult result;
ares_search(channel_, "www.facebook.com.", ns_c_in, ns_t_a,
@ -88,6 +190,15 @@ TEST_F(DefaultChannelTest, LiveSearchA) {
EXPECT_EQ(ARES_SUCCESS, result.status_);
}
TEST_F(DefaultChannelTest, LiveSearchEmptyA) {
SearchResult result;
ares_search(channel_, "", ns_c_in, ns_t_a,
SearchCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_NE(ARES_SUCCESS, result.status_);
}
TEST_F(DefaultChannelTest, LiveSearchNS) {
SearchResult result;
ares_search(channel_, "google.com.", ns_c_in, ns_t_ns,
@ -124,6 +235,15 @@ TEST_F(DefaultChannelTest, LiveSearchSOA) {
EXPECT_EQ(ARES_SUCCESS, result.status_);
}
TEST_F(DefaultChannelTest, LiveSearchSRV) {
SearchResult result;
ares_search(channel_, "_imap._tcp.gmail.com.", ns_c_in, ns_t_srv,
SearchCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_SUCCESS, result.status_);
}
TEST_F(DefaultChannelTest, LiveSearchANY) {
SearchResult result;
ares_search(channel_, "facebook.com.", ns_c_in, ns_t_any,
@ -133,7 +253,7 @@ TEST_F(DefaultChannelTest, LiveSearchANY) {
EXPECT_EQ(ARES_SUCCESS, result.status_);
}
TEST_F(DefaultChannelTest, LiveGetNameInfo) {
TEST_F(DefaultChannelTest, LiveGetNameInfoV4) {
NameInfoResult result;
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
@ -148,5 +268,68 @@ TEST_F(DefaultChannelTest, LiveGetNameInfo) {
EXPECT_EQ(ARES_SUCCESS, result.status_);
}
TEST_F(DefaultChannelTest, LiveGetNameInfoV6) {
NameInfoResult result;
struct sockaddr_in6 sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin6_family = AF_INET6;
sockaddr.sin6_port = htons(53);
memcpy(sockaddr.sin6_addr.s6_addr, gdns_addr6, 16);
ares_getnameinfo(channel_, (const struct sockaddr*)&sockaddr, sizeof(sockaddr),
ARES_NI_LOOKUPHOST|ARES_NI_LOOKUPSERVICE|ARES_NI_UDP,
NameInfoCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_SUCCESS, result.status_);
}
TEST_F(DefaultChannelTest, LiveGetNameInvalidFamily) {
NameInfoResult result;
struct sockaddr_in6 sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin6_family = AF_INET6 + AF_INET;
sockaddr.sin6_port = htons(53);
memcpy(sockaddr.sin6_addr.s6_addr, gdns_addr6, 16);
ares_getnameinfo(channel_, (const struct sockaddr*)&sockaddr, sizeof(sockaddr),
ARES_NI_LOOKUPHOST|ARES_NI_LOOKUPSERVICE|ARES_NI_UDP,
NameInfoCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_ENOTIMP, result.status_);
}
TEST_F(DefaultChannelTest, LiveGetServiceInfo) {
NameInfoResult result;
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(53);
sockaddr.sin_addr.s_addr = htonl(0x08080808);
// Just look up service info
ares_getnameinfo(channel_, (const struct sockaddr*)&sockaddr, sizeof(sockaddr),
ARES_NI_LOOKUPSERVICE|ARES_NI_UDP,
NameInfoCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_SUCCESS, result.status_);
EXPECT_EQ("", result.node_);
}
TEST_F(DefaultChannelTest, LiveGetNameInfoAllocFail) {
NameInfoResult result;
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(53);
sockaddr.sin_addr.s_addr = htonl(0x08080808);
SetAllocFail(1);
ares_getnameinfo(channel_, (const struct sockaddr*)&sockaddr, sizeof(sockaddr),
ARES_NI_LOOKUPHOST|ARES_NI_LOOKUPSERVICE|ARES_NI_UDP,
NameInfoCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_ENOMEM, result.status_);
}
} // namespace test
} // namespace ares

@ -207,6 +207,60 @@ TEST_F(LibraryTest, CreateQueryFailures) {
&p, &len, 0));
}
std::string ExpandName(const std::vector<byte>& data, ssize_t offset,
long *enclen) {
char *name = nullptr;
int rc = ares_expand_name(data.data() + offset, data.data(), data.size(),
&name, enclen);
EXPECT_EQ(ARES_SUCCESS, rc);
std::string result;
if (rc == ARES_SUCCESS) {
result = name;
} else {
result = "<error>";
}
free(name);
return result;
}
TEST_F(LibraryTest, ExpandName) {
long enclen;
std::vector<byte> data1 = {1, 'a', 2, 'b', 'c', 3, 'd', 'e', 'f', 0};
EXPECT_EQ("a.bc.def", ExpandName(data1, 0, &enclen));
EXPECT_EQ(data1.size(), enclen);
std::vector<byte> data2 = {0};
EXPECT_EQ("", ExpandName(data2, 0, &enclen));
EXPECT_EQ(1, enclen);
// Complete name indirection
std::vector<byte> data3 = {0x12, 0x23,
3, 'd', 'e', 'f', 0,
0xC0, 2};
EXPECT_EQ("def", ExpandName(data3, 2, &enclen));
EXPECT_EQ(5, enclen);
EXPECT_EQ("def", ExpandName(data3, 7, &enclen));
EXPECT_EQ(2, enclen);
// One label then indirection
std::vector<byte> data4 = {0x12, 0x23,
3, 'd', 'e', 'f', 0,
1, 'a', 0xC0, 2};
EXPECT_EQ("def", ExpandName(data4, 2, &enclen));
EXPECT_EQ(5, enclen);
EXPECT_EQ("a.def", ExpandName(data4, 7, &enclen));
EXPECT_EQ(4, enclen);
// Two labels then indirection
std::vector<byte> data5 = {0x12, 0x23,
3, 'd', 'e', 'f', 0,
1, 'a', 1, 'b', 0xC0, 2};
EXPECT_EQ("def", ExpandName(data5, 2, &enclen));
EXPECT_EQ(5, enclen);
EXPECT_EQ("a.b.def", ExpandName(data5, 7, &enclen));
EXPECT_EQ(6, enclen);
}
TEST_F(LibraryTest, ExpandNameFailure) {
std::vector<byte> data1 = {0x03, 'c', 'o', 'm', 0x00};
char *name = nullptr;
@ -216,21 +270,37 @@ TEST_F(LibraryTest, ExpandNameFailure) {
ares_expand_name(data1.data(), data1.data(), data1.size(),
&name, &enclen));
// Empty packet
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data1.data(), data1.data(), 0, &name, &enclen));
// Start beyond enclosing data
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data1.data() + data1.size(), data1.data(), data1.size(),
&name, &enclen));
// Length beyond size of enclosing data
std::vector<byte> data2 = {0x13, 'c', 'o', 'm', 0x00};
std::vector<byte> data2a = {0x13, 'c', 'o', 'm', 0x00};
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data2.data(), data2.data(), data2.size(),
ares_expand_name(data2a.data(), data2a.data(), data2a.size(),
&name, &enclen));
std::vector<byte> data2b = {0x1};
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data2b.data(), data2b.data(), data2b.size(),
&name, &enclen));
std::vector<byte> data2c = {0xC0};
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data2c.data(), data2c.data(), data2c.size(),
&name, &enclen));
// Indirection beyond enclosing data
std::vector<byte> data3 = {0xCA, 'c', 'o', 'm', 0x00};
std::vector<byte> data3a = {0xC0, 0x02};
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data3a.data(), data3a.data(), data3a.size(),
&name, &enclen));
std::vector<byte> data3b = {0xC0, 0x0A, 'c', 'o', 'm', 0x00};
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data3.data(), data3.data(), data3.size(),
ares_expand_name(data3b.data(), data3b.data(), data3b.size(),
&name, &enclen));
// Invalid top bits in label length
@ -256,11 +326,21 @@ TEST_F(LibraryTest, ExpandNameFailure) {
ares_expand_name(data6.data() + 5, data6.data(), data6.size(),
&name, &enclen));
// Indirection loop
// Indirection loops
std::vector<byte> data7 = {0xC0, 0x02, 0xC0, 0x00};
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data7.data(), data7.data(), data7.size(),
&name, &enclen));
std::vector<byte> data8 = {3, 'd', 'e', 'f', 0xC0, 0x08, 0x00, 0x00,
3, 'a', 'b', 'c', 0xC0, 0x00};
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data8.data(), data8.data(), data8.size(),
&name, &enclen));
std::vector<byte> data9 = {0x12, 0x23, // start 2 bytes in
3, 'd', 'e', 'f', 0xC0, 0x02};
EXPECT_EQ(ARES_EBADNAME,
ares_expand_name(data9.data() + 2, data9.data(), data9.size(),
&name, &enclen));
}
TEST_F(LibraryTest, CreateEDNSQuery) {

@ -11,7 +11,7 @@ TEST_F(LibraryTest, ParseAReplyOK) {
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_aa()
.add_question(new DNSQuestion("example.com", ns_t_a))
.add_answer(new DNSARR("example.com", 0x01020304, {0x02, 0x03, 0x04, 0x05}));
.add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5}));
std::vector<byte> data = {
0x12, 0x34, // qid
0x84, // response + query + AA + not-TC + not-RD
@ -46,6 +46,7 @@ TEST_F(LibraryTest, ParseAReplyOK) {
EXPECT_EQ(0x01020304, info[0].ttl);
unsigned long expected_addr = htonl(0x02030405);
EXPECT_EQ(expected_addr, info[0].ipaddr.s_addr);
EXPECT_EQ("2.3.4.5", AddressToString(&(info[0].ipaddr), 4));
ASSERT_NE(nullptr, host);
std::stringstream ss;
ss << HostEnt(host);
@ -53,6 +54,106 @@ TEST_F(LibraryTest, ParseAReplyOK) {
ares_free_hostent(host);
}
TEST_F(LibraryTest, ParseAReplyVariantA) {
DNSPacket pkt;
pkt.set_qid(6366).set_rd().set_ra()
.add_question(new DNSQuestion("mit.edu", ns_t_a))
.add_answer(new DNSARR("mit.edu", 52, {18,7,22,69}))
.add_auth(new DNSNsRR("mit.edu", 292, "W20NS.mit.edu"))
.add_auth(new DNSNsRR("mit.edu", 292, "BITSY.mit.edu"))
.add_auth(new DNSNsRR("mit.edu", 292, "STRAWB.mit.edu"))
.add_additional(new DNSARR("STRAWB.mit.edu", 292, {18,71,0,151}));
struct hostent *host = nullptr;
struct ares_addrttl info[2];
int count = 2;
std::vector<byte> data = pkt.data();
EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
&host, info, &count));
EXPECT_EQ(1, count);
EXPECT_EQ("18.7.22.69", AddressToString(&(info[0].ipaddr), 4));
EXPECT_EQ(52, info[0].ttl);
ares_free_hostent(host);
}
TEST_F(LibraryTest, ParseAReplyVariantCname) {
DNSPacket pkt;
pkt.set_qid(6366).set_rd().set_ra()
.add_question(new DNSQuestion("query.example.com", ns_t_a))
.add_answer(new DNSCnameRR("query.example.com", 300, "redirect.query.example.com"))
.add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,22}))
.add_auth(new DNSNsRR("example.com", 218, "aa.ns1.example.com"))
.add_auth(new DNSNsRR("example.com", 218, "ns2.example.com"))
.add_auth(new DNSNsRR("example.com", 218, "ns3.example.com"))
.add_auth(new DNSNsRR("example.com", 218, "ns4.example.com"))
.add_additional(new DNSARR("aa.ns1.example.com", 218, {129,97,1,1}))
.add_additional(new DNSARR("ns2.example.com", 218, {129,97,1,2}))
.add_additional(new DNSARR("ns3.example.com", 218, {129,97,1,3}))
.add_additional(new DNSARR("ns4.example.com", 218, {129,97,1,4}));
struct hostent *host = nullptr;
struct ares_addrttl info[2];
int count = 2;
std::vector<byte> data = pkt.data();
EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
&host, info, &count));
EXPECT_EQ(1, count);
EXPECT_EQ("129.97.123.22", AddressToString(&(info[0].ipaddr), 4));
EXPECT_EQ(300, info[0].ttl);
ares_free_hostent(host);
}
TEST_F(LibraryTest, ParseAReplyVariantCnameChain) {
DNSPacket pkt;
pkt.set_qid(6366).set_rd().set_ra()
.add_question(new DNSQuestion("c1.localhost", ns_t_a))
.add_answer(new DNSCnameRR("c1.localhost", 604800, "c2.localhost"))
.add_answer(new DNSCnameRR("c2.localhost", 604800, "c3.localhost"))
.add_answer(new DNSCnameRR("c3.localhost", 604800, "c4.localhost"))
.add_answer(new DNSARR("c4.localhost", 604800, {8,8,8,8}))
.add_auth(new DNSNsRR("localhost", 604800, "localhost"))
.add_additional(new DNSARR("localhost", 604800, {127,0,0,1}))
.add_additional(new DNSAaaaRR("localhost", 604800,
{0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}));
struct hostent *host = nullptr;
struct ares_addrttl info[2];
int count = 2;
std::vector<byte> data = pkt.data();
EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
&host, info, &count));
EXPECT_EQ(1, count);
EXPECT_EQ("8.8.8.8", AddressToString(&(info[0].ipaddr), 4));
EXPECT_EQ(604800, info[0].ttl);
ares_free_hostent(host);
}
TEST_F(LibraryTest, DISABLED_ParseAReplyVariantCnameLast) {
DNSPacket pkt;
pkt.set_qid(6366).set_rd().set_ra()
.add_question(new DNSQuestion("query.example.com", ns_t_a))
.add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,221}))
.add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,222}))
.add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,223}))
.add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,224}))
.add_answer(new DNSCnameRR("query.example.com", 60, "redirect.query.example.com"))
.add_additional(new DNSTxtRR("query.example.com", 60, {"text record"}));
struct hostent *host = nullptr;
struct ares_addrttl info[8];
int count = 8;
std::vector<byte> data = pkt.data();
EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
&host, info, &count));
EXPECT_EQ(4, count);
EXPECT_EQ("129.97.123.221", AddressToString(&(info[0].ipaddr), 4));
EXPECT_EQ("129.97.123.222", AddressToString(&(info[1].ipaddr), 4));
EXPECT_EQ("129.97.123.223", AddressToString(&(info[2].ipaddr), 4));
EXPECT_EQ("129.97.123.224", AddressToString(&(info[3].ipaddr), 4));
EXPECT_EQ(300, info[0].ttl);
EXPECT_EQ(300, info[1].ttl);
EXPECT_EQ(300, info[2].ttl);
EXPECT_EQ(300, info[3].ttl);
ares_free_hostent(host);
}
TEST_F(LibraryTest, ParseAReplyErrors) {
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_aa()
@ -249,6 +350,30 @@ TEST_F(LibraryTest, ParsePtrReplyOK) {
ares_free_hostent(host);
}
TEST_F(LibraryTest, ParsePtrReplyAdditional) {
byte addrv4[4] = {0x10, 0x20, 0x30, 0x40};
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_aa()
.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", ns_t_ptr))
.add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 55, "other.com"))
.add_auth(new DNSNsRR("16.in-addr.arpa", 234, "ns1.other.com"))
.add_auth(new DNSNsRR("16.in-addr.arpa", 234, "bb.ns2.other.com"))
.add_auth(new DNSNsRR("16.in-addr.arpa", 234, "ns3.other.com"))
.add_additional(new DNSARR("ns1.other.com", 229, {10,20,30,41}))
.add_additional(new DNSARR("bb.ns2.other.com", 229, {10,20,30,42}))
.add_additional(new DNSARR("ns3.other.com", 229, {10,20,30,43}));
std::vector<byte> data = pkt.data();
struct hostent *host = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), data.size(),
addrv4, sizeof(addrv4), AF_INET, &host));
ASSERT_NE(nullptr, host);
std::stringstream ss;
ss << HostEnt(host);
EXPECT_EQ("{'other.com' aliases=[other.com] addrs=[16.32.48.64]}", ss.str());
ares_free_hostent(host);
}
TEST_F(LibraryTest, ParseNsReplyOK) {
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_aa()
@ -265,6 +390,29 @@ TEST_F(LibraryTest, ParseNsReplyOK) {
ares_free_hostent(host);
}
TEST_F(LibraryTest, ParseNsReplyMultiple) {
DNSPacket pkt;
pkt.set_qid(10501).set_response().set_rd().set_ra()
.add_question(new DNSQuestion("google.com", ns_t_ns))
.add_answer(new DNSNsRR("google.com", 59, "ns1.google.com"))
.add_answer(new DNSNsRR("google.com", 59, "ns2.google.com"))
.add_answer(new DNSNsRR("google.com", 59, "ns3.google.com"))
.add_answer(new DNSNsRR("google.com", 59, "ns4.google.com"))
.add_additional(new DNSARR("ns4.google.com", 247, {216,239,38,10}))
.add_additional(new DNSARR("ns2.google.com", 247, {216,239,34,10}))
.add_additional(new DNSARR("ns1.google.com", 247, {216,239,32,10}))
.add_additional(new DNSARR("ns3.google.com", 247, {216,239,36,10}));
std::vector<byte> data = pkt.data();
struct hostent *host = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_parse_ns_reply(data.data(), data.size(), &host));
ASSERT_NE(nullptr, host);
std::stringstream ss;
ss << HostEnt(host);
EXPECT_EQ("{'google.com' aliases=[ns1.google.com, ns2.google.com, ns3.google.com, ns4.google.com] addrs=[]}", ss.str());
ares_free_hostent(host);
}
TEST_F(LibraryTest, ParseSrvReplyOK) {
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_aa()
@ -293,6 +441,153 @@ TEST_F(LibraryTest, ParseSrvReplyOK) {
ares_free_data(srv);
}
TEST_F(LibraryTest, ParseSrvReplySingle) {
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_aa()
.add_question(new DNSQuestion("example.abc.def.com", ns_t_srv))
.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com"))
.add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com"))
.add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com"))
.add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com"))
.add_auth(new DNSNsRR("abc.def.com", 44, "else4.where.com"))
.add_auth(new DNSNsRR("abc.def.com", 44, "else5.where.com"))
.add_additional(new DNSARR("else2.where.com", 42, {172,19,0,1}))
.add_additional(new DNSARR("else5.where.com", 42, {172,19,0,2}));
std::vector<byte> data = pkt.data();
struct ares_srv_reply* srv = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv));
ASSERT_NE(nullptr, srv);
EXPECT_EQ("example.abc.def.com", std::string(srv->host));
EXPECT_EQ(0, srv->priority);
EXPECT_EQ(10, srv->weight);
EXPECT_EQ(8160, srv->port);
EXPECT_EQ(nullptr, srv->next);
ares_free_data(srv);
}
TEST_F(LibraryTest, ParseSrvReplyMultiple) {
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_ra().set_rd()
.add_question(new DNSQuestion("srv.example.com", ns_t_srv))
.add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com"))
.add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com"))
.add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com"))
.add_auth(new DNSNsRR("example.com", 300, "ns1.example.com"))
.add_auth(new DNSNsRR("example.com", 300, "ns2.example.com"))
.add_auth(new DNSNsRR("example.com", 300, "ns3.example.com"))
.add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1}))
.add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2}))
.add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3}))
.add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1}))
.add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2}))
.add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3}));
std::vector<byte> data = pkt.data();
struct ares_srv_reply* srv0 = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0));
ASSERT_NE(nullptr, srv0);
struct ares_srv_reply* srv = srv0;
EXPECT_EQ("a1.srv.example.com", std::string(srv->host));
EXPECT_EQ(0, srv->priority);
EXPECT_EQ(5, srv->weight);
EXPECT_EQ(6789, srv->port);
EXPECT_NE(nullptr, srv->next);
srv = srv->next;
EXPECT_EQ("a2.srv.example.com", std::string(srv->host));
EXPECT_EQ(0, srv->priority);
EXPECT_EQ(5, srv->weight);
EXPECT_EQ(4567, srv->port);
EXPECT_NE(nullptr, srv->next);
srv = srv->next;
EXPECT_EQ("a3.srv.example.com", std::string(srv->host));
EXPECT_EQ(0, srv->priority);
EXPECT_EQ(5, srv->weight);
EXPECT_EQ(5678, srv->port);
EXPECT_EQ(nullptr, srv->next);
ares_free_data(srv0);
}
TEST_F(LibraryTest, ParseSrvReplyCname) {
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_aa()
.add_question(new DNSQuestion("example.abc.def.com", ns_t_srv))
.add_answer(new DNSCnameRR("example.abc.def.com", 300, "cname.abc.def.com"))
.add_answer(new DNSSrvRR("cname.abc.def.com", 300, 0, 10, 1234, "srv.abc.def.com"))
.add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com"))
.add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com"))
.add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com"))
.add_additional(new DNSARR("example.abc.def.com", 300, {172,19,0,1}))
.add_additional(new DNSARR("else1.where.com", 42, {172,19,0,1}))
.add_additional(new DNSARR("else2.where.com", 42, {172,19,0,2}))
.add_additional(new DNSARR("else3.where.com", 42, {172,19,0,3}));
std::vector<byte> data = pkt.data();
struct ares_srv_reply* srv = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv));
ASSERT_NE(nullptr, srv);
EXPECT_EQ("srv.abc.def.com", std::string(srv->host));
EXPECT_EQ(0, srv->priority);
EXPECT_EQ(10, srv->weight);
EXPECT_EQ(1234, srv->port);
EXPECT_EQ(nullptr, srv->next);
ares_free_data(srv);
}
TEST_F(LibraryTest, ParseSrvReplyCnameMultiple) {
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_ra().set_rd()
.add_question(new DNSQuestion("query.example.com", ns_t_srv))
.add_answer(new DNSCnameRR("query.example.com", 300, "srv.example.com"))
.add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com"))
.add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com"))
.add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com"))
.add_auth(new DNSNsRR("example.com", 300, "ns1.example.com"))
.add_auth(new DNSNsRR("example.com", 300, "ns2.example.com"))
.add_auth(new DNSNsRR("example.com", 300, "ns3.example.com"))
.add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1}))
.add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2}))
.add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3}))
.add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1}))
.add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2}))
.add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3}));
std::vector<byte> data = pkt.data();
struct ares_srv_reply* srv0 = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0));
ASSERT_NE(nullptr, srv0);
struct ares_srv_reply* srv = srv0;
EXPECT_EQ("a1.srv.example.com", std::string(srv->host));
EXPECT_EQ(0, srv->priority);
EXPECT_EQ(5, srv->weight);
EXPECT_EQ(6789, srv->port);
EXPECT_NE(nullptr, srv->next);
srv = srv->next;
EXPECT_EQ("a2.srv.example.com", std::string(srv->host));
EXPECT_EQ(0, srv->priority);
EXPECT_EQ(5, srv->weight);
EXPECT_EQ(4567, srv->port);
EXPECT_NE(nullptr, srv->next);
srv = srv->next;
EXPECT_EQ("a3.srv.example.com", std::string(srv->host));
EXPECT_EQ(0, srv->priority);
EXPECT_EQ(5, srv->weight);
EXPECT_EQ(5678, srv->port);
EXPECT_EQ(nullptr, srv->next);
ares_free_data(srv0);
}
TEST_F(LibraryTest, ParseMxReplyOK) {
DNSPacket pkt;
pkt.set_qid(0x1234).set_response().set_aa()

@ -119,6 +119,10 @@ void DefaultChannelTest::Process() {
ProcessWork(channel_, -1, nullptr);
}
void DefaultChannelModeTest::Process() {
ProcessWork(channel_, -1, nullptr);
}
MockServer::MockServer(int port) : port_(port) {
// Create a UDP socket to receive data on.
sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);

@ -75,6 +75,32 @@ class DefaultChannelTest : public LibraryTest {
ares_channel channel_;
};
// Test fixture that uses a default channel with the specified lookup mode.
class DefaultChannelModeTest
: public LibraryTest,
public ::testing::WithParamInterface<std::string> {
public:
DefaultChannelModeTest() : channel_(nullptr) {
struct ares_options opts = {0};
opts.lookups = strdup(GetParam().c_str());
int optmask = ARES_OPT_LOOKUPS;
EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel_, &opts, optmask));
EXPECT_NE(nullptr, channel_);
free(opts.lookups);
}
~DefaultChannelModeTest() {
ares_destroy(channel_);
channel_ = nullptr;
}
// Process all pending work on ares-owned file descriptors.
void Process();
protected:
ares_channel channel_;
};
// Mock DNS server to allow responses to be scripted by tests.
class MockServer {
public:

@ -150,7 +150,8 @@ std::string ClassToString(int qclass) {
}
}
std::string AddressToString(const byte* addr, int len) {
std::string AddressToString(const void* vaddr, int len) {
const byte* addr = reinterpret_cast<const byte*>(vaddr);
std::stringstream ss;
if (len == 4) {
char buffer[4*4 + 3 + 1];
@ -173,10 +174,6 @@ std::string AddressToString(const byte* addr, int len) {
return ss.str();
}
std::string AddressToString(const char* addr, int len) {
return AddressToString(reinterpret_cast<const byte*>(addr), len);
}
std::string PacketToString(const std::vector<byte>& packet) {
const byte* data = packet.data();
int len = packet.size();

@ -22,8 +22,7 @@ std::string StatusToString(int status);
std::string RcodeToString(int rcode);
std::string RRTypeToString(int rrtype);
std::string ClassToString(int qclass);
std::string AddressToString(const byte* addr, int len);
std::string AddressToString(const char* addr, int len);
std::string AddressToString(const void* addr, int len);
// Convert DNS protocol data to strings.
// Note that these functions are not defensive; they assume

Loading…
Cancel
Save