1 /*
2  * Copyright 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 #ifdef NDEBUG
18 #undef NDEBUG
19 #endif
20 
21 #include <netdb.h>
22 
23 #include <iostream>
24 #include <regex>
25 #include <string>
26 #include <thread>
27 #include <vector>
28 
29 #include <aidl/android/net/IDnsResolver.h>
30 #include <android-base/file.h>
31 #include <android-base/format.h>
32 #include <android-base/strings.h>
33 #include <android-base/unique_fd.h>
34 #include <android/binder_manager.h>
35 #include <android/binder_process.h>
36 #include <gmock/gmock-matchers.h>
37 #include <gtest/gtest.h>
38 #include <netdutils/NetNativeTestBase.h>
39 #include <netdutils/Stopwatch.h>
40 #include <nettestutils/DumpService.h>
41 
42 #include <util.h>
43 #include "dns_metrics_listener/base_metrics_listener.h"
44 #include "dns_metrics_listener/test_metrics.h"
45 #include "unsolicited_listener/unsolicited_event_listener.h"
46 
47 #include "ResolverStats.h"
48 #include "dns_responder.h"
49 #include "dns_responder_client_ndk.h"
50 
51 using aidl::android::net::IDnsResolver;
52 using aidl::android::net::ResolverHostsParcel;
53 using aidl::android::net::ResolverOptionsParcel;
54 using aidl::android::net::ResolverParamsParcel;
55 using aidl::android::net::metrics::INetdEventListener;
56 using aidl::android::net::resolv::aidl::DohParamsParcel;
57 using android::base::ReadFdToString;
58 using android::base::StringReplace;
59 using android::base::unique_fd;
60 using android::net::ResolverStats;
61 using android::net::metrics::TestOnDnsEvent;
62 using android::net::resolv::aidl::UnsolicitedEventListener;
63 using android::netdutils::Stopwatch;
64 
65 // TODO: make this dynamic and stop depending on implementation details.
66 // Sync from TEST_NETID in dns_responder_client.cpp as resolv_integration_test.cpp does.
67 constexpr int TEST_NETID = 30;
68 
69 class DnsResolverBinderTest : public NetNativeTestBase {
70   public:
DnsResolverBinderTest()71     DnsResolverBinderTest() {
72         ndk::SpAIBinder resolvBinder = ndk::SpAIBinder(AServiceManager_getService("dnsresolver"));
73 
74         mDnsResolver = IDnsResolver::fromBinder(resolvBinder);
75         // This could happen when the test isn't running as root, or if netd isn't running.
76         assert(nullptr != mDnsResolver.get());
77         // Create cache for test
78         mDnsResolver->createNetworkCache(TEST_NETID);
79     }
80 
~DnsResolverBinderTest()81     ~DnsResolverBinderTest() {
82         expectLog();
83         // Destroy cache for test
84         mDnsResolver->destroyNetworkCache(TEST_NETID);
85     }
86 
87   protected:
expectLog()88     void expectLog() {
89         ndk::SpAIBinder netdBinder = ndk::SpAIBinder(AServiceManager_getService("netd"));
90         // This could happen when the test isn't running as root, or if netd isn't running.
91         assert(nullptr != netdBinder.get());
92         // Send the service dump request to netd.
93         std::vector<std::string> lines;
94         const android::status_t ret =
95                 dumpService(netdBinder, /*args=*/nullptr, /*num_args=*/0, lines);
96         ASSERT_EQ(android::OK, ret) << "Error dumping service: " << android::statusToString(ret);
97 
98         // Basic regexp to match dump output lines. Matches the beginning and end of the line, and
99         // puts the output of the command itself into the first match group.
100         // Example: "      11-05 00:23:39.481 myCommand(args) <2.02ms>".
101         // Accept any number of the leading space.
102         const std::basic_regex lineRegex(
103                 "^\\s*[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}[.][0-9]{3} "
104                 "(.*)"
105                 " <[0-9]+[.][0-9]{2}ms>$");
106 
107         // For each element of testdata, check that the expected output appears in the dump output.
108         // If not, fail the test and use hintRegex to print similar lines to assist in debugging.
109         for (const auto& td : mExpectedLogData) {
110             const bool found =
111                     std::any_of(lines.begin(), lines.end(), [&](const std::string& line) {
112                         std::smatch match;
113                         if (!std::regex_match(line, match, lineRegex)) return false;
114                         if (match.size() != 2) return false;
115 
116                         // The binder_to_string format is changed over time to include more
117                         // information. To keep it working on Q/R/..., remove what has been
118                         // added for now. TODO(b/266248339)
119                         std::string output = match[1].str();
120                         output = StringReplace(output, "(null)", "", /*all=*/true);
121                         output = StringReplace(output, "<unimplemented>", "", /*all=*/true);
122                         output = StringReplace(output, "<interface>", "", /*all=*/true);
123                         return output == td.output;
124                     });
125             EXPECT_TRUE(found) << "Didn't find line '" << td.output << "' in dumpsys output.";
126             if (found) continue;
127             std::cerr << "Similar lines" << std::endl;
128             for (const auto& line : lines) {
129                 if (std::regex_search(line, std::basic_regex(td.hintRegex))) {
130                     std::cerr << line << std::endl;
131                 }
132             }
133         }
134 
135         // The log output is different between R and S, either one is fine for the
136         // test to avoid test compatible issue.
137         // TODO: Remove after S.
138         for (const auto& td : mExpectedLogDataWithPacel) {
139             const bool found =
140                     std::any_of(lines.begin(), lines.end(), [&](const std::string& line) {
141                         std::smatch match;
142                         if (!std::regex_match(line, match, lineRegex)) return false;
143                         return (match.size() == 2) && ((match[1].str() == td.withPacel.output) ||
144                                                        (match[1].str() == td.withoutPacel.output));
145                     });
146             EXPECT_TRUE(found) << fmt::format("Didn't find line '{}' or '{}' in dumpsys output.",
147                                               td.withPacel.output, td.withoutPacel.output);
148             if (found) continue;
149             std::cerr << "Similar lines" << std::endl;
150             for (const auto& line : lines) {
151                 if (std::regex_search(line, std::basic_regex(td.withPacel.hintRegex))) {
152                     std::cerr << line << std::endl;
153                 }
154                 if (std::regex_search(line, std::basic_regex(td.withoutPacel.hintRegex))) {
155                     std::cerr << line << std::endl;
156                 }
157             }
158         }
159     }
160 
161     struct LogData {
162         // Expected contents of the dump command.
163         const std::string output;
164         // A regex that might be helpful in matching relevant lines in the output.
165         // Used to make it easier to add test cases for this code.
166         const std::string hintRegex;
167     };
168 
169     // TODO: Remove this struct and below toString methods after S.
170     struct PossibleLogData {
171         LogData withPacel;
172         LogData withoutPacel;
173     };
174 
toSetResolverConfigurationLogData(const ResolverParamsParcel & parms,int returnCode=0)175     PossibleLogData toSetResolverConfigurationLogData(const ResolverParamsParcel& parms,
176                                                       int returnCode = 0) {
177         // Replace "\n" with "\\n" in parms.caCertificate.
178         std::string outputWithParcel =
179                 fmt::format("setResolverConfiguration({})",
180                             StringReplace(parms.toString(), "\n", "\\n", /*all=*/true));
181         std::string hintRegexWithParcel = fmt::format("setResolverConfiguration.*{}", parms.netId);
182 
183         std::string outputWithoutParcel = "setResolverConfiguration()";
184         std::string hintRegexWithoutParcel = "setResolverConfiguration";
185         if (returnCode != 0) {
186             outputWithParcel.append(fmt::format(" -> ServiceSpecificException({}, \"{}\")",
187                                                 returnCode, strerror(returnCode)));
188             hintRegexWithParcel.append(fmt::format(".*{}", returnCode));
189             outputWithoutParcel.append(fmt::format(" -> ServiceSpecificException({}, \"{}\")",
190                                                    returnCode, strerror(returnCode)));
191             hintRegexWithoutParcel.append(fmt::format(".*{}", returnCode));
192         }
193         return {{std::move(outputWithParcel), std::move(hintRegexWithParcel)},
194                 {std::move(outputWithoutParcel), std::move(hintRegexWithoutParcel)}};
195     }
196 
197     std::shared_ptr<aidl::android::net::IDnsResolver> mDnsResolver;
198     std::vector<LogData> mExpectedLogData;
199     std::vector<PossibleLogData> mExpectedLogDataWithPacel;
200 };
201 
202 class TimedOperation : public Stopwatch {
203   public:
TimedOperation(const std::string & name)204     explicit TimedOperation(const std::string& name) : mName(name) {}
~TimedOperation()205     virtual ~TimedOperation() {
206         std::cerr << "    " << mName << ": " << timeTakenUs() << "us" << std::endl;
207     }
208 
209   private:
210     std::string mName;
211 };
212 
TEST_F(DnsResolverBinderTest,IsAlive)213 TEST_F(DnsResolverBinderTest, IsAlive) {
214     TimedOperation t("isAlive RPC");
215     bool isAlive = false;
216     mDnsResolver->isAlive(&isAlive);
217     ASSERT_TRUE(isAlive);
218 }
219 
TEST_F(DnsResolverBinderTest,RegisterEventListener_NullListener)220 TEST_F(DnsResolverBinderTest, RegisterEventListener_NullListener) {
221     ::ndk::ScopedAStatus status = mDnsResolver->registerEventListener(nullptr);
222     ASSERT_FALSE(status.isOk());
223     ASSERT_EQ(EINVAL, status.getServiceSpecificError());
224     mExpectedLogData.push_back(
225             {"registerEventListener() -> ServiceSpecificException(22, \"Invalid argument\")",
226              "registerEventListener.*22"});
227 }
228 
TEST_F(DnsResolverBinderTest,RegisterEventListener_DuplicateSubscription)229 TEST_F(DnsResolverBinderTest, RegisterEventListener_DuplicateSubscription) {
230     class FakeListener : public android::net::metrics::BaseMetricsListener {};
231 
232     // Expect to subscribe successfully.
233     std::shared_ptr<FakeListener> fakeListener = ndk::SharedRefBase::make<FakeListener>();
234     ::ndk::ScopedAStatus status = mDnsResolver->registerEventListener(fakeListener);
235     ASSERT_TRUE(status.isOk()) << status.getMessage();
236     mExpectedLogData.push_back({"registerEventListener()", "registerEventListener.*"});
237 
238     // Expect to subscribe failed with registered listener instance.
239     status = mDnsResolver->registerEventListener(fakeListener);
240     ASSERT_FALSE(status.isOk());
241     ASSERT_EQ(EEXIST, status.getServiceSpecificError());
242     mExpectedLogData.push_back(
243             {"registerEventListener() -> ServiceSpecificException(17, \"File exists\")",
244              "registerEventListener.*17"});
245 }
246 
TEST_F(DnsResolverBinderTest,RegisterUnsolicitedEventListener_NullListener)247 TEST_F(DnsResolverBinderTest, RegisterUnsolicitedEventListener_NullListener) {
248     ::ndk::ScopedAStatus status = mDnsResolver->registerUnsolicitedEventListener(nullptr);
249     ASSERT_FALSE(status.isOk());
250     ASSERT_EQ(EINVAL, status.getServiceSpecificError());
251     mExpectedLogData.push_back(
252             {"registerUnsolicitedEventListener() -> ServiceSpecificException(22, \"Invalid "
253              "argument\")",
254              "registerUnsolicitedEventListener.*22"});
255 }
256 
TEST_F(DnsResolverBinderTest,RegisterUnsolicitedEventListener_DuplicateSubscription)257 TEST_F(DnsResolverBinderTest, RegisterUnsolicitedEventListener_DuplicateSubscription) {
258     // Expect to subscribe successfully.
259     std::shared_ptr<UnsolicitedEventListener> listener =
260             ndk::SharedRefBase::make<UnsolicitedEventListener>(TEST_NETID);
261     ::ndk::ScopedAStatus status = mDnsResolver->registerUnsolicitedEventListener(listener);
262     ASSERT_TRUE(status.isOk()) << status.getMessage();
263     mExpectedLogData.push_back(
264             {"registerUnsolicitedEventListener()", "registerUnsolicitedEventListener.*"});
265 
266     // Expect to subscribe failed with registered listener instance.
267     status = mDnsResolver->registerUnsolicitedEventListener(listener);
268     ASSERT_FALSE(status.isOk());
269     ASSERT_EQ(EEXIST, status.getServiceSpecificError());
270     mExpectedLogData.push_back(
271             {"registerUnsolicitedEventListener() -> ServiceSpecificException(17, \"File exists\")",
272              "registerUnsolicitedEventListener.*17"});
273 }
274 
275 // TODO: Move this test to resolv_integration_test.cpp
TEST_F(DnsResolverBinderTest,RegisterEventListener_onDnsEvent)276 TEST_F(DnsResolverBinderTest, RegisterEventListener_onDnsEvent) {
277     // The test configs are used to trigger expected events. The expected results are defined in
278     // expectedResults.
279     static const struct TestConfig {
280         std::string hostname;
281         int returnCode;
282     } testConfigs[] = {
283             {"hi", 0 /*success*/},
284             {"nonexistent", EAI_NODATA},
285     };
286 
287     // The expected results define expected event content for test verification.
288     static const std::vector<TestOnDnsEvent::TestResult> expectedResults = {
289             {TEST_NETID, INetdEventListener::EVENT_GETADDRINFO, 0 /*success*/, 1, "hi", "1.2.3.4"},
290             {TEST_NETID, INetdEventListener::EVENT_GETADDRINFO, EAI_NODATA, 0, "nonexistent", ""},
291     };
292 
293     // Start the Binder thread pool.
294     // TODO: Consider doing this once if there has another event listener unit test.
295     ABinderProcess_startThreadPool();
296 
297     // Setup network.
298     // TODO: Setup device configuration and DNS responser server as resolver test does.
299     // Currently, leave DNS related configuration in this test because only it needs DNS
300     // client-server testing environment.
301     DnsResponderClient dnsClient;
302     dnsClient.SetUp();
303 
304     // Setup DNS responder server.
305     constexpr char listen_srv[] = "53";
306     test::DNSResponder dns(kDefaultServer, listen_srv, ns_rcode::ns_r_servfail);
307     dns.addMapping("hi.example.com.", ns_type::ns_t_a, "1.2.3.4");
308     ASSERT_TRUE(dns.startServer());
309 
310     // Setup DNS configuration.
311     ASSERT_TRUE(dnsClient.SetResolversForNetwork());
312     dns.clearQueries();
313 
314     // Register event listener.
315     std::shared_ptr<TestOnDnsEvent> testOnDnsEvent =
316             ndk::SharedRefBase::make<TestOnDnsEvent>(expectedResults);
317     ::ndk::ScopedAStatus status = mDnsResolver->registerEventListener(testOnDnsEvent);
318     ASSERT_TRUE(status.isOk()) << status.getMessage();
319     mExpectedLogData.push_back({"registerEventListener()", "registerEventListener.*"});
320 
321     // DNS queries.
322     // Once all expected events of expectedResults are received by the listener, the unit test will
323     // be notified. Otherwise, notified with a timeout expired failure.
324     auto& cv = testOnDnsEvent->getCv();
325     auto& cvMutex = testOnDnsEvent->getCvMutex();
326     {
327         std::unique_lock lock(cvMutex);
328 
329         for (const auto& config : testConfigs) {
330             SCOPED_TRACE(config.hostname);
331 
332             addrinfo* result = nullptr;
333             addrinfo hints = {.ai_family = AF_INET, .ai_socktype = SOCK_DGRAM};
334             int status = getaddrinfo(config.hostname.c_str(), nullptr, &hints, &result);
335             EXPECT_EQ(config.returnCode, status);
336 
337             if (result) freeaddrinfo(result);
338         }
339 
340         // Wait for receiving expected events.
341         EXPECT_EQ(std::cv_status::no_timeout, cv.wait_for(lock, std::chrono::seconds(2)));
342     }
343 
344     // Verify that all testcases are passed.
345     EXPECT_TRUE(testOnDnsEvent->isVerified());
346 
347     dnsClient.TearDown();
348 }
349 
350 // TODO: Need to test more than one server cases.
TEST_F(DnsResolverBinderTest,SetResolverConfiguration_Tls)351 TEST_F(DnsResolverBinderTest, SetResolverConfiguration_Tls) {
352     const std::vector<std::string> LOCALLY_ASSIGNED_DNS{"8.8.8.8", "2001:4860:4860::8888"};
353     static const std::vector<std::string> valid_v4_addr = {"192.0.2.1"};
354     static const std::vector<std::string> valid_v6_addr = {"2001:db8::2"};
355     static const std::vector<std::string> invalid_v4_addr = {"192.0.*.5"};
356     static const std::vector<std::string> invalid_v6_addr = {"2001:dg8::6"};
357     constexpr char valid_tls_name[] = "example.com";
358     // We enumerate valid and invalid v4/v6 address, and several different TLS names
359     // to be the input data and verify the binder status.
360     static const struct TestData {
361         const std::vector<std::string> servers;
362         const std::string tlsName;
363         const int expectedReturnCode;
364     } kTlsTestData[] = {
365             {valid_v4_addr, valid_tls_name, 0},
366             {valid_v4_addr, "host.com", 0},
367             {valid_v4_addr, "@@@@", 0},
368             {valid_v4_addr, "", 0},
369             {valid_v6_addr, valid_tls_name, 0},
370             {valid_v6_addr, "host.com", 0},
371             {valid_v6_addr, "@@@@", 0},
372             {valid_v6_addr, "", 0},
373             {invalid_v4_addr, valid_tls_name, EINVAL},
374             {invalid_v4_addr, "host.com", EINVAL},
375             {invalid_v4_addr, "@@@@", EINVAL},
376             {invalid_v4_addr, "", EINVAL},
377             {invalid_v6_addr, valid_tls_name, EINVAL},
378             {invalid_v6_addr, "host.com", EINVAL},
379             {invalid_v6_addr, "@@@@", EINVAL},
380             {invalid_v6_addr, "", EINVAL},
381             {{}, "", 0},
382             {{""}, "", EINVAL},
383     };
384 
385     for (size_t i = 0; i < std::size(kTlsTestData); i++) {
386         const auto& td = kTlsTestData[i];
387         const auto resolverParams = ResolverParams::Builder()
388                                             .setDnsServers(LOCALLY_ASSIGNED_DNS)
389                                             .setDotServers(td.servers)
390                                             .setPrivateDnsProvider(td.tlsName)
391                                             .build();
392         ::ndk::ScopedAStatus status = mDnsResolver->setResolverConfiguration(resolverParams);
393 
394         if (td.expectedReturnCode == 0) {
395             SCOPED_TRACE(fmt::format("test case {} should have passed", i));
396             SCOPED_TRACE(status.getMessage());
397             EXPECT_EQ(0, status.getServiceSpecificError());
398             mExpectedLogDataWithPacel.push_back(toSetResolverConfigurationLogData(resolverParams));
399         } else {
400             SCOPED_TRACE(fmt::format("test case {} should have failed", i));
401             EXPECT_EQ(EX_SERVICE_SPECIFIC, status.getExceptionCode());
402             EXPECT_EQ(td.expectedReturnCode, status.getServiceSpecificError());
403             mExpectedLogDataWithPacel.push_back(
404                     toSetResolverConfigurationLogData(resolverParams, td.expectedReturnCode));
405         }
406     }
407 }
408 
TEST_F(DnsResolverBinderTest,SetResolverConfiguration_TransportTypes)409 TEST_F(DnsResolverBinderTest, SetResolverConfiguration_TransportTypes) {
410     using ::testing::HasSubstr;
411     auto resolverParams = DnsResponderClient::GetDefaultResolverParamsParcel();
412     resolverParams.transportTypes = {IDnsResolver::TRANSPORT_WIFI, IDnsResolver::TRANSPORT_VPN};
413     ::ndk::ScopedAStatus status = mDnsResolver->setResolverConfiguration(resolverParams);
414     EXPECT_TRUE(status.isOk()) << status.getMessage();
415     mExpectedLogDataWithPacel.push_back(toSetResolverConfigurationLogData(resolverParams));
416     // TODO: Find a way to fix a potential deadlock here if it's larger than pipe buffer
417     // size(65535).
418     android::base::unique_fd writeFd, readFd;
419     EXPECT_TRUE(Pipe(&readFd, &writeFd));
420     EXPECT_EQ(mDnsResolver->dump(writeFd.get(), nullptr, 0), 0);
421     writeFd.reset();
422     std::string str;
423     ASSERT_TRUE(ReadFdToString(readFd, &str)) << strerror(errno);
424     EXPECT_THAT(str, HasSubstr("WIFI_VPN"));
425 }
426 
TEST_F(DnsResolverBinderTest,SetResolverConfiguration_TransportTypes_Default)427 TEST_F(DnsResolverBinderTest, SetResolverConfiguration_TransportTypes_Default) {
428     using ::testing::HasSubstr;
429     auto resolverParams = DnsResponderClient::GetDefaultResolverParamsParcel();
430     ::ndk::ScopedAStatus status = mDnsResolver->setResolverConfiguration(resolverParams);
431     EXPECT_TRUE(status.isOk()) << status.getMessage();
432     mExpectedLogDataWithPacel.push_back(toSetResolverConfigurationLogData(resolverParams));
433     android::base::unique_fd writeFd, readFd;
434     EXPECT_TRUE(Pipe(&readFd, &writeFd));
435     EXPECT_EQ(mDnsResolver->dump(writeFd.get(), nullptr, 0), 0);
436     writeFd.reset();
437     std::string str;
438     ASSERT_TRUE(ReadFdToString(readFd, &str)) << strerror(errno);
439     EXPECT_THAT(str, HasSubstr("UNKNOWN"));
440 }
441 
TEST_F(DnsResolverBinderTest,SetResolverConfiguration_DohParams)442 TEST_F(DnsResolverBinderTest, SetResolverConfiguration_DohParams) {
443     const auto paramsWithoutDohParams = ResolverParams::Builder().build();
444     ::ndk::ScopedAStatus status = mDnsResolver->setResolverConfiguration(paramsWithoutDohParams);
445     EXPECT_TRUE(status.isOk()) << status.getMessage();
446     mExpectedLogDataWithPacel.push_back(toSetResolverConfigurationLogData(paramsWithoutDohParams));
447 
448     const DohParamsParcel dohParams = {
449             .name = "doh.google",
450             .ips = {"1.2.3.4", "2001:db8::2"},
451             .dohpath = "/dns-query{?dns}",
452             .port = 443,
453     };
454     const auto paramsWithDohParams = ResolverParams::Builder().setDohParams(dohParams).build();
455     status = mDnsResolver->setResolverConfiguration(paramsWithDohParams);
456     EXPECT_TRUE(status.isOk()) << status.getMessage();
457     mExpectedLogDataWithPacel.push_back(toSetResolverConfigurationLogData(paramsWithDohParams));
458 }
459 
460 class MeteredNetworkParameterizedTest : public DnsResolverBinderTest,
461                                         public testing::WithParamInterface<bool> {};
462 
463 INSTANTIATE_TEST_SUITE_P(SetResolverConfigurationTest, MeteredNetworkParameterizedTest,
__anon76907eed0302(const testing::TestParamInfo<bool>& info) 464                          testing::Bool(), [](const testing::TestParamInfo<bool>& info) {
465                              return info.param ? "Metered" : "NotMetered";
466                          });
467 
TEST_P(MeteredNetworkParameterizedTest,MeteredTest)468 TEST_P(MeteredNetworkParameterizedTest, MeteredTest) {
469     const auto resolverParams = ResolverParams::Builder().setMetered(GetParam()).build();
470     ::ndk::ScopedAStatus status = mDnsResolver->setResolverConfiguration(resolverParams);
471     EXPECT_TRUE(status.isOk()) << status.getMessage();
472 
473     mExpectedLogDataWithPacel.push_back(toSetResolverConfigurationLogData(resolverParams));
474 }
475 
TEST_F(DnsResolverBinderTest,GetResolverInfo)476 TEST_F(DnsResolverBinderTest, GetResolverInfo) {
477     std::vector<std::string> servers = {"127.0.0.1", "127.0.0.2"};
478     std::vector<std::string> domains = {"example.com"};
479     std::array<int, aidl::android::net::IDnsResolver::RESOLVER_PARAMS_COUNT> testParams = {
480             300,     // sample validity in seconds
481             25,      // success threshod in percent
482             8,   8,  // {MIN,MAX}_SAMPLES
483             100,     // BASE_TIMEOUT_MSEC
484             3,       // retry count
485     };
486     const auto resolverParams = ResolverParams::Builder()
487                                         .setDomains(domains)
488                                         .setDnsServers(servers)
489                                         .setDotServers({})
490                                         .setParams(testParams)
491                                         .build();
492     ::ndk::ScopedAStatus status = mDnsResolver->setResolverConfiguration(resolverParams);
493     EXPECT_TRUE(status.isOk()) << status.getMessage();
494     mExpectedLogDataWithPacel.push_back(toSetResolverConfigurationLogData(resolverParams));
495 
496     std::vector<std::string> res_servers;
497     std::vector<std::string> res_domains;
498     std::vector<std::string> res_tls_servers;
499     std::vector<int32_t> params32;
500     std::vector<int32_t> stats32;
501     std::vector<int32_t> wait_for_pending_req_timeout_count32{0};
502     status = mDnsResolver->getResolverInfo(TEST_NETID, &res_servers, &res_domains, &res_tls_servers,
503                                            &params32, &stats32,
504                                            &wait_for_pending_req_timeout_count32);
505 
506     EXPECT_TRUE(status.isOk()) << status.getMessage();
507     EXPECT_EQ(servers.size(), res_servers.size());
508     EXPECT_EQ(domains.size(), res_domains.size());
509     EXPECT_EQ(0U, res_tls_servers.size());
510     ASSERT_EQ(static_cast<size_t>(IDnsResolver::RESOLVER_PARAMS_COUNT), testParams.size());
511     EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY],
512               params32[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY]);
513     EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD],
514               params32[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD]);
515     EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES],
516               params32[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES]);
517     EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES],
518               params32[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES]);
519     EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC],
520               params32[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC]);
521     EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_RETRY_COUNT],
522               params32[IDnsResolver::RESOLVER_PARAMS_RETRY_COUNT]);
523 
524     std::vector<ResolverStats> stats;
525     ResolverStats::decodeAll(stats32, &stats);
526 
527     EXPECT_EQ(servers.size(), stats.size());
528 
529     EXPECT_THAT(res_servers, testing::UnorderedElementsAreArray(servers));
530     EXPECT_THAT(res_domains, testing::UnorderedElementsAreArray(domains));
531 }
532 
TEST_F(DnsResolverBinderTest,CreateDestroyNetworkCache)533 TEST_F(DnsResolverBinderTest, CreateDestroyNetworkCache) {
534     // Must not be the same as TEST_NETID
535     const int ANOTHER_TEST_NETID = TEST_NETID + 1;
536 
537     // Create a new network cache.
538     EXPECT_TRUE(mDnsResolver->createNetworkCache(ANOTHER_TEST_NETID).isOk());
539     mExpectedLogData.push_back({"createNetworkCache(31)", "createNetworkCache.*31"});
540 
541     // create it again, expect a EEXIST.
542     EXPECT_EQ(EEXIST,
543               mDnsResolver->createNetworkCache(ANOTHER_TEST_NETID).getServiceSpecificError());
544     mExpectedLogData.push_back(
545             {"createNetworkCache(31) -> ServiceSpecificException(17, \"File exists\")",
546              "createNetworkCache.*31.*17"});
547 
548     // destroy it.
549     EXPECT_TRUE(mDnsResolver->destroyNetworkCache(ANOTHER_TEST_NETID).isOk());
550     mExpectedLogData.push_back({"destroyNetworkCache(31)", "destroyNetworkCache.*31"});
551 
552     // re-create it
553     EXPECT_TRUE(mDnsResolver->createNetworkCache(ANOTHER_TEST_NETID).isOk());
554     mExpectedLogData.push_back({"createNetworkCache(31)", "createNetworkCache.*31"});
555 
556     // destroy it.
557     EXPECT_TRUE(mDnsResolver->destroyNetworkCache(ANOTHER_TEST_NETID).isOk());
558     mExpectedLogData.push_back({"destroyNetworkCache(31)", "destroyNetworkCache.*31"});
559 
560     // re-destroy it
561     EXPECT_TRUE(mDnsResolver->destroyNetworkCache(ANOTHER_TEST_NETID).isOk());
562     mExpectedLogData.push_back({"destroyNetworkCache(31)", "destroyNetworkCache.*31"});
563 }
564 
TEST_F(DnsResolverBinderTest,FlushNetworkCache)565 TEST_F(DnsResolverBinderTest, FlushNetworkCache) {
566     SKIP_IF_REMOTE_VERSION_LESS_THAN(mDnsResolver.get(), 4);
567     // cache has beed created in DnsResolverBinderTest constructor
568     EXPECT_TRUE(mDnsResolver->flushNetworkCache(TEST_NETID).isOk());
569     mExpectedLogData.push_back({"flushNetworkCache(30)", "destroyNetworkCache.*30"});
570     EXPECT_EQ(ENONET, mDnsResolver->flushNetworkCache(-1).getServiceSpecificError());
571     mExpectedLogData.push_back(
572             {"flushNetworkCache(-1) -> ServiceSpecificException(64, \"Machine is not on the "
573              "network\")",
574              "flushNetworkCache.*-1.*64"});
575 }
576 
TEST_F(DnsResolverBinderTest,setLogSeverity)577 TEST_F(DnsResolverBinderTest, setLogSeverity) {
578     // Expect fail
579     EXPECT_EQ(EINVAL, mDnsResolver->setLogSeverity(-1).getServiceSpecificError());
580     mExpectedLogData.push_back(
581             {"setLogSeverity(-1) -> ServiceSpecificException(22, \"Invalid argument\")",
582              "flushNetworkCache.*-1.*22"});
583 
584     // Test set different log level
585     EXPECT_TRUE(mDnsResolver->setLogSeverity(IDnsResolver::DNS_RESOLVER_LOG_VERBOSE).isOk());
586     mExpectedLogData.push_back({"setLogSeverity(0)", "setLogSeverity.*0"});
587 
588     EXPECT_TRUE(mDnsResolver->setLogSeverity(IDnsResolver::DNS_RESOLVER_LOG_DEBUG).isOk());
589     mExpectedLogData.push_back({"setLogSeverity(1)", "setLogSeverity.*1"});
590 
591     EXPECT_TRUE(mDnsResolver->setLogSeverity(IDnsResolver::DNS_RESOLVER_LOG_INFO).isOk());
592     mExpectedLogData.push_back({"setLogSeverity(2)", "setLogSeverity.*2"});
593 
594     EXPECT_TRUE(mDnsResolver->setLogSeverity(IDnsResolver::DNS_RESOLVER_LOG_WARNING).isOk());
595     mExpectedLogData.push_back({"setLogSeverity(3)", "setLogSeverity.*3"});
596 
597     EXPECT_TRUE(mDnsResolver->setLogSeverity(IDnsResolver::DNS_RESOLVER_LOG_ERROR).isOk());
598     mExpectedLogData.push_back({"setLogSeverity(4)", "setLogSeverity.*4"});
599 
600     // Set back to default based off resolv_init(), the default is INFO for userdebug/eng builds
601     // and is WARNING for the other builds.
602     if (isDebuggable()) {
603         EXPECT_TRUE(mDnsResolver->setLogSeverity(IDnsResolver::DNS_RESOLVER_LOG_INFO).isOk());
604         mExpectedLogData.push_back({"setLogSeverity(2)", "setLogSeverity.*2"});
605     } else {
606         EXPECT_TRUE(mDnsResolver->setLogSeverity(IDnsResolver::DNS_RESOLVER_LOG_WARNING).isOk());
607         mExpectedLogData.push_back({"setLogSeverity(3)", "setLogSeverity.*3"});
608     }
609 }
610 
TEST_F(DnsResolverBinderTest,SetResolverOptions)611 TEST_F(DnsResolverBinderTest, SetResolverOptions) {
612     SKIP_IF_REMOTE_VERSION_LESS_THAN(mDnsResolver.get(), 9);
613     ResolverOptionsParcel options;
614     options.tcMode = 1;
615     options.enforceDnsUid = true;
616     EXPECT_TRUE(mDnsResolver->setResolverOptions(TEST_NETID, options).isOk());
617     mExpectedLogData.push_back(
618             {"setResolverOptions(30, " + options.toString() + ")", "setResolverOptions.*30"});
619     EXPECT_EQ(ENONET, mDnsResolver->setResolverOptions(-1, options).getServiceSpecificError());
620     mExpectedLogData.push_back({"setResolverOptions(-1, " + options.toString() +
621                                         ") -> ServiceSpecificException(64, \"Machine is not on the "
622                                         "network\")",
623                                 "setResolverOptions.*-1.*64"});
624 }
625 
getNetworkInterfaceNames(int netId,const std::vector<std::string> & lines)626 static std::string getNetworkInterfaceNames(int netId, const std::vector<std::string>& lines) {
627     bool foundNetId = false;
628     for (const auto& line : lines) {
629         // Find the beginning of the section for this netId.
630         const std::string netIdMarker = "NetId: " + std::to_string(netId);
631         if (!foundNetId && !line.compare(0, netIdMarker.size(), netIdMarker)) {
632             foundNetId = true;
633             continue;
634         }
635 
636         // A blank line terminates the section for this netId.
637         if (foundNetId && line.size() == 0) {
638             foundNetId = false;
639             break;
640         }
641 
642         const std::string interfacesNamesPrefix = "  Interface names: ";
643         if (foundNetId && !line.compare(0, interfacesNamesPrefix.size(), interfacesNamesPrefix)) {
644             return line.substr(interfacesNamesPrefix.size());
645         }
646     }
647     return "";
648 }
649 
TEST_F(DnsResolverBinderTest,InterfaceNamesInDumpsys)650 TEST_F(DnsResolverBinderTest, InterfaceNamesInDumpsys) {
651     SKIP_IF_REMOTE_VERSION_LESS_THAN(mDnsResolver.get(), 15);
652 
653     std::vector<std::string> lines;
654     ndk::SpAIBinder netdBinder = ndk::SpAIBinder(AServiceManager_getService("dnsresolver"));
655 
656     auto resolverParams = DnsResponderClient::GetDefaultResolverParamsParcel();
657     resolverParams.interfaceNames = {"myinterface0"};
658     ::ndk::ScopedAStatus status = mDnsResolver->setResolverConfiguration(resolverParams);
659     ASSERT_TRUE(status.isOk()) << status.getMessage();
660 
661     android::status_t ret = dumpService(netdBinder, /*args=*/nullptr, /*num_args=*/0, lines);
662     ASSERT_EQ(android::OK, ret) << "Error dumping service: " << android::statusToString(ret);
663     EXPECT_EQ("[myinterface0]", getNetworkInterfaceNames(TEST_NETID, lines));
664 
665     lines = {};
666     resolverParams.interfaceNames = {"myinterface0", "myinterface1"};
667     status = mDnsResolver->setResolverConfiguration(resolverParams);
668     ASSERT_TRUE(status.isOk()) << status.getMessage();
669 
670     ret = dumpService(netdBinder, /*args=*/nullptr, /*num_args=*/0, lines);
671     ASSERT_EQ(android::OK, ret) << "Error dumping service: " << android::statusToString(ret);
672     EXPECT_EQ("[myinterface0, myinterface1]", getNetworkInterfaceNames(TEST_NETID, lines));
673 }
674