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