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_, ¬hird));
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_, ¬hird));
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_, ¬hird));
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(), ¬implrsp));
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(), ¬implrsp));
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(), ¬implrsp));
1345 EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1346 .WillOnce(SetReply(servers_[2].get(), ¬implrsp));
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