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