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, ¶ms,
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, ¶ms, 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, ¶ms, 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