summaryrefslogtreecommitdiff
path: root/test/ares-test.h
diff options
context:
space:
mode:
Diffstat (limited to 'test/ares-test.h')
-rw-r--r--test/ares-test.h383
1 files changed, 0 insertions, 383 deletions
diff --git a/test/ares-test.h b/test/ares-test.h
deleted file mode 100644
index a00e53a..0000000
--- a/test/ares-test.h
+++ /dev/null
@@ -1,383 +0,0 @@
-// -*- mode: c++ -*-
-#ifndef ARES_TEST_H
-#define ARES_TEST_H
-
-#include "ares.h"
-
-#include "dns-proto.h"
-
-// Include ares internal file for DNS protocol constants
-#include "nameser.h"
-
-#include "gtest/gtest.h"
-#include "gmock/gmock.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#if defined(HAVE_USER_NAMESPACE) && defined(HAVE_UTS_NAMESPACE)
-#define HAVE_CONTAINER
-#endif
-
-#include <functional>
-#include <list>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace ares {
-
-typedef unsigned char byte;
-
-namespace test {
-
-extern bool verbose;
-extern int mock_port;
-
-// Process all pending work on ares-owned file descriptors, plus
-// optionally the given set-of-FDs + work function.
-void ProcessWork(ares_channel channel,
- std::function<std::set<int>()> get_extrafds,
- std::function<void(int)> process_extra);
-std::set<int> NoExtraFDs();
-
-// Test fixture that ensures library initialization, and allows
-// memory allocations to be failed.
-class LibraryTest : public ::testing::Test {
- public:
- LibraryTest() {
- EXPECT_EQ(ARES_SUCCESS,
- ares_library_init_mem(ARES_LIB_INIT_ALL,
- &LibraryTest::amalloc,
- &LibraryTest::afree,
- &LibraryTest::arealloc));
- }
- ~LibraryTest() {
- ares_library_cleanup();
- ClearFails();
- }
- // Set the n-th malloc call (of any size) from the library to fail.
- // (nth == 1 means the next call)
- static void SetAllocFail(int nth);
- // Set the next malloc call for the given size to fail.
- static void SetAllocSizeFail(size_t size);
- // Remove any pending alloc failures.
- static void ClearFails();
-
- static void *amalloc(size_t size);
- static void* arealloc(void *ptr, size_t size);
- static void afree(void *ptr);
- private:
- static bool ShouldAllocFail(size_t size);
- static unsigned long long fails_;
- static std::map<size_t, int> size_fails_;
-};
-
-// Test fixture that uses a default channel.
-class DefaultChannelTest : public LibraryTest {
- public:
- DefaultChannelTest() : channel_(nullptr) {
- EXPECT_EQ(ARES_SUCCESS, ares_init(&channel_));
- EXPECT_NE(nullptr, channel_);
- }
-
- ~DefaultChannelTest() {
- ares_destroy(channel_);
- channel_ = nullptr;
- }
-
- // Process all pending work on ares-owned file descriptors.
- void Process();
-
- protected:
- 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:
- MockServer(int family, int port, int tcpport = 0);
- ~MockServer();
-
- // Mock method indicating the processing of a particular <name, RRtype>
- // request.
- MOCK_METHOD2(OnRequest, void(const std::string& name, int rrtype));
-
- // Set the reply to be sent next; the query ID field will be overwritten
- // with the value from the request.
- void SetReplyData(const std::vector<byte>& reply) { reply_ = reply; }
- void SetReply(const DNSPacket* reply) { SetReplyData(reply->data()); }
- void SetReplyQID(int qid) { qid_ = qid; }
-
- // The set of file descriptors that the server handles.
- std::set<int> fds() const;
-
- // Process activity on a file descriptor.
- void ProcessFD(int fd);
-
- // Ports the server is responding to
- int udpport() const { return udpport_; }
- int tcpport() const { return tcpport_; }
-
- private:
- void ProcessRequest(int fd, struct sockaddr_storage* addr, int addrlen,
- int qid, const std::string& name, int rrtype);
-
- int udpport_;
- int tcpport_;
- int udpfd_;
- int tcpfd_;
- std::set<int> connfds_;
- std::vector<byte> reply_;
- int qid_;
-};
-
-// Test fixture that uses a mock DNS server.
-class MockChannelOptsTest : public LibraryTest {
- public:
- MockChannelOptsTest(int count, int family, bool force_tcp, struct ares_options* givenopts, int optmask);
- ~MockChannelOptsTest();
-
- // Process all pending work on ares-owned and mock-server-owned file descriptors.
- void Process();
-
- protected:
- // NiceMockServer doesn't complain about uninteresting calls.
- typedef testing::NiceMock<MockServer> NiceMockServer;
- typedef std::vector< std::unique_ptr<NiceMockServer> > NiceMockServers;
-
- std::set<int> fds() const;
- void ProcessFD(int fd);
-
- static NiceMockServers BuildServers(int count, int family, int base_port);
-
- NiceMockServers servers_;
- // Convenience reference to first server.
- NiceMockServer& server_;
- ares_channel channel_;
-};
-
-class MockChannelTest
- : public MockChannelOptsTest,
- public ::testing::WithParamInterface< std::pair<int, bool> > {
- public:
- MockChannelTest() : MockChannelOptsTest(1, GetParam().first, GetParam().second, nullptr, 0) {}
-};
-
-class MockUDPChannelTest
- : public MockChannelOptsTest,
- public ::testing::WithParamInterface<int> {
- public:
- MockUDPChannelTest() : MockChannelOptsTest(1, GetParam(), false, nullptr, 0) {}
-};
-
-class MockTCPChannelTest
- : public MockChannelOptsTest,
- public ::testing::WithParamInterface<int> {
- public:
- MockTCPChannelTest() : MockChannelOptsTest(1, GetParam(), true, nullptr, 0) {}
-};
-
-// gMock action to set the reply for a mock server.
-ACTION_P2(SetReplyData, mockserver, data) {
- mockserver->SetReplyData(data);
-}
-ACTION_P2(SetReply, mockserver, reply) {
- mockserver->SetReply(reply);
-}
-ACTION_P2(SetReplyQID, mockserver, qid) {
- mockserver->SetReplyQID(qid);
-}
-// gMock action to cancel a channel.
-ACTION_P2(CancelChannel, mockserver, channel) {
- ares_cancel(channel);
-}
-
-// C++ wrapper for struct hostent.
-struct HostEnt {
- HostEnt() : addrtype_(-1) {}
- HostEnt(const struct hostent* hostent);
- std::string name_;
- std::vector<std::string> aliases_;
- int addrtype_; // AF_INET or AF_INET6
- std::vector<std::string> addrs_;
-};
-std::ostream& operator<<(std::ostream& os, const HostEnt& result);
-
-// Structure that describes the result of an ares_host_callback invocation.
-struct HostResult {
- // Whether the callback has been invoked.
- bool done_;
- // Explicitly provided result information.
- int status_;
- int timeouts_;
- // Contents of the hostent structure, if provided.
- HostEnt host_;
-};
-std::ostream& operator<<(std::ostream& os, const HostResult& result);
-
-// Structure that describes the result of an ares_callback invocation.
-struct SearchResult {
- // Whether the callback has been invoked.
- bool done_;
- // Explicitly provided result information.
- int status_;
- int timeouts_;
- std::vector<byte> data_;
-};
-std::ostream& operator<<(std::ostream& os, const SearchResult& result);
-
-// Structure that describes the result of an ares_nameinfo_callback invocation.
-struct NameInfoResult {
- // Whether the callback has been invoked.
- bool done_;
- // Explicitly provided result information.
- int status_;
- int timeouts_;
- std::string node_;
- std::string service_;
-};
-std::ostream& operator<<(std::ostream& os, const NameInfoResult& result);
-
-// Standard implementation of ares callbacks that fill out the corresponding
-// structures.
-void HostCallback(void *data, int status, int timeouts,
- struct hostent *hostent);
-void SearchCallback(void *data, int status, int timeouts,
- unsigned char *abuf, int alen);
-void NameInfoCallback(void *data, int status, int timeouts,
- char *node, char *service);
-
-// Retrieve the name servers used by a channel.
-std::vector<std::string> GetNameServers(ares_channel channel);
-
-
-// RAII class to temporarily create a directory of a given name.
-class TransientDir {
- public:
- TransientDir(const std::string& dirname);
- ~TransientDir();
-
- private:
- std::string dirname_;
-};
-
-// C++ wrapper around tempnam()
-std::string TempNam(const char *dir, const char *prefix);
-
-// RAII class to temporarily create file of a given name and contents.
-class TransientFile {
- public:
- TransientFile(const std::string &filename, const std::string &contents);
- ~TransientFile();
-
- protected:
- std::string filename_;
-};
-
-// RAII class for a temporary file with the given contents.
-class TempFile : public TransientFile {
- public:
- TempFile(const std::string& contents);
- const char* filename() const { return filename_.c_str(); }
-};
-
-#ifndef WIN32
-// RAII class for a temporary environment variable value.
-class EnvValue {
- public:
- EnvValue(const char *name, const char *value) : name_(name), restore_(false) {
- char *original = getenv(name);
- if (original) {
- restore_ = true;
- original_ = original;
- }
- setenv(name_.c_str(), value, 1);
- }
- ~EnvValue() {
- if (restore_) {
- setenv(name_.c_str(), original_.c_str(), 1);
- } else {
- unsetenv(name_.c_str());
- }
- }
- private:
- std::string name_;
- bool restore_;
- std::string original_;
-};
-#endif
-
-
-#ifdef HAVE_CONTAINER
-// Linux-specific functionality for running code in a container, implemented
-// in ares-test-ns.cc
-typedef std::function<int(void)> VoidToIntFn;
-typedef std::vector<std::pair<std::string, std::string>> NameContentList;
-
-class ContainerFilesystem {
- public:
- ContainerFilesystem(NameContentList files, const std::string& mountpt);
- ~ContainerFilesystem();
- std::string root() const { return rootdir_; };
- std::string mountpt() const { return mountpt_; };
- private:
- void EnsureDirExists(const std::string& dir);
- std::string rootdir_;
- std::string mountpt_;
- std::list<std::string> dirs_;
- std::vector<std::unique_ptr<TransientFile>> files_;
-};
-
-int RunInContainer(ContainerFilesystem* fs, const std::string& hostname,
- const std::string& domainname, VoidToIntFn fn);
-
-#define ICLASS_NAME(casename, testname) Contained##casename##_##testname
-#define CONTAINED_TEST_F(casename, testname, hostname, domainname, files) \
- class ICLASS_NAME(casename, testname) : public casename { \
- public: \
- ICLASS_NAME(casename, testname)() {} \
- static int InnerTestBody(); \
- }; \
- TEST_F(ICLASS_NAME(casename, testname), _) { \
- ContainerFilesystem chroot(files, ".."); \
- VoidToIntFn fn(ICLASS_NAME(casename, testname)::InnerTestBody); \
- EXPECT_EQ(0, RunInContainer(&chroot, hostname, domainname, fn)); \
- } \
- int ICLASS_NAME(casename, testname)::InnerTestBody()
-
-#endif
-
-} // namespace test
-} // namespace ares
-
-#endif