Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3bad8551 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 7538072 from 8cf4d1e1 to mainline-media-release

Change-Id: I27889aec5549c62fd81656f14cd601b6a5ca4c64
parents 136e2a75 8cf4d1e1
Loading
Loading
Loading
Loading
+4 −5
Original line number Original line Diff line number Diff line
@@ -147,9 +147,6 @@ cc_defaults {
            suffix: "64",
            suffix: "64",
        },
        },
    },
    },
    data: [
        ":resolv_test_keys",
    ],
}
}


cc_library {
cc_library {
@@ -266,7 +263,8 @@ cc_library_static {
genrule {
genrule {
    name: "statslog_resolv.h",
    name: "statslog_resolv.h",
    tools: ["stats-log-api-gen"],
    tools: ["stats-log-api-gen"],
    cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_resolv.h --module resolv --namespace android,net,stats",
    cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_resolv.h --module resolv" +
         " --namespace android,net,stats --minApiLevel 29",
    out: [
    out: [
        "statslog_resolv.h",
        "statslog_resolv.h",
    ],
    ],
@@ -275,7 +273,8 @@ genrule {
genrule {
genrule {
    name: "statslog_resolv.cpp",
    name: "statslog_resolv.cpp",
    tools: ["stats-log-api-gen"],
    tools: ["stats-log-api-gen"],
    cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_resolv.cpp --module resolv --namespace android,net,stats --importHeader statslog_resolv.h --supportQ",
    cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_resolv.cpp --module resolv" +
         " --namespace android,net,stats --importHeader statslog_resolv.h --minApiLevel 29",
    out: [
    out: [
        "statslog_resolv.cpp",
        "statslog_resolv.cpp",
    ],
    ],
+25 −22
Original line number Original line Diff line number Diff line
@@ -59,10 +59,10 @@ std::string rcodeToName(int rcode) {
    // clang-format on
    // clang-format on
}
}


bool ensureNoInvalidIp(const std::vector<IPSockAddr>& servers) {
bool ensureNoInvalidIp(const std::vector<IPSockAddr>& addrs) {
    for (const auto& server : servers) {
    for (const auto& addr : addrs) {
        if (server.ip() == INVALID_IPADDRESS || server.port() == 0) {
        if (addr.ip() == INVALID_IPADDRESS || addr.port() == 0) {
            LOG(WARNING) << "Invalid server: " << server;
            LOG(WARNING) << "Invalid addr: " << addr;
            return false;
            return false;
        }
        }
    }
    }
@@ -73,8 +73,8 @@ bool ensureNoInvalidIp(const std::vector<IPSockAddr>& servers) {


// The comparison ignores the last update time.
// The comparison ignores the last update time.
bool StatsData::operator==(const StatsData& o) const {
bool StatsData::operator==(const StatsData& o) const {
    return std::tie(serverSockAddr, total, rcodeCounts, latencyUs) ==
    return std::tie(sockAddr, total, rcodeCounts, latencyUs) ==
           std::tie(o.serverSockAddr, o.total, o.rcodeCounts, o.latencyUs);
           std::tie(o.sockAddr, o.total, o.rcodeCounts, o.latencyUs);
}
}


int StatsData::averageLatencyMs() const {
int StatsData::averageLatencyMs() const {
@@ -82,7 +82,7 @@ int StatsData::averageLatencyMs() const {
}
}


std::string StatsData::toString() const {
std::string StatsData::toString() const {
    if (total == 0) return StringPrintf("%s <no data>", serverSockAddr.ip().toString().c_str());
    if (total == 0) return StringPrintf("%s <no data>", sockAddr.ip().toString().c_str());


    const auto now = std::chrono::steady_clock::now();
    const auto now = std::chrono::steady_clock::now();
    const int lastUpdateSec = duration_cast<seconds>(now - lastUpdate).count();
    const int lastUpdateSec = duration_cast<seconds>(now - lastUpdate).count();
@@ -92,7 +92,7 @@ std::string StatsData::toString() const {
            buf += StringPrintf("%s:%d ", rcodeToName(rcode).c_str(), counts);
            buf += StringPrintf("%s:%d ", rcodeToName(rcode).c_str(), counts);
        }
        }
    }
    }
    return StringPrintf("%s (%d, %dms, [%s], %ds)", serverSockAddr.ip().toString().c_str(), total,
    return StringPrintf("%s (%d, %dms, [%s], %ds)", sockAddr.ip().toString().c_str(), total,
                        averageLatencyMs(), buf.c_str(), lastUpdateSec);
                        averageLatencyMs(), buf.c_str(), lastUpdateSec);
}
}


@@ -171,20 +171,20 @@ void StatsRecords::incrementSkippedCount() {
    mSkippedCount = std::min(mSkippedCount + 1, kMaxQuality);
    mSkippedCount = std::min(mSkippedCount + 1, kMaxQuality);
}
}


bool DnsStats::setServers(const std::vector<netdutils::IPSockAddr>& servers, Protocol protocol) {
bool DnsStats::setAddrs(const std::vector<netdutils::IPSockAddr>& addrs, Protocol protocol) {
    if (!ensureNoInvalidIp(servers)) return false;
    if (!ensureNoInvalidIp(addrs)) return false;


    ServerStatsMap& statsMap = mStats[protocol];
    StatsMap& statsMap = mStats[protocol];
    for (const auto& server : servers) {
    for (const auto& addr : addrs) {
        statsMap.try_emplace(server, StatsRecords(server, kLogSize));
        statsMap.try_emplace(addr, StatsRecords(addr, kLogSize));
    }
    }


    // Clean up the map to eliminate the nodes not belonging to the given list of servers.
    // Clean up the map to eliminate the nodes not belonging to the given list of servers.
    const auto cleanup = [&](ServerStatsMap* statsMap) {
    const auto cleanup = [&](StatsMap* statsMap) {
        ServerStatsMap tmp;
        StatsMap tmp;
        for (const auto& server : servers) {
        for (const auto& addr : addrs) {
            if (statsMap->find(server) != statsMap->end()) {
            if (statsMap->find(addr) != statsMap->end()) {
                tmp.insert(statsMap->extract(server));
                tmp.insert(statsMap->extract(addr));
            }
            }
        }
        }
        statsMap->swap(tmp);
        statsMap->swap(tmp);
@@ -199,8 +199,8 @@ bool DnsStats::addStats(const IPSockAddr& ipSockAddr, const DnsQueryEvent& recor
    if (ipSockAddr.ip() == INVALID_IPADDRESS) return false;
    if (ipSockAddr.ip() == INVALID_IPADDRESS) return false;


    bool added = false;
    bool added = false;
    for (auto& [serverSockAddr, statsRecords] : mStats[record.protocol()]) {
    for (auto& [sockAddr, statsRecords] : mStats[record.protocol()]) {
        if (serverSockAddr == ipSockAddr) {
        if (sockAddr == ipSockAddr) {
            const StatsRecords::Record rec = {
            const StatsRecords::Record rec = {
                    .rcode = record.rcode(),
                    .rcode = record.rcode(),
                    .linux_errno = record.linux_errno(),
                    .linux_errno = record.linux_errno(),
@@ -265,10 +265,10 @@ std::vector<StatsData> DnsStats::getStats(Protocol protocol) const {
}
}


void DnsStats::dump(DumpWriter& dw) {
void DnsStats::dump(DumpWriter& dw) {
    const auto dumpStatsMap = [&](ServerStatsMap& statsMap) {
    const auto dumpStatsMap = [&](StatsMap& statsMap) {
        ScopedIndent indentLog(dw);
        ScopedIndent indentLog(dw);
        if (statsMap.size() == 0) {
        if (statsMap.size() == 0) {
            dw.println("<no server>");
            dw.println("<no data>");
            return;
            return;
        }
        }
        for (const auto& [_, statsRecords] : statsMap) {
        for (const auto& [_, statsRecords] : statsMap) {
@@ -290,6 +290,9 @@ void DnsStats::dump(DumpWriter& dw) {


    dw.println("over TCP");
    dw.println("over TCP");
    dumpStatsMap(mStats[PROTO_TCP]);
    dumpStatsMap(mStats[PROTO_TCP]);

    dw.println("over MDNS");
    dumpStatsMap(mStats[PROTO_MDNS]);
}
}


}  // namespace android::net
}  // namespace android::net
+8 −8
Original line number Original line Diff line number Diff line
@@ -33,12 +33,12 @@ namespace android::net {


// The overall information of a StatsRecords.
// The overall information of a StatsRecords.
struct StatsData {
struct StatsData {
    StatsData(const netdutils::IPSockAddr& ipSockAddr) : serverSockAddr(ipSockAddr) {
    StatsData(const netdutils::IPSockAddr& ipSockAddr) : sockAddr(ipSockAddr) {
        lastUpdate = std::chrono::steady_clock::now();
        lastUpdate = std::chrono::steady_clock::now();
    };
    };


    // Server socket address.
    // Socket address.
    netdutils::IPSockAddr serverSockAddr;
    netdutils::IPSockAddr sockAddr;


    // The most recent number of records being accumulated.
    // The most recent number of records being accumulated.
    int total = 0;
    int total = 0;
@@ -106,15 +106,15 @@ class StatsRecords {
    static constexpr int kMaxQuality = 10000;
    static constexpr int kMaxQuality = 10000;
};
};


// DnsStats class manages the statistics of DNS servers per netId.
// DnsStats class manages the statistics of DNS servers or MDNS multicast addresses per netId.
// The class itself is not thread-safe.
// The class itself is not thread-safe.
class DnsStats {
class DnsStats {
  public:
  public:
    using ServerStatsMap = std::map<netdutils::IPSockAddr, StatsRecords>;
    using StatsMap = std::map<netdutils::IPSockAddr, StatsRecords>;


    // Add |servers| to the map, and remove no-longer-used servers.
    // Add |addrs| to the map, and remove no-longer-used addresses.
    // Return true if they are successfully added; otherwise, return false.
    // Return true if they are successfully added; otherwise, return false.
    bool setServers(const std::vector<netdutils::IPSockAddr>& servers, Protocol protocol);
    bool setAddrs(const std::vector<netdutils::IPSockAddr>& addrs, Protocol protocol);


    // Return true if |record| is successfully added into |server|'s stats; otherwise, return false.
    // Return true if |record| is successfully added into |server|'s stats; otherwise, return false.
    bool addStats(const netdutils::IPSockAddr& server, const DnsQueryEvent& record);
    bool addStats(const netdutils::IPSockAddr& server, const DnsQueryEvent& record);
@@ -133,7 +133,7 @@ class DnsStats {
    static constexpr size_t kLogSize = 128;
    static constexpr size_t kLogSize = 128;


  private:
  private:
    std::map<Protocol, ServerStatsMap> mStats;
    std::map<Protocol, StatsMap> mStats;
};
};


}  // namespace android::net
}  // namespace android::net
+75 −41
Original line number Original line Diff line number Diff line
@@ -116,7 +116,8 @@ class DnsStatsTest : public ::testing::Test {
    // Get the output string from dump() and check the content.
    // Get the output string from dump() and check the content.
    void verifyDumpOutput(const std::vector<StatsData>& tcpData,
    void verifyDumpOutput(const std::vector<StatsData>& tcpData,
                          const std::vector<StatsData>& udpData,
                          const std::vector<StatsData>& udpData,
                          const std::vector<StatsData>& dotData) {
                          const std::vector<StatsData>& dotData,
                          const std::vector<StatsData>& mdnsData) {
        // A pattern to capture three matches:
        // A pattern to capture three matches:
        //     server address (empty allowed), the statistics, and the score.
        //     server address (empty allowed), the statistics, and the score.
        const std::regex pattern(R"(\s{4,}([0-9a-fA-F:\.]*)[ ]?([<(].*[>)])[ ]?(\S*))");
        const std::regex pattern(R"(\s{4,}([0-9a-fA-F:\.]*)[ ]?([<(].*[>)])[ ]?(\S*))");
@@ -128,11 +129,11 @@ class DnsStatsTest : public ::testing::Test {
            ASSERT_NE(dumpString->find(protocol), std::string::npos);
            ASSERT_NE(dumpString->find(protocol), std::string::npos);
            std::smatch sm;
            std::smatch sm;


            // Expect to show something even if none of servers is set.
            // Expect to show something even if none of servers or mdns multicast addresses is set.
            if (statsData.empty()) {
            if (statsData.empty()) {
                ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
                ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
                EXPECT_TRUE(sm[1].str().empty());
                EXPECT_TRUE(sm[1].str().empty());
                EXPECT_EQ(sm[2], "<no server>");
                EXPECT_EQ(sm[2], "<no data>");
                EXPECT_TRUE(sm[3].str().empty());
                EXPECT_TRUE(sm[3].str().empty());
                *dumpString = sm.suffix();
                *dumpString = sm.suffix();
                return;
                return;
@@ -140,7 +141,7 @@ class DnsStatsTest : public ::testing::Test {


            for (const auto& stats : statsData) {
            for (const auto& stats : statsData) {
                ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
                ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
                EXPECT_EQ(sm[1], stats.serverSockAddr.ip().toString());
                EXPECT_EQ(sm[1], stats.sockAddr.ip().toString());
                EXPECT_FALSE(sm[2].str().empty());
                EXPECT_FALSE(sm[2].str().empty());
                EXPECT_FALSE(sm[3].str().empty());
                EXPECT_FALSE(sm[3].str().empty());
                *dumpString = sm.suffix();
                *dumpString = sm.suffix();
@@ -150,6 +151,7 @@ class DnsStatsTest : public ::testing::Test {
        check(udpData, "UDP", &dumpString);
        check(udpData, "UDP", &dumpString);
        check(dotData, "TLS", &dumpString);
        check(dotData, "TLS", &dumpString);
        check(tcpData, "TCP", &dumpString);
        check(tcpData, "TCP", &dumpString);
        check(mdnsData, "MDNS", &dumpString);


        // Ensure the whole string has been checked.
        // Ensure the whole string has been checked.
        EXPECT_EQ(dumpString, "\n");
        EXPECT_EQ(dumpString, "\n");
@@ -169,9 +171,9 @@ class DnsStatsTest : public ::testing::Test {
    DnsStats mDnsStats;
    DnsStats mDnsStats;
};
};


TEST_F(DnsStatsTest, SetServers) {
TEST_F(DnsStatsTest, SetAddrs) {
    // Check before any operation to mDnsStats.
    // Check before any operation to mDnsStats.
    verifyDumpOutput({}, {}, {});
    verifyDumpOutput({}, {}, {}, {});


    static const struct {
    static const struct {
        std::vector<std::string> servers;
        std::vector<std::string> servers;
@@ -213,9 +215,9 @@ TEST_F(DnsStatsTest, SetServers) {
            ipSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53));
            ipSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53));
        }
        }


        EXPECT_TRUE(mDnsStats.setServers(ipSockAddrs, PROTO_TCP) == isSuccess);
        EXPECT_TRUE(mDnsStats.setAddrs(ipSockAddrs, PROTO_TCP) == isSuccess);
        EXPECT_TRUE(mDnsStats.setServers(ipSockAddrs, PROTO_UDP) == isSuccess);
        EXPECT_TRUE(mDnsStats.setAddrs(ipSockAddrs, PROTO_UDP) == isSuccess);
        EXPECT_TRUE(mDnsStats.setServers(ipSockAddrs, PROTO_DOT) == isSuccess);
        EXPECT_TRUE(mDnsStats.setAddrs(ipSockAddrs, PROTO_DOT) == isSuccess);


        std::vector<StatsData> expectedStats;
        std::vector<StatsData> expectedStats;
        expectedStats.reserve(expectation.size());
        expectedStats.reserve(expectation.size());
@@ -228,7 +230,7 @@ TEST_F(DnsStatsTest, SetServers) {
        EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
        EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
    }
    }


    verifyDumpOutput({}, {}, {});
    verifyDumpOutput({}, {}, {}, {});
}
}


TEST_F(DnsStatsTest, SetServersDifferentPorts) {
TEST_F(DnsStatsTest, SetServersDifferentPorts) {
@@ -240,18 +242,18 @@ TEST_F(DnsStatsTest, SetServersDifferentPorts) {
    };
    };


    // Servers setup fails due to port unset.
    // Servers setup fails due to port unset.
    EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_TCP));
    EXPECT_FALSE(mDnsStats.setAddrs(servers, PROTO_TCP));
    EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_UDP));
    EXPECT_FALSE(mDnsStats.setAddrs(servers, PROTO_UDP));
    EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_DOT));
    EXPECT_FALSE(mDnsStats.setAddrs(servers, PROTO_DOT));


    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    verifyDumpOutput({}, {}, {});
    verifyDumpOutput({}, {}, {}, {});


    EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setAddrs(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(std::vector(servers.begin() + 2, servers.end()), PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_DOT));
    EXPECT_TRUE(mDnsStats.setAddrs(std::vector(servers.begin() + 2, servers.end()), PROTO_DOT));


    const std::vector<StatsData> expectedStats = {
    const std::vector<StatsData> expectedStats = {
            makeStatsData(servers[2], 0, 0ms, {}), makeStatsData(servers[3], 0, 0ms, {}),
            makeStatsData(servers[2], 0, 0ms, {}), makeStatsData(servers[3], 0, 0ms, {}),
@@ -262,7 +264,7 @@ TEST_F(DnsStatsTest, SetServersDifferentPorts) {
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
    verifyDumpOutput(expectedStats, expectedStats, expectedStats);
    verifyDumpOutput(expectedStats, expectedStats, expectedStats, {});
}
}


TEST_F(DnsStatsTest, AddStatsAndClear) {
TEST_F(DnsStatsTest, AddStatsAndClear) {
@@ -270,10 +272,16 @@ TEST_F(DnsStatsTest, AddStatsAndClear) {
            IPSockAddr::toIPSockAddr("127.0.0.1", 53),
            IPSockAddr::toIPSockAddr("127.0.0.1", 53),
            IPSockAddr::toIPSockAddr("127.0.0.2", 53),
            IPSockAddr::toIPSockAddr("127.0.0.2", 53),
    };
    };
    const std::vector<IPSockAddr> mdnsaddrs = {
            IPSockAddr::toIPSockAddr("ff02::fb", 5353),
            IPSockAddr::toIPSockAddr("224.0.0.251", 5353),
    };
    const DnsQueryEvent record = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
    const DnsQueryEvent record = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
    const DnsQueryEvent mdnsrecord = makeDnsQueryEvent(PROTO_MDNS, NS_R_NO_ERROR, 10ms);


    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(mdnsaddrs, PROTO_MDNS));


    // Fail to add stats because of incorrect arguments.
    // Fail to add stats because of incorrect arguments.
    EXPECT_FALSE(mDnsStats.addStats(IPSockAddr::toIPSockAddr("127.0.0.4", 53), record));
    EXPECT_FALSE(mDnsStats.addStats(IPSockAddr::toIPSockAddr("127.0.0.4", 53), record));
@@ -282,6 +290,8 @@ TEST_F(DnsStatsTest, AddStatsAndClear) {
    EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
    EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
    EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
    EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
    EXPECT_TRUE(mDnsStats.addStats(servers[1], record));
    EXPECT_TRUE(mDnsStats.addStats(servers[1], record));
    EXPECT_TRUE(mDnsStats.addStats(mdnsaddrs[0], mdnsrecord));
    EXPECT_TRUE(mDnsStats.addStats(mdnsaddrs[1], mdnsrecord));


    const std::vector<StatsData> expectedStatsForTcp = {
    const std::vector<StatsData> expectedStatsForTcp = {
            makeStatsData(servers[0], 0, 0ms, {}),
            makeStatsData(servers[0], 0, 0ms, {}),
@@ -292,19 +302,27 @@ TEST_F(DnsStatsTest, AddStatsAndClear) {
            makeStatsData(servers[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
            makeStatsData(servers[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
    };
    };


    const std::vector<StatsData> expectedStatsForMdns = {
            makeStatsData(mdnsaddrs[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
            makeStatsData(mdnsaddrs[0], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
    };

    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStatsForTcp, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStatsForTcp, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStatsForUdp, 10ms));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStatsForUdp, 10ms));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {});
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, expectedStatsForMdns, 10ms));
    verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {}, expectedStatsForMdns);


    // Clear stats.
    // Clear stats.
    EXPECT_TRUE(mDnsStats.setServers({}, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setServers({}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setServers({}, PROTO_DOT));
    EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_DOT));
    EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_MDNS));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    verifyDumpOutput({}, {}, {});
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, {}, NO_AVERAGE_LATENCY));
    verifyDumpOutput({}, {}, {}, {});
}
}


TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
@@ -315,7 +333,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
    const DnsQueryEvent recordNoError = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
    const DnsQueryEvent recordNoError = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
    const DnsQueryEvent recordTimeout = makeDnsQueryEvent(PROTO_UDP, NS_R_TIMEOUT, 250ms);
    const DnsQueryEvent recordTimeout = makeDnsQueryEvent(PROTO_UDP, NS_R_TIMEOUT, 250ms);


    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));


    // Add a record to 127.0.0.1.
    // Add a record to 127.0.0.1.
    EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
    EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
@@ -332,7 +350,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
    };
    };
    EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
    EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms));
    verifyDumpOutput({}, expectedStats, {});
    verifyDumpOutput({}, expectedStats, {}, {});


    // Update the server list, the stats of 127.0.0.2 will remain.
    // Update the server list, the stats of 127.0.0.2 will remain.
    servers = {
    servers = {
@@ -340,7 +358,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
            IPSockAddr::toIPSockAddr("127.0.0.3", 53),
            IPSockAddr::toIPSockAddr("127.0.0.3", 53),
            IPSockAddr::toIPSockAddr("127.0.0.4", 53),
            IPSockAddr::toIPSockAddr("127.0.0.4", 53),
    };
    };
    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
    expectedStats = {
    expectedStats = {
            makeStatsData(servers[0], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}),
            makeStatsData(servers[0], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}),
            makeStatsData(servers[1], 0, 0ms, {}),
            makeStatsData(servers[1], 0, 0ms, {}),
@@ -348,7 +366,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
    };
    };
    EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
    EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 130ms));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 130ms));
    verifyDumpOutput({}, expectedStats, {});
    verifyDumpOutput({}, expectedStats, {}, {});


    // Let's add a record to 127.0.0.2 again.
    // Let's add a record to 127.0.0.2 again.
    EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
    EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
@@ -359,7 +377,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
    };
    };
    EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
    EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms));
    verifyDumpOutput({}, expectedStats, {});
    verifyDumpOutput({}, expectedStats, {}, {});
}
}


