• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* MIT License
2  *
3  * Copyright (c) The c-ares project and its contributors
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  * SPDX-License-Identifier: MIT
25  */
26 #include "ares-test.h"
27 #include "dns-proto.h"
28 
29 #ifdef CARES_THREADS
30 
31 #ifndef WIN32
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #endif
35 
36 #include <sstream>
37 #include <vector>
38 
39 using testing::InvokeWithoutArgs;
40 using testing::DoAll;
41 
42 namespace ares {
43 namespace test {
44 
45 // UDP only so mock server doesn't get confused by concatenated requests
TEST_P(MockUDPEventThreadTest,GetHostByNameParallelLookups)46 TEST_P(MockUDPEventThreadTest, GetHostByNameParallelLookups) {
47   DNSPacket rsp1;
48   rsp1.set_response().set_aa()
49     .add_question(new DNSQuestion("www.google.com", T_A))
50     .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
51   ON_CALL(server_, OnRequest("www.google.com", T_A))
52     .WillByDefault(SetReply(&server_, &rsp1));
53   DNSPacket rsp2;
54   rsp2.set_response().set_aa()
55     .add_question(new DNSQuestion("www.example.com", T_A))
56     .add_answer(new DNSARR("www.example.com", 100, {1, 2, 3, 4}));
57   ON_CALL(server_, OnRequest("www.example.com", T_A))
58     .WillByDefault(SetReply(&server_, &rsp2));
59 
60   HostResult result1;
61   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result1);
62   HostResult result2;
63   ares_gethostbyname(channel_, "www.example.com.", AF_INET, HostCallback, &result2);
64   HostResult result3;
65   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result3);
66   Process();
67   EXPECT_TRUE(result1.done_);
68   EXPECT_TRUE(result2.done_);
69   EXPECT_TRUE(result3.done_);
70   std::stringstream ss1;
71   ss1 << result1.host_;
72   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss1.str());
73   std::stringstream ss2;
74   ss2 << result2.host_;
75   EXPECT_EQ("{'www.example.com' aliases=[] addrs=[1.2.3.4]}", ss2.str());
76   std::stringstream ss3;
77   ss3 << result3.host_;
78   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss3.str());
79 }
80 
81 // c-ares issue #819
TEST_P(MockUDPEventThreadTest,BadLoopbackServerNoTimeouts)82 TEST_P(MockUDPEventThreadTest, BadLoopbackServerNoTimeouts) {
83   ares_set_servers_csv(channel_, "127.0.0.1:12345");
84 #define BADLOOPBACK_TESTCNT 5
85   HostResult result[BADLOOPBACK_TESTCNT];
86   for (size_t i=0; i<BADLOOPBACK_TESTCNT; i++) {
87     ares_gethostbyname(channel_, "www.google.com.", AF_UNSPEC, HostCallback, &result[i]);
88   }
89   Process();
90   for (size_t i=0; i<BADLOOPBACK_TESTCNT; i++) {
91     EXPECT_TRUE(result[i].done_);
92 
93     /* This test relies on the ICMP unreachable packet coming back on UDP connections
94      * when there is no listener on the other end.  Most OS's handle this properly,
95      * but not all.  For instance, Solaris 11 seems to not be compliant (it
96      * does however honor it sometimes, just not always) so while we still run
97      * the test, we don't do a strict validation of the result.
98      *
99      * Windows also appears to have intermittent issues, AppVeyor fails but GitHub Actions
100      * succeeds, which seems strange.  This test goes to loopback so the network
101      * it resides on shouldn't matter.
102      *
103      * This test is really just testing an optimization, UDP is connectionless so you
104      * should expect most connections to rely on timeouts and not ICMP unreachable.
105      */
106 # if defined(__sun) || defined(_WIN32) || defined(__NetBSD__)
107     EXPECT_TRUE(result[i].status_ == ARES_ECONNREFUSED || result[i].status_ == ARES_ETIMEOUT || result[i].status_ == ARES_ESERVFAIL);
108 # else
109     EXPECT_EQ(ARES_ECONNREFUSED, result[i].status_);
110     EXPECT_EQ(0, result[i].timeouts_);
111 #endif
112   }
113 }
114 
115 // UDP to TCP specific test
TEST_P(MockUDPEventThreadTest,TruncationRetry)116 TEST_P(MockUDPEventThreadTest, TruncationRetry) {
117   DNSPacket rsptruncated;
118   rsptruncated.set_response().set_aa().set_tc()
119     .add_question(new DNSQuestion("www.google.com", T_A));
120   DNSPacket rspok;
121   rspok.set_response()
122     .add_question(new DNSQuestion("www.google.com", T_A))
123     .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4}));
124   EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
125     .WillOnce(SetReply(&server_, &rsptruncated))
126     .WillOnce(SetReply(&server_, &rspok));
127   HostResult result;
128   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
129   Process();
130   EXPECT_TRUE(result.done_);
131   std::stringstream ss;
132   ss << result.host_;
133   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str());
134 }
135 
136 static int sock_cb_count = 0;
SocketConnectCallback(ares_socket_t fd,int type,void * data)137 static int SocketConnectCallback(ares_socket_t fd, int type, void *data) {
138   int rc = *(int*)data;
139   (void)type;
140   sock_cb_count++;
141   if (verbose) std::cerr << "SocketConnectCallback(fd: " << fd << ", cnt: " << sock_cb_count << ") invoked" << std::endl;
142   return rc;
143 }
144 
TEST_P(MockEventThreadTest,SockCallback)145 TEST_P(MockEventThreadTest, SockCallback) {
146   DNSPacket rsp;
147   rsp.set_response().set_aa()
148     .add_question(new DNSQuestion("www.google.com", T_A))
149     .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
150   EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
151     .WillOnce(SetReply(&server_, &rsp));
152 
153   // Get notified of new sockets
154   int rc = ARES_SUCCESS;
155   ares_set_socket_callback(channel_, SocketConnectCallback, &rc);
156 
157   HostResult result;
158   sock_cb_count = 0;
159   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
160   Process();
161   EXPECT_EQ(1, sock_cb_count);
162   EXPECT_TRUE(result.done_);
163   std::stringstream ss;
164   ss << result.host_;
165   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
166 }
167 
TEST_P(MockEventThreadTest,SockFailCallback)168 TEST_P(MockEventThreadTest, SockFailCallback) {
169   // Notification of new sockets gives an error.
170   int rc = -1;
171   ares_set_socket_callback(channel_, SocketConnectCallback, &rc);
172 
173   HostResult result;
174   sock_cb_count = 0;
175   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
176   Process();
177   EXPECT_LT(1, sock_cb_count);
178   EXPECT_TRUE(result.done_);
179   EXPECT_EQ(ARES_ECONNREFUSED, result.status_);
180 }
181 
182 
TEST_P(MockEventThreadTest,ReInit)183 TEST_P(MockEventThreadTest, ReInit) {
184   DNSPacket rsp;
185   rsp.set_response().set_aa()
186     .add_question(new DNSQuestion("www.google.com", T_A))
187     .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
188   EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
189     .WillOnce(SetReply(&server_, &rsp));
190 
191   HostResult result;
192   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
193   EXPECT_EQ(ARES_SUCCESS, ares_reinit(channel_));
194   Process();
195   EXPECT_TRUE(result.done_);
196   std::stringstream ss;
197   ss << result.host_;
198   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
199 }
200 
201 #define MAXUDPQUERIES_TOTAL 32
202 #define MAXUDPQUERIES_LIMIT 8
203 
204 class MockUDPEventThreadMaxQueriesTest
205     : public MockEventThreadOptsTest,
206       public ::testing::WithParamInterface<std::tuple<ares_evsys_t,int>> {
207  public:
MockUDPEventThreadMaxQueriesTest()208   MockUDPEventThreadMaxQueriesTest()
209     : MockEventThreadOptsTest(1, std::get<0>(GetParam()), std::get<1>(GetParam()), false,
210                           FillOptions(&opts_),
211                           ARES_OPT_UDP_MAX_QUERIES|ARES_OPT_FLAGS) {}
FillOptions(struct ares_options * opts)212   static struct ares_options* FillOptions(struct ares_options * opts) {
213     memset(opts, 0, sizeof(struct ares_options));
214     opts->flags = ARES_FLAG_STAYOPEN|ARES_FLAG_EDNS;
215     opts->udp_max_queries = MAXUDPQUERIES_LIMIT;
216     return opts;
217   }
218  private:
219   struct ares_options opts_;
220 };
221 
TEST_P(MockUDPEventThreadMaxQueriesTest,GetHostByNameParallelLookups)222 TEST_P(MockUDPEventThreadMaxQueriesTest, GetHostByNameParallelLookups) {
223   DNSPacket rsp;
224   rsp.set_response().set_aa()
225     .add_question(new DNSQuestion("www.google.com", T_A))
226     .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
227   ON_CALL(server_, OnRequest("www.google.com", T_A))
228     .WillByDefault(SetReply(&server_, &rsp));
229 
230   // Get notified of new sockets so we can validate how many are created
231   int rc = ARES_SUCCESS;
232   ares_set_socket_callback(channel_, SocketConnectCallback, &rc);
233   sock_cb_count = 0;
234 
235   HostResult result[MAXUDPQUERIES_TOTAL];
236   for (size_t i=0; i<MAXUDPQUERIES_TOTAL; i++) {
237     ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result[i]);
238   }
239 
240   Process();
241 
242   EXPECT_EQ(MAXUDPQUERIES_TOTAL / MAXUDPQUERIES_LIMIT, sock_cb_count);
243 
244   for (size_t i=0; i<MAXUDPQUERIES_TOTAL; i++) {
245     std::stringstream ss;
246     EXPECT_TRUE(result[i].done_);
247     ss << result[i].host_;
248     EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
249   }
250 }
251 
252 /* This test case is likely to fail in heavily loaded environments, it was
253  * there to stress the windows event system.  Not needed to be on normally */
254 #if 0
255 class MockUDPEventThreadSingleQueryPerConnTest
256     : public MockEventThreadOptsTest,
257       public ::testing::WithParamInterface<std::tuple<ares_evsys_t,int>> {
258  public:
259   MockUDPEventThreadSingleQueryPerConnTest()
260     : MockEventThreadOptsTest(1, std::get<0>(GetParam()), std::get<1>(GetParam()), false,
261                           FillOptions(&opts_),
262                           ARES_OPT_UDP_MAX_QUERIES) {}
263   static struct ares_options* FillOptions(struct ares_options * opts) {
264     memset(opts, 0, sizeof(struct ares_options));
265     opts->udp_max_queries = 1;
266     return opts;
267   }
268  private:
269   struct ares_options opts_;
270 };
271 
272 #define LOTSOFCONNECTIONS_CNT 64
273 TEST_P(MockUDPEventThreadSingleQueryPerConnTest, LotsOfConnections) {
274   DNSPacket rsp;
275   rsp.set_response().set_aa()
276     .add_question(new DNSQuestion("www.google.com", T_A))
277     .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
278   ON_CALL(server_, OnRequest("www.google.com", T_A))
279     .WillByDefault(SetReply(&server_, &rsp));
280 
281   // Get notified of new sockets so we can validate how many are created
282   int rc = ARES_SUCCESS;
283   ares_set_socket_callback(channel_, SocketConnectCallback, &rc);
284   sock_cb_count = 0;
285 
286   HostResult result[LOTSOFCONNECTIONS_CNT];
287   for (size_t i=0; i<LOTSOFCONNECTIONS_CNT; i++) {
288     ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result[i]);
289   }
290 
291   Process();
292 
293   EXPECT_EQ(LOTSOFCONNECTIONS_CNT, sock_cb_count);
294 
295   for (size_t i=0; i<LOTSOFCONNECTIONS_CNT; i++) {
296     std::stringstream ss;
297     EXPECT_TRUE(result[i].done_);
298     ss << result[i].host_;
299     EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
300   }
301 }
302 #endif
303 
304 class CacheQueriesEventThreadTest
305     : public MockEventThreadOptsTest,
306       public ::testing::WithParamInterface<std::tuple<ares_evsys_t,int>> {
307  public:
CacheQueriesEventThreadTest()308   CacheQueriesEventThreadTest()
309     : MockEventThreadOptsTest(1, std::get<0>(GetParam()), std::get<1>(GetParam()), false,
310                           FillOptions(&opts_),
311                           ARES_OPT_QUERY_CACHE) {}
FillOptions(struct ares_options * opts)312   static struct ares_options* FillOptions(struct ares_options * opts) {
313     memset(opts, 0, sizeof(struct ares_options));
314     opts->qcache_max_ttl = 3600;
315     return opts;
316   }
317  private:
318   struct ares_options opts_;
319 };
320 
TEST_P(CacheQueriesEventThreadTest,GetHostByNameCache)321 TEST_P(CacheQueriesEventThreadTest, GetHostByNameCache) {
322   DNSPacket rsp;
323   rsp.set_response().set_aa()
324     .add_question(new DNSQuestion("www.google.com", T_A))
325     .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
326   ON_CALL(server_, OnRequest("www.google.com", T_A))
327     .WillByDefault(SetReply(&server_, &rsp));
328 
329   // Get notified of new sockets so we can validate how many are created
330   int rc = ARES_SUCCESS;
331   ares_set_socket_callback(channel_, SocketConnectCallback, &rc);
332   sock_cb_count = 0;
333 
334   HostResult result1;
335   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result1);
336   Process();
337 
338   std::stringstream ss1;
339   EXPECT_TRUE(result1.done_);
340   ss1 << result1.host_;
341   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss1.str());
342 
343   /* Run again, should return cached result */
344   HostResult result2;
345   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result2);
346   Process();
347 
348   std::stringstream ss2;
349   EXPECT_TRUE(result2.done_);
350   ss2 << result2.host_;
351   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss2.str());
352 
353   EXPECT_EQ(1, sock_cb_count);
354 }
355 
356 #define TCPPARALLELLOOKUPS 32
357 
358 class MockTCPEventThreadStayOpenTest
359     : public MockEventThreadOptsTest,
360       public ::testing::WithParamInterface<std::tuple<ares_evsys_t,int>> {
361  public:
MockTCPEventThreadStayOpenTest()362   MockTCPEventThreadStayOpenTest()
363     : MockEventThreadOptsTest(1, std::get<0>(GetParam()), std::get<1>(GetParam()), true /* tcp */,
364                           FillOptions(&opts_),
365                           ARES_OPT_FLAGS) {}
FillOptions(struct ares_options * opts)366   static struct ares_options* FillOptions(struct ares_options * opts) {
367     memset(opts, 0, sizeof(struct ares_options));
368     opts->flags = ARES_FLAG_STAYOPEN|ARES_FLAG_EDNS;
369     return opts;
370   }
371  private:
372   struct ares_options opts_;
373 };
374 
TEST_P(MockTCPEventThreadStayOpenTest,GetHostByNameParallelLookups)375 TEST_P(MockTCPEventThreadStayOpenTest, GetHostByNameParallelLookups) {
376   DNSPacket rsp;
377   rsp.set_response().set_aa()
378     .add_question(new DNSQuestion("www.google.com", T_A))
379     .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
380   ON_CALL(server_, OnRequest("www.google.com", T_A))
381     .WillByDefault(SetReply(&server_, &rsp));
382 
383   // Get notified of new sockets so we can validate how many are created
384   int rc = ARES_SUCCESS;
385   ares_set_socket_callback(channel_, SocketConnectCallback, &rc);
386   sock_cb_count = 0;
387 
388   HostResult result[TCPPARALLELLOOKUPS];
389   for (size_t i=0; i<TCPPARALLELLOOKUPS; i++) {
390     ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result[i]);
391   }
392 
393   Process();
394 
395   EXPECT_EQ(1, sock_cb_count);
396 
397   for (size_t i=0; i<TCPPARALLELLOOKUPS; i++) {
398     std::stringstream ss;
399     EXPECT_TRUE(result[i].done_);
400     ss << result[i].host_;
401     EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
402   }
403 }
404 
TEST_P(MockTCPEventThreadTest,MalformedResponse)405 TEST_P(MockTCPEventThreadTest, MalformedResponse) {
406   std::vector<byte> one = {0x00};
407   ON_CALL(server_, OnRequest("www.google.com", T_A))
408     .WillByDefault(SetReplyData(&server_, one));
409 
410   HostResult result;
411   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
412   Process();
413   EXPECT_TRUE(result.done_);
414   EXPECT_EQ(ARES_EBADRESP, result.status_);
415 }
416 
TEST_P(MockTCPEventThreadTest,FormErrResponse)417 TEST_P(MockTCPEventThreadTest, FormErrResponse) {
418   DNSPacket rsp;
419   rsp.set_response().set_aa()
420     .add_question(new DNSQuestion("www.google.com", T_A));
421   rsp.set_rcode(FORMERR);
422   EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
423     .WillOnce(SetReply(&server_, &rsp));
424   HostResult result;
425   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
426   Process();
427   EXPECT_TRUE(result.done_);
428   EXPECT_EQ(ARES_EFORMERR, result.status_);
429 }
430 
TEST_P(MockTCPEventThreadTest,ServFailResponse)431 TEST_P(MockTCPEventThreadTest, ServFailResponse) {
432   DNSPacket rsp;
433   rsp.set_response().set_aa()
434     .add_question(new DNSQuestion("www.google.com", T_A));
435   rsp.set_rcode(SERVFAIL);
436   ON_CALL(server_, OnRequest("www.google.com", T_A))
437     .WillByDefault(SetReply(&server_, &rsp));
438   HostResult result;
439   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
440   Process();
441   EXPECT_TRUE(result.done_);
442   EXPECT_EQ(ARES_ESERVFAIL, result.status_);
443 }
444 
TEST_P(MockTCPEventThreadTest,NotImplResponse)445 TEST_P(MockTCPEventThreadTest, NotImplResponse) {
446   DNSPacket rsp;
447   rsp.set_response().set_aa()
448     .add_question(new DNSQuestion("www.google.com", T_A));
449   rsp.set_rcode(NOTIMP);
450   ON_CALL(server_, OnRequest("www.google.com", T_A))
451     .WillByDefault(SetReply(&server_, &rsp));
452   HostResult result;
453   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
454   Process();
455   EXPECT_TRUE(result.done_);
456   EXPECT_EQ(ARES_ENOTIMP, result.status_);
457 }
458 
TEST_P(MockTCPEventThreadTest,RefusedResponse)459 TEST_P(MockTCPEventThreadTest, RefusedResponse) {
460   DNSPacket rsp;
461   rsp.set_response().set_aa()
462     .add_question(new DNSQuestion("www.google.com", T_A));
463   rsp.set_rcode(REFUSED);
464   ON_CALL(server_, OnRequest("www.google.com", T_A))
465     .WillByDefault(SetReply(&server_, &rsp));
466   HostResult result;
467   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
468   Process();
469   EXPECT_TRUE(result.done_);
470   EXPECT_EQ(ARES_EREFUSED, result.status_);
471 }
472 
TEST_P(MockTCPEventThreadTest,YXDomainResponse)473 TEST_P(MockTCPEventThreadTest, YXDomainResponse) {
474   DNSPacket rsp;
475   rsp.set_response().set_aa()
476     .add_question(new DNSQuestion("www.google.com", T_A));
477   rsp.set_rcode(YXDOMAIN);
478   EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
479     .WillOnce(SetReply(&server_, &rsp));
480   HostResult result;
481   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
482   Process();
483   EXPECT_TRUE(result.done_);
484   EXPECT_EQ(ARES_ENODATA, result.status_);
485 }
486 
487 class MockExtraOptsEventThreadTest
488     : public MockEventThreadOptsTest,
489       public ::testing::WithParamInterface<std::tuple<ares_evsys_t, int, bool> > {
490  public:
MockExtraOptsEventThreadTest()491   MockExtraOptsEventThreadTest()
492     : MockEventThreadOptsTest(1, std::get<0>(GetParam()), std::get<1>(GetParam()), std::get<2>(GetParam()),
493                           FillOptions(&opts_),
494                           ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF) {}
FillOptions(struct ares_options * opts)495   static struct ares_options* FillOptions(struct ares_options * opts) {
496     memset(opts, 0, sizeof(struct ares_options));
497     // Set a few options that affect socket communications
498     opts->socket_send_buffer_size = 514;
499     opts->socket_receive_buffer_size = 514;
500     return opts;
501   }
502  private:
503   struct ares_options opts_;
504 };
505 
TEST_P(MockExtraOptsEventThreadTest,SimpleQuery)506 TEST_P(MockExtraOptsEventThreadTest, SimpleQuery) {
507   ares_set_local_ip4(channel_, 0x7F000001);
508   byte addr6[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
510   ares_set_local_ip6(channel_, addr6);
511   ares_set_local_dev(channel_, "dummy");
512 
513   DNSPacket rsp;
514   rsp.set_response().set_aa()
515     .add_question(new DNSQuestion("www.google.com", T_A))
516     .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
517   ON_CALL(server_, OnRequest("www.google.com", T_A))
518     .WillByDefault(SetReply(&server_, &rsp));
519 
520   HostResult result;
521   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
522   Process();
523   EXPECT_TRUE(result.done_);
524   std::stringstream ss;
525   ss << result.host_;
526   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
527 }
528 
529 class MockFlagsEventThreadOptsTest
530     : public MockEventThreadOptsTest,
531       public ::testing::WithParamInterface< std::tuple<ares_evsys_t, int, bool> > {
532  public:
MockFlagsEventThreadOptsTest(int flags)533   MockFlagsEventThreadOptsTest(int flags)
534     : MockEventThreadOptsTest(1, std::get<0>(GetParam()), std::get<1>(GetParam()), std::get<2>(GetParam()),
535                           FillOptions(&opts_, flags), ARES_OPT_FLAGS) {}
FillOptions(struct ares_options * opts,int flags)536   static struct ares_options* FillOptions(struct ares_options * opts, int flags) {
537     memset(opts, 0, sizeof(struct ares_options));
538     opts->flags = flags;
539     return opts;
540   }
541  private:
542   struct ares_options opts_;
543 };
544 
545 class MockNoCheckRespEventThreadTest : public MockFlagsEventThreadOptsTest {
546  public:
MockNoCheckRespEventThreadTest()547   MockNoCheckRespEventThreadTest() : MockFlagsEventThreadOptsTest(ARES_FLAG_NOCHECKRESP) {}
548 };
549 
TEST_P(MockNoCheckRespEventThreadTest,ServFailResponse)550 TEST_P(MockNoCheckRespEventThreadTest, ServFailResponse) {
551   DNSPacket rsp;
552   rsp.set_response().set_aa()
553     .add_question(new DNSQuestion("www.google.com", T_A));
554   rsp.set_rcode(SERVFAIL);
555   ON_CALL(server_, OnRequest("www.google.com", T_A))
556     .WillByDefault(SetReply(&server_, &rsp));
557   HostResult result;
558   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
559   Process();
560   EXPECT_TRUE(result.done_);
561   EXPECT_EQ(ARES_ESERVFAIL, result.status_);
562 }
563 
TEST_P(MockNoCheckRespEventThreadTest,NotImplResponse)564 TEST_P(MockNoCheckRespEventThreadTest, NotImplResponse) {
565   DNSPacket rsp;
566   rsp.set_response().set_aa()
567     .add_question(new DNSQuestion("www.google.com", T_A));
568   rsp.set_rcode(NOTIMP);
569   ON_CALL(server_, OnRequest("www.google.com", T_A))
570     .WillByDefault(SetReply(&server_, &rsp));
571   HostResult result;
572   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
573   Process();
574   EXPECT_TRUE(result.done_);
575   EXPECT_EQ(ARES_ENOTIMP, result.status_);
576 }
577 
TEST_P(MockNoCheckRespEventThreadTest,RefusedResponse)578 TEST_P(MockNoCheckRespEventThreadTest, RefusedResponse) {
579   DNSPacket rsp;
580   rsp.set_response().set_aa()
581     .add_question(new DNSQuestion("www.google.com", T_A));
582   rsp.set_rcode(REFUSED);
583   ON_CALL(server_, OnRequest("www.google.com", T_A))
584     .WillByDefault(SetReply(&server_, &rsp));
585   HostResult result;
586   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
587   Process();
588   EXPECT_TRUE(result.done_);
589   EXPECT_EQ(ARES_EREFUSED, result.status_);
590 }
591 
592 class MockEDNSEventThreadTest : public MockFlagsEventThreadOptsTest {
593  public:
MockEDNSEventThreadTest()594   MockEDNSEventThreadTest() : MockFlagsEventThreadOptsTest(ARES_FLAG_EDNS) {}
595 };
596 
TEST_P(MockEDNSEventThreadTest,RetryWithoutEDNS)597 TEST_P(MockEDNSEventThreadTest, RetryWithoutEDNS) {
598   DNSPacket rspfail;
599   rspfail.set_response().set_aa().set_rcode(FORMERR)
600     .add_question(new DNSQuestion("www.google.com", T_A));
601   DNSPacket rspok;
602   rspok.set_response()
603     .add_question(new DNSQuestion("www.google.com", T_A))
604     .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4}));
605   EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
606     .WillOnce(SetReply(&server_, &rspfail))
607     .WillOnce(SetReply(&server_, &rspok));
608   HostResult result;
609   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
610   Process();
611   EXPECT_TRUE(result.done_);
612   std::stringstream ss;
613   ss << result.host_;
614   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str());
615 }
616 
TEST_P(MockEventThreadTest,SearchDomains)617 TEST_P(MockEventThreadTest, SearchDomains) {
618   DNSPacket nofirst;
619   nofirst.set_response().set_aa().set_rcode(NXDOMAIN)
620     .add_question(new DNSQuestion("www.first.com", T_A));
621   ON_CALL(server_, OnRequest("www.first.com", T_A))
622     .WillByDefault(SetReply(&server_, &nofirst));
623   DNSPacket nosecond;
624   nosecond.set_response().set_aa().set_rcode(NXDOMAIN)
625     .add_question(new DNSQuestion("www.second.org", T_A));
626   ON_CALL(server_, OnRequest("www.second.org", T_A))
627     .WillByDefault(SetReply(&server_, &nosecond));
628   DNSPacket yesthird;
629   yesthird.set_response().set_aa()
630     .add_question(new DNSQuestion("www.third.gov", T_A))
631     .add_answer(new DNSARR("www.third.gov", 0x0200, {2, 3, 4, 5}));
632   ON_CALL(server_, OnRequest("www.third.gov", T_A))
633     .WillByDefault(SetReply(&server_, &yesthird));
634 
635   HostResult result;
636   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
637   Process();
638   EXPECT_TRUE(result.done_);
639   std::stringstream ss;
640   ss << result.host_;
641   EXPECT_EQ("{'www.third.gov' aliases=[] addrs=[2.3.4.5]}", ss.str());
642 }
643 
644 // Relies on retries so is UDP-only
TEST_P(MockUDPEventThreadTest,SearchDomainsWithResentReply)645 TEST_P(MockUDPEventThreadTest, SearchDomainsWithResentReply) {
646   DNSPacket nofirst;
647   nofirst.set_response().set_aa().set_rcode(NXDOMAIN)
648     .add_question(new DNSQuestion("www.first.com", T_A));
649   EXPECT_CALL(server_, OnRequest("www.first.com", T_A))
650     .WillOnce(SetReply(&server_, &nofirst));
651   DNSPacket nosecond;
652   nosecond.set_response().set_aa().set_rcode(NXDOMAIN)
653     .add_question(new DNSQuestion("www.second.org", T_A));
654   EXPECT_CALL(server_, OnRequest("www.second.org", T_A))
655     .WillOnce(SetReply(&server_, &nosecond));
656   DNSPacket yesthird;
657   yesthird.set_response().set_aa()
658     .add_question(new DNSQuestion("www.third.gov", T_A))
659     .add_answer(new DNSARR("www.third.gov", 0x0200, {2, 3, 4, 5}));
660   // Before sending the real answer, resend an earlier reply
661   EXPECT_CALL(server_, OnRequest("www.third.gov", T_A))
662     .WillOnce(DoAll(SetReply(&server_, &nofirst),
663                     SetReplyQID(&server_, 123)))
664     .WillOnce(DoAll(SetReply(&server_, &yesthird),
665                     SetReplyQID(&server_, -1)));
666 
667   HostResult result;
668   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
669   Process();
670   EXPECT_TRUE(result.done_);
671   std::stringstream ss;
672   ss << result.host_;
673   EXPECT_EQ("{'www.third.gov' aliases=[] addrs=[2.3.4.5]}", ss.str());
674 }
675 
TEST_P(MockEventThreadTest,SearchDomainsBare)676 TEST_P(MockEventThreadTest, SearchDomainsBare) {
677   DNSPacket nofirst;
678   nofirst.set_response().set_aa().set_rcode(NXDOMAIN)
679     .add_question(new DNSQuestion("www.first.com", T_A));
680   ON_CALL(server_, OnRequest("www.first.com", T_A))
681     .WillByDefault(SetReply(&server_, &nofirst));
682   DNSPacket nosecond;
683   nosecond.set_response().set_aa().set_rcode(NXDOMAIN)
684     .add_question(new DNSQuestion("www.second.org", T_A));
685   ON_CALL(server_, OnRequest("www.second.org", T_A))
686     .WillByDefault(SetReply(&server_, &nosecond));
687   DNSPacket nothird;
688   nothird.set_response().set_aa().set_rcode(NXDOMAIN)
689     .add_question(new DNSQuestion("www.third.gov", T_A));
690   ON_CALL(server_, OnRequest("www.third.gov", T_A))
691     .WillByDefault(SetReply(&server_, &nothird));
692   DNSPacket yesbare;
693   yesbare.set_response().set_aa()
694     .add_question(new DNSQuestion("www", T_A))
695     .add_answer(new DNSARR("www", 0x0200, {2, 3, 4, 5}));
696   ON_CALL(server_, OnRequest("www", T_A))
697     .WillByDefault(SetReply(&server_, &yesbare));
698 
699   HostResult result;
700   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
701   Process();
702   EXPECT_TRUE(result.done_);
703   std::stringstream ss;
704   ss << result.host_;
705   EXPECT_EQ("{'www' aliases=[] addrs=[2.3.4.5]}", ss.str());
706 }
707 
TEST_P(MockEventThreadTest,SearchNoDataThenSuccess)708 TEST_P(MockEventThreadTest, SearchNoDataThenSuccess) {
709   // First two search domains recognize the name but have no A records.
710   DNSPacket nofirst;
711   nofirst.set_response().set_aa()
712     .add_question(new DNSQuestion("www.first.com", T_A));
713   ON_CALL(server_, OnRequest("www.first.com", T_A))
714     .WillByDefault(SetReply(&server_, &nofirst));
715   DNSPacket nosecond;
716   nosecond.set_response().set_aa()
717     .add_question(new DNSQuestion("www.second.org", T_A));
718   ON_CALL(server_, OnRequest("www.second.org", T_A))
719     .WillByDefault(SetReply(&server_, &nosecond));
720   DNSPacket yesthird;
721   yesthird.set_response().set_aa()
722     .add_question(new DNSQuestion("www.third.gov", T_A))
723     .add_answer(new DNSARR("www.third.gov", 0x0200, {2, 3, 4, 5}));
724   ON_CALL(server_, OnRequest("www.third.gov", T_A))
725     .WillByDefault(SetReply(&server_, &yesthird));
726 
727   HostResult result;
728   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
729   Process();
730   EXPECT_TRUE(result.done_);
731   std::stringstream ss;
732   ss << result.host_;
733   EXPECT_EQ("{'www.third.gov' aliases=[] addrs=[2.3.4.5]}", ss.str());
734 }
735 
TEST_P(MockEventThreadTest,SearchNoDataThenNoDataBare)736 TEST_P(MockEventThreadTest, SearchNoDataThenNoDataBare) {
737   // First two search domains recognize the name but have no A records.
738   DNSPacket nofirst;
739   nofirst.set_response().set_aa()
740     .add_question(new DNSQuestion("www.first.com", T_A));
741   ON_CALL(server_, OnRequest("www.first.com", T_A))
742     .WillByDefault(SetReply(&server_, &nofirst));
743   DNSPacket nosecond;
744   nosecond.set_response().set_aa()
745     .add_question(new DNSQuestion("www.second.org", T_A));
746   ON_CALL(server_, OnRequest("www.second.org", T_A))
747     .WillByDefault(SetReply(&server_, &nosecond));
748   DNSPacket nothird;
749   nothird.set_response().set_aa()
750     .add_question(new DNSQuestion("www.third.gov", T_A));
751   ON_CALL(server_, OnRequest("www.third.gov", T_A))
752     .WillByDefault(SetReply(&server_, &nothird));
753   DNSPacket nobare;
754   nobare.set_response().set_aa()
755     .add_question(new DNSQuestion("www", T_A));
756   ON_CALL(server_, OnRequest("www", T_A))
757     .WillByDefault(SetReply(&server_, &nobare));
758 
759   HostResult result;
760   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
761   Process();
762   EXPECT_TRUE(result.done_);
763   EXPECT_EQ(ARES_ENODATA, result.status_);
764 }
765 
TEST_P(MockEventThreadTest,SearchNoDataThenFail)766 TEST_P(MockEventThreadTest, SearchNoDataThenFail) {
767   // First two search domains recognize the name but have no A records.
768   DNSPacket nofirst;
769   nofirst.set_response().set_aa()
770     .add_question(new DNSQuestion("www.first.com", T_A));
771   ON_CALL(server_, OnRequest("www.first.com", T_A))
772     .WillByDefault(SetReply(&server_, &nofirst));
773   DNSPacket nosecond;
774   nosecond.set_response().set_aa()
775     .add_question(new DNSQuestion("www.second.org", T_A));
776   ON_CALL(server_, OnRequest("www.second.org", T_A))
777     .WillByDefault(SetReply(&server_, &nosecond));
778   DNSPacket nothird;
779   nothird.set_response().set_aa()
780     .add_question(new DNSQuestion("www.third.gov", T_A));
781   ON_CALL(server_, OnRequest("www.third.gov", T_A))
782     .WillByDefault(SetReply(&server_, &nothird));
783   DNSPacket nobare;
784   nobare.set_response().set_aa().set_rcode(NXDOMAIN)
785     .add_question(new DNSQuestion("www", T_A));
786   ON_CALL(server_, OnRequest("www", T_A))
787     .WillByDefault(SetReply(&server_, &nobare));
788 
789   HostResult result;
790   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
791   Process();
792   EXPECT_TRUE(result.done_);
793   EXPECT_EQ(ARES_ENODATA, result.status_);
794 }
795 
TEST_P(MockEventThreadTest,SearchHighNdots)796 TEST_P(MockEventThreadTest, SearchHighNdots) {
797   DNSPacket nobare;
798   nobare.set_response().set_aa().set_rcode(NXDOMAIN)
799     .add_question(new DNSQuestion("a.b.c.w.w.w", T_A));
800   ON_CALL(server_, OnRequest("a.b.c.w.w.w", T_A))
801     .WillByDefault(SetReply(&server_, &nobare));
802   DNSPacket yesfirst;
803   yesfirst.set_response().set_aa()
804     .add_question(new DNSQuestion("a.b.c.w.w.w.first.com", T_A))
805     .add_answer(new DNSARR("a.b.c.w.w.w.first.com", 0x0200, {2, 3, 4, 5}));
806   ON_CALL(server_, OnRequest("a.b.c.w.w.w.first.com", T_A))
807     .WillByDefault(SetReply(&server_, &yesfirst));
808 
809   SearchResult result;
810   ares_search(channel_, "a.b.c.w.w.w", C_IN, T_A, SearchCallback, &result);
811   Process();
812   EXPECT_TRUE(result.done_);
813   EXPECT_EQ(ARES_SUCCESS, result.status_);
814   std::stringstream ss;
815   ss << PacketToString(result.data_);
816   EXPECT_EQ("RSP QRY AA NOERROR Q:{'a.b.c.w.w.w.first.com' IN A} "
817             "A:{'a.b.c.w.w.w.first.com' IN A TTL=512 2.3.4.5}",
818             ss.str());
819 }
820 
TEST_P(MockEventThreadTest,V4WorksV6Timeout)821 TEST_P(MockEventThreadTest, V4WorksV6Timeout) {
822   std::vector<byte> nothing;
823   DNSPacket reply;
824   reply.set_response().set_aa()
825     .add_question(new DNSQuestion("www.google.com", T_A))
826     .add_answer(new DNSARR("www.google.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
827 
828   ON_CALL(server_, OnRequest("www.google.com", T_A))
829     .WillByDefault(SetReply(&server_, &reply));
830 
831   ON_CALL(server_, OnRequest("www.google.com", T_AAAA))
832     .WillByDefault(SetReplyData(&server_, nothing));
833 
834   HostResult result;
835   ares_gethostbyname(channel_, "www.google.com.", AF_UNSPEC, HostCallback, &result);
836   Process();
837   EXPECT_TRUE(result.done_);
838   EXPECT_EQ(1, result.timeouts_);
839   std::stringstream ss;
840   ss << result.host_;
841   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str());
842 }
843 
TEST_P(MockEventThreadTest,DestroyQuick)844 TEST_P(MockEventThreadTest, DestroyQuick) {
845   /* We are not looking for any particular result as its possible (but unlikely)
846    * it finished before the destroy completed. We really just want to make sure
847    * cleanup works in this case properly. */
848   HostResult result;
849   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
850   ares_destroy(channel_);
851   channel_ = nullptr;
852   EXPECT_TRUE(result.done_);
853 }
854 
855 // Test case for Issue #662
TEST_P(MockEventThreadTest,PartialQueryCancel)856 TEST_P(MockEventThreadTest, PartialQueryCancel) {
857   std::vector<byte> nothing;
858   DNSPacket reply;
859   reply.set_response().set_aa()
860     .add_question(new DNSQuestion("www.google.com", T_A))
861     .add_answer(new DNSARR("www.google.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
862 
863   ON_CALL(server_, OnRequest("www.google.com", T_A))
864     .WillByDefault(SetReply(&server_, &reply));
865 
866   ON_CALL(server_, OnRequest("www.google.com", T_AAAA))
867     .WillByDefault(SetReplyData(&server_, nothing));
868 
869   HostResult result;
870   ares_gethostbyname(channel_, "www.google.com.", AF_UNSPEC, HostCallback, &result);
871   // After 100ms, issues ares_cancel(), this should be enough time for the A
872   // record reply, but before the timeout on the AAAA record.
873   Process(100);
874   EXPECT_TRUE(result.done_);
875   EXPECT_EQ(ARES_ECANCELLED, result.status_);
876 }
877 
878 // Test case for Issue #798, we're really looking for a crash, the results
879 // don't matter.  Should either be successful or canceled.
TEST_P(MockEventThreadTest,BulkCancel)880 TEST_P(MockEventThreadTest, BulkCancel) {
881   std::vector<byte> nothing;
882   DNSPacket reply;
883   reply.set_response().set_aa()
884     .add_question(new DNSQuestion("www.google.com", T_A))
885     .add_answer(new DNSARR("www.google.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
886 
887   ON_CALL(server_, OnRequest("www.google.com", T_A))
888     .WillByDefault(SetReply(&server_, &reply));
889 
890 #define BULKCANCEL_LOOP 5
891 #define BULKCANCEL_CNT 50
892   for (size_t l = 0; l<BULKCANCEL_LOOP; l++) {
893     HostResult result[BULKCANCEL_CNT];
894     for (size_t i = 0; i<BULKCANCEL_CNT; i++) {
895       ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result[i]);
896     }
897     // After 1ms, issues ares_cancel(), there should be queries outstanding that
898     // are cancelled.
899     Process(1);
900 
901     size_t success_cnt = 0;
902     size_t cancel_cnt = 0;
903     for (size_t i = 0; i<BULKCANCEL_CNT; i++) {
904       EXPECT_TRUE(result[i].done_);
905       EXPECT_TRUE(result[i].status_ == ARES_ECANCELLED || result[i].status_ == ARES_SUCCESS);
906       if (result[i].done_ && result[i].status_ == ARES_SUCCESS)
907         success_cnt++;
908       if (result[i].done_ && result[i].status_ == ARES_ECANCELLED)
909         cancel_cnt++;
910     }
911     if (verbose) std::cerr << "success: " << success_cnt << ", cancel: " << cancel_cnt << std::endl;
912   }
913 }
914 
TEST_P(MockEventThreadTest,UnspecifiedFamilyV6)915 TEST_P(MockEventThreadTest, UnspecifiedFamilyV6) {
916   DNSPacket rsp6;
917   rsp6.set_response().set_aa()
918     .add_question(new DNSQuestion("example.com", T_AAAA))
919     .add_answer(new DNSAaaaRR("example.com", 100,
920                               {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
921                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03}));
922   ON_CALL(server_, OnRequest("example.com", T_AAAA))
923     .WillByDefault(SetReply(&server_, &rsp6));
924 
925   DNSPacket rsp4;
926   rsp4.set_response().set_aa()
927     .add_question(new DNSQuestion("example.com", T_A));
928   ON_CALL(server_, OnRequest("example.com", T_A))
929     .WillByDefault(SetReply(&server_, &rsp4));
930 
931   HostResult result;
932   ares_gethostbyname(channel_, "example.com.", AF_UNSPEC, HostCallback, &result);
933   Process();
934   EXPECT_TRUE(result.done_);
935   std::stringstream ss;
936   ss << result.host_;
937   // Default to IPv6 when both are available.
938   EXPECT_EQ("{'example.com' aliases=[] addrs=[2121:0000:0000:0000:0000:0000:0000:0303]}", ss.str());
939 }
940 
TEST_P(MockEventThreadTest,UnspecifiedFamilyV4)941 TEST_P(MockEventThreadTest, UnspecifiedFamilyV4) {
942   DNSPacket rsp6;
943   rsp6.set_response().set_aa()
944     .add_question(new DNSQuestion("example.com", T_AAAA));
945   ON_CALL(server_, OnRequest("example.com", T_AAAA))
946     .WillByDefault(SetReply(&server_, &rsp6));
947   DNSPacket rsp4;
948   rsp4.set_response().set_aa()
949     .add_question(new DNSQuestion("example.com", T_A))
950     .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5}));
951   ON_CALL(server_, OnRequest("example.com", T_A))
952     .WillByDefault(SetReply(&server_, &rsp4));
953 
954   HostResult result;
955   ares_gethostbyname(channel_, "example.com.", AF_UNSPEC, HostCallback, &result);
956   Process();
957   EXPECT_TRUE(result.done_);
958   std::stringstream ss;
959   ss << result.host_;
960   EXPECT_EQ("{'example.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
961 }
962 
TEST_P(MockEventThreadTest,UnspecifiedFamilyNoData)963 TEST_P(MockEventThreadTest, UnspecifiedFamilyNoData) {
964   DNSPacket rsp6;
965   rsp6.set_response().set_aa()
966     .add_question(new DNSQuestion("example.com", T_AAAA))
967     .add_answer(new DNSCnameRR("example.com", 100, "elsewhere.com"));
968   ON_CALL(server_, OnRequest("example.com", T_AAAA))
969     .WillByDefault(SetReply(&server_, &rsp6));
970   DNSPacket rsp4;
971   rsp4.set_response().set_aa()
972     .add_question(new DNSQuestion("example.com", T_A));
973   ON_CALL(server_, OnRequest("example.com", T_A))
974     .WillByDefault(SetReply(&server_, &rsp4));
975 
976   HostResult result;
977   ares_gethostbyname(channel_, "example.com.", AF_UNSPEC, HostCallback, &result);
978   Process();
979   EXPECT_TRUE(result.done_);
980   std::stringstream ss;
981   ss << result.host_;
982   EXPECT_EQ("{'' aliases=[] addrs=[]}", ss.str());
983 }
984 
TEST_P(MockEventThreadTest,UnspecifiedFamilyCname6A4)985 TEST_P(MockEventThreadTest, UnspecifiedFamilyCname6A4) {
986   DNSPacket rsp6;
987   rsp6.set_response().set_aa()
988     .add_question(new DNSQuestion("example.com", T_AAAA))
989     .add_answer(new DNSCnameRR("example.com", 100, "elsewhere.com"));
990   ON_CALL(server_, OnRequest("example.com", T_AAAA))
991     .WillByDefault(SetReply(&server_, &rsp6));
992   DNSPacket rsp4;
993   rsp4.set_response().set_aa()
994     .add_question(new DNSQuestion("example.com", T_A))
995     .add_answer(new DNSARR("example.com", 100, {1, 2, 3, 4}));
996   ON_CALL(server_, OnRequest("example.com", T_A))
997     .WillByDefault(SetReply(&server_, &rsp4));
998 
999   HostResult result;
1000   ares_gethostbyname(channel_, "example.com.", AF_UNSPEC, HostCallback, &result);
1001   Process();
1002   EXPECT_TRUE(result.done_);
1003   std::stringstream ss;
1004   ss << result.host_;
1005   EXPECT_EQ("{'example.com' aliases=[] addrs=[1.2.3.4]}", ss.str());
1006 }
1007 
TEST_P(MockEventThreadTest,ExplicitIP)1008 TEST_P(MockEventThreadTest, ExplicitIP) {
1009   HostResult result;
1010   ares_gethostbyname(channel_, "1.2.3.4", AF_INET, HostCallback, &result);
1011   EXPECT_TRUE(result.done_);  // Immediate return
1012   EXPECT_EQ(ARES_SUCCESS, result.status_);
1013   std::stringstream ss;
1014   ss << result.host_;
1015   EXPECT_EQ("{'1.2.3.4' aliases=[] addrs=[1.2.3.4]}", ss.str());
1016 }
1017 
TEST_P(MockEventThreadTest,SortListV4)1018 TEST_P(MockEventThreadTest, SortListV4) {
1019   DNSPacket rsp;
1020   rsp.set_response().set_aa()
1021     .add_question(new DNSQuestion("example.com", T_A))
1022     .add_answer(new DNSARR("example.com", 100, {22, 23, 24, 25}))
1023     .add_answer(new DNSARR("example.com", 100, {12, 13, 14, 15}))
1024     .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5}));
1025   ON_CALL(server_, OnRequest("example.com", T_A))
1026     .WillByDefault(SetReply(&server_, &rsp));
1027 
1028   {
1029     EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "12.13.0.0/255.255.0.0 1234::5678"));
1030     HostResult result;
1031     ares_gethostbyname(channel_, "example.com.", AF_INET, HostCallback, &result);
1032     Process();
1033     EXPECT_TRUE(result.done_);
1034     std::stringstream ss;
1035     ss << result.host_;
1036     EXPECT_EQ("{'example.com' aliases=[] addrs=[12.13.14.15, 22.23.24.25, 2.3.4.5]}", ss.str());
1037   }
1038   {
1039     EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "2.3.0.0/16 130.140.150.160/26"));
1040     HostResult result;
1041     ares_gethostbyname(channel_, "example.com.", AF_INET, HostCallback, &result);
1042     Process();
1043     EXPECT_TRUE(result.done_);
1044     std::stringstream ss;
1045     ss << result.host_;
1046     EXPECT_EQ("{'example.com' aliases=[] addrs=[2.3.4.5, 22.23.24.25, 12.13.14.15]}", ss.str());
1047   }
1048   struct ares_options options;
1049   memset(&options, 0, sizeof(options));
1050   int optmask = 0;
1051   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &options, &optmask));
1052   EXPECT_TRUE((optmask & ARES_OPT_SORTLIST) == ARES_OPT_SORTLIST);
1053   ares_destroy_options(&options);
1054 }
1055 
TEST_P(MockEventThreadTest,SortListV6)1056 TEST_P(MockEventThreadTest, SortListV6) {
1057   DNSPacket rsp;
1058   rsp.set_response().set_aa()
1059     .add_question(new DNSQuestion("example.com", T_AAAA))
1060     .add_answer(new DNSAaaaRR("example.com", 100,
1061                               {0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1062                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02}))
1063     .add_answer(new DNSAaaaRR("example.com", 100,
1064                               {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1065                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03}));
1066   ON_CALL(server_, OnRequest("example.com", T_AAAA))
1067     .WillByDefault(SetReply(&server_, &rsp));
1068 
1069   {
1070     ares_set_sortlist(channel_, "1111::/16 2.3.0.0/255.255.0.0");
1071     HostResult result;
1072     ares_gethostbyname(channel_, "example.com.", AF_INET6, HostCallback, &result);
1073     Process();
1074     EXPECT_TRUE(result.done_);
1075     std::stringstream ss;
1076     ss << result.host_;
1077     EXPECT_EQ("{'example.com' aliases=[] addrs=[1111:0000:0000:0000:0000:0000:0000:0202, "
1078               "2121:0000:0000:0000:0000:0000:0000:0303]}", ss.str());
1079   }
1080   {
1081     ares_set_sortlist(channel_, "2121::/8");
1082     HostResult result;
1083     ares_gethostbyname(channel_, "example.com.", AF_INET6, HostCallback, &result);
1084     Process();
1085     EXPECT_TRUE(result.done_);
1086     std::stringstream ss;
1087     ss << result.host_;
1088     EXPECT_EQ("{'example.com' aliases=[] addrs=[2121:0000:0000:0000:0000:0000:0000:0303, "
1089               "1111:0000:0000:0000:0000:0000:0000:0202]}", ss.str());
1090   }
1091 }
1092 
1093 // Relies on retries so is UDP-only
TEST_P(MockUDPEventThreadTest,Resend)1094 TEST_P(MockUDPEventThreadTest, Resend) {
1095   std::vector<byte> nothing;
1096   DNSPacket reply;
1097   reply.set_response().set_aa()
1098     .add_question(new DNSQuestion("www.google.com", T_A))
1099     .add_answer(new DNSARR("www.google.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
1100 
1101   EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
1102     .WillOnce(SetReplyData(&server_, nothing))
1103     .WillOnce(SetReplyData(&server_, nothing))
1104     .WillOnce(SetReply(&server_, &reply));
1105 
1106   HostResult result;
1107   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
1108   Process();
1109   EXPECT_TRUE(result.done_);
1110   EXPECT_EQ(2, result.timeouts_);
1111   std::stringstream ss;
1112   ss << result.host_;
1113   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str());
1114 }
1115 
TEST_P(MockEventThreadTest,CancelImmediate)1116 TEST_P(MockEventThreadTest, CancelImmediate) {
1117   HostResult result;
1118   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
1119   ares_cancel(channel_);
1120   EXPECT_TRUE(result.done_);
1121   EXPECT_EQ(ARES_ECANCELLED, result.status_);
1122   EXPECT_EQ(0, result.timeouts_);
1123 }
1124 
TEST_P(MockEventThreadTest,CancelImmediateGetHostByAddr)1125 TEST_P(MockEventThreadTest, CancelImmediateGetHostByAddr) {
1126   HostResult result;
1127   struct in_addr addr;
1128   addr.s_addr = htonl(0x08080808);
1129 
1130   ares_gethostbyaddr(channel_, &addr, sizeof(addr), AF_INET, HostCallback, &result);
1131   ares_cancel(channel_);
1132   EXPECT_TRUE(result.done_);
1133   EXPECT_EQ(ARES_ECANCELLED, result.status_);
1134   EXPECT_EQ(0, result.timeouts_);
1135 }
1136 
1137 // Relies on retries so is UDP-only
TEST_P(MockUDPEventThreadTest,CancelLater)1138 TEST_P(MockUDPEventThreadTest, CancelLater) {
1139   std::vector<byte> nothing;
1140 
1141   // On second request, cancel the channel.
1142   EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
1143     .WillOnce(SetReplyData(&server_, nothing))
1144     .WillOnce(CancelChannel(&server_, channel_));
1145 
1146   HostResult result;
1147   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
1148   Process();
1149   EXPECT_TRUE(result.done_);
1150   EXPECT_EQ(ARES_ECANCELLED, result.status_);
1151   EXPECT_EQ(0, result.timeouts_);
1152 }
1153 
TEST_P(MockEventThreadTest,DisconnectFirstAttempt)1154 TEST_P(MockEventThreadTest, DisconnectFirstAttempt) {
1155   DNSPacket reply;
1156   reply.set_response().set_aa()
1157     .add_question(new DNSQuestion("www.google.com", T_A))
1158     .add_answer(new DNSARR("www.google.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
1159 
1160   // On second request, cancel the channel.
1161   EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
1162     .WillOnce(Disconnect(&server_))
1163     .WillOnce(SetReply(&server_, &reply));
1164 
1165   HostResult result;
1166   ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
1167   Process();
1168   EXPECT_TRUE(result.done_);
1169   if (result.done_) {
1170     std::stringstream ss;
1171     ss << result.host_;
1172     EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str());
1173   }
1174 }
1175 
TEST_P(MockEventThreadTest,GetHostByNameCNAMENoData)1176 TEST_P(MockEventThreadTest, GetHostByNameCNAMENoData) {
1177   DNSPacket response;
1178   response.set_response().set_aa()
1179     .add_question(new DNSQuestion("cname.first.com", T_A))
1180     .add_answer(new DNSCnameRR("cname.first.com", 100, "a.first.com"));
1181   ON_CALL(server_, OnRequest("cname.first.com", T_A))
1182     .WillByDefault(SetReply(&server_, &response));
1183 
1184   HostResult result;
1185   ares_gethostbyname(channel_, "cname.first.com.", AF_INET, HostCallback, &result);
1186   Process();
1187   EXPECT_TRUE(result.done_);
1188   EXPECT_EQ(ARES_ENODATA, result.status_);
1189 }
1190 
1191 #ifndef WIN32
TEST_P(MockEventThreadTest,HostAlias)1192 TEST_P(MockEventThreadTest, HostAlias) {
1193   DNSPacket reply;
1194   reply.set_response().set_aa()
1195     .add_question(new DNSQuestion("www.google.com", T_A))
1196     .add_answer(new DNSARR("www.google.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
1197   ON_CALL(server_, OnRequest("www.google.com", T_A))
1198     .WillByDefault(SetReply(&server_, &reply));
1199 
1200   TempFile aliases("\n\n# www commentedout\nwww www.google.com\n");
1201   EnvValue with_env("HOSTALIASES", aliases.filename());
1202 
1203   HostResult result;
1204   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
1205   Process();
1206   EXPECT_TRUE(result.done_);
1207   std::stringstream ss;
1208   ss << result.host_;
1209   EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str());
1210 }
1211 
TEST_P(MockEventThreadTest,HostAliasMissing)1212 TEST_P(MockEventThreadTest, HostAliasMissing) {
1213   DNSPacket yesfirst;
1214   yesfirst.set_response().set_aa()
1215     .add_question(new DNSQuestion("www.first.com", T_A))
1216     .add_answer(new DNSARR("www.first.com", 0x0200, {2, 3, 4, 5}));
1217   ON_CALL(server_, OnRequest("www.first.com", T_A))
1218     .WillByDefault(SetReply(&server_, &yesfirst));
1219 
1220   TempFile aliases("\n\n# www commentedout\nww www.google.com\n");
1221   EnvValue with_env("HOSTALIASES", aliases.filename());
1222   HostResult result;
1223   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
1224   Process();
1225   EXPECT_TRUE(result.done_);
1226   std::stringstream ss;
1227   ss << result.host_;
1228   EXPECT_EQ("{'www.first.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
1229 }
1230 
TEST_P(MockEventThreadTest,HostAliasMissingFile)1231 TEST_P(MockEventThreadTest, HostAliasMissingFile) {
1232   DNSPacket yesfirst;
1233   yesfirst.set_response().set_aa()
1234     .add_question(new DNSQuestion("www.first.com", T_A))
1235     .add_answer(new DNSARR("www.first.com", 0x0200, {2, 3, 4, 5}));
1236   ON_CALL(server_, OnRequest("www.first.com", T_A))
1237     .WillByDefault(SetReply(&server_, &yesfirst));
1238 
1239   EnvValue with_env("HOSTALIASES", "bogus.mcfile");
1240   HostResult result;
1241   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
1242   Process();
1243   EXPECT_TRUE(result.done_);
1244   std::stringstream ss;
1245   ss << result.host_;
1246   EXPECT_EQ("{'www.first.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
1247 }
1248 
TEST_P(MockEventThreadTest,HostAliasUnreadable)1249 TEST_P(MockEventThreadTest, HostAliasUnreadable) {
1250   TempFile aliases("www www.google.com\n");
1251   EXPECT_EQ(chmod(aliases.filename(), 0), 0);
1252 
1253   /* Perform OS sanity checks.  We are observing on Debian after the chmod(fn, 0)
1254    * that we are still able to fopen() the file which is unexpected.  Skip the
1255    * test if we observe this behavior */
1256   struct stat st;
1257   EXPECT_EQ(stat(aliases.filename(), &st), 0);
1258   EXPECT_EQ(st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO), 0);
1259   FILE *fp = fopen(aliases.filename(), "r");
1260   if (fp != NULL) {
1261     if (verbose) std::cerr << "Skipping Test due to OS incompatibility (open file caching)" << std::endl;
1262     fclose(fp);
1263     return;
1264   }
1265 
1266   EnvValue with_env("HOSTALIASES", aliases.filename());
1267 
1268   HostResult result;
1269   ares_gethostbyname(channel_, "www", AF_INET, HostCallback, &result);
1270   Process();
1271   EXPECT_TRUE(result.done_);
1272   EXPECT_EQ(ARES_EFILE, result.status_);
1273   chmod(aliases.filename(), 0777);
1274 }
1275 #endif
1276 
1277 
1278 class MockMultiServerEventThreadTest
1279   : public MockEventThreadOptsTest,
1280     public ::testing::WithParamInterface< std::tuple<ares_evsys_t, int, bool> > {
1281  public:
MockMultiServerEventThreadTest(ares_options * opts,int optmask)1282   MockMultiServerEventThreadTest(ares_options *opts, int optmask)
1283     : MockEventThreadOptsTest(3, std::get<0>(GetParam()), std::get<1>(GetParam()), std::get<2>(GetParam()), opts, optmask) {}
CheckExample()1284   void CheckExample() {
1285     HostResult result;
1286     ares_gethostbyname(channel_, "www.example.com.", AF_INET, HostCallback, &result);
1287     Process();
1288     EXPECT_TRUE(result.done_);
1289     std::stringstream ss;
1290     ss << result.host_;
1291     EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
1292   }
1293 };
1294 
1295 class NoRotateMultiMockEventThreadTest : public MockMultiServerEventThreadTest {
1296  public:
NoRotateMultiMockEventThreadTest()1297   NoRotateMultiMockEventThreadTest() : MockMultiServerEventThreadTest(nullptr, ARES_OPT_NOROTATE) {}
1298 };
1299 
1300 
TEST_P(NoRotateMultiMockEventThreadTest,ThirdServer)1301 TEST_P(NoRotateMultiMockEventThreadTest, ThirdServer) {
1302   struct ares_options opts;
1303   int optmask = 0;
1304   memset(&opts, 0, sizeof(opts));
1305   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask));
1306   EXPECT_EQ(ARES_OPT_NOROTATE, (optmask & ARES_OPT_NOROTATE));
1307   ares_destroy_options(&opts);
1308 
1309   DNSPacket servfailrsp;
1310   servfailrsp.set_response().set_aa().set_rcode(SERVFAIL)
1311     .add_question(new DNSQuestion("www.example.com", T_A));
1312   DNSPacket notimplrsp;
1313   notimplrsp.set_response().set_aa().set_rcode(NOTIMP)
1314     .add_question(new DNSQuestion("www.example.com", T_A));
1315   DNSPacket okrsp;
1316   okrsp.set_response().set_aa()
1317     .add_question(new DNSQuestion("www.example.com", T_A))
1318     .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5}));
1319 
1320   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1321     .WillOnce(SetReply(servers_[0].get(), &servfailrsp));
1322   EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1323     .WillOnce(SetReply(servers_[1].get(), &notimplrsp));
1324   EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1325     .WillOnce(SetReply(servers_[2].get(), &okrsp));
1326   CheckExample();
1327 
1328   // Second time around, still starts from server [2], as [0] and [1] both
1329   // recorded failures
1330   EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1331     .WillOnce(SetReply(servers_[2].get(), &servfailrsp));
1332   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1333     .WillOnce(SetReply(servers_[0].get(), &notimplrsp));
1334   EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1335     .WillOnce(SetReply(servers_[1].get(), &okrsp));
1336   CheckExample();
1337 
1338   // Third time around, server order is [1] (f0), [2] (f1), [0] (f2), which
1339   // means [1] will get called twice in a row as after the first call
1340   // order will be  [1] (f1), [2] (f1), [0] (f2) since sort order is
1341   // (failure count, index)
1342   EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1343     .WillOnce(SetReply(servers_[1].get(), &servfailrsp))
1344     .WillOnce(SetReply(servers_[1].get(), &notimplrsp));
1345   EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1346     .WillOnce(SetReply(servers_[2].get(), &notimplrsp));
1347   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1348     .WillOnce(SetReply(servers_[0].get(), &okrsp));
1349   CheckExample();
1350 }
1351 
TEST_P(NoRotateMultiMockEventThreadTest,ServerNoResponseFailover)1352 TEST_P(NoRotateMultiMockEventThreadTest, ServerNoResponseFailover) {
1353   std::vector<byte> nothing;
1354   DNSPacket okrsp;
1355   okrsp.set_response().set_aa()
1356     .add_question(new DNSQuestion("www.example.com", T_A))
1357     .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5}));
1358 
1359   /* Server #1 works fine on first attempt, then acts like its offline on
1360    * second, then backonline on the third. */
1361   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1362     .WillOnce(SetReply(servers_[0].get(), &okrsp))
1363     .WillOnce(SetReplyData(servers_[0].get(), nothing))
1364     .WillOnce(SetReply(servers_[0].get(), &okrsp));
1365 
1366   /* Server #2 always acts like its offline */
1367   ON_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1368     .WillByDefault(SetReplyData(servers_[1].get(), nothing));
1369 
1370   /* Server #3 works fine on first and second request, then no reply on 3rd */
1371   EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1372     .WillOnce(SetReply(servers_[2].get(), &okrsp))
1373     .WillOnce(SetReply(servers_[2].get(), &okrsp))
1374     .WillOnce(SetReplyData(servers_[2].get(), nothing));
1375 
1376   HostResult result;
1377 
1378   /* 1. First server returns a response on the first request immediately, normal
1379    *    operation on channel. */
1380   ares_gethostbyname(channel_, "www.example.com.", AF_INET, HostCallback, &result);
1381   Process();
1382   EXPECT_TRUE(result.done_);
1383   EXPECT_EQ(0, result.timeouts_);
1384   std::stringstream ss1;
1385   ss1 << result.host_;
1386   EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss1.str());
1387 
1388   /* 2. On the second request, simulate the first and second servers not
1389    *    returning a response at all, but the 3rd server works, so should have
1390    *    2 timeouts. */
1391   ares_gethostbyname(channel_, "www.example.com.", AF_INET, HostCallback, &result);
1392   Process();
1393   EXPECT_TRUE(result.done_);
1394   EXPECT_EQ(2, result.timeouts_);
1395   std::stringstream ss2;
1396   ss2 << result.host_;
1397   EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss2.str());
1398 
1399   /* 3. On the third request, the active server should be #3, so should respond
1400    *    immediately with no timeouts */
1401   ares_gethostbyname(channel_, "www.example.com.", AF_INET, HostCallback, &result);
1402   Process();
1403   EXPECT_TRUE(result.done_);
1404   EXPECT_EQ(0, result.timeouts_);
1405   std::stringstream ss3;
1406   ss3 << result.host_;
1407   EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss3.str());
1408 
1409   /* 4. On the fourth request, the active server should be #3, but will timeout,
1410    *    and the first server should then respond */
1411   ares_gethostbyname(channel_, "www.example.com.", AF_INET, HostCallback, &result);
1412   Process();
1413   EXPECT_TRUE(result.done_);
1414   EXPECT_EQ(1, result.timeouts_);
1415   std::stringstream ss4;
1416   ss4 << result.host_;
1417   EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss4.str());
1418 }
1419 
1420 #if defined(_WIN32)
1421 #  define SERVER_FAILOVER_RETRY_DELAY 500
1422 #else
1423 #  define SERVER_FAILOVER_RETRY_DELAY 330
1424 #endif
1425 
1426 
1427 class ServerFailoverOptsMockEventThreadTest
1428   : public MockEventThreadOptsTest,
1429     public ::testing::WithParamInterface<std::tuple<ares_evsys_t, int, bool> > {
1430  public:
ServerFailoverOptsMockEventThreadTest()1431   ServerFailoverOptsMockEventThreadTest()
1432     : MockEventThreadOptsTest(4, std::get<0>(GetParam()), std::get<1>(GetParam()), std::get<2>(GetParam()),
1433                           FillOptions(&opts_),
1434                           ARES_OPT_SERVER_FAILOVER | ARES_OPT_NOROTATE) {}
CheckExample()1435   void CheckExample() {
1436     HostResult result;
1437     ares_gethostbyname(channel_, "www.example.com.", AF_INET, HostCallback, &result);
1438     Process();
1439     EXPECT_TRUE(result.done_);
1440     std::stringstream ss;
1441     ss << result.host_;
1442     EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
1443   }
1444 
FillOptions(struct ares_options * opts)1445   static struct ares_options* FillOptions(struct ares_options *opts) {
1446     memset(opts, 0, sizeof(struct ares_options));
1447     opts->server_failover_opts.retry_chance = 1;
1448     opts->server_failover_opts.retry_delay = SERVER_FAILOVER_RETRY_DELAY;
1449     return opts;
1450   }
1451  private:
1452   struct ares_options opts_;
1453 };
1454 
1455 // Test case to trigger server failover behavior. We use a retry chance of
1456 // 100% and a retry delay so that we can test behavior reliably.
TEST_P(ServerFailoverOptsMockEventThreadTest,ServerFailoverOpts)1457 TEST_P(ServerFailoverOptsMockEventThreadTest, ServerFailoverOpts) {
1458   DNSPacket servfailrsp;
1459   servfailrsp.set_response().set_aa().set_rcode(SERVFAIL)
1460     .add_question(new DNSQuestion("www.example.com", T_A));
1461   DNSPacket okrsp;
1462   okrsp.set_response().set_aa()
1463     .add_question(new DNSQuestion("www.example.com", T_A))
1464     .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5}));
1465 
1466   auto tv_begin = std::chrono::high_resolution_clock::now();
1467   auto tv_now   = std::chrono::high_resolution_clock::now();
1468   unsigned int delay_ms;
1469 
1470   // At start all servers are healthy, first server should be selected
1471   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: First server should be selected" << std::endl;
1472   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1473     .WillOnce(SetReply(servers_[0].get(), &okrsp));
1474   CheckExample();
1475 
1476   // Fail server #0 but leave server #1 as healthy.  This results in server
1477   // order:
1478   //  #1 (failures: 0), #2 (failures: 0), #3 (failures: 0), #0 (failures: 1)
1479   tv_now = std::chrono::high_resolution_clock::now();
1480   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: Server0 will fail but leave Server1 as healthy" << std::endl;
1481   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1482     .WillOnce(SetReply(servers_[0].get(), &servfailrsp));
1483   EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1484     .WillOnce(SetReply(servers_[1].get(), &okrsp));
1485   CheckExample();
1486 
1487   // Sleep for the retry delay (actually a little more than the retry delay to account
1488   // for unreliable timing, e.g. NTP slew) and send in another query. The real
1489   // query will be sent to Server #1 (which will succeed) and Server #0 will
1490   // be probed and return a successful result.  This leaves the server order
1491   // of:
1492   //   #0 (failures: 0), #1 (failures: 0), #2 (failures: 0), #3 (failures: 0)
1493   tv_now = std::chrono::high_resolution_clock::now();
1494   delay_ms = SERVER_FAILOVER_RETRY_DELAY + (SERVER_FAILOVER_RETRY_DELAY / 10);
1495   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: sleep " << delay_ms << "ms" << std::endl;
1496   ares_sleep_time(delay_ms);
1497   tv_now = std::chrono::high_resolution_clock::now();
1498   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: Server0 should be past retry delay and should be probed (successful), server 1 will respond successful for real query" << std::endl;
1499   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1500     .WillOnce(SetReply(servers_[0].get(), &okrsp));
1501   EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1502     .WillOnce(SetReply(servers_[1].get(), &okrsp));
1503   CheckExample();
1504 
1505 
1506   // Fail all servers for the first round of tries. On the second round, #0
1507   // responds successfully. This should leave server order of:
1508   //   #1 (failures: 0), #2 (failures: 1), #3 (failures: 1), #0 (failures: 2)
1509   // NOTE: A single query being retried won't spawn probes to downed servers,
1510   //       only an initial query attempt is eligible to spawn probes.  So
1511   //       no probes are sent for this test.
1512   tv_now = std::chrono::high_resolution_clock::now();
1513   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: All 4 servers will fail on the first attempt, server 0 will fail on second. Server 1 will succeed on second." << std::endl;
1514   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1515     .WillOnce(SetReply(servers_[0].get(), &servfailrsp))
1516     .WillOnce(SetReply(servers_[0].get(), &servfailrsp));
1517   EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1518     .WillOnce(SetReply(servers_[1].get(), &servfailrsp))
1519     .WillOnce(SetReply(servers_[1].get(), &okrsp));
1520   EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1521     .WillOnce(SetReply(servers_[2].get(), &servfailrsp));
1522   EXPECT_CALL(*servers_[3], OnRequest("www.example.com", T_A))
1523     .WillOnce(SetReply(servers_[3].get(), &servfailrsp));
1524   CheckExample();
1525 
1526 
1527   // Sleep for the retry delay and send in another query. Server #1 is the
1528   // highest priority server and will respond with success, however a probe
1529   // will be sent for Server #2 which will succeed:
1530   //  #1 (failures: 0), #2 (failures: 0), #3 (failures: 1 - expired), #0 (failures: 2 - expired)
1531   tv_now = std::chrono::high_resolution_clock::now();
1532   delay_ms = SERVER_FAILOVER_RETRY_DELAY + (SERVER_FAILOVER_RETRY_DELAY / 10);
1533   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: sleep " << delay_ms << "ms" << std::endl;
1534   ares_sleep_time(delay_ms);
1535   tv_now = std::chrono::high_resolution_clock::now();
1536   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: Past retry delay, will query Server 1 and probe Server 2, both will succeed." << std::endl;
1537   EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1538     .WillOnce(SetReply(servers_[1].get(), &okrsp));
1539   EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1540     .WillOnce(SetReply(servers_[2].get(), &okrsp));
1541   CheckExample();
1542 
1543   // Cause another server to fail so we have at least one non-expired failed
1544   // server and one expired failed server.  #1 is highest priority, which we
1545   // will fail, #2 will succeed, and #3 will be probed and succeed:
1546   //  #2 (failures: 0), #3 (failures: 0), #1 (failures: 1 not expired), #0 (failures: 2 expired)
1547   tv_now = std::chrono::high_resolution_clock::now();
1548   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: Will query Server 1 and fail, Server 2 will answer successfully. Server 3 will be probed and succeed." << std::endl;
1549   EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1550     .WillOnce(SetReply(servers_[1].get(), &servfailrsp));
1551   EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1552     .WillOnce(SetReply(servers_[2].get(), &okrsp));
1553   EXPECT_CALL(*servers_[3], OnRequest("www.example.com", T_A))
1554     .WillOnce(SetReply(servers_[3].get(), &okrsp));
1555   CheckExample();
1556 
1557   // We need to make sure that if there is a failed server that is higher priority
1558   // but not yet expired that it will probe the next failed server instead.
1559   // In this case #2 is the server that the query will go to and succeed, and
1560   // then a probe will be sent for #0 (since #1 is not expired) and succeed.  We
1561   // will sleep for 1/4 the retry duration before spawning the queries so we can
1562   // then sleep for the rest for the follow-up test.  This will leave the servers
1563   // in this state:
1564   //   #0 (failures: 0), #2 (failures: 0), #3 (failures: 0), #1 (failures: 1 not expired)
1565   tv_now = std::chrono::high_resolution_clock::now();
1566 
1567   // We need to track retry delay time to know what is expired when.
1568   auto elapse_start = tv_now;
1569 
1570   delay_ms = (SERVER_FAILOVER_RETRY_DELAY/4);
1571   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: sleep " << delay_ms << "ms" << std::endl;
1572   ares_sleep_time(delay_ms);
1573   tv_now = std::chrono::high_resolution_clock::now();
1574 
1575   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: Retry delay has not been hit yet. Server2 will be queried and succeed. Server 0 (not server 1 due to non-expired retry delay) will be probed and succeed." << std::endl;
1576   EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1577     .WillOnce(SetReply(servers_[2].get(), &okrsp));
1578   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1579     .WillOnce(SetReply(servers_[0].get(), &okrsp));
1580   CheckExample();
1581 
1582   // Finally we sleep for the remainder of the retry delay, send another
1583   // query, which should succeed on Server #0, and also probe Server #1 which
1584   // will also succeed.
1585   tv_now = std::chrono::high_resolution_clock::now();
1586 
1587   unsigned int elapsed_time = (unsigned int)std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - elapse_start).count();
1588   delay_ms = (SERVER_FAILOVER_RETRY_DELAY) + (SERVER_FAILOVER_RETRY_DELAY / 10);
1589   if (elapsed_time > delay_ms) {
1590     if (verbose) std::cerr << "elapsed duration " << elapsed_time << "ms greater than desired delay of " << delay_ms << "ms, not sleeping" << std::endl;
1591   } else {
1592     delay_ms -= elapsed_time; // subtract already elapsed time
1593     if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: sleep " << delay_ms << "ms" << std::endl;
1594     ares_sleep_time(delay_ms);
1595   }
1596   tv_now = std::chrono::high_resolution_clock::now();
1597   if (verbose) std::cerr << std::chrono::duration_cast<std::chrono::milliseconds>(tv_now - tv_begin).count() << "ms: Retry delay has expired on Server1, Server 0 will be queried and succeed, Server 1 will be probed and succeed." << std::endl;
1598   EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1599     .WillOnce(SetReply(servers_[0].get(), &okrsp));
1600   EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1601     .WillOnce(SetReply(servers_[1].get(), &okrsp));
1602   CheckExample();
1603 }
1604 
evsys_tostr(ares_evsys_t evsys)1605 static const char *evsys_tostr(ares_evsys_t evsys)
1606 {
1607   switch (evsys) {
1608     case ARES_EVSYS_WIN32:
1609       return "WIN32";
1610     case ARES_EVSYS_EPOLL:
1611       return "EPOLL";
1612     case ARES_EVSYS_KQUEUE:
1613       return "KQUEUE";
1614     case ARES_EVSYS_POLL:
1615       return "POLL";
1616     case ARES_EVSYS_SELECT:
1617       return "SELECT";
1618     case ARES_EVSYS_DEFAULT:
1619       return "DEFAULT";
1620   }
1621   return "UNKNOWN";
1622 }
1623 
1624 
PrintEvsysFamilyMode(const testing::TestParamInfo<std::tuple<ares_evsys_t,int,bool>> & info)1625 static std::string PrintEvsysFamilyMode(const testing::TestParamInfo<std::tuple<ares_evsys_t, int, bool>> &info)
1626 {
1627   std::string name;
1628 
1629   name += evsys_tostr(std::get<0>(info.param));
1630   name += "_";
1631   name += af_tostr(std::get<1>(info.param));
1632   name += "_";
1633   name += mode_tostr(std::get<2>(info.param));
1634   return name;
1635 }
1636 
PrintEvsysFamily(const testing::TestParamInfo<std::tuple<ares_evsys_t,int>> & info)1637 static std::string PrintEvsysFamily(const testing::TestParamInfo<std::tuple<ares_evsys_t, int>> &info)
1638 {
1639   std::string name;
1640 
1641   name += evsys_tostr(std::get<0>(info.param));
1642   name += "_";
1643   name += af_tostr(std::get<1>(info.param));
1644   return name;
1645 }
1646 
1647 INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockEventThreadTest, ::testing::ValuesIn(ares::test::evsys_families_modes), ares::test::PrintEvsysFamilyMode);
1648 
1649 INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockUDPEventThreadTest, ::testing::ValuesIn(ares::test::evsys_families), ares::test::PrintEvsysFamily);
1650 
1651 INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockUDPEventThreadMaxQueriesTest, ::testing::ValuesIn(ares::test::evsys_families), ares::test::PrintEvsysFamily);
1652 
1653 INSTANTIATE_TEST_SUITE_P(AddressFamilies, CacheQueriesEventThreadTest, ::testing::ValuesIn(ares::test::evsys_families), ares::test::PrintEvsysFamily);
1654 
1655 INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockTCPEventThreadTest, ::testing::ValuesIn(ares::test::evsys_families), ares::test::PrintEvsysFamily);
1656 
1657 INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockTCPEventThreadStayOpenTest, ::testing::ValuesIn(ares::test::evsys_families), ares::test::PrintEvsysFamily);
1658 
1659 INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockExtraOptsEventThreadTest, ::testing::ValuesIn(ares::test::evsys_families_modes), ares::test::PrintEvsysFamilyMode);
1660 
1661 INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockNoCheckRespEventThreadTest, ::testing::ValuesIn(ares::test::evsys_families_modes), ares::test::PrintEvsysFamilyMode);
1662 
1663 INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockEDNSEventThreadTest, ::testing::ValuesIn(ares::test::evsys_families_modes), ares::test::PrintEvsysFamilyMode);
1664 
1665 INSTANTIATE_TEST_SUITE_P(TransportModes, NoRotateMultiMockEventThreadTest, ::testing::ValuesIn(ares::test::evsys_families_modes), ares::test::PrintEvsysFamilyMode);
1666 
1667 INSTANTIATE_TEST_SUITE_P(TransportModes, ServerFailoverOptsMockEventThreadTest, ::testing::ValuesIn(ares::test::evsys_families_modes), ares::test::PrintEvsysFamilyMode);
1668 
1669 #if 0
1670 INSTANTIATE_TEST_SUITE_P(AddressFamilies, MockUDPEventThreadSingleQueryPerConnTest, ::testing::ValuesIn(ares::test::evsys_families), ares::test::PrintEvsysFamily);
1671 #endif
1672 
1673 }  // namespace test
1674 }  // namespace ares
1675 
1676 #endif /* CARES_THREADS */
1677