blob: 03f8806c181e8f2b30ae8f384ffa5a91d3663cb9 [file] [log] [blame]
Mike Yud1ec2542019-06-06 17:17:53 +08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Luke Huange126fbe2019-07-20 17:36:30 +080017#include <netdb.h>
Mike Yud1ec2542019-06-06 17:17:53 +080018
Mike Yuc7649d12019-05-22 15:28:07 +080019#include <array>
Mike Yud1ec2542019-06-06 17:17:53 +080020#include <atomic>
21#include <chrono>
22#include <ctime>
23#include <thread>
24
25#include <android-base/logging.h>
26#include <android-base/stringprintf.h>
27#include <android/multinetwork.h>
Ken Chen766feae2019-10-30 15:13:44 +080028#include <arpa/inet.h>
Luke Huange126fbe2019-07-20 17:36:30 +080029#include <cutils/properties.h>
30#include <gmock/gmock-matchers.h>
31#include <gtest/gtest.h>
Mike Yud1ec2542019-06-06 17:17:53 +080032
Bernie Innocenti08487112019-10-11 21:14:13 +090033#include "res_init.h"
Mike Yud1ec2542019-06-06 17:17:53 +080034#include "resolv_cache.h"
35#include "resolv_private.h"
Ken Chen99c0b322019-11-20 14:24:09 +080036#include "stats.h"
chenbruceb43ec752019-07-24 20:19:41 +080037#include "tests/dns_responder/dns_responder.h"
Mike Yud1ec2542019-06-06 17:17:53 +080038
39using namespace std::chrono_literals;
40
41constexpr int TEST_NETID = 30;
42constexpr int TEST_NETID_2 = 31;
Ken Chen766feae2019-10-30 15:13:44 +080043constexpr int DNS_PORT = 53;
Mike Yud1ec2542019-06-06 17:17:53 +080044
45// Constant values sync'd from res_cache.cpp
46constexpr int DNS_HEADER_SIZE = 12;
47constexpr int MAX_ENTRIES = 64 * 2 * 5;
Mike Yud1ec2542019-06-06 17:17:53 +080048
49namespace {
50
51struct CacheEntry {
52 std::vector<char> query;
53 std::vector<char> answer;
54};
55
Mike Yuc7649d12019-05-22 15:28:07 +080056struct SetupParams {
57 std::vector<std::string> servers;
58 std::vector<std::string> domains;
59 res_params params;
60};
61
62struct CacheStats {
63 SetupParams setup;
64 std::vector<res_stats> stats;
65 int pendingReqTimeoutCount;
66};
67
Mike Yud1ec2542019-06-06 17:17:53 +080068std::vector<char> makeQuery(int op, const char* qname, int qclass, int qtype) {
Mike Yud1ec2542019-06-06 17:17:53 +080069 uint8_t buf[MAXPACKET] = {};
Bernie Innocenti08487112019-10-11 21:14:13 +090070 const int len = res_nmkquery(op, qname, qclass, qtype, /*data=*/nullptr, /*datalen=*/0, buf,
71 sizeof(buf),
72 /*netcontext_flags=*/0);
Mike Yud1ec2542019-06-06 17:17:53 +080073 return std::vector<char>(buf, buf + len);
74}
75
76std::vector<char> makeAnswer(const std::vector<char>& query, const char* rdata_str,
77 const unsigned ttl) {
78 test::DNSHeader header;
79 header.read(query.data(), query.data() + query.size());
80
81 for (const test::DNSQuestion& question : header.questions) {
82 std::string rname(question.qname.name);
83 test::DNSRecord record{
84 .name = {.name = question.qname.name},
85 .rtype = question.qtype,
86 .rclass = question.qclass,
87 .ttl = ttl,
88 };
Hungming Chenbb90ab32019-10-28 18:20:31 +080089 test::DNSResponder::fillRdata(rdata_str, record);
Mike Yud1ec2542019-06-06 17:17:53 +080090 header.answers.push_back(std::move(record));
91 }
92
93 char answer[MAXPACKET] = {};
94 char* answer_end = header.write(answer, answer + sizeof(answer));
95 return std::vector<char>(answer, answer_end);
96}
97
98// Get the current time in unix timestamp since the Epoch.
99time_t currentTime() {
100 return std::time(nullptr);
101}
102
Mike Yuc7649d12019-05-22 15:28:07 +0800103// Comparison for res_stats. Simply check the count in the cache test.
104bool operator==(const res_stats& a, const res_stats& b) {
105 return std::tie(a.sample_count, a.sample_next) == std::tie(b.sample_count, b.sample_next);
106}
107
108// Comparison for res_params.
109bool operator==(const res_params& a, const res_params& b) {
110 return std::tie(a.sample_validity, a.success_threshold, a.min_samples, a.max_samples,
111 a.base_timeout_msec, a.retry_count) ==
112 std::tie(b.sample_validity, b.success_threshold, b.min_samples, b.max_samples,
113 b.base_timeout_msec, b.retry_count);
114}
115
Mike Yud1ec2542019-06-06 17:17:53 +0800116} // namespace
117
118class ResolvCacheTest : public ::testing::Test {
119 protected:
Mike Yuc7649d12019-05-22 15:28:07 +0800120 static constexpr res_params kParams = {
121 .sample_validity = 300,
122 .success_threshold = 25,
123 .min_samples = 8,
124 .max_samples = 8,
125 .base_timeout_msec = 1000,
126 .retry_count = 2,
127 };
128
Mike Yud1ec2542019-06-06 17:17:53 +0800129 ResolvCacheTest() {
130 // Store the default one and conceal 10000+ lines of resolver cache logs.
131 defaultLogSeverity = android::base::SetMinimumLogSeverity(
132 static_cast<android::base::LogSeverity>(android::base::WARNING));
133 }
134 ~ResolvCacheTest() {
135 cacheDelete(TEST_NETID);
136 cacheDelete(TEST_NETID_2);
137
138 // Restore the log severity.
139 android::base::SetMinimumLogSeverity(defaultLogSeverity);
140 }
141
142 [[nodiscard]] bool cacheLookup(ResolvCacheStatus expectedCacheStatus, uint32_t netId,
143 const CacheEntry& ce, uint32_t flags = 0) {
144 int anslen = 0;
145 std::vector<char> answer(MAXPACKET);
146 const auto cacheStatus = resolv_cache_lookup(netId, ce.query.data(), ce.query.size(),
147 answer.data(), answer.size(), &anslen, flags);
148 if (cacheStatus != expectedCacheStatus) {
149 ADD_FAILURE() << "cacheStatus: expected = " << expectedCacheStatus
150 << ", actual =" << cacheStatus;
151 return false;
152 }
153
154 if (cacheStatus == RESOLV_CACHE_FOUND) {
155 answer.resize(anslen);
156 if (answer != ce.answer) {
157 ADD_FAILURE() << "The answer from the cache is not as expected.";
158 return false;
159 }
160 }
161 return true;
162 }
163
164 int cacheCreate(uint32_t netId) {
165 return resolv_create_cache_for_net(netId);
166 }
167
168 void cacheDelete(uint32_t netId) {
169 resolv_delete_cache_for_net(netId);
170 }
171
172 int cacheAdd(uint32_t netId, const CacheEntry& ce) {
173 return resolv_cache_add(netId, ce.query.data(), ce.query.size(), ce.answer.data(),
174 ce.answer.size());
175 }
176
177 int cacheAdd(uint32_t netId, const std::vector<char>& query, const std::vector<char>& answer) {
178 return resolv_cache_add(netId, query.data(), query.size(), answer.data(), answer.size());
179 }
180
181 int cacheGetExpiration(uint32_t netId, const std::vector<char>& query, time_t* expiration) {
182 return resolv_cache_get_expiration(netId, query, expiration);
183 }
184
185 void cacheQueryFailed(uint32_t netId, const CacheEntry& ce, uint32_t flags) {
186 _resolv_cache_query_failed(netId, ce.query.data(), ce.query.size(), flags);
187 }
188
Mike Yuc7649d12019-05-22 15:28:07 +0800189 int cacheSetupResolver(uint32_t netId, const SetupParams& setup) {
190 return resolv_set_nameservers(netId, setup.servers, setup.domains, setup.params);
191 }
192
Ken Chen766feae2019-10-30 15:13:44 +0800193 void cacheAddStats(uint32_t netId, int revision_id, const sockaddr* sa,
194 const res_sample& sample, int max_samples) {
195 resolv_cache_add_resolver_stats_sample(netId, revision_id, sa, sample, max_samples);
196 }
197
198 int cacheFlush(uint32_t netId) { return resolv_flush_cache_for_net(netId); }
199
Mike Yuc7649d12019-05-22 15:28:07 +0800200 void expectCacheStats(const std::string& msg, uint32_t netId, const CacheStats& expected) {
201 int nscount = -1;
202 sockaddr_storage servers[MAXNS];
203 int dcount = -1;
204 char domains[MAXDNSRCH][MAXDNSRCHPATH];
205 res_stats stats[MAXNS];
206 res_params params = {};
207 int res_wait_for_pending_req_timeout_count;
208 android_net_res_stats_get_info_for_net(netId, &nscount, servers, &dcount, domains, &params,
209 stats, &res_wait_for_pending_req_timeout_count);
210
211 // Server checking.
212 EXPECT_EQ(nscount, static_cast<int>(expected.setup.servers.size())) << msg;
213 for (int i = 0; i < nscount; i++) {
214 EXPECT_EQ(addrToString(&servers[i]), expected.setup.servers[i]) << msg;
215 }
216
217 // Domain checking
218 EXPECT_EQ(dcount, static_cast<int>(expected.setup.domains.size())) << msg;
219 for (int i = 0; i < dcount; i++) {
220 EXPECT_EQ(std::string(domains[i]), expected.setup.domains[i]) << msg;
221 }
222
223 // res_params checking.
224 EXPECT_TRUE(params == expected.setup.params) << msg;
225
226 // res_stats checking.
Ken Chen8cfe5562019-11-03 11:37:06 +0800227 if (expected.stats.size() == 0) {
228 for (int ns = 0; ns < nscount; ns++) {
229 EXPECT_EQ(0U, stats[ns].sample_count) << msg;
230 }
231 }
Mike Yuc7649d12019-05-22 15:28:07 +0800232 for (size_t i = 0; i < expected.stats.size(); i++) {
233 EXPECT_TRUE(stats[i] == expected.stats[i]) << msg;
234 }
235
236 // wait_for_pending_req_timeout_count checking.
237 EXPECT_EQ(res_wait_for_pending_req_timeout_count, expected.pendingReqTimeoutCount) << msg;
238 }
239
Mike Yud1ec2542019-06-06 17:17:53 +0800240 CacheEntry makeCacheEntry(int op, const char* qname, int qclass, int qtype, const char* rdata,
241 std::chrono::seconds ttl = 10s) {
242 CacheEntry ce;
243 ce.query = makeQuery(op, qname, qclass, qtype);
244 ce.answer = makeAnswer(ce.query, rdata, static_cast<unsigned>(ttl.count()));
245 return ce;
246 }
247
248 private:
249 android::base::LogSeverity defaultLogSeverity;
250};
251
252TEST_F(ResolvCacheTest, CreateAndDeleteCache) {
253 // Create the cache for network 1.
254 EXPECT_EQ(0, cacheCreate(TEST_NETID));
255 EXPECT_EQ(-EEXIST, cacheCreate(TEST_NETID));
256 EXPECT_TRUE(has_named_cache(TEST_NETID));
257
258 // Create the cache for network 2.
259 EXPECT_EQ(0, cacheCreate(TEST_NETID_2));
260 EXPECT_EQ(-EEXIST, cacheCreate(TEST_NETID_2));
261 EXPECT_TRUE(has_named_cache(TEST_NETID_2));
262
263 // Delete the cache in network 1.
264 cacheDelete(TEST_NETID);
265 EXPECT_FALSE(has_named_cache(TEST_NETID));
266 EXPECT_TRUE(has_named_cache(TEST_NETID_2));
267}
268
269// Missing checks for the argument 'answer'.
270TEST_F(ResolvCacheTest, CacheAdd_InvalidArgs) {
271 EXPECT_EQ(0, cacheCreate(TEST_NETID));
272
273 const std::vector<char> queryEmpty(MAXPACKET, 0);
274 const std::vector<char> queryTooSmall(DNS_HEADER_SIZE - 1, 0);
275 CacheEntry ce = makeCacheEntry(QUERY, "valid.cache", ns_c_in, ns_t_a, "1.2.3.4");
276
277 EXPECT_EQ(-EINVAL, cacheAdd(TEST_NETID, queryEmpty, ce.answer));
278 EXPECT_EQ(-EINVAL, cacheAdd(TEST_NETID, queryTooSmall, ce.answer));
279
280 // Cache not existent in TEST_NETID_2.
281 EXPECT_EQ(-ENONET, cacheAdd(TEST_NETID_2, ce));
282}
283
284TEST_F(ResolvCacheTest, CacheAdd_DuplicateEntry) {
285 EXPECT_EQ(0, cacheCreate(TEST_NETID));
286 CacheEntry ce = makeCacheEntry(QUERY, "existent.in.cache", ns_c_in, ns_t_a, "1.2.3.4");
287 time_t now = currentTime();
288
289 // Add the cache entry.
290 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
291 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
292 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
293
294 // Get the expiration time and verify its value is greater than now.
295 time_t expiration1;
296 EXPECT_EQ(0, cacheGetExpiration(TEST_NETID, ce.query, &expiration1));
297 EXPECT_GT(expiration1, now);
298
299 // Adding the duplicate entry will return an error, and the expiration time won't be modified.
300 EXPECT_EQ(-EEXIST, cacheAdd(TEST_NETID, ce));
301 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
302 time_t expiration2;
303 EXPECT_EQ(0, cacheGetExpiration(TEST_NETID, ce.query, &expiration2));
304 EXPECT_EQ(expiration1, expiration2);
305}
306
307TEST_F(ResolvCacheTest, CacheLookup) {
308 EXPECT_EQ(0, cacheCreate(TEST_NETID));
309 EXPECT_EQ(0, cacheCreate(TEST_NETID_2));
310 CacheEntry ce = makeCacheEntry(QUERY, "existent.in.cache", ns_c_in, ns_t_a, "1.2.3.4");
311
312 // Cache found in network 1.
313 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
314 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
315 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
316
317 // No cache found in network 2.
318 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID_2, ce));
319
320 ce = makeCacheEntry(QUERY, "existent.in.cache", ns_c_in, ns_t_aaaa, "2001:db8::1.2.3.4");
321
322 // type A and AAAA are independent.
323 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
324 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
325 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
326}
327
328TEST_F(ResolvCacheTest, CacheLookup_CacheFlags) {
329 EXPECT_EQ(0, cacheCreate(TEST_NETID));
330 std::vector<char> answerFromCache;
331 CacheEntry ce = makeCacheEntry(QUERY, "existent.in.cache", ns_c_in, ns_t_a, "1.2.3.4");
332
333 // The entry can't be found when only no-cache-lookup bit is carried.
334 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_LOOKUP));
335
336 // Ensure RESOLV_CACHE_SKIP is returned when there's no such the same entry in the cache.
337 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_SKIP, TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_STORE));
338
339 // Skip the cache lookup if no-cache-lookup and no-cache-store bits are carried
340 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_SKIP, TEST_NETID, ce,
341 ANDROID_RESOLV_NO_CACHE_LOOKUP | ANDROID_RESOLV_NO_CACHE_STORE));
342
343 // Add the cache entry.
344 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
345 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
346 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
347
348 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_LOOKUP));
349
350 // Now no-cache-store has no effect if a same entry is existent in the cache.
351 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_STORE));
352
353 // Skip the cache lookup again regardless of a same entry being already in the cache.
354 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_SKIP, TEST_NETID, ce,
355 ANDROID_RESOLV_NO_CACHE_LOOKUP | ANDROID_RESOLV_NO_CACHE_STORE));
356}
357
358TEST_F(ResolvCacheTest, CacheLookup_Types) {
359 EXPECT_EQ(0, cacheCreate(TEST_NETID));
360 static const struct QueryTypes {
361 int type;
362 std::string rdata;
363 } Types[] = {
364 {ns_t_a, "1.2.3.4"},
365 {ns_t_aaaa, "2001:db8::1.2.3.4"},
366 {ns_t_ptr, "4.3.2.1.in-addr.arpa."},
367 {ns_t_ptr, "4.0.3.0.2.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa."},
368 };
369
370 for (const auto& t : Types) {
371 std::string name = android::base::StringPrintf("cache.lookup.type.%s", t.rdata.c_str());
372 SCOPED_TRACE(name);
373
374 CacheEntry ce = makeCacheEntry(QUERY, name.data(), ns_c_in, t.type, t.rdata.data());
375 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
376 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
377 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
378 }
379}
380
381TEST_F(ResolvCacheTest, CacheLookup_InvalidArgs) {
382 EXPECT_EQ(0, cacheCreate(TEST_NETID));
383
384 const std::vector<char> queryEmpty(MAXPACKET, 0);
385 const std::vector<char> queryTooSmall(DNS_HEADER_SIZE - 1, 0);
386 std::vector<char> answerTooSmall(DNS_HEADER_SIZE - 1, 0);
387 const CacheEntry ce = makeCacheEntry(QUERY, "valid.cache", ns_c_in, ns_t_a, "1.2.3.4");
388 auto cacheLookupFn = [](const std::vector<char>& query,
389 std::vector<char> answer) -> ResolvCacheStatus {
390 int anslen = 0;
391 return resolv_cache_lookup(TEST_NETID, query.data(), query.size(), answer.data(),
392 answer.size(), &anslen, 0);
393 };
394
395 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
396
397 EXPECT_EQ(RESOLV_CACHE_UNSUPPORTED, cacheLookupFn(queryEmpty, ce.answer));
398 EXPECT_EQ(RESOLV_CACHE_UNSUPPORTED, cacheLookupFn(queryTooSmall, ce.answer));
399 EXPECT_EQ(RESOLV_CACHE_UNSUPPORTED, cacheLookupFn(ce.query, answerTooSmall));
400
401 // It can actually be found with valid arguments.
402 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
403
404 // Cache not existent in TEST_NETID_2.
405 EXPECT_EQ(-ENONET, cacheAdd(TEST_NETID_2, ce));
406 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_UNSUPPORTED, TEST_NETID_2, ce));
407}
408
409TEST_F(ResolvCacheTest, CacheLookup_Expired) {
410 EXPECT_EQ(0, cacheCreate(TEST_NETID));
411
412 // An entry with zero ttl won't be stored in the cache.
413 CacheEntry ce = makeCacheEntry(QUERY, "expired.in.0s", ns_c_in, ns_t_a, "1.2.3.4", 0s);
414 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
415 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
416
417 // Create an entry expired in 1s.
418 ce = makeCacheEntry(QUERY, "expired.in.1s", ns_c_in, ns_t_a, "1.2.3.4", 1s);
419 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
420
421 // Cache found.
422 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
423 time_t expiration;
424 EXPECT_EQ(0, cacheGetExpiration(TEST_NETID, ce.query, &expiration));
425
426 // Wait for the cache expired.
427 std::this_thread::sleep_for(1500ms);
428 EXPECT_GE(currentTime(), expiration);
429 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
430}
431
432TEST_F(ResolvCacheTest, PendingRequest_QueryDeferred) {
433 EXPECT_EQ(0, cacheCreate(TEST_NETID));
434 EXPECT_EQ(0, cacheCreate(TEST_NETID_2));
435
436 CacheEntry ce = makeCacheEntry(QUERY, "query.deferred", ns_c_in, ns_t_a, "1.2.3.4");
437 std::atomic_bool done(false);
438
439 // This is the first lookup. The following lookups from other threads will be in the
440 // pending request list.
441 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
442
443 std::vector<std::thread> threads(5);
444 for (std::thread& thread : threads) {
445 thread = std::thread([&]() {
446 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
447
448 // Ensure this thread gets stuck in lookups before we wake it.
449 EXPECT_TRUE(done);
450 });
451 }
452
453 // Wait for a while for the threads performing lookups.
454 // TODO: Perhaps implement a test-only function to get the number of pending requests
455 // instead of sleep.
456 std::this_thread::sleep_for(100ms);
457
458 // The threads keep waiting regardless of any other networks or even if cache flag is set.
459 EXPECT_EQ(0, cacheAdd(TEST_NETID_2, ce));
460 cacheQueryFailed(TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_STORE);
461 cacheQueryFailed(TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_LOOKUP);
462 cacheQueryFailed(TEST_NETID_2, ce, ANDROID_RESOLV_NO_CACHE_STORE);
463 cacheQueryFailed(TEST_NETID_2, ce, ANDROID_RESOLV_NO_CACHE_LOOKUP);
464 cacheDelete(TEST_NETID_2);
465
466 // Ensure none of the threads has finished the lookups.
467 std::this_thread::sleep_for(100ms);
468
469 // Wake up the threads
470 done = true;
471 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
472
473 for (std::thread& thread : threads) {
474 thread.join();
475 }
476}
477
478TEST_F(ResolvCacheTest, PendingRequest_QueryFailed) {
479 EXPECT_EQ(0, cacheCreate(TEST_NETID));
480
481 CacheEntry ce = makeCacheEntry(QUERY, "query.failed", ns_c_in, ns_t_a, "1.2.3.4");
482 std::atomic_bool done(false);
483
484 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
485
486 std::vector<std::thread> threads(5);
487 for (std::thread& thread : threads) {
488 thread = std::thread([&]() {
489 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
490
491 // Ensure this thread gets stuck in lookups before we wake it.
492 EXPECT_TRUE(done);
493 });
494 }
495
496 // Wait for a while for the threads performing lookups.
497 std::this_thread::sleep_for(100ms);
498
499 // Wake up the threads
500 done = true;
501 cacheQueryFailed(TEST_NETID, ce, 0);
502
503 for (std::thread& thread : threads) {
504 thread.join();
505 }
506}
507
508TEST_F(ResolvCacheTest, PendingRequest_CacheDestroyed) {
509 EXPECT_EQ(0, cacheCreate(TEST_NETID));
510 EXPECT_EQ(0, cacheCreate(TEST_NETID_2));
511
512 CacheEntry ce = makeCacheEntry(QUERY, "query.failed", ns_c_in, ns_t_a, "1.2.3.4");
513 std::atomic_bool done(false);
514
515 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
516
517 std::vector<std::thread> threads(5);
518 for (std::thread& thread : threads) {
519 thread = std::thread([&]() {
520 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
521
522 // Ensure this thread gets stuck in lookups before we wake it.
523 EXPECT_TRUE(done);
524 });
525 }
526
527 // Wait for a while for the threads performing lookups.
528 std::this_thread::sleep_for(100ms);
529
530 // Deleting another network must not cause the threads to wake up.
531 cacheDelete(TEST_NETID_2);
532
533 // Ensure none of the threads has finished the lookups.
534 std::this_thread::sleep_for(100ms);
535
536 // Wake up the threads
537 done = true;
538 cacheDelete(TEST_NETID);
539
540 for (std::thread& thread : threads) {
541 thread.join();
542 }
543}
544
545TEST_F(ResolvCacheTest, MaxEntries) {
546 EXPECT_EQ(0, cacheCreate(TEST_NETID));
547 std::vector<CacheEntry> ces;
548
549 for (int i = 0; i < 2 * MAX_ENTRIES; i++) {
550 std::string qname = android::base::StringPrintf("cache.%04d", i);
551 SCOPED_TRACE(qname);
552 CacheEntry ce = makeCacheEntry(QUERY, qname.data(), ns_c_in, ns_t_a, "1.2.3.4");
553 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
554 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
555 ces.emplace_back(ce);
556 }
557
558 for (int i = 0; i < 2 * MAX_ENTRIES; i++) {
559 std::string qname = android::base::StringPrintf("cache.%04d", i);
560 SCOPED_TRACE(qname);
561 if (i < MAX_ENTRIES) {
562 // Because the cache is LRU, the oldest queries should have been purged,
563 // and the most recent MAX_ENTRIES ones should still be present.
564 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ces[i]));
565 } else {
566 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ces[i]));
567 }
568 }
569}
570
571TEST_F(ResolvCacheTest, CacheFull) {
572 EXPECT_EQ(0, cacheCreate(TEST_NETID));
573
574 CacheEntry ce1 = makeCacheEntry(QUERY, "cache.0000", ns_c_in, ns_t_a, "1.2.3.4", 100s);
575 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce1));
576 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce1));
577
578 CacheEntry ce2 = makeCacheEntry(QUERY, "cache.0001", ns_c_in, ns_t_a, "1.2.3.4", 1s);
579 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce2));
580 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce2));
581
582 // Stuff the resolver cache.
583 for (int i = 2; i < MAX_ENTRIES; i++) {
584 std::string qname = android::base::StringPrintf("cache.%04d", i);
585 SCOPED_TRACE(qname);
586 CacheEntry ce = makeCacheEntry(QUERY, qname.data(), ns_c_in, ns_t_a, "1.2.3.4", 50s);
587 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
588 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
589 }
590
591 // Wait for ce2 expired.
592 std::this_thread::sleep_for(1500ms);
593
594 // The cache is full now, and the expired ce2 will be removed first.
595 CacheEntry ce3 = makeCacheEntry(QUERY, "cache.overfilled.1", ns_c_in, ns_t_a, "1.2.3.4", 50s);
596 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce3));
597 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce3));
598 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce2));
599
600 // The cache is full again but there's no one expired, so the oldest ce1 will be removed.
601 CacheEntry ce4 = makeCacheEntry(QUERY, "cache.overfilled.2", ns_c_in, ns_t_a, "1.2.3.4", 50s);
602 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce4));
603 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce4));
604 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce1));
605}
606
Mike Yuc7649d12019-05-22 15:28:07 +0800607TEST_F(ResolvCacheTest, ResolverSetup) {
608 const SetupParams setup = {
609 .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"},
610 .domains = {"domain1.com", "domain2.com"},
611 .params = kParams,
612 };
613
614 // Failed to setup resolver because of the cache not created.
615 EXPECT_EQ(-ENONET, cacheSetupResolver(TEST_NETID, setup));
616 EXPECT_FALSE(resolv_has_nameservers(TEST_NETID));
617
618 // The cache is created now.
619 EXPECT_EQ(0, cacheCreate(TEST_NETID));
620 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
621 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
622}
623
624TEST_F(ResolvCacheTest, ResolverSetup_InvalidNameServers) {
625 EXPECT_EQ(0, cacheCreate(TEST_NETID));
626 const std::string invalidServers[]{
627 "127.A.b.1",
628 "127.^.0",
629 "::^:1",
630 "",
631 };
632 SetupParams setup = {
633 .servers = {},
634 .domains = {"domain1.com"},
635 .params = kParams,
636 };
637
638 // Failed to setup resolver because of invalid name servers.
639 for (const auto& server : invalidServers) {
640 SCOPED_TRACE(server);
641 setup.servers = {"127.0.0.1", server, "127.0.0.2"};
642 EXPECT_EQ(-EINVAL, cacheSetupResolver(TEST_NETID, setup));
643 EXPECT_FALSE(resolv_has_nameservers(TEST_NETID));
644 }
645}
646
647TEST_F(ResolvCacheTest, ResolverSetup_DropDomain) {
648 EXPECT_EQ(0, cacheCreate(TEST_NETID));
649
650 // Setup with one domain which is too long.
651 const std::vector<std::string> servers = {"127.0.0.1", "fe80::1"};
652 const std::string domainTooLong(MAXDNSRCHPATH, '1');
653 const std::string validDomain1(MAXDNSRCHPATH - 1, '2');
654 const std::string validDomain2(MAXDNSRCHPATH - 1, '3');
655 SetupParams setup = {
656 .servers = servers,
657 .domains = {},
658 .params = kParams,
659 };
660 CacheStats expect = {
661 .setup = setup,
662 .stats = {},
663 .pendingReqTimeoutCount = 0,
664 };
665
666 // Overlength domains are dropped.
667 setup.domains = {validDomain1, domainTooLong, validDomain2};
668 expect.setup.domains = {validDomain1, validDomain2};
669 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
670 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
671 expectCacheStats("ResolverSetup_Domains drop overlength", TEST_NETID, expect);
672
673 // Duplicate domains are dropped.
674 setup.domains = {validDomain1, validDomain2, validDomain1, validDomain2};
675 expect.setup.domains = {validDomain1, validDomain2};
676 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
677 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
678 expectCacheStats("ResolverSetup_Domains drop duplicates", TEST_NETID, expect);
679}
680
681TEST_F(ResolvCacheTest, ResolverSetup_Prune) {
682 EXPECT_EQ(0, cacheCreate(TEST_NETID));
683 const std::vector<std::string> servers = {"127.0.0.1", "::127.0.0.2", "fe80::1", "fe80::2",
684 "fe80::3"};
685 const std::vector<std::string> domains = {"d1.com", "d2.com", "d3.com", "d4.com",
686 "d5.com", "d6.com", "d7.com"};
687 const SetupParams setup = {
688 .servers = servers,
689 .domains = domains,
690 .params = kParams,
691 };
692
693 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
694 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
695
696 const CacheStats cacheStats = {
697 .setup = {.servers = std::vector(servers.begin(), servers.begin() + MAXNS),
698 .domains = std::vector(domains.begin(), domains.begin() + MAXDNSRCH),
699 .params = setup.params},
700 .stats = {},
701 .pendingReqTimeoutCount = 0,
702 };
703 expectCacheStats("ResolverSetup_Prune", TEST_NETID, cacheStats);
704}
705
706TEST_F(ResolvCacheTest, GetStats) {
707 EXPECT_EQ(0, cacheCreate(TEST_NETID));
708 const SetupParams setup = {
709 .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"},
710 .domains = {"domain1.com", "domain2.com"},
711 .params = kParams,
712 };
713
714 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
715 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
716
717 const CacheStats cacheStats = {
718 .setup = setup,
719 .stats = {},
720 .pendingReqTimeoutCount = 0,
721 };
722 expectCacheStats("GetStats", TEST_NETID, cacheStats);
723}
724
Ken Chen766feae2019-10-30 15:13:44 +0800725TEST_F(ResolvCacheTest, FlushCache) {
726 EXPECT_EQ(0, cacheCreate(TEST_NETID));
727 const SetupParams setup = {
728 .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"},
729 .domains = {"domain1.com", "domain2.com"},
730 .params = kParams,
731 };
732 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
733 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
734
735 res_sample sample = {.at = time(NULL), .rtt = 100, .rcode = ns_r_noerror};
736 sockaddr_in sin = {.sin_family = AF_INET, .sin_port = htons(DNS_PORT)};
737 ASSERT_TRUE(inet_pton(AF_INET, setup.servers[0].c_str(), &sin.sin_addr));
738 cacheAddStats(TEST_NETID, 1 /*revision_id*/, (const sockaddr*)&sin, sample,
739 setup.params.max_samples);
740
741 const CacheStats cacheStats = {
742 .setup = setup,
743 .stats = {{{sample}, 1 /*sample_count*/, 1 /*sample_next*/}},
744 .pendingReqTimeoutCount = 0,
745 };
746 expectCacheStats("FlushCache: a record in cache stats", TEST_NETID, cacheStats);
747
748 EXPECT_EQ(0, cacheFlush(TEST_NETID));
749 const CacheStats cacheStats_empty = {
750 .setup = setup,
751 .stats = {},
752 .pendingReqTimeoutCount = 0,
753 };
754 expectCacheStats("FlushCache: no record in cache stats", TEST_NETID, cacheStats_empty);
755}
756
Ken Chen0d08fbe2019-10-22 21:38:20 +0800757TEST_F(ResolvCacheTest, GetHostByAddrFromCache_InvalidArgs) {
758 char domain_name[NS_MAXDNAME] = {};
759 const char query_v4[] = "1.2.3.5";
760
761 // invalid buffer size
762 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME + 1, nullptr,
763 AF_INET));
764 EXPECT_STREQ("", domain_name);
765
766 // invalid query
767 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, nullptr,
768 AF_INET));
769 EXPECT_STREQ("", domain_name);
770
771 // unsupported AF
772 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
773 AF_UNSPEC));
774 EXPECT_STREQ("", domain_name);
775}
776
777TEST_F(ResolvCacheTest, GetHostByAddrFromCache) {
778 char domain_name[NS_MAXDNAME] = {};
779 const char query_v4[] = "1.2.3.5";
780 const char query_v6[] = "2001:db8::102:304";
781 const char query_v6_unabbreviated[] = "2001:0db8:0000:0000:0000:0000:0102:0304";
782 const char query_v6_mixed[] = "2001:db8::1.2.3.4";
783 const char answer[] = "existent.in.cache";
784
785 // cache does not exist
786 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
787 AF_INET));
788 EXPECT_STREQ("", domain_name);
789
790 // cache is empty
791 EXPECT_EQ(0, cacheCreate(TEST_NETID));
792 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
793 AF_INET));
794 EXPECT_STREQ("", domain_name);
795
796 // no v4 match in cache
797 CacheEntry ce = makeCacheEntry(QUERY, "any.data", ns_c_in, ns_t_a, "1.2.3.4");
798 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
799 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
800 AF_INET));
801 EXPECT_STREQ("", domain_name);
802
803 // v4 match
804 ce = makeCacheEntry(QUERY, answer, ns_c_in, ns_t_a, query_v4);
805 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
806 EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
807 AF_INET));
808 EXPECT_STREQ(answer, domain_name);
809
810 // no v6 match in cache
811 memset(domain_name, 0, NS_MAXDNAME);
812 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v6,
813 AF_INET6));
814 EXPECT_STREQ("", domain_name);
815
816 // v6 match
817 ce = makeCacheEntry(QUERY, answer, ns_c_in, ns_t_aaaa, query_v6);
818 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
819 EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v6,
820 AF_INET6));
821 EXPECT_STREQ(answer, domain_name);
822
823 // v6 match with unabbreviated address format
824 memset(domain_name, 0, NS_MAXDNAME);
825 EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME,
826 query_v6_unabbreviated, AF_INET6));
827 EXPECT_STREQ(answer, domain_name);
828
829 // v6 with mixed address format
830 memset(domain_name, 0, NS_MAXDNAME);
831 EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME,
832 query_v6_mixed, AF_INET6));
833 EXPECT_STREQ(answer, domain_name);
834}
835
Luke Huange126fbe2019-07-20 17:36:30 +0800836namespace {
837
838constexpr int EAI_OK = 0;
839constexpr char DNS_EVENT_SUBSAMPLING_MAP_FLAG[] =
840 "persist.device_config.netd_native.dns_event_subsample_map";
841
842class ScopedCacheCreate {
843 public:
844 explicit ScopedCacheCreate(unsigned netid, const char* subsampling_map,
845 const char* property = DNS_EVENT_SUBSAMPLING_MAP_FLAG)
846 : mStoredNetId(netid), mStoredProperty(property) {
847 property_get(property, mStoredMap, "");
848 property_set(property, subsampling_map);
849 EXPECT_EQ(0, resolv_create_cache_for_net(netid));
850 }
851 ~ScopedCacheCreate() {
852 resolv_delete_cache_for_net(mStoredNetId);
853 property_set(mStoredProperty, mStoredMap);
854 }
855
856 private:
857 unsigned mStoredNetId;
858 const char* mStoredProperty;
859 char mStoredMap[PROPERTY_VALUE_MAX]{};
860};
861
862} // namespace
863
864TEST_F(ResolvCacheTest, DnsEventSubsampling) {
865 // Test defaults, default flag is "default:1 0:100 7:10" if no experiment flag is set
866 {
867 ScopedCacheCreate scopedCacheCreate(TEST_NETID, "");
868 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_NODATA), 10U);
869 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_OK), 100U);
870 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_BADFLAGS),
871 1U); // default
872 EXPECT_THAT(resolv_cache_dump_subsampling_map(TEST_NETID),
873 testing::UnorderedElementsAreArray({"default:1", "0:100", "7:10"}));
874 }
875 // Now change the experiment flag to "0:42 default:666"
876 {
877 ScopedCacheCreate scopedCacheCreate(TEST_NETID, "0:42 default:666");
878 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_OK), 42U);
879 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_NODATA),
880 666U); // default
881 EXPECT_THAT(resolv_cache_dump_subsampling_map(TEST_NETID),
882 testing::UnorderedElementsAreArray({"default:666", "0:42"}));
883 }
884 // Now change the experiment flag to something illegal
885 {
886 ScopedCacheCreate scopedCacheCreate(TEST_NETID, "asvaxx");
887 // 0(disable log) is the default value if experiment flag is invalid.
888 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_OK), 0U);
889 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_NODATA), 0U);
890 EXPECT_TRUE(resolv_cache_dump_subsampling_map(TEST_NETID).empty());
891 }
892 // Test negative and zero denom
893 {
894 ScopedCacheCreate scopedCacheCreate(TEST_NETID, "0:-42 default:-666 7:10 10:0");
895 // 0(disable log) is the default value if no valid denom is set
896 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_OK), 0U);
897 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_BADFLAGS), 0U);
898 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_NODATA), 10U);
899 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_SOCKTYPE), 0U);
900 EXPECT_THAT(resolv_cache_dump_subsampling_map(TEST_NETID),
901 testing::UnorderedElementsAreArray({"7:10", "10:0"}));
902 }
903}
904
Mike Yud5918e62019-10-25 18:51:04 +0800905// TODO: Tests for NetConfig, including:
Mike Yud1ec2542019-06-06 17:17:53 +0800906// - res_params
907// -- resolv_cache_get_resolver_stats()
908// - res_stats
909// -- _resolv_cache_add_resolver_stats_sample()
910// -- android_net_res_stats_get_info_for_net()
911// TODO: inject a mock timer into the cache to make TTL tests pass instantly
912// TODO: test TTL of RFC 2308 negative caching