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