TEST_F(DnsStatsTest, AddStatsRecords_100000) {
TEST_F(DnsStatsTest, AddStatsRecords_100000) {
@@ -375,6 +393,11 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
            IPSockAddr::toIPSockAddr("127.0.0.4", 53),
            IPSockAddr::toIPSockAddr("127.0.0.4", 53),
    };
    };


    const std::vector<IPSockAddr> mdnsaddrs = {
            IPSockAddr::toIPSockAddr("ff02::fb", 5353),
            IPSockAddr::toIPSockAddr("224.0.0.251", 5353),
    };

    // To test unknown rcode in rcodeToName(), store the elements as type int.
    // To test unknown rcode in rcodeToName(), store the elements as type int.
    const std::array<int, rcodeNum> rcodes = {
    const std::array<int, rcodeNum> rcodes = {
            NS_R_NO_ERROR,        // NOERROR
            NS_R_NO_ERROR,        // NOERROR
@@ -383,9 +406,10 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
            NS_R_INTERNAL_ERROR,  // INTERNAL_ERROR
            NS_R_INTERNAL_ERROR,  // INTERNAL_ERROR
    };
    };


    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_DOT));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_DOT));
    EXPECT_TRUE(mDnsStats.setAddrs(mdnsaddrs, PROTO_MDNS));


    for (size_t i = 0; i < operations; i++) {
    for (size_t i = 0; i < operations; i++) {
        const NsRcode rcode = static_cast<NsRcode>(rcodes[i % rcodeNum]);
        const NsRcode rcode = static_cast<NsRcode>(rcodes[i % rcodeNum]);
@@ -398,6 +422,11 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
            ASSERT_TRUE(mDnsStats.addStats(server, eventUdp));
            ASSERT_TRUE(mDnsStats.addStats(server, eventUdp));
            ASSERT_TRUE(mDnsStats.addStats(server, eventDot));
            ASSERT_TRUE(mDnsStats.addStats(server, eventDot));
        }
        }
        const auto eventMdns = makeDnsQueryEvent(PROTO_MDNS, rcode, milliseconds(i));
        for (const auto& mdnsaddr : mdnsaddrs) {
            SCOPED_TRACE(mdnsaddr.toString() + "-" + std::to_string(i));
            ASSERT_TRUE(mDnsStats.addStats(mdnsaddr, eventMdns));
        }
    }
    }


    std::map<int, int> expectedRcodeCounts;
    std::map<int, int> expectedRcodeCounts;
