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