test: More initialization tests

pull/34/head
David Drysdale 9 years ago
parent ff1f7a1c3c
commit 86beb81892
  1. 174
      test/ares-test-init.cc
  2. 48
      test/ares-test-mock.cc

@ -297,8 +297,32 @@ TEST(Init, NoLibraryInit) {
// These tests rely on the ability of non-root users to create a chroot // These tests rely on the ability of non-root users to create a chroot
// using Linux namespaces. // using Linux namespaces.
// The library uses a variety of information sources to initialize a channel,
// in particular to determine:
// - search: the search domains to use
// - servers: the name servers to use
// - lookup: whether to check files or DNS or both (e.g. "fb")
// - options: various resolver options
// - sortlist: the order of preference for IP addresses
//
// The first source from the following list is used:
// - init_by_options(): explicitly specified values in struct ares_options
// - init_by_environment(): values from the environment:
// - LOCALDOMAIN -> search (single value)
// - RES_OPTIONS -> options
// - init_by_resolv_conf(): values from various config files:
// - /etc/resolv.conf -> search, lookup, servers, sortlist, options
// - /etc/nsswitch.conf -> lookup
// - /etc/host.conf -> lookup
// - /etc/svc.conf -> lookup
// - init_by_defaults(): fallback values:
// - gethostname(3) -> domain
// - "fb" -> lookup
NameContentList filelist = { NameContentList filelist = {
{"/etc/resolv.conf", "nameserver 1.2.3.4\n" {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
"sortlist 1.2.3.4/16 2.3.4.5\n"
"search first.com second.com\n"}, "search first.com second.com\n"},
{"/etc/hosts", "3.4.5.6 ahostname.com\n"}, {"/etc/hosts", "3.4.5.6 ahostname.com\n"},
{"/etc/nsswitch.conf", "hosts: files\n"}}; {"/etc/nsswitch.conf", "hosts: files\n"}};
@ -325,8 +349,158 @@ CONTAINED_TEST_F(LibraryTest, ContainerChannelInit,
std::stringstream ss; std::stringstream ss;
ss << result.host_; ss << result.host_;
EXPECT_EQ("{'ahostname.com' aliases=[] addrs=[3.4.5.6]}", ss.str()); EXPECT_EQ("{'ahostname.com' aliases=[] addrs=[3.4.5.6]}", ss.str());
ares_destroy(channel);
return HasFailure();
}
NameContentList fullresolv = {
{"/etc/resolv.conf", " nameserver 1.2.3.4 \n"
"search first.com second.com\n"
"lookup bind\n"
"options debug ndots:5\n"
"sortlist 1.2.3.4/16 2.3.4.5\n"}};
CONTAINED_TEST_F(LibraryTest, ContainerFullResolvInit,
"myhostname", "mydomainname.org", fullresolv) {
ares_channel channel = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
struct ares_options opts;
int optmask = 0;
ares_save_options(channel, &opts, &optmask);
EXPECT_EQ(std::string("b"), std::string(opts.lookups));
EXPECT_EQ(5, opts.ndots);
ares_destroy_options(&opts);
ares_destroy(channel);
return HasFailure(); return HasFailure();
} }
NameContentList hostconf = {
{"/etc/resolv.conf", "nameserver 1.2.3.4\n"
"sortlist1.2.3.4\n" // malformed line
"search first.com second.com\n"},
{"/etc/host.conf", "order bind hosts\n"}};
CONTAINED_TEST_F(LibraryTest, ContainerHostConfInit,
"myhostname", "mydomainname.org", hostconf) {
ares_channel channel = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
struct ares_options opts;
int optmask = 0;
ares_save_options(channel, &opts, &optmask);
EXPECT_EQ(std::string("bf"), std::string(opts.lookups));
ares_destroy_options(&opts);
ares_destroy(channel);
return HasFailure();
}
NameContentList svcconf = {
{"/etc/resolv.conf", "nameserver 1.2.3.4\n"
"search first.com second.com\n"},
{"/etc/svc.conf", "hosts= bind\n"}};
CONTAINED_TEST_F(LibraryTest, ContainerSvcConfInit,
"myhostname", "mydomainname.org", svcconf) {
ares_channel channel = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
struct ares_options opts;
int optmask = 0;
ares_save_options(channel, &opts, &optmask);
EXPECT_EQ(std::string("b"), std::string(opts.lookups));
ares_destroy_options(&opts);
ares_destroy(channel);
return HasFailure();
}
// Failures when expected config filenames are inaccessible.
class MakeUnreadable {
public:
explicit MakeUnreadable(const std::string& filename)
: filename_(filename) {
chmod(filename_.c_str(), 0000);
}
~MakeUnreadable() { chmod(filename_.c_str(), 0644); }
private:
std::string filename_;
};
CONTAINED_TEST_F(LibraryTest, ContainerResolvConfNotReadable,
"myhostname", "mydomainname.org", filelist) {
ares_channel channel = nullptr;
MakeUnreadable hide("/etc/resolv.conf");
EXPECT_EQ(ARES_EFILE, ares_init(&channel));
return HasFailure();
}
CONTAINED_TEST_F(LibraryTest, ContainerNsswitchConfNotReadable,
"myhostname", "mydomainname.org", filelist) {
ares_channel channel = nullptr;
MakeUnreadable hide("/etc/nsswitch.conf");
EXPECT_EQ(ARES_EFILE, ares_init(&channel));
return HasFailure();
}
CONTAINED_TEST_F(LibraryTest, ContainerHostConfNotReadable,
"myhostname", "mydomainname.org", hostconf) {
ares_channel channel = nullptr;
MakeUnreadable hide("/etc/host.conf");
EXPECT_EQ(ARES_EFILE, ares_init(&channel));
return HasFailure();
}
CONTAINED_TEST_F(LibraryTest, ContainerSvcConfNotReadable,
"myhostname", "mydomainname.org", svcconf) {
ares_channel channel = nullptr;
MakeUnreadable hide("/etc/svc.conf");
EXPECT_EQ(ARES_EFILE, ares_init(&channel));
return HasFailure();
}
NameContentList multiresolv = {
{"/etc/resolv.conf", " nameserver 1::2 ; ;;\n"
" domain first.com\n"},
{"/etc/nsswitch.conf", "hosts: files\n"}};
CONTAINED_TEST_F(LibraryTest, ContainerMultiResolvInit,
"myhostname", "mydomainname.org", multiresolv) {
ares_channel channel = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
std::vector<std::string> actual = GetNameServers(channel);
std::vector<std::string> expected = {"0001:0000:0000:0000:0000:0000:0000:0002"};
EXPECT_EQ(expected, actual);
struct ares_options opts;
int optmask = 0;
ares_save_options(channel, &opts, &optmask);
EXPECT_EQ(1, opts.ndomains);
EXPECT_EQ(std::string("first.com"), std::string(opts.domains[0]));
ares_destroy_options(&opts);
ares_destroy(channel);
return HasFailure();
}
NameContentList empty = {}; // no files
CONTAINED_TEST_F(LibraryTest, ContainerEmptyInit,
"host.domain.org", "domain.org", empty) {
ares_channel channel = nullptr;
EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
std::vector<std::string> actual = GetNameServers(channel);
std::vector<std::string> expected = {"127.0.0.1"};
EXPECT_EQ(expected, actual);
struct ares_options opts;
int optmask = 0;
ares_save_options(channel, &opts, &optmask);
EXPECT_EQ(1, opts.ndomains);
EXPECT_EQ(std::string("domain.org"), std::string(opts.domains[0]));
EXPECT_EQ(std::string("fb"), std::string(opts.lookups));
ares_destroy_options(&opts);
ares_destroy(channel);
return HasFailure();
}
#endif #endif
} // namespace test } // namespace test

