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