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