@ -223,6 +223,48 @@ TEST_P(MockTCPChannelTest, YXDomainResponse) {
EXPECT_EQ(ARES_ENODATA, result.status_); EXPECT_EQ(ARES_ENODATA, result.status_);
} }
class MockExtraOptsTest
: public MockChannelOptsTest,
public ::testing::WithParamInterface< std::pair<int, bool> > {
public:
MockExtraOptsTest()
: 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(MockExtraOptsTest, 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}));
EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a))
.WillOnce(SetReply(&server_, &rsp));
HostResult result;
ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
std::stringstream ss;
ss << result.host_;
EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
}
class MockFlagsChannelOptsTest class MockFlagsChannelOptsTest
: public MockChannelOptsTest, : public MockChannelOptsTest,
public ::testing::WithParamInterface< std::pair<int, bool> > { public ::testing::WithParamInterface< std::pair<int, bool> > {
@ -1002,6 +1044,12 @@ INSTANTIATE_TEST_CASE_P(AddressFamilies, MockUDPChannelTest,
INSTANTIATE_TEST_CASE_P(AddressFamilies, MockTCPChannelTest, INSTANTIATE_TEST_CASE_P(AddressFamilies, MockTCPChannelTest,
::testing::Values(AF_INET, AF_INET6)); ::testing::Values(AF_INET, AF_INET6));
INSTANTIATE_TEST_CASE_P(AddressFamilies, MockExtraOptsTest,
::testing::Values(std::make_pair<int, bool>(AF_INET, false),
std::make_pair<int, bool>(AF_INET, true),
std::make_pair<int, bool>(AF_INET6, false),
std::make_pair<int, bool>(AF_INET6, true)));
INSTANTIATE_TEST_CASE_P(AddressFamilies, MockNoCheckRespChannelTest, INSTANTIATE_TEST_CASE_P(AddressFamilies, MockNoCheckRespChannelTest,
::testing::Values(std::make_pair<int, bool>(AF_INET, false), ::testing::Values(std::make_pair<int, bool>(AF_INET, false),
std::make_pair<int, bool>(AF_INET, true), std::make_pair<int, bool>(AF_INET, true),

Loading…
Cancel
Save