@@ -414,10 +443,15 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
            makeStatsData(servers[3], logSize, logSize * 99935500us, expectedRcodeCounts),
            makeStatsData(servers[3], logSize, logSize * 99935500us, expectedRcodeCounts),
    };
    };


    const std::vector<StatsData> expectedMdnsStats = {
            makeStatsData(mdnsaddrs[1], logSize, logSize * 99935500us, expectedRcodeCounts),
            makeStatsData(mdnsaddrs[0], logSize, logSize * 99935500us, expectedRcodeCounts),
    };
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, 99935500us));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, 99935500us));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 99935500us));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 99935500us));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, 99935500us));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, 99935500us));
    verifyDumpOutput(expectedStats, expectedStats, expectedStats);
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, expectedMdnsStats, 99935500us));
    verifyDumpOutput(expectedStats, expectedStats, expectedStats, expectedMdnsStats);
}
}


TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
@@ -430,8 +464,8 @@ TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
    EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP), IsEmpty());
    EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP), IsEmpty());


    // Before there's any stats, the list of the sorted servers is the same as the setup's one.
    // Before there's any stats, the list of the sorted servers is the same as the setup's one.
    EXPECT_TRUE(mDnsStats.setServers({server1, server2, server3, server4}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs({server1, server2, server3, server4}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setServers({server1, server2, server3, server4}, PROTO_DOT));
    EXPECT_TRUE(mDnsStats.setAddrs({server1, server2, server3, server4}, PROTO_DOT));
    EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
    EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
                testing::ElementsAreArray({server1, server2, server3, server4}));
                testing::ElementsAreArray({server1, server2, server3, server4}));


