ares-test.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. // -*- mode: c++ -*-
  2. #ifndef ARES_TEST_H
  3. #define ARES_TEST_H
  4. #include "ares_setup.h"
  5. #include "ares.h"
  6. #include "dns-proto.h"
  7. // Include ares internal file for DNS protocol constants
  8. #include "ares_nameser.h"
  9. #include "gtest/gtest.h"
  10. #include "gmock/gmock.h"
  11. #ifdef HAVE_CONFIG_H
  12. #include "config.h"
  13. #endif
  14. #if defined(HAVE_USER_NAMESPACE) && defined(HAVE_UTS_NAMESPACE)
  15. #define HAVE_CONTAINER
  16. #endif
  17. #include <functional>
  18. #include <list>
  19. #include <map>
  20. #include <memory>
  21. #include <set>
  22. #include <string>
  23. #include <utility>
  24. #include <vector>
  25. namespace ares {
  26. typedef unsigned char byte;
  27. namespace test {
  28. extern bool verbose;
  29. extern int mock_port;
  30. extern const std::vector<int> both_families;
  31. extern const std::vector<int> ipv4_family;
  32. extern const std::vector<int> ipv6_family;
  33. extern const std::vector<std::pair<int, bool>> both_families_both_modes;
  34. extern const std::vector<std::pair<int, bool>> ipv4_family_both_modes;
  35. extern const std::vector<std::pair<int, bool>> ipv6_family_both_modes;
  36. // Which parameters to use in tests
  37. extern std::vector<int> families;
  38. extern std::vector<std::pair<int, bool>> families_modes;
  39. // Process all pending work on ares-owned file descriptors, plus
  40. // optionally the given set-of-FDs + work function.
  41. void ProcessWork(ares_channel channel,
  42. std::function<std::set<int>()> get_extrafds,
  43. std::function<void(int)> process_extra);
  44. std::set<int> NoExtraFDs();
  45. // Test fixture that ensures library initialization, and allows
  46. // memory allocations to be failed.
  47. class LibraryTest : public ::testing::Test {
  48. public:
  49. LibraryTest() {
  50. EXPECT_EQ(ARES_SUCCESS,
  51. ares_library_init_mem(ARES_LIB_INIT_ALL,
  52. &LibraryTest::amalloc,
  53. &LibraryTest::afree,
  54. &LibraryTest::arealloc));
  55. }
  56. ~LibraryTest() {
  57. ares_library_cleanup();
  58. ClearFails();
  59. }
  60. // Set the n-th malloc call (of any size) from the library to fail.
  61. // (nth == 1 means the next call)
  62. static void SetAllocFail(int nth);
  63. // Set the next malloc call for the given size to fail.
  64. static void SetAllocSizeFail(size_t size);
  65. // Remove any pending alloc failures.
  66. static void ClearFails();
  67. static void *amalloc(size_t size);
  68. static void* arealloc(void *ptr, size_t size);
  69. static void afree(void *ptr);
  70. private:
  71. static bool ShouldAllocFail(size_t size);
  72. static unsigned long long fails_;
  73. static std::map<size_t, int> size_fails_;
  74. };
  75. // Test fixture that uses a default channel.
  76. class DefaultChannelTest : public LibraryTest {
  77. public:
  78. DefaultChannelTest() : channel_(nullptr) {
  79. EXPECT_EQ(ARES_SUCCESS, ares_init(&channel_));
  80. EXPECT_NE(nullptr, channel_);
  81. }
  82. ~DefaultChannelTest() {
  83. ares_destroy(channel_);
  84. channel_ = nullptr;
  85. }
  86. // Process all pending work on ares-owned file descriptors.
  87. void Process();
  88. protected:
  89. ares_channel channel_;
  90. };
  91. // Test fixture that uses a default channel with the specified lookup mode.
  92. class DefaultChannelModeTest
  93. : public LibraryTest,
  94. public ::testing::WithParamInterface<std::string> {
  95. public:
  96. DefaultChannelModeTest() : channel_(nullptr) {
  97. struct ares_options opts = {0};
  98. opts.lookups = strdup(GetParam().c_str());
  99. int optmask = ARES_OPT_LOOKUPS;
  100. EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel_, &opts, optmask));
  101. EXPECT_NE(nullptr, channel_);
  102. free(opts.lookups);
  103. }
  104. ~DefaultChannelModeTest() {
  105. ares_destroy(channel_);
  106. channel_ = nullptr;
  107. }
  108. // Process all pending work on ares-owned file descriptors.
  109. void Process();
  110. protected:
  111. ares_channel channel_;
  112. };
  113. // Mock DNS server to allow responses to be scripted by tests.
  114. class MockServer {
  115. public:
  116. MockServer(int family, int port);
  117. ~MockServer();
  118. // Mock method indicating the processing of a particular <name, RRtype>
  119. // request.
  120. MOCK_METHOD2(OnRequest, void(const std::string& name, int rrtype));
  121. // Set the reply to be sent next; the query ID field will be overwritten
  122. // with the value from the request.
  123. void SetReplyData(const std::vector<byte>& reply) { reply_ = reply; }
  124. void SetReply(const DNSPacket* reply) { SetReplyData(reply->data()); }
  125. void SetReplyQID(int qid) { qid_ = qid; }
  126. // The set of file descriptors that the server handles.
  127. std::set<int> fds() const;
  128. // Process activity on a file descriptor.
  129. void ProcessFD(int fd);
  130. // Ports the server is responding to
  131. int udpport() const { return udpport_; }
  132. int tcpport() const { return tcpport_; }
  133. private:
  134. void ProcessRequest(int fd, struct sockaddr_storage* addr, int addrlen,
  135. int qid, const std::string& name, int rrtype);
  136. void ProcessPacket(int fd, struct sockaddr_storage *addr, socklen_t addrlen,
  137. byte *data, int len);
  138. int udpport_;
  139. int tcpport_;
  140. int udpfd_;
  141. int tcpfd_;
  142. std::set<int> connfds_;
  143. std::vector<byte> reply_;
  144. int qid_;
  145. };
  146. // Test fixture that uses a mock DNS server.
  147. class MockChannelOptsTest : public LibraryTest {
  148. public:
  149. MockChannelOptsTest(int count, int family, bool force_tcp, struct ares_options* givenopts, int optmask);
  150. ~MockChannelOptsTest();
  151. // Process all pending work on ares-owned and mock-server-owned file descriptors.
  152. void Process();
  153. protected:
  154. // NiceMockServer doesn't complain about uninteresting calls.
  155. typedef testing::NiceMock<MockServer> NiceMockServer;
  156. typedef std::vector< std::unique_ptr<NiceMockServer> > NiceMockServers;
  157. std::set<int> fds() const;
  158. void ProcessFD(int fd);
  159. static NiceMockServers BuildServers(int count, int family, int base_port);
  160. NiceMockServers servers_;
  161. // Convenience reference to first server.
  162. NiceMockServer& server_;
  163. ares_channel channel_;
  164. };
  165. class MockChannelTest
  166. : public MockChannelOptsTest,
  167. public ::testing::WithParamInterface< std::pair<int, bool> > {
  168. public:
  169. MockChannelTest() : MockChannelOptsTest(1, GetParam().first, GetParam().second, nullptr, 0) {}
  170. };
  171. class MockUDPChannelTest
  172. : public MockChannelOptsTest,
  173. public ::testing::WithParamInterface<int> {
  174. public:
  175. MockUDPChannelTest() : MockChannelOptsTest(1, GetParam(), false, nullptr, 0) {}
  176. };
  177. class MockTCPChannelTest
  178. : public MockChannelOptsTest,
  179. public ::testing::WithParamInterface<int> {
  180. public:
  181. MockTCPChannelTest() : MockChannelOptsTest(1, GetParam(), true, nullptr, 0) {}
  182. };
  183. // gMock action to set the reply for a mock server.
  184. ACTION_P2(SetReplyData, mockserver, data) {
  185. mockserver->SetReplyData(data);
  186. }
  187. ACTION_P2(SetReply, mockserver, reply) {
  188. mockserver->SetReply(reply);
  189. }
  190. ACTION_P2(SetReplyQID, mockserver, qid) {
  191. mockserver->SetReplyQID(qid);
  192. }
  193. // gMock action to cancel a channel.
  194. ACTION_P2(CancelChannel, mockserver, channel) {
  195. ares_cancel(channel);
  196. }
  197. // C++ wrapper for struct hostent.
  198. struct HostEnt {
  199. HostEnt() : addrtype_(-1) {}
  200. HostEnt(const struct hostent* hostent);
  201. std::string name_;
  202. std::vector<std::string> aliases_;
  203. int addrtype_; // AF_INET or AF_INET6
  204. std::vector<std::string> addrs_;
  205. };
  206. std::ostream& operator<<(std::ostream& os, const HostEnt& result);
  207. // Structure that describes the result of an ares_host_callback invocation.
  208. struct HostResult {
  209. HostResult() : done_(false), status_(0), timeouts_(0) {}
  210. // Whether the callback has been invoked.
  211. bool done_;
  212. // Explicitly provided result information.
  213. int status_;
  214. int timeouts_;
  215. // Contents of the hostent structure, if provided.
  216. HostEnt host_;
  217. };
  218. std::ostream& operator<<(std::ostream& os, const HostResult& result);
  219. // Structure that describes the result of an ares_callback invocation.
  220. struct SearchResult {
  221. // Whether the callback has been invoked.
  222. bool done_;
  223. // Explicitly provided result information.
  224. int status_;
  225. int timeouts_;
  226. std::vector<byte> data_;
  227. };
  228. std::ostream& operator<<(std::ostream& os, const SearchResult& result);
  229. // Structure that describes the result of an ares_nameinfo_callback invocation.
  230. struct NameInfoResult {
  231. // Whether the callback has been invoked.
  232. bool done_;
  233. // Explicitly provided result information.
  234. int status_;
  235. int timeouts_;
  236. std::string node_;
  237. std::string service_;
  238. };
  239. std::ostream& operator<<(std::ostream& os, const NameInfoResult& result);
  240. struct AddrInfoDeleter {
  241. void operator() (ares_addrinfo *ptr) {
  242. if (ptr) ares_freeaddrinfo(ptr);
  243. }
  244. };
  245. // C++ wrapper for struct ares_addrinfo.
  246. using AddrInfo = std::unique_ptr<ares_addrinfo, AddrInfoDeleter>;
  247. std::ostream& operator<<(std::ostream& os, const AddrInfo& result);
  248. // Structure that describes the result of an ares_addrinfo_callback invocation.
  249. struct AddrInfoResult {
  250. AddrInfoResult() : done_(false), status_(-1), timeouts_(0) {}
  251. // Whether the callback has been invoked.
  252. bool done_;
  253. // Explicitly provided result information.
  254. int status_;
  255. int timeouts_;
  256. // Contents of the ares_addrinfo structure, if provided.
  257. AddrInfo ai_;
  258. };
  259. std::ostream& operator<<(std::ostream& os, const AddrInfoResult& result);
  260. // Standard implementation of ares callbacks that fill out the corresponding
  261. // structures.
  262. void HostCallback(void *data, int status, int timeouts,
  263. struct hostent *hostent);
  264. void SearchCallback(void *data, int status, int timeouts,
  265. unsigned char *abuf, int alen);
  266. void NameInfoCallback(void *data, int status, int timeouts,
  267. char *node, char *service);
  268. void AddrInfoCallback(void *data, int status, int timeouts,
  269. struct ares_addrinfo *res);
  270. // Retrieve the name servers used by a channel.
  271. std::vector<std::string> GetNameServers(ares_channel channel);
  272. // RAII class to temporarily create a directory of a given name.
  273. class TransientDir {
  274. public:
  275. TransientDir(const std::string& dirname);
  276. ~TransientDir();
  277. private:
  278. std::string dirname_;
  279. };
  280. // C++ wrapper around tempnam()
  281. std::string TempNam(const char *dir, const char *prefix);
  282. // RAII class to temporarily create file of a given name and contents.
  283. class TransientFile {
  284. public:
  285. TransientFile(const std::string &filename, const std::string &contents);
  286. ~TransientFile();
  287. protected:
  288. std::string filename_;
  289. };
  290. // RAII class for a temporary file with the given contents.
  291. class TempFile : public TransientFile {
  292. public:
  293. TempFile(const std::string& contents);
  294. const char* filename() const { return filename_.c_str(); }
  295. };
  296. #ifdef _WIN32
  297. extern "C" {
  298. static int setenv(const char *name, const char *value, int overwrite)
  299. {
  300. char *buffer;
  301. size_t buf_size;
  302. if (name == NULL)
  303. return -1;
  304. if (value == NULL)
  305. value = ""; /* For unset */
  306. if (!overwrite && getenv(name) != NULL) {
  307. return -1;
  308. }
  309. buf_size = strlen(name) + strlen(value) + 1 /* = */ + 1 /* NULL */;
  310. buffer = (char *)malloc(buf_size);
  311. _snprintf(buffer, buf_size, "%s=%s", name, value);
  312. _putenv(buffer);
  313. free(buffer);
  314. return 0;
  315. }
  316. static int unsetenv(const char *name)
  317. {
  318. return setenv(name, NULL, 1);
  319. }
  320. } /* extern "C" */
  321. #endif
  322. // RAII class for a temporary environment variable value.
  323. class EnvValue {
  324. public:
  325. EnvValue(const char *name, const char *value) : name_(name), restore_(false) {
  326. char *original = getenv(name);
  327. if (original) {
  328. restore_ = true;
  329. original_ = original;
  330. }
  331. setenv(name_.c_str(), value, 1);
  332. }
  333. ~EnvValue() {
  334. if (restore_) {
  335. setenv(name_.c_str(), original_.c_str(), 1);
  336. } else {
  337. unsetenv(name_.c_str());
  338. }
  339. }
  340. private:
  341. std::string name_;
  342. bool restore_;
  343. std::string original_;
  344. };
  345. #ifdef HAVE_CONTAINER
  346. // Linux-specific functionality for running code in a container, implemented
  347. // in ares-test-ns.cc
  348. typedef std::function<int(void)> VoidToIntFn;
  349. typedef std::vector<std::pair<std::string, std::string>> NameContentList;
  350. class ContainerFilesystem {
  351. public:
  352. ContainerFilesystem(NameContentList files, const std::string& mountpt);
  353. ~ContainerFilesystem();
  354. std::string root() const { return rootdir_; };
  355. std::string mountpt() const { return mountpt_; };
  356. private:
  357. void EnsureDirExists(const std::string& dir);
  358. std::string rootdir_;
  359. std::string mountpt_;
  360. std::list<std::string> dirs_;
  361. std::vector<std::unique_ptr<TransientFile>> files_;
  362. };
  363. int RunInContainer(ContainerFilesystem* fs, const std::string& hostname,
  364. const std::string& domainname, VoidToIntFn fn);
  365. #define ICLASS_NAME(casename, testname) Contained##casename##_##testname
  366. #define CONTAINED_TEST_F(casename, testname, hostname, domainname, files) \
  367. class ICLASS_NAME(casename, testname) : public casename { \
  368. public: \
  369. ICLASS_NAME(casename, testname)() {} \
  370. static int InnerTestBody(); \
  371. }; \
  372. TEST_F(ICLASS_NAME(casename, testname), _) { \
  373. ContainerFilesystem chroot(files, ".."); \
  374. VoidToIntFn fn(ICLASS_NAME(casename, testname)::InnerTestBody); \
  375. EXPECT_EQ(0, RunInContainer(&chroot, hostname, domainname, fn)); \
  376. } \
  377. int ICLASS_NAME(casename, testname)::InnerTestBody()
  378. #endif
  379. /* Assigns virtual IO functions to a channel. These functions simply call
  380. * the actual system functions.
  381. */
  382. class VirtualizeIO {
  383. public:
  384. VirtualizeIO(ares_channel);
  385. ~VirtualizeIO();
  386. static const ares_socket_functions default_functions;
  387. private:
  388. ares_channel channel_;
  389. };
  390. /*
  391. * Slightly white-box macro to generate two runs for a given test case:
  392. * One with no modifications, and one with all IO functions set to use
  393. * the virtual io structure.
  394. * Since no magic socket setup or anything is done in the latter case
  395. * this should probably only be used for test with very vanilla IO
  396. * requirements.
  397. */
  398. #define VCLASS_NAME(casename, testname) Virt##casename##_##testname
  399. #define VIRT_NONVIRT_TEST_F(casename, testname) \
  400. class VCLASS_NAME(casename, testname) : public casename { \
  401. public: \
  402. VCLASS_NAME(casename, testname)() {} \
  403. void InnerTestBody(); \
  404. }; \
  405. GTEST_TEST_(casename, testname, VCLASS_NAME(casename, testname), \
  406. ::testing::internal::GetTypeId<casename>()) { \
  407. InnerTestBody(); \
  408. } \
  409. GTEST_TEST_(casename, testname##_virtualized, \
  410. VCLASS_NAME(casename, testname), \
  411. ::testing::internal::GetTypeId<casename>()) { \
  412. VirtualizeIO vio(channel_); \
  413. InnerTestBody(); \
  414. } \
  415. void VCLASS_NAME(casename, testname)::InnerTestBody()
  416. } // namespace test
  417. } // namespace ares
  418. #endif