blob: 5efd186e2638e42e704923bf2c049b882de64334 [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;
29using std::chrono::milliseconds;
30using ::testing::IsEmpty;
31using ::testing::UnorderedElementsAreArray;
32
33namespace {
34
35DnsQueryEvent makeDnsQueryEvent(const Protocol protocol, const NsRcode rcode,
36 const milliseconds& latency) {
37 DnsQueryEvent event;
38 event.set_protocol(protocol);
39 event.set_rcode(rcode);
40 event.set_latency_micros(latency.count() * 1000);
41 return event;
42}
43
44StatsData makeStatsData(const IPSockAddr& server, const int total, const milliseconds& latencyMs,
45 const std::map<int, int>& rcodeCounts) {
46 StatsData ret(server);
47 ret.total = total;
48 ret.latencyUs = latencyMs;
49 ret.rcodeCounts = rcodeCounts;
50 return ret;
51}
52
53} // namespace
54
Mike Yu61d17262020-02-15 18:56:22 +080055// TODO: add StatsDataTest to ensure its methods return correct outputs.
56
Mike Yue655b1d2019-08-28 17:49:59 +080057class StatsRecordsTest : public ::testing::Test {};
58
59TEST_F(StatsRecordsTest, PushRecord) {
60 const IPSockAddr server = IPSockAddr::toIPSockAddr("127.0.0.2", 53);
61 constexpr size_t size = 3;
Mike Yu9100c292020-12-04 14:20:34 +080062 const StatsRecords::Record recordNoError = {
63 .rcode = NS_R_NO_ERROR,
64 .linux_errno = 0,
65 .latencyUs{10ms},
66 };
67 const StatsRecords::Record recordTimeout = {
68 .rcode = NS_R_TIMEOUT,
69 .linux_errno = 0,
70 .latencyUs{250ms},
71 };
Mike Yue655b1d2019-08-28 17:49:59 +080072
73 StatsRecords sr(server, size);
74 EXPECT_EQ(sr.getStatsData(), makeStatsData(server, 0, 0ms, {}));
75
76 sr.push(recordNoError);
77 EXPECT_EQ(sr.getStatsData(), makeStatsData(server, 1, 10ms, {{NS_R_NO_ERROR, 1}}));
78
79 sr.push(recordNoError);
80 EXPECT_EQ(sr.getStatsData(), makeStatsData(server, 2, 20ms, {{NS_R_NO_ERROR, 2}}));
81
82 sr.push(recordTimeout);
83 EXPECT_EQ(sr.getStatsData(),
84 makeStatsData(server, 3, 270ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 1}}));
85
86 sr.push(recordTimeout);
87 EXPECT_EQ(sr.getStatsData(),
88 makeStatsData(server, 3, 510ms, {{NS_R_NO_ERROR, 1}, {NS_R_TIMEOUT, 2}}));
89
90 sr.push(recordTimeout);
91 EXPECT_EQ(sr.getStatsData(),
92 makeStatsData(server, 3, 750ms, {{NS_R_NO_ERROR, 0}, {NS_R_TIMEOUT, 3}}));
93}
94
95class DnsStatsTest : public ::testing::Test {
96 protected:
Mike Yu61d118e2019-12-23 21:08:19 +080097 std::string captureDumpOutput() {
98 netdutils::DumpWriter dw(STDOUT_FILENO);
99 CapturedStdout captured;
100 mDnsStats.dump(dw);
101 return captured.str();
102 }
103
104 // Get the output string from dump() and check the content.
105 void verifyDumpOutput(const std::vector<StatsData>& tcpData,
106 const std::vector<StatsData>& udpData,
107 const std::vector<StatsData>& dotData) {
Mike Yu61d17262020-02-15 18:56:22 +0800108 // A pattern to capture three matches:
109 // server address (empty allowed), the statistics, and the score.
110 const std::regex pattern(R"(\s{4,}([0-9a-fA-F:\.]*)[ ]?([<(].*[>)])[ ]?(\S*))");
Mike Yu61d118e2019-12-23 21:08:19 +0800111 std::string dumpString = captureDumpOutput();
112
113 const auto check = [&](const std::vector<StatsData>& statsData, const std::string& protocol,
114 std::string* dumpString) {
115 SCOPED_TRACE(protocol);
116 ASSERT_NE(dumpString->find(protocol), std::string::npos);
117 std::smatch sm;
118
119 // Expect to show something even if none of servers is set.
120 if (statsData.empty()) {
121 ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
122 EXPECT_TRUE(sm[1].str().empty());
123 EXPECT_EQ(sm[2], "<no server>");
Mike Yu61d17262020-02-15 18:56:22 +0800124 EXPECT_TRUE(sm[3].str().empty());
Mike Yu61d118e2019-12-23 21:08:19 +0800125 *dumpString = sm.suffix();
126 return;
127 }
128
129 for (const auto& stats : statsData) {
130 ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
131 EXPECT_EQ(sm[1], stats.serverSockAddr.ip().toString());
132 EXPECT_FALSE(sm[2].str().empty());
Mike Yu61d17262020-02-15 18:56:22 +0800133 EXPECT_FALSE(sm[3].str().empty());
Mike Yu61d118e2019-12-23 21:08:19 +0800134 *dumpString = sm.suffix();
135 }
136 };
137
138 check(udpData, "UDP", &dumpString);
139 check(dotData, "TLS", &dumpString);
140 check(tcpData, "TCP", &dumpString);
141
142 // Ensure the whole string has been checked.
143 EXPECT_EQ(dumpString, "\n");
144 }
145
Mike Yue655b1d2019-08-28 17:49:59 +0800146 DnsStats mDnsStats;
147};
148
149TEST_F(DnsStatsTest, SetServers) {
Mike Yu61d118e2019-12-23 21:08:19 +0800150 // Check before any operation to mDnsStats.
151 verifyDumpOutput({}, {}, {});
152
Mike Yue655b1d2019-08-28 17:49:59 +0800153 static const struct {
154 std::vector<std::string> servers;
155 std::vector<std::string> expectation;
156 bool isSuccess;
157 } tests[] = {
158 // Normal case.
159 {
160 {"127.0.0.1", "127.0.0.2", "fe80::1%22", "2001:db8::2", "::1"},
161 {"127.0.0.1", "127.0.0.2", "fe80::1%22", "2001:db8::2", "::1"},
162 true,
163 },
164 // Duplicate servers.
165 {
166 {"127.0.0.1", "2001:db8::2", "127.0.0.1", "2001:db8::2"},
167 {"127.0.0.1", "2001:db8::2"},
168 true,
169 },
170 // Invalid server addresses. The state remains in previous state.
171 {
172 {"not_an_ip", "127.0.0.3", "127.a.b.2"},
173 {"127.0.0.1", "2001:db8::2"},
174 false,
175 },
176 // Clean up the old servers 127.0.0.1 and 127.0.0.2.
177 {
178 {"127.0.0.4", "2001:db8::5"},
179 {"127.0.0.4", "2001:db8::5"},
180 true,
181 },
182 // Empty list.
183 {{}, {}, true},
184 };
185
186 for (const auto& [servers, expectation, isSuccess] : tests) {
187 std::vector<IPSockAddr> ipSockAddrs;
188 ipSockAddrs.reserve(servers.size());
189 for (const auto& server : servers) {
190 ipSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53));
191 }
192
193 EXPECT_TRUE(mDnsStats.setServers(ipSockAddrs, PROTO_TCP) == isSuccess);
194 EXPECT_TRUE(mDnsStats.setServers(ipSockAddrs, PROTO_UDP) == isSuccess);
195 EXPECT_TRUE(mDnsStats.setServers(ipSockAddrs, PROTO_DOT) == isSuccess);
196
197 std::vector<StatsData> expectedStats;
198 expectedStats.reserve(expectation.size());
199 for (const auto& exp : expectation) {
200 expectedStats.push_back(makeStatsData(IPSockAddr::toIPSockAddr(exp, 53), 0, 0ms, {}));
201 }
202
203 EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStats));
204 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
205 EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), UnorderedElementsAreArray(expectedStats));
206 }
Mike Yu61d118e2019-12-23 21:08:19 +0800207
208 verifyDumpOutput({}, {}, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800209}
210
211TEST_F(DnsStatsTest, SetServersDifferentPorts) {
212 const std::vector<IPSockAddr> servers = {
213 IPSockAddr::toIPSockAddr("127.0.0.1", 0), IPSockAddr::toIPSockAddr("fe80::1", 0),
214 IPSockAddr::toIPSockAddr("127.0.0.1", 53), IPSockAddr::toIPSockAddr("127.0.0.1", 5353),
215 IPSockAddr::toIPSockAddr("127.0.0.1", 853), IPSockAddr::toIPSockAddr("fe80::1", 53),
216 IPSockAddr::toIPSockAddr("fe80::1", 5353), IPSockAddr::toIPSockAddr("fe80::1", 853),
217 };
218
219 // Servers setup fails due to port unset.
220 EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_TCP));
221 EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_UDP));
222 EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_DOT));
223
224 EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), IsEmpty());
225 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), IsEmpty());
226 EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), IsEmpty());
Mike Yu61d118e2019-12-23 21:08:19 +0800227 verifyDumpOutput({}, {}, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800228
229 EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP));
230 EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_UDP));
231 EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_DOT));
232
233 const std::vector<StatsData> expectedStats = {
234 makeStatsData(servers[2], 0, 0ms, {}), makeStatsData(servers[3], 0, 0ms, {}),
235 makeStatsData(servers[4], 0, 0ms, {}), makeStatsData(servers[5], 0, 0ms, {}),
236 makeStatsData(servers[6], 0, 0ms, {}), makeStatsData(servers[7], 0, 0ms, {}),
237 };
238
239 EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStats));
240 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
241 EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), UnorderedElementsAreArray(expectedStats));
Mike Yu61d118e2019-12-23 21:08:19 +0800242 verifyDumpOutput(expectedStats, expectedStats, expectedStats);
Mike Yue655b1d2019-08-28 17:49:59 +0800243}
244
245TEST_F(DnsStatsTest, AddStatsAndClear) {
246 const std::vector<IPSockAddr> servers = {
247 IPSockAddr::toIPSockAddr("127.0.0.1", 53),
248 IPSockAddr::toIPSockAddr("127.0.0.2", 53),
249 };
250 const DnsQueryEvent record = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
251
252 EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_TCP));
253 EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
254
255 // Fail to add stats because of incorrect arguments.
256 EXPECT_FALSE(mDnsStats.addStats(IPSockAddr::toIPSockAddr("127.0.0.4", 53), record));
257 EXPECT_FALSE(mDnsStats.addStats(IPSockAddr::toIPSockAddr("127.a.b.4", 53), record));
258
259 EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
260 EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
261 EXPECT_TRUE(mDnsStats.addStats(servers[1], record));
262
263 const std::vector<StatsData> expectedStatsForTcp = {
264 makeStatsData(servers[0], 0, 0ms, {}),
265 makeStatsData(servers[1], 0, 0ms, {}),
266 };
267 const std::vector<StatsData> expectedStatsForUdp = {
268 makeStatsData(servers[0], 2, 20ms, {{NS_R_NO_ERROR, 2}}),
269 makeStatsData(servers[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
270 };
271
272 EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStatsForTcp));
273 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStatsForUdp));
274 EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), IsEmpty());
Mike Yu61d118e2019-12-23 21:08:19 +0800275 verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800276
277 // Clear stats.
278 EXPECT_TRUE(mDnsStats.setServers({}, PROTO_TCP));
279 EXPECT_TRUE(mDnsStats.setServers({}, PROTO_UDP));
280 EXPECT_TRUE(mDnsStats.setServers({}, PROTO_DOT));
281 EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), IsEmpty());
282 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), IsEmpty());
283 EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), IsEmpty());
Mike Yu61d118e2019-12-23 21:08:19 +0800284 verifyDumpOutput({}, {}, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800285}
286
287TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
288 std::vector<IPSockAddr> servers = {
289 IPSockAddr::toIPSockAddr("127.0.0.1", 53),
290 IPSockAddr::toIPSockAddr("127.0.0.2", 53),
291 };
292 const DnsQueryEvent recordNoError = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
293 const DnsQueryEvent recordTimeout = makeDnsQueryEvent(PROTO_UDP, NS_R_TIMEOUT, 250ms);
294
295 EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
296
297 // Add a record to 127.0.0.1.
298 EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
299
300 // Add four records to 127.0.0.2.
301 EXPECT_TRUE(mDnsStats.addStats(servers[1], recordNoError));
302 EXPECT_TRUE(mDnsStats.addStats(servers[1], recordNoError));
303 EXPECT_TRUE(mDnsStats.addStats(servers[1], recordTimeout));
304 EXPECT_TRUE(mDnsStats.addStats(servers[1], recordTimeout));
305
306 std::vector<StatsData> expectedStats = {
307 makeStatsData(servers[0], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
308 makeStatsData(servers[1], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}),
309 };
310 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
Mike Yu61d118e2019-12-23 21:08:19 +0800311 verifyDumpOutput({}, expectedStats, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800312
313 // Update the server list, the stats of 127.0.0.2 will remain.
314 servers = {
315 IPSockAddr::toIPSockAddr("127.0.0.2", 53),
316 IPSockAddr::toIPSockAddr("127.0.0.3", 53),
317 IPSockAddr::toIPSockAddr("127.0.0.4", 53),
318 };
319 EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
320 expectedStats = {
321 makeStatsData(servers[0], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}),
322 makeStatsData(servers[1], 0, 0ms, {}),
323 makeStatsData(servers[2], 0, 0ms, {}),
324 };
325 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
Mike Yu61d118e2019-12-23 21:08:19 +0800326 verifyDumpOutput({}, expectedStats, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800327
328 // Let's add a record to 127.0.0.2 again.
329 EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
330 expectedStats = {
331 makeStatsData(servers[0], 5, 530ms, {{NS_R_NO_ERROR, 3}, {NS_R_TIMEOUT, 2}}),
332 makeStatsData(servers[1], 0, 0ms, {}),
333 makeStatsData(servers[2], 0, 0ms, {}),
334 };
335 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
Mike Yu61d118e2019-12-23 21:08:19 +0800336 verifyDumpOutput({}, expectedStats, {});
Mike Yue655b1d2019-08-28 17:49:59 +0800337}
338
339TEST_F(DnsStatsTest, AddStatsRecords_100000) {
Mike Yu61d118e2019-12-23 21:08:19 +0800340 constexpr size_t operations = 100000;
341 constexpr size_t logSize = DnsStats::kLogSize;
342 constexpr size_t rcodeNum = 4; // A value by which kLogSize is divisible.
343 ASSERT_EQ(logSize % rcodeNum, 0U);
344
Mike Yue655b1d2019-08-28 17:49:59 +0800345 const std::vector<IPSockAddr> servers = {
346 IPSockAddr::toIPSockAddr("127.0.0.1", 53),
347 IPSockAddr::toIPSockAddr("127.0.0.2", 53),
348 IPSockAddr::toIPSockAddr("127.0.0.3", 53),
349 IPSockAddr::toIPSockAddr("127.0.0.4", 53),
350 };
351
Mike Yu61d118e2019-12-23 21:08:19 +0800352 // To test unknown rcode in rcodeToName(), store the elements as type int.
353 const std::array<int, rcodeNum> rcodes = {
354 NS_R_NO_ERROR, // NOERROR
355 NS_R_NXDOMAIN, // NXDOMAIN
356 99, // UNKNOWN(99)
357 NS_R_INTERNAL_ERROR, // INTERNAL_ERROR
358 };
359
Mike Yue655b1d2019-08-28 17:49:59 +0800360 EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_TCP));
361 EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
362 EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_DOT));
363
Mike Yu61d118e2019-12-23 21:08:19 +0800364 for (size_t i = 0; i < operations; i++) {
365 const NsRcode rcode = static_cast<NsRcode>(rcodes[i % rcodeNum]);
366 const auto eventTcp = makeDnsQueryEvent(PROTO_TCP, rcode, 10ms);
367 const auto eventUdp = makeDnsQueryEvent(PROTO_UDP, rcode, 10ms);
368 const auto eventDot = makeDnsQueryEvent(PROTO_DOT, rcode, 10ms);
Mike Yue655b1d2019-08-28 17:49:59 +0800369 for (const auto& server : servers) {
Mike Yu61d118e2019-12-23 21:08:19 +0800370 SCOPED_TRACE(server.toString() + "-" + std::to_string(i));
371 ASSERT_TRUE(mDnsStats.addStats(server, eventTcp));
372 ASSERT_TRUE(mDnsStats.addStats(server, eventUdp));
373 ASSERT_TRUE(mDnsStats.addStats(server, eventDot));
Mike Yue655b1d2019-08-28 17:49:59 +0800374 }
375 }
Mike Yu61d118e2019-12-23 21:08:19 +0800376
377 std::map<int, int> expectedRcodeCounts;
378 for (const auto& rcode : rcodes) {
379 expectedRcodeCounts.try_emplace(rcode, 32);
380 }
381 const std::vector<StatsData> expectedStats = {
382 makeStatsData(servers[0], logSize, logSize * 10ms, expectedRcodeCounts),
383 makeStatsData(servers[1], logSize, logSize * 10ms, expectedRcodeCounts),
384 makeStatsData(servers[2], logSize, logSize * 10ms, expectedRcodeCounts),
385 makeStatsData(servers[3], logSize, logSize * 10ms, expectedRcodeCounts),
386 };
387
388 EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStats));
389 EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
390 EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), UnorderedElementsAreArray(expectedStats));
391 verifyDumpOutput(expectedStats, expectedStats, expectedStats);
Mike Yue655b1d2019-08-28 17:49:59 +0800392}
393
Mike Yu61d17262020-02-15 18:56:22 +0800394TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
395 const IPSockAddr server1 = IPSockAddr::toIPSockAddr("127.0.0.1", 53);
396 const IPSockAddr server2 = IPSockAddr::toIPSockAddr("127.0.0.2", 53);
397 const IPSockAddr server3 = IPSockAddr::toIPSockAddr("2001:db8:cafe:d00d::1", 53);
398 const IPSockAddr server4 = IPSockAddr::toIPSockAddr("2001:db8:cafe:d00d::2", 53);
399
400 // Return empty list before setup.
401 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP), IsEmpty());
402
403 // Before there's any stats, the list of the sorted servers is the same as the setup's one.
404 EXPECT_TRUE(mDnsStats.setServers({server1, server2, server3, server4}, PROTO_UDP));
405 EXPECT_TRUE(mDnsStats.setServers({server1, server2, server3, server4}, PROTO_DOT));
406 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
407 testing::ElementsAreArray({server1, server2, server3, server4}));
408
409 // Add a record to server1. The qualities of the other servers increase.
410 EXPECT_TRUE(mDnsStats.addStats(server1, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms)));
411 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
412 testing::ElementsAreArray({server2, server3, server4, server1}));
413
414 // Add a record, with less repose time than server1, to server3.
415 EXPECT_TRUE(mDnsStats.addStats(server3, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 5ms)));
416 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
417 testing::ElementsAreArray({server2, server4, server3, server1}));
418
419 // Even though server2 has zero response time, select server4 as the first server because it
420 // doesn't have stats yet.
421 EXPECT_TRUE(mDnsStats.addStats(server2, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 0ms)));
422 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
423 testing::ElementsAreArray({server4, server2, server3, server1}));
424
425 // Updating DoT record to server4 changes nothing.
426 EXPECT_TRUE(mDnsStats.addStats(server4, makeDnsQueryEvent(PROTO_DOT, NS_R_NO_ERROR, 10ms)));
427 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
428 testing::ElementsAreArray({server4, server2, server3, server1}));
429
430 // Add a record, with a very large value of respose time, to server4.
431 EXPECT_TRUE(mDnsStats.addStats(server4, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 500000ms)));
432 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
433 testing::ElementsAreArray({server2, server3, server1, server4}));
434
Mike Yu9100c292020-12-04 14:20:34 +0800435 // Add some internal_error records with permission error to server2.
436 // The internal_error won't cause the priority of server2 drop. (but some of the other
437 // quality factors will still be counted, such as skipped_count and latency)
438 auto recordFromNetworkRestricted = makeDnsQueryEvent(PROTO_UDP, NS_R_INTERNAL_ERROR, 1ms);
439 recordFromNetworkRestricted.set_linux_errno(static_cast<LinuxErrno>(EPERM));
440 for (int i = 0; i < 3; i++) {
441 EXPECT_TRUE(mDnsStats.addStats(server2, recordFromNetworkRestricted));
442 }
443 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
444 testing::ElementsAreArray({server2, server3, server1, server4}));
445
Mike Yu61d17262020-02-15 18:56:22 +0800446 // The list of the DNS servers changed.
447 EXPECT_TRUE(mDnsStats.setServers({server2, server4}, PROTO_UDP));
448 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
449 testing::ElementsAreArray({server2, server4}));
450
451 // It fails to add records to an non-existing server, and nothing is changed in getting
452 // the sorted servers.
453 EXPECT_FALSE(mDnsStats.addStats(server1, makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms)));
454 EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
455 testing::ElementsAreArray({server2, server4}));
456}
457
458TEST_F(DnsStatsTest, GetServers_DeprioritizingBadServers) {
459 const IPSockAddr server1 = IPSockAddr::toIPSockAddr("127.0.0.1", 53);
460 const IPSockAddr server2 = IPSockAddr::toIPSockAddr("127.0.0.2", 53);
461 const IPSockAddr server3 = IPSockAddr::toIPSockAddr("127.0.0.3", 53);
462 const IPSockAddr server4 = IPSockAddr::toIPSockAddr("127.0.0.4", 53);
463
464 EXPECT_TRUE(mDnsStats.setServers({server1, server2, server3, server4}, PROTO_UDP));
465
466 int server1Counts = 0;
467 int server2Counts = 0;
468 for (int i = 0; i < 5000; i++) {
469 const auto servers = mDnsStats.getSortedServers(PROTO_UDP);
470 EXPECT_EQ(servers.size(), 4U);
471 if (servers[0] == server1) {
472 // server1 is relatively slowly responsive.
473 EXPECT_TRUE(mDnsStats.addStats(servers[0],
474 makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 200ms)));
475 server1Counts++;
476 } else if (servers[0] == server2) {
477 // server2 is relatively quickly responsive.
478 EXPECT_TRUE(mDnsStats.addStats(servers[0],
479 makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 100ms)));
480 server2Counts++;
481 } else if (servers[0] == server3) {
482 // server3 always times out.
483 EXPECT_TRUE(mDnsStats.addStats(servers[0],
484 makeDnsQueryEvent(PROTO_UDP, NS_R_TIMEOUT, 1000ms)));
485 } else if (servers[0] == server4) {
486 // server4 is unusable.
487 EXPECT_TRUE(mDnsStats.addStats(servers[0],
488 makeDnsQueryEvent(PROTO_UDP, NS_R_INTERNAL_ERROR, 1ms)));
489 }
490 }
491
492 const std::vector<StatsData> allStatsData = mDnsStats.getStats(PROTO_UDP);
493 for (const auto& data : allStatsData) {
494 EXPECT_EQ(data.rcodeCounts.size(), 1U);
495 if (data.serverSockAddr == server1 || data.serverSockAddr == server2) {
496 const auto it = data.rcodeCounts.find(NS_R_NO_ERROR);
497 ASSERT_NE(it, data.rcodeCounts.end());
498 EXPECT_GT(server2Counts, 2 * server1Counts); // At least twice larger.
499 } else if (data.serverSockAddr == server3) {
500 const auto it = data.rcodeCounts.find(NS_R_TIMEOUT);
501 ASSERT_NE(it, data.rcodeCounts.end());
502 EXPECT_LT(it->second, 10);
503 } else if (data.serverSockAddr == server4) {
504 const auto it = data.rcodeCounts.find(NS_R_INTERNAL_ERROR);
505 ASSERT_NE(it, data.rcodeCounts.end());
506 EXPECT_LT(it->second, 10);
507 }
508 }
509}
510
Mike Yue655b1d2019-08-28 17:49:59 +0800511} // namespace android::net