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