@@ -473,7 +507,7 @@ TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
                testing::ElementsAreArray({server2, server3, server1, server4}));
                testing::ElementsAreArray({server2, server3, server1, server4}));


    // The list of the DNS servers changed.
    // The list of the DNS servers changed.
    EXPECT_TRUE(mDnsStats.setServers({server2, server4}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs({server2, server4}, PROTO_UDP));
    EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
    EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
                testing::ElementsAreArray({server2, server4}));
                testing::ElementsAreArray({server2, server4}));


@@ -490,7 +524,7 @@ TEST_F(DnsStatsTest, GetServers_DeprioritizingBadServers) {
    const IPSockAddr server3 = IPSockAddr::toIPSockAddr("127.0.0.3", 53);
    const IPSockAddr server3 = IPSockAddr::toIPSockAddr("127.0.0.3", 53);
    const IPSockAddr server4 = IPSockAddr::toIPSockAddr("127.0.0.4", 53);
    const IPSockAddr server4 = IPSockAddr::toIPSockAddr("127.0.0.4", 53);


    EXPECT_TRUE(mDnsStats.setServers({server1, server2, server3, server4}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs({server1, server2, server3, server4}, PROTO_UDP));


    int server1Counts = 0;
    int server1Counts = 0;
    int server2Counts = 0;
    int server2Counts = 0;
@@ -521,15 +555,15 @@ TEST_F(DnsStatsTest, GetServers_DeprioritizingBadServers) {
    const std::vector<StatsData> allStatsData = mDnsStats.getStats(PROTO_UDP);
    const std::vector<StatsData> allStatsData = mDnsStats.getStats(PROTO_UDP);
    for (const auto& data : allStatsData) {
    for (const auto& data : allStatsData) {
        EXPECT_EQ(data.rcodeCounts.size(), 1U);
        EXPECT_EQ(data.rcodeCounts.size(), 1U);
        if (data.serverSockAddr == server1 || data.serverSockAddr == server2) {
        if (data.sockAddr == server1 || data.sockAddr == server2) {
            const auto it = data.rcodeCounts.find(NS_R_NO_ERROR);
            const auto it = data.rcodeCounts.find(NS_R_NO_ERROR);
            ASSERT_NE(it, data.rcodeCounts.end());
            ASSERT_NE(it, data.rcodeCounts.end());
            EXPECT_GT(server2Counts, 2 * server1Counts);  // At least twice larger.
            EXPECT_GT(server2Counts, 2 * server1Counts);  // At least twice larger.
        } else if (data.serverSockAddr == server3) {
        } else if (data.sockAddr == server3) {
            const auto it = data.rcodeCounts.find(NS_R_TIMEOUT);
            const auto it = data.rcodeCounts.find(NS_R_TIMEOUT);
            ASSERT_NE(it, data.rcodeCounts.end());
            ASSERT_NE(it, data.rcodeCounts.end());
            EXPECT_LT(it->second, 10);
            EXPECT_LT(it->second, 10);
        } else if (data.serverSockAddr == server4) {
        } else if (data.sockAddr == server4) {
            const auto it = data.rcodeCounts.find(NS_R_INTERNAL_ERROR);
            const auto it = data.rcodeCounts.find(NS_R_INTERNAL_ERROR);
            ASSERT_NE(it, data.rcodeCounts.end());
            ASSERT_NE(it, data.rcodeCounts.end());
            EXPECT_LT(it->second, 10);
            EXPECT_LT(it->second, 10);
+1 −0
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ class Experiments {
            "dot_validation_latency_factor",
            "dot_validation_latency_factor",
            "dot_validation_latency_offset_ms",
            "dot_validation_latency_offset_ms",
            "doh",
            "doh",
            "mdns_resolution",
    };
    };
    // This value is used in updateInternal as the default value if any flags can't be found.
    // This value is used in updateInternal as the default value if any flags can't be found.
    static constexpr int kFlagIntDefault = INT_MIN;
    static constexpr int kFlagIntDefault = INT_MIN;
Loading