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, &params,
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, &params, 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, &params, 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