blob: 39a0e6a66e34515ca90505aa44175615a141ec52 [file] [log] [blame]
Luke Huang403c0442019-02-25 15:33:42 +08001/*
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 * binder_test.cpp - unit tests for netd binder RPCs.
17 */
18
19#include <vector>
20
Luke Huang7b26b202019-03-28 14:09:24 +080021#include <openssl/base64.h>
22
Luke Huang403c0442019-02-25 15:33:42 +080023#include <android-base/strings.h>
24#include <android/net/IDnsResolver.h>
Hungming Chena32c8c12019-01-25 10:47:40 +080025#include <binder/IPCThreadState.h>
Luke Huang403c0442019-02-25 15:33:42 +080026#include <binder/IServiceManager.h>
Luke Huang7b26b202019-03-28 14:09:24 +080027#include <gmock/gmock-matchers.h>
Luke Huang403c0442019-02-25 15:33:42 +080028#include <gtest/gtest.h>
Hungming Chena32c8c12019-01-25 10:47:40 +080029#include <netdb.h>
Mike Yu40ea2ad2019-03-13 17:15:48 +080030#include <netdutils/Stopwatch.h>
Hungming Chena32c8c12019-01-25 10:47:40 +080031
32#include "tests/BaseTestMetricsListener.h"
33#include "tests/TestMetrics.h"
Luke Huang403c0442019-02-25 15:33:42 +080034
Luke Huang7b26b202019-03-28 14:09:24 +080035#include "NetdConstants.h" // SHA256_SIZE
36#include "ResolverStats.h"
Hungming Chena32c8c12019-01-25 10:47:40 +080037#include "dns_responder.h"
38#include "dns_responder_client.h"
Luke Huang403c0442019-02-25 15:33:42 +080039
Luke Huang7b26b202019-03-28 14:09:24 +080040namespace binder = android::binder;
41
Luke Huang403c0442019-02-25 15:33:42 +080042using android::IBinder;
43using android::IServiceManager;
Hungming Chena32c8c12019-01-25 10:47:40 +080044using android::ProcessState;
Luke Huang403c0442019-02-25 15:33:42 +080045using android::sp;
46using android::String16;
Luke Huang7b26b202019-03-28 14:09:24 +080047using android::String8;
Luke Huang403c0442019-02-25 15:33:42 +080048using android::net::IDnsResolver;
Luke Huang7b26b202019-03-28 14:09:24 +080049using android::net::ResolverStats;
Hungming Chena32c8c12019-01-25 10:47:40 +080050using android::net::metrics::INetdEventListener;
51using android::net::metrics::TestOnDnsEvent;
Mike Yu40ea2ad2019-03-13 17:15:48 +080052using android::netdutils::Stopwatch;
Hungming Chena32c8c12019-01-25 10:47:40 +080053
54// TODO: make this dynamic and stop depending on implementation details.
55// Sync from TEST_NETID in dns_responder_client.cpp as resolver_test.cpp does.
56static const int TEST_NETID = 30;
Luke Huang403c0442019-02-25 15:33:42 +080057
58class DnsResolverBinderTest : public ::testing::Test {
59 public:
60 DnsResolverBinderTest() {
61 sp<IServiceManager> sm = android::defaultServiceManager();
62 sp<IBinder> binder = sm->getService(String16("dnsresolver"));
63 if (binder != nullptr) {
64 mDnsResolver = android::interface_cast<IDnsResolver>(binder);
65 }
66 }
67
68 void SetUp() override { ASSERT_NE(nullptr, mDnsResolver.get()); }
69
70 protected:
71 sp<IDnsResolver> mDnsResolver;
72};
73
74class TimedOperation : public Stopwatch {
75 public:
76 explicit TimedOperation(const std::string& name) : mName(name) {}
77 virtual ~TimedOperation() { fprintf(stderr, " %s: %6.1f ms\n", mName.c_str(), timeTaken()); }
78
79 private:
80 std::string mName;
81};
82
Luke Huang7b26b202019-03-28 14:09:24 +080083namespace {
84
85std::string base64Encode(const std::vector<uint8_t>& input) {
86 size_t out_len;
87 EXPECT_EQ(1, EVP_EncodedLength(&out_len, input.size()));
88 // out_len includes the trailing NULL.
89 uint8_t output_bytes[out_len];
90 EXPECT_EQ(out_len - 1, EVP_EncodeBlock(output_bytes, input.data(), input.size()));
91 return std::string(reinterpret_cast<char*>(output_bytes));
92} // namespace
93
94} // namespace
95
Luke Huang403c0442019-02-25 15:33:42 +080096TEST_F(DnsResolverBinderTest, IsAlive) {
97 TimedOperation t("isAlive RPC");
98 bool isAlive = false;
99 mDnsResolver->isAlive(&isAlive);
100 ASSERT_TRUE(isAlive);
Hungming Chena32c8c12019-01-25 10:47:40 +0800101}
102
103TEST_F(DnsResolverBinderTest, EventListener_onDnsEvent) {
104 // The test configs are used to trigger expected events. The expected results are defined in
105 // expectedResults.
106 static const struct TestConfig {
107 std::string hostname;
108 int returnCode;
109 } testConfigs[] = {
110 {"hi", 0 /*success*/},
111 {"nonexistent", EAI_NODATA},
112 };
113
114 // The expected results define expected event content for test verification.
115 static const std::vector<TestOnDnsEvent::TestResult> expectedResults = {
116 {TEST_NETID, INetdEventListener::EVENT_GETADDRINFO, 0 /*success*/, 1, "hi", "1.2.3.4"},
117 {TEST_NETID, INetdEventListener::EVENT_GETADDRINFO, EAI_NODATA, 0, "nonexistent", ""},
118 };
119
120 // Start the Binder thread pool.
121 // TODO: Consider doing this once if there has another event listener unit test.
122 android::ProcessState::self()->startThreadPool();
123
124 // Setup network.
125 // TODO: Setup device configuration and DNS responser server as resolver test does.
126 // Currently, leave DNS related configuration in this test because only it needs DNS
127 // client-server testing environment.
128 DnsResponderClient dnsClient;
129 dnsClient.SetUp();
130
131 // Setup DNS responder server.
132 constexpr char listen_addr[] = "127.0.0.3";
133 constexpr char listen_srv[] = "53";
134 test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail);
135 dns.addMapping("hi.example.com.", ns_type::ns_t_a, "1.2.3.4");
136 ASSERT_TRUE(dns.startServer());
137
138 // Setup DNS configuration.
139 const std::vector<std::string> test_servers = {listen_addr};
140 std::vector<std::string> test_domains = {"example.com"};
141 std::vector<int> test_params = {300 /*sample_validity*/, 25 /*success_threshold*/,
142 8 /*min_samples*/, 8 /*max_samples*/};
143 ASSERT_TRUE(dnsClient.SetResolversForNetwork(test_servers, test_domains, test_params));
144 dns.clearQueries();
145
146 // Register event listener.
Hungming Chenfbfa1ce2019-03-26 17:46:46 +0800147 android::sp<TestOnDnsEvent> testOnDnsEvent = new TestOnDnsEvent(expectedResults);
Hungming Chena32c8c12019-01-25 10:47:40 +0800148 android::binder::Status status = mDnsResolver->registerEventListener(
149 android::interface_cast<INetdEventListener>(testOnDnsEvent));
150 ASSERT_TRUE(status.isOk()) << status.exceptionMessage();
151
152 // DNS queries.
Hungming Chenfbfa1ce2019-03-26 17:46:46 +0800153 // Once all expected events of expectedResults are received by the listener, the unit test will
154 // be notified. Otherwise, notified with a timeout expired failure.
Hungming Chena32c8c12019-01-25 10:47:40 +0800155 auto& cv = testOnDnsEvent->getCv();
156 auto& cvMutex = testOnDnsEvent->getCvMutex();
157 {
158 std::unique_lock lock(cvMutex);
159
160 for (const auto& config : testConfigs) {
161 SCOPED_TRACE(config.hostname);
162
163 addrinfo* result = nullptr;
164 addrinfo hints = {.ai_family = AF_INET, .ai_socktype = SOCK_DGRAM};
165 int status = getaddrinfo(config.hostname.c_str(), nullptr, &hints, &result);
166 EXPECT_EQ(config.returnCode, status);
167
168 if (result) freeaddrinfo(result);
169 }
170
171 // Wait for receiving expected events.
172 EXPECT_EQ(std::cv_status::no_timeout, cv.wait_for(lock, std::chrono::seconds(2)));
173 }
174
175 // Verify that all testcases are passed.
176 EXPECT_TRUE(testOnDnsEvent->isVerified());
177
178 dnsClient.TearDown();
Luke Huang7b26b202019-03-28 14:09:24 +0800179}
180
181TEST_F(DnsResolverBinderTest, SetResolverConfiguration_Tls) {
182 const std::vector<std::string> LOCALLY_ASSIGNED_DNS{"8.8.8.8", "2001:4860:4860::8888"};
183 std::vector<uint8_t> fp(SHA256_SIZE);
184 std::vector<uint8_t> short_fp(1);
185 std::vector<uint8_t> long_fp(SHA256_SIZE + 1);
186 std::vector<std::string> test_domains;
187 std::vector<int> test_params = {300, 25, 8, 8};
188 unsigned test_netid = 0;
189 static const struct TestData {
190 const std::vector<std::string> servers;
191 const std::string tlsName;
192 const std::vector<std::vector<uint8_t>> tlsFingerprints;
193 const int expectedReturnCode;
194 } kTlsTestData[] = {
195 {{"192.0.2.1"}, "", {}, 0},
196 {{"2001:db8::2"}, "host.name", {}, 0},
197 {{"192.0.2.3"}, "@@@@", {fp}, 0},
198 {{"2001:db8::4"}, "", {fp}, 0},
199 {{}, "", {}, 0},
200 {{""}, "", {}, EINVAL},
201 {{"192.0.*.5"}, "", {}, EINVAL},
202 {{"2001:dg8::6"}, "", {}, EINVAL},
203 {{"2001:db8::c"}, "", {short_fp}, EINVAL},
204 {{"192.0.2.12"}, "", {long_fp}, EINVAL},
205 {{"2001:db8::e"}, "", {fp, fp, fp}, 0},
206 {{"192.0.2.14"}, "", {fp, short_fp}, EINVAL},
207 };
208
209 for (size_t i = 0; i < std::size(kTlsTestData); i++) {
210 const auto& td = kTlsTestData[i];
211
212 std::vector<std::string> fingerprints;
213 for (const auto& fingerprint : td.tlsFingerprints) {
214 fingerprints.push_back(base64Encode(fingerprint));
215 }
216 binder::Status status = mDnsResolver->setResolverConfiguration(
217 test_netid, LOCALLY_ASSIGNED_DNS, test_domains, test_params, td.tlsName, td.servers,
218 fingerprints);
219
220 if (td.expectedReturnCode == 0) {
221 SCOPED_TRACE(String8::format("test case %zu should have passed", i));
222 SCOPED_TRACE(status.toString8());
223 EXPECT_EQ(0, status.exceptionCode());
224 } else {
225 SCOPED_TRACE(String8::format("test case %zu should have failed", i));
226 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, status.exceptionCode());
227 EXPECT_EQ(td.expectedReturnCode, status.serviceSpecificErrorCode());
228 }
229 }
230 // Ensure TLS is disabled before the start of the next test.
231 mDnsResolver->setResolverConfiguration(test_netid, kTlsTestData[0].servers, test_domains,
232 test_params, "", {}, {});
233}
234
235TEST_F(DnsResolverBinderTest, GetResolverInfo) {
236 std::vector<std::string> servers = {"127.0.0.1", "127.0.0.2"};
237 std::vector<std::string> domains = {"example.com"};
238 std::vector<int> testParams = {
239 300, // sample validity in seconds
240 25, // success threshod in percent
241 8, 8, // {MIN,MAX}_SAMPLES
242 100, // BASE_TIMEOUT_MSEC
243 2, // retry count
244 };
245 binder::Status status = mDnsResolver->setResolverConfiguration(TEST_NETID, servers, domains,
246 testParams, "", {}, {});
247 EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
248
249 std::vector<std::string> res_servers;
250 std::vector<std::string> res_domains;
251 std::vector<std::string> res_tls_servers;
252 std::vector<int32_t> params32;
253 std::vector<int32_t> stats32;
254 std::vector<int32_t> wait_for_pending_req_timeout_count32{0};
255 status = mDnsResolver->getResolverInfo(TEST_NETID, &res_servers, &res_domains, &res_tls_servers,
256 &params32, &stats32,
257 &wait_for_pending_req_timeout_count32);
258
259 EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
260 EXPECT_EQ(servers.size(), res_servers.size());
261 EXPECT_EQ(domains.size(), res_domains.size());
262 EXPECT_EQ(0U, res_tls_servers.size());
263 ASSERT_EQ(static_cast<size_t>(IDnsResolver::RESOLVER_PARAMS_COUNT), testParams.size());
264 EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY],
265 params32[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY]);
266 EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD],
267 params32[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD]);
268 EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES],
269 params32[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES]);
270 EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES],
271 params32[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES]);
272 EXPECT_EQ(testParams[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC],
273 params32[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC]);
274
275 std::vector<ResolverStats> stats;
276 ResolverStats::decodeAll(stats32, &stats);
277
278 EXPECT_EQ(servers.size(), stats.size());
279
280 EXPECT_THAT(res_servers, testing::UnorderedElementsAreArray(servers));
281 EXPECT_THAT(res_domains, testing::UnorderedElementsAreArray(domains));
Mike Yu40ea2ad2019-03-13 17:15:48 +0800282}