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