blob: d5b8618c71b99091ed70a96cdd5663ba67324d05 [file] [log] [blame]
Mike Yue655b1d2019-08-28 17:49:59 +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
Mike Yu61d118e2019-12-23 21:08:19 +080017#include <array>
18
19#include <android-base/test_utils.h>
Mike Yue655b1d2019-08-28 17:49:59 +080020#include <gmock/gmock.h>
21#include <gtest/gtest.h>
22
23#include "DnsStats.h"
24
25namespace android::net {
26
27using namespace std::chrono_literals;
28using android::netdutils::IPSockAddr;
Mike Yub5006192021-05-07 18:21:49 +080029using std::chrono::microseconds;
Mike Yue655b1d2019-08-28 17:49:59 +080030using std::chrono::milliseconds;
31using ::testing::IsEmpty;
32using ::testing::UnorderedElementsAreArray;
33
34namespace {
35
Mike Yub5006192021-05-07 18:21:49 +080036constexpr auto NO_AVERAGE_LATENCY = std::nullopt;
37
38// A helper which can propagate the failure to outside of the stmt to know which line
39// of stmt fails. The expectation fails only for the first failed stmt.
40#define EXPECT_NO_FAILURE(stmt) \
41 do { \
42 bool alreadyFailed = HasFailure(); \
43 stmt; \
44 if (!alreadyFailed && HasFailure()) EXPECT_FALSE(HasFailure()); \
45 } while (0)
46
Mike Yue655b1d2019-08-28 17:49:59 +080047DnsQueryEvent makeDnsQueryEvent(const Protocol protocol, const NsRcode rcode,
48 const milliseconds& latency) {
49 DnsQueryEvent event;
50 event.set_protocol(protocol);
51 event.set_rcode(rcode);
52 event.set_latency_micros(latency.count() * 1000);
53 return event;
54}
55
Mike Yub5006192021-05-07 18:21:49 +080056StatsData makeStatsData(const IPSockAddr& server, const int total, const microseconds& latencyUs,
Mike Yue655b1d2019-08-28 17:49:59 +080057 const std::map<int, int>& rcodeCounts) {
58 StatsData ret(server);
59 ret.total = total;
Mike Yub5006192021-05-07 18:21:49 +080060 ret.latencyUs = latencyUs;
Mike Yue655b1d2019-08-28 17:49:59 +080061 ret.rcodeCounts = rcodeCounts;
62 return ret;
63}
64
65} // namespace
66
Mike Yu61d17262020-02-15 18:56:22 +080067// TODO: add StatsDataTest to ensure its methods return correct outputs.
68
Mike Yue655b1d2019-08-28 17:49:59 +080069class StatsRecordsTest : public ::testing::Test {};
70
71TEST_F(StatsRecordsTest, PushRecord) {
72 const IPSockAddr server = IPSockAddr::toIPSockAddr("127.0.0.2", 53);
73 constexpr size_t size = 3;
Mike Yu9100c292020-12-04 14:20:34 +080074 const StatsRecords::Record recordNoError = {
75 .rcode = NS_R_NO_ERROR,
76 .linux_errno = 0,
77 .latencyUs{10ms},
78 };
79 const StatsRecords::Record recordTimeout = {
80 .rcode = NS_R_TIMEOUT,
81 .linux_errno = 0,
82 .latencyUs{250ms},
83 };
Mike Yue655b1d2019-08-28 17:49:59 +080084
85 StatsRecords sr(server, size);
86 EXPECT_EQ(sr.getStatsData(), makeStatsData(server, 0, 0ms, {}));
87
88 sr.push(recordNoError);
89 EXPECT_EQ(sr.getStatsData(), makeStatsData(server, 1, 10ms, {{NS_R_NO_ERROR, 1}}));
90
91 sr.push(recordNoError);
92 EXPECT_EQ(sr.getStatsData(), makeStatsData(server, 2, 20ms, {{NS_R_NO_ERROR, 2}}));
93
94 sr.push(recordTimeout);
95 EXPECT_EQ(sr.getStatsData(),
96 makeStatsData(server, 3, 270ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 1}}));
97
98 sr.push(recordTimeout);
99 EXPECT_EQ(sr.getStatsData(),
100 makeStatsData(server, 3, 510ms, {{NS_R_NO_ERROR, 1}, {NS_R_TIMEOUT, 2}}));
101
102 sr.push(recordTimeout);
103 EXPECT_EQ(sr.getStatsData(),
104 makeStatsData(server, 3, 750ms, {{NS_R_NO_ERROR, 0}, {NS_R_TIMEOUT, 3}}));
105}
106
107class DnsStatsTest : public ::testing::Test {
108 protected:
Mike Yu61d118e2019-12-23 21:08:19 +0800109 std::string captureDumpOutput() {
110 netdutils::DumpWriter dw(STDOUT_FILENO);
111 CapturedStdout captured;
112 mDnsStats.dump(dw);
113 return captured.str();
114 }
115
116 // Get the output string from dump() and check the content.
117 void verifyDumpOutput(const std::vector<StatsData>& tcpData,
118 const std::vector<StatsData>& udpData,
chenbruceedec3e12021-06-27 23:25:07 +0800119 const std::vector<StatsData>& dotData,
120 const std::vector<StatsData>& mdnsData) {
Mike Yu61d17262020-02-15 18:56:22 +0800121 // A pattern to capture three matches:
122 // server address (empty allowed), the statistics, and the score.
123 const std::regex pattern(R"(\s{4,}([0-9a-fA-F:\.]*)[ ]?([<(].*[>)])[ ]?(\S*))");
Mike Yu61d118e2019-12-23 21:08:19 +0800124 std::string dumpString = captureDumpOutput();
125
126 const auto check = [&](const std::vector<StatsData>& statsData, const std::string& protocol,
127 std::string* dumpString) {
128 SCOPED_TRACE(protocol);
129 ASSERT_NE(dumpString->find(protocol), std::string::npos);
130 std::smatch sm;
131
chenbruceedec3e12021-06-27 23:25:07 +0800132 // Expect to show something even if none of servers or mdns multicast addresses is set.
Mike Yu61d118e2019-12-23 21:08:19 +0800133 if (statsData.empty()) {
134 ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
135 EXPECT_TRUE(sm[1].str().empty());
chenbruceedec3e12021-06-27 23:25:07 +0800136 EXPECT_EQ(sm[2], "<no data>");
Mike Yu61d17262020-02-15 18:56:22 +0800137 EXPECT_TRUE(sm[3].str().empty());
Mike Yu61d118e2019-12-23 21:08:19 +0800138 *dumpString = sm.suffix();
139 return;
140 }
141
142 for (const auto& stats : statsData) {
143 ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
chenbruce72a646c2021-06-27 23:03:39 +0800144 EXPECT_EQ(sm[1], stats.sockAddr.ip().toString());
Mike Yu61d118e2019-12-23 21:08:19 +0800145 EXPECT_FALSE(sm[2].str().empty());
Mike Yu61d17262020-02-15 18:56:22 +0800146 EXPECT_FALSE(sm[3].str().empty());
Mike Yu61d118e2019-12-23 21:08:19 +0800147 *dumpString = sm.suffix();
148 }
149 };
150
151 check(udpData, "UDP", &dumpString);
152 check(dotData, "TLS", &dumpString);
153 check(tcpData, "TCP", &dumpString);
chenbruceedec3e12021-06-27 23:25:07 +0800154 check(mdnsData, "MDNS", &dumpString);
Mike Yu61d118e2019-12-23 21:08:19 +0800155
156 // Ensure the whole string has been checked.
157 EXPECT_EQ(dumpString, "\n");
158 }
159
Mike Yub5006192021-05-07 18:21:49 +0800160 void verifyDnsStatsContent(Protocol protocol, const std::vector<StatsData>& expectedStats,
161 const std::optional<microseconds>& expectedAvgLatency) {
162 if (expectedStats.empty()) {
163 EXPECT_THAT(mDnsStats.getStats(protocol), IsEmpty());
164 } else {
165 EXPECT_THAT(mDnsStats.getStats(protocol), UnorderedElementsAreArray(expectedStats));
166 }
167
168 EXPECT_EQ(mDnsStats.getAverageLatencyUs(protocol), expectedAvgLatency);
169 }
170
Mike Yue655b1d2019-08-28 17:49:59 +0800171 DnsStats mDnsStats;
172};
173
chenbruce72a646c2021-06-27 23:03:39 +0800174TEST_F(DnsStatsTest, SetAddrs) {
Mike Yu61d118e2019-12-23 21:08:19 +0800175 // Check before any operation to mDnsStats.
chenbruceedec3e12021-06-27 23:25:07 +0800176 verifyDumpOutput({}, {}, {}, {});
Mike Yu61d118e2019-12-23 21:08:19 +0800177
Mike Yue655b1d2019-08-28 17:49:59 +0800178 static const struct {
179 std::vector<std::string> servers;
180 std::vector<std::string> expectation;
181 bool isSuccess;
182 } tests[] = {
183 // Normal case.
184 {
185 {"127.0.0.1", "127.0.0.2", "fe80::1%22", "2001:db8::2", "::1"},
186 {"127.0.0.1", "127.0.0.2", "fe80::1%22", "2001:db8::2", "::1"},
187 true,
188 },
189 // Duplicate servers.
190 {
191 {"127.0.0.1", "2001:db8::2", "127.0.0.1", "2001:db8::2"},
192 {"127.0.0.1", "2001:db8::2"},
193 true,
194 },
195 // Invalid server addresses. The state remains in previous state.
196 {
197 {"not_an_ip", "127.0.0.3", "127.a.b.2"},
198 {"127.0.0.1", "2001:db8::2"},
199 false,
200 },
201 // Clean up the old servers 127.0.0.1 and 127.0.0.2.
202 {
203 {"127.0.0.4", "2001:db8::5"},
204 {"127.0.0.4", "2001:db8::5"},
205 true,
206 },
207 // Empty list.
208 {{}, {}, true},
209 };
210
211 for (const auto& [servers, expectation, isSuccess] : tests) {
212 std::vector<IPSockAddr> ipSockAddrs;
213 ipSockAddrs.reserve(servers.size());
214 for (const auto& server : servers) {
215 ipSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53));
216 }
217
chenbruce72a646c2021-06-27 23:03:39 +0800218 EXPECT_TRUE(mDnsStats.setAddrs(ipSockAddrs, PROTO_TCP) == isSuccess);
219 EXPECT_TRUE(mDnsStats.setAddrs(ipSockAddrs, PROTO_UDP) == isSuccess);
220 EXPECT_TRUE(mDnsStats.setAddrs(ipSockAddrs, PROTO_DOT) == isSuccess);
Mike Yue655b1d2019-08-28 17:49:59 +0800221
222 std::vector<StatsData> expectedStats;
223 expectedStats.reserve(expectation.size());
224 for (const auto& exp : expectation) {
225 expectedStats.push_back(makeStatsData(IPSockAddr::toIPSockAddr(exp, 53), 0, 0ms, {}));
226 }
227
Mike Yub5006192021-05-07 18:21:49 +0800228 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, NO_AVERAGE_LATENCY));
229 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, NO_AVERAGE_LATENCY));
230 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
Mike Yue655b1d2019-08-28 17:49:59 +0800231 }
Mike Yu61d118e2019-12-23 21:08:19 +0800232
chenbruceedec3e12021-06-27 23:25:07 +0800233 verifyDumpOutput({}, {}, {}, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800234}
235
236TEST_F(DnsStatsTest, SetServersDifferentPorts) {
237 const std::vector<IPSockAddr> servers = {
238 IPSockAddr::toIPSockAddr("127.0.0.1", 0), IPSockAddr::toIPSockAddr("fe80::1", 0),
239 IPSockAddr::toIPSockAddr("127.0.0.1", 53), IPSockAddr::toIPSockAddr("127.0.0.1", 5353),
240 IPSockAddr::toIPSockAddr("127.0.0.1", 853), IPSockAddr::toIPSockAddr("fe80::1", 53),
241 IPSockAddr::toIPSockAddr("fe80::1", 5353), IPSockAddr::toIPSockAddr("fe80::1", 853),
242 };
243
244 // Servers setup fails due to port unset.
chenbruce72a646c2021-06-27 23:03:39 +0800245 EXPECT_FALSE(mDnsStats.setAddrs(servers, PROTO_TCP));
246 EXPECT_FALSE(mDnsStats.setAddrs(servers, PROTO_UDP));
247 EXPECT_FALSE(mDnsStats.setAddrs(servers, PROTO_DOT));
Mike Yue655b1d2019-08-28 17:49:59 +0800248
Mike Yub5006192021-05-07 18:21:49 +0800249 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY));
250 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY));
251 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
chenbruceedec3e12021-06-27 23:25:07 +0800252 verifyDumpOutput({}, {}, {}, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800253
chenbruce72a646c2021-06-27 23:03:39 +0800254 EXPECT_TRUE(mDnsStats.setAddrs(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP));
255 EXPECT_TRUE(mDnsStats.setAddrs(std::vector(servers.begin() + 2, servers.end()), PROTO_UDP));
256 EXPECT_TRUE(mDnsStats.setAddrs(std::vector(servers.begin() + 2, servers.end()), PROTO_DOT));
Mike Yue655b1d2019-08-28 17:49:59 +0800257
258 const std::vector<StatsData> expectedStats = {
259 makeStatsData(servers[2], 0, 0ms, {}), makeStatsData(servers[3], 0, 0ms, {}),
260 makeStatsData(servers[4], 0, 0ms, {}), makeStatsData(servers[5], 0, 0ms, {}),
261 makeStatsData(servers[6], 0, 0ms, {}), makeStatsData(servers[7], 0, 0ms, {}),
262 };
263
Mike Yub5006192021-05-07 18:21:49 +0800264 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, NO_AVERAGE_LATENCY));
265 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, NO_AVERAGE_LATENCY));
266 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
chenbruceedec3e12021-06-27 23:25:07 +0800267 verifyDumpOutput(expectedStats, expectedStats, expectedStats, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800268}
269
270TEST_F(DnsStatsTest, AddStatsAndClear) {
271 const std::vector<IPSockAddr> servers = {
272 IPSockAddr::toIPSockAddr("127.0.0.1", 53),
273 IPSockAddr::toIPSockAddr("127.0.0.2", 53),
274 };
chenbruceedec3e12021-06-27 23:25:07 +0800275 const std::vector<IPSockAddr> mdnsaddrs = {
276 IPSockAddr::toIPSockAddr("ff02::fb", 5353),
277 IPSockAddr::toIPSockAddr("224.0.0.251", 5353),
278 };
Mike Yue655b1d2019-08-28 17:49:59 +0800279 const DnsQueryEvent record = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
chenbruceedec3e12021-06-27 23:25:07 +0800280 const DnsQueryEvent mdnsrecord = makeDnsQueryEvent(PROTO_MDNS, NS_R_NO_ERROR, 10ms);
Mike Yue655b1d2019-08-28 17:49:59 +0800281
chenbruce72a646c2021-06-27 23:03:39 +0800282 EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_TCP));
283 EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
chenbruceedec3e12021-06-27 23:25:07 +0800284 EXPECT_TRUE(mDnsStats.setAddrs(mdnsaddrs, PROTO_MDNS));
Mike Yue655b1d2019-08-28 17:49:59 +0800285
286 // Fail to add stats because of incorrect arguments.
287 EXPECT_FALSE(mDnsStats.addStats(IPSockAddr::toIPSockAddr("127.0.0.4", 53), record));
288 EXPECT_FALSE(mDnsStats.addStats(IPSockAddr::toIPSockAddr("127.a.b.4", 53), record));
289
290 EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
291 EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
292 EXPECT_TRUE(mDnsStats.addStats(servers[1], record));
chenbruceedec3e12021-06-27 23:25:07 +0800293 EXPECT_TRUE(mDnsStats.addStats(mdnsaddrs[0], mdnsrecord));
294 EXPECT_TRUE(mDnsStats.addStats(mdnsaddrs[1], mdnsrecord));
Mike Yue655b1d2019-08-28 17:49:59 +0800295
296 const std::vector<StatsData> expectedStatsForTcp = {
297 makeStatsData(servers[0], 0, 0ms, {}),
298 makeStatsData(servers[1], 0, 0ms, {}),
299 };
300 const std::vector<StatsData> expectedStatsForUdp = {
301 makeStatsData(servers[0], 2, 20ms, {{NS_R_NO_ERROR, 2}}),
302 makeStatsData(servers[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
303 };
304
chenbruceedec3e12021-06-27 23:25:07 +0800305 const std::vector<StatsData> expectedStatsForMdns = {
306 makeStatsData(mdnsaddrs[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
307 makeStatsData(mdnsaddrs[0], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
308 };
309
Mike Yub5006192021-05-07 18:21:49 +0800310 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStatsForTcp, NO_AVERAGE_LATENCY));
311 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStatsForUdp, 10ms));
312 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
chenbruceedec3e12021-06-27 23:25:07 +0800313 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, expectedStatsForMdns, 10ms));
314 verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {}, expectedStatsForMdns);
Mike Yue655b1d2019-08-28 17:49:59 +0800315
316 // Clear stats.
chenbruce72a646c2021-06-27 23:03:39 +0800317 EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_TCP));
318 EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_UDP));
319 EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_DOT));
chenbruceedec3e12021-06-27 23:25:07 +0800320 EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_MDNS));
Mike Yub5006192021-05-07 18:21:49 +0800321 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY));
322 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY));
323 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
chenbruceedec3e12021-06-27 23:25:07 +0800324 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, {}, NO_AVERAGE_LATENCY));
325 verifyDumpOutput({}, {}, {}, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800326}
327
328TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
329 std::vector<IPSockAddr> servers = {
330 IPSockAddr::toIPSockAddr("127.0.0.1", 53),
331 IPSockAddr::toIPSockAddr("127.0.0.2", 53),
332 };
333 const DnsQueryEvent recordNoError = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
334 const DnsQueryEvent recordTimeout = makeDnsQueryEvent(PROTO_UDP, NS_R_TIMEOUT, 250ms);
335
chenbruce72a646c2021-06-27 23:03:39 +0800336 EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
Mike Yue655b1d2019-08-28 17:49:59 +0800337
338 // Add a record to 127.0.0.1.
339 EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
340
341 // Add four records to 127.0.0.2.
342 EXPECT_TRUE(mDnsStats.addStats(servers[1], recordNoError));
343 EXPECT_TRUE(mDnsStats.addStats(servers[1], recordNoError));
344 EXPECT_TRUE(mDnsStats.addStats(servers[1], recordTimeout));
345 EXPECT_TRUE(mDnsStats.addStats(servers[1], recordTimeout));
346
347 std::vector<StatsData> expectedStats = {
348 makeStatsData(servers[0], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
349 makeStatsData(servers[1], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}),
350 };
351 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
Mike Yub5006192021-05-07 18:21:49 +0800352 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms));
chenbruceedec3e12021-06-27 23:25:07 +0800353 verifyDumpOutput({}, expectedStats, {}, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800354
355 // Update the server list, the stats of 127.0.0.2 will remain.
356 servers = {
357 IPSockAddr::toIPSockAddr("127.0.0.2", 53),
358 IPSockAddr::toIPSockAddr("127.0.0.3", 53),
359 IPSockAddr::toIPSockAddr("127.0.0.4", 53),
360 };
chenbruce72a646c2021-06-27 23:03:39 +0800361 EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
Mike Yue655b1d2019-08-28 17:49:59 +0800362 expectedStats = {
363 makeStatsData(servers[0], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}),
364 makeStatsData(servers[1], 0, 0ms, {}),
365 makeStatsData(servers[2], 0, 0ms, {}),
366 };
367 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
Mike Yub5006192021-05-07 18:21:49 +0800368 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 130ms));
chenbruceedec3e12021-06-27 23:25:07 +0800369 verifyDumpOutput({}, expectedStats, {}, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800370
371 // Let's add a record to 127.0.0.2 again.
372 EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
373 expectedStats = {
374 makeStatsData(servers[0], 5, 530ms, {{NS_R_NO_ERROR, 3}, {NS_R_TIMEOUT, 2}}),
375 makeStatsData(servers[1], 0, 0ms, {}),
376 makeStatsData(servers[2], 0, 0ms, {}),
377 };
378 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
Mike Yub5006192021-05-07 18:21:49 +0800379 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms));
chenbruceedec3e12021-06-27 23:25:07 +0800380 verifyDumpOutput({}, expectedStats, {}, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800381}
382
383TEST_F(DnsStatsTest, AddStatsRecords_100000) {
Mike Yu61d118e2019-12-23 21:08:19 +0800384 constexpr size_t operations = 100000;
385 constexpr size_t logSize = DnsStats::kLogSize;
386 constexpr size_t rcodeNum = 4; // A value by which kLogSize is divisible.
387 ASSERT_EQ(logSize % rcodeNum, 0U);
388
Mike Yue655b1d2019-08-28 17:49:59 +0800389 const std::vector<IPSockAddr> servers = {
390 IPSockAddr::toIPSockAddr("127.0.0.1", 53),
391 IPSockAddr::toIPSockAddr("127.0.0.2", 53),
392 IPSockAddr::toIPSockAddr("127.0.0.3", 53),
393 IPSockAddr::toIPSockAddr("127.0.0.4", 53),
394 };
395
chenbruceedec3e12021-06-27 23:25:07 +0800396 const std::vector<IPSockAddr> mdnsaddrs = {
397 IPSockAddr::toIPSockAddr("ff02::fb", 5353),
398 IPSockAddr::toIPSockAddr("224.0.0.251", 5353),
399 };
400
Mike Yu61d118e2019-12-23 21:08:19 +0800401 // To test unknown rcode in rcodeToName(), store the elements as type int.
402 const std::array<int, rcodeNum> rcodes = {
403 NS_R_NO_ERROR, // NOERROR
404 NS_R_NXDOMAIN, // NXDOMAIN
405 99, // UNKNOWN(99)
406 NS_R_INTERNAL_ERROR, // INTERNAL_ERROR
407 };
408
chenbruce72a646c2021-06-27 23:03:39 +0800409 EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_TCP));
410 EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
411 EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_DOT));
chenbruceedec3e12021-06-27 23:25:07 +0800412 EXPECT_TRUE(mDnsStats.setAddrs(mdnsaddrs, PROTO_MDNS));
Mike Yue655b1d2019-08-28 17:49:59 +0800413
Mike Yu61d118e2019-12-23 21:08:19 +0800414 for (size_t i = 0; i < operations; i++) {
415 const NsRcode rcode = static_cast<NsRcode>(rcodes[i % rcodeNum]);
Mike Yub5006192021-05-07 18:21:49 +0800416 const auto eventTcp = makeDnsQueryEvent(PROTO_TCP, rcode, milliseconds(i));
417 const auto eventUdp = makeDnsQueryEvent(PROTO_UDP, rcode, milliseconds(i));
418 const auto eventDot = makeDnsQueryEvent(PROTO_DOT, rcode, milliseconds(i));
Mike Yue655b1d2019-08-28 17:49:59 +0800419 for (const auto& server : servers) {
Mike Yu61d118e2019-12-23 21:08:19 +0800420 SCOPED_TRACE(server.toString() + "-" + std::to_string(i));
421 ASSERT_TRUE(mDnsStats.addStats(server, eventTcp));
422 ASSERT_TRUE(mDnsStats.addStats(server, eventUdp));
423 ASSERT_TRUE(mDnsStats.addStats(server, eventDot));
Mike Yue655b1d2019-08-28 17:49:59 +0800424 }
chenbruceedec3e12021-06-27 23:25:07 +0800425 const auto eventMdns = makeDnsQueryEvent(PROTO_MDNS, rcode, milliseconds(i));
426 for (const auto& mdnsaddr : mdnsaddrs) {
427 SCOPED_TRACE(mdnsaddr.toString() + "-" + std::to_string(i));
428 ASSERT_TRUE(mDnsStats.addStats(mdnsaddr, eventMdns));
429 }
Mike Yue655b1d2019-08-28 17:49:59 +0800430 }
Mike Yu61d118e2019-12-23 21:08:19 +0800431
432 std::map<int, int> expectedRcodeCounts;
433 for (const auto& rcode : rcodes) {
434 expectedRcodeCounts.try_emplace(rcode, 32);
435 }
Mike Yub5006192021-05-07 18:21:49 +0800436
437 // The average latency 99935.5 ms is derived from (99872ms + 99873ms + ... + 99999ms) / logSize,
438 // where logSize is 128.
Mike Yu61d118e2019-12-23 21:08:19 +0800439 const std::vector<StatsData> expectedStats = {
Mike Yub5006192021-05-07 18:21:49 +0800440 makeStatsData(servers[0], logSize, logSize * 99935500us, expectedRcodeCounts),
441 makeStatsData(servers[1], logSize, logSize * 99935500us, expectedRcodeCounts),
442 makeStatsData(servers[2], logSize, logSize * 99935500us, expectedRcodeCounts),
443 makeStatsData(servers[3], logSize, logSize * 99935500us, expectedRcodeCounts),
Mike Yu61d118e2019-12-23 21:08:19 +0800444 };
445
chenbruceedec3e12021-06-27 23:25:07 +0800446 const std::vector<StatsData> expectedMdnsStats = {
447 makeStatsData(mdnsaddrs[1], logSize, logSize * 99935500us, expectedRcodeCounts),
448 makeStatsData(mdnsaddrs[0], logSize, logSize * 99935500us, expectedRcodeCounts),
449 };
Mike Yub5006192021-05-07 18:21:49 +0800450 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, 99935500us));
451 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 99935500us));
452 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, 99935500us));
chenbruceedec3e12021-06-27 23:25:07 +0800453 EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, expectedMdnsStats, 99935500us));
454 verifyDumpOutput(expectedStats, expectedStats, expectedStats, expectedMdnsStats);
Mike Yue655b1d2019-08-28 17:49:59 +0800455}
456
Mike Yu61d17262020-02-15 18:56:22 +0800457TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
458 const IPSockAddr server1 = IPSockAddr::toIPSockAddr("127.0.0.1", 53);
459 const IPSockAddr server2 = IPSockAddr::toIPSockAddr("127.0.0.2", 53);
460 const IPSockAddr server3 = IPSockAddr::toIPSockAddr("2001:db8:cafe:d00d::1", 53);
461 const IPSockAddr server4 = IPSockAddr::toIPSockAddr("2001:db8:cafe:d00d::2", 53);
462
463 // Return empty list before setup.
464 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP), IsEmpty());
465
466 // Before there's any stats, the list of the sorted servers is the same as the setup's one.
chenbruce72a646c2021-06-27 23:03:39 +0800467 EXPECT_TRUE(mDnsStats.setAddrs({server1, server2, server3, server4}, PROTO_UDP));
468 EXPECT_TRUE(mDnsStats.setAddrs({server1, server2, server3, server4}, PROTO_DOT));
Mike Yu61d17262020-02-15 18:56:22 +0800469 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
470 testing::ElementsAreArray({server1, server2, server3, server4}));
471
472 // Add a record to server1. The qualities of the other servers increase.
473 EXPECT_TRUE(mDnsStats.addStats(server1, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms)));
474 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
475 testing::ElementsAreArray({server2, server3, server4, server1}));
476
477 // Add a record, with less repose time than server1, to server3.
478 EXPECT_TRUE(mDnsStats.addStats(server3, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 5ms)));
479 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
480 testing::ElementsAreArray({server2, server4, server3, server1}));
481
482 // Even though server2 has zero response time, select server4 as the first server because it
483 // doesn't have stats yet.
484 EXPECT_TRUE(mDnsStats.addStats(server2, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 0ms)));
485 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
486 testing::ElementsAreArray({server4, server2, server3, server1}));
487
488 // Updating DoT record to server4 changes nothing.
489 EXPECT_TRUE(mDnsStats.addStats(server4, makeDnsQueryEvent(PROTO_DOT, NS_R_NO_ERROR, 10ms)));
490 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
491 testing::ElementsAreArray({server4, server2, server3, server1}));
492
493 // Add a record, with a very large value of respose time, to server4.
494 EXPECT_TRUE(mDnsStats.addStats(server4, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 500000ms)));
495 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
496 testing::ElementsAreArray({server2, server3, server1, server4}));
497
Mike Yu9100c292020-12-04 14:20:34 +0800498 // Add some internal_error records with permission error to server2.
499 // The internal_error won't cause the priority of server2 drop. (but some of the other
500 // quality factors will still be counted, such as skipped_count and latency)
501 auto recordFromNetworkRestricted = makeDnsQueryEvent(PROTO_UDP, NS_R_INTERNAL_ERROR, 1ms);
502 recordFromNetworkRestricted.set_linux_errno(static_cast<LinuxErrno>(EPERM));
503 for (int i = 0; i < 3; i++) {
504 EXPECT_TRUE(mDnsStats.addStats(server2, recordFromNetworkRestricted));
505 }
506 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
507 testing::ElementsAreArray({server2, server3, server1, server4}));
508
Mike Yu61d17262020-02-15 18:56:22 +0800509 // The list of the DNS servers changed.
chenbruce72a646c2021-06-27 23:03:39 +0800510 EXPECT_TRUE(mDnsStats.setAddrs({server2, server4}, PROTO_UDP));
Mike Yu61d17262020-02-15 18:56:22 +0800511 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
512 testing::ElementsAreArray({server2, server4}));
513
514 // It fails to add records to an non-existing server, and nothing is changed in getting
515 // the sorted servers.
516 EXPECT_FALSE(mDnsStats.addStats(server1, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms)));
517 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
518 testing::ElementsAreArray({server2, server4}));
519}
520
521TEST_F(DnsStatsTest, GetServers_DeprioritizingBadServers) {
522 const IPSockAddr server1 = IPSockAddr::toIPSockAddr("127.0.0.1", 53);
523 const IPSockAddr server2 = IPSockAddr::toIPSockAddr("127.0.0.2", 53);
524 const IPSockAddr server3 = IPSockAddr::toIPSockAddr("127.0.0.3", 53);
525 const IPSockAddr server4 = IPSockAddr::toIPSockAddr("127.0.0.4", 53);
526
chenbruce72a646c2021-06-27 23:03:39 +0800527 EXPECT_TRUE(mDnsStats.setAddrs({server1, server2, server3, server4}, PROTO_UDP));
Mike Yu61d17262020-02-15 18:56:22 +0800528
529 int server1Counts = 0;
530 int server2Counts = 0;
531 for (int i = 0; i < 5000; i++) {
532 const auto servers = mDnsStats.getSortedServers(PROTO_UDP);
533 EXPECT_EQ(servers.size(), 4U);
534 if (servers[0] == server1) {
535 // server1 is relatively slowly responsive.
536 EXPECT_TRUE(mDnsStats.addStats(servers[0],
537 makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 200ms)));
538 server1Counts++;
539 } else if (servers[0] == server2) {
540 // server2 is relatively quickly responsive.
541 EXPECT_TRUE(mDnsStats.addStats(servers[0],
542 makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 100ms)));
543 server2Counts++;
544 } else if (servers[0] == server3) {
545 // server3 always times out.
546 EXPECT_TRUE(mDnsStats.addStats(servers[0],
547 makeDnsQueryEvent(PROTO_UDP, NS_R_TIMEOUT, 1000ms)));
548 } else if (servers[0] == server4) {
549 // server4 is unusable.
550 EXPECT_TRUE(mDnsStats.addStats(servers[0],
551 makeDnsQueryEvent(PROTO_UDP, NS_R_INTERNAL_ERROR, 1ms)));
552 }
553 }
554
555 const std::vector<StatsData> allStatsData = mDnsStats.getStats(PROTO_UDP);
556 for (const auto& data : allStatsData) {
557 EXPECT_EQ(data.rcodeCounts.size(), 1U);
chenbruce72a646c2021-06-27 23:03:39 +0800558 if (data.sockAddr == server1 || data.sockAddr == server2) {
Mike Yu61d17262020-02-15 18:56:22 +0800559 const auto it = data.rcodeCounts.find(NS_R_NO_ERROR);
560 ASSERT_NE(it, data.rcodeCounts.end());
561 EXPECT_GT(server2Counts, 2 * server1Counts); // At least twice larger.
chenbruce72a646c2021-06-27 23:03:39 +0800562 } else if (data.sockAddr == server3) {
Mike Yu61d17262020-02-15 18:56:22 +0800563 const auto it = data.rcodeCounts.find(NS_R_TIMEOUT);
564 ASSERT_NE(it, data.rcodeCounts.end());
565 EXPECT_LT(it->second, 10);
chenbruce72a646c2021-06-27 23:03:39 +0800566 } else if (data.sockAddr == server4) {
Mike Yu61d17262020-02-15 18:56:22 +0800567 const auto it = data.rcodeCounts.find(NS_R_INTERNAL_ERROR);
568 ASSERT_NE(it, data.rcodeCounts.end());
569 EXPECT_LT(it->second, 10);
570 }
571 }
572}
573
Mike Yue655b1d2019-08-28 17:49:59 +0800574} // namespace android::net