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

Commit c6ac1ade authored by Luke Huang's avatar Luke Huang Committed by Gerrit Code Review
Browse files

Merge changes I1519e541,I43555fe7

* changes:
  Fix netclient test and add it to test mapping
  Separate GetAddrInfoStressTest* from resolv_integration_test to resolv_stress_test
parents 28ddc094 fde82482
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -163,8 +163,9 @@ cc_test {
    defaults: ["netd_defaults"],
    srcs: [
        "dns_responder/dns_responder.cpp",
        "resolver_test.cpp",
        "dnsresolver_binder_test.cpp",
        "resolver_test.cpp",
        "tests/resolv_test_utils.cpp",
    ],
    include_dirs: [
        "system/netd/resolv/include",
+22 −188
Original line number Diff line number Diff line
@@ -61,9 +61,8 @@
#include "binder/IServiceManager.h"
#include "netdutils/ResponseCode.h"
#include "netdutils/SocketOption.h"
#include "tests/resolv_test_utils.h"

// TODO: make this dynamic and stop depending on implementation details.
constexpr int TEST_NETID = 30;
// Valid VPN netId range is 100 ~ 65535
constexpr int TEST_VPN_NETID = 65502;
constexpr int MAXPACKET = (8 * 1024);
@@ -83,6 +82,7 @@ using android::netdutils::ResponseCode;

// TODO: move into libnetdutils?
namespace {

ScopedAddrinfo safe_getaddrinfo(const char* node, const char* service,
                                const struct addrinfo* hints) {
    addrinfo* result = nullptr;
@@ -91,6 +91,7 @@ ScopedAddrinfo safe_getaddrinfo(const char* node, const char* service,
    }
    return ScopedAddrinfo(result);
}

}  // namespace

class ResolverTest : public ::testing::Test {
@@ -106,112 +107,6 @@ class ResolverTest : public ::testing::Test {
        mDnsClient.TearDown();
    }

    bool GetResolverInfo(std::vector<std::string>* servers, std::vector<std::string>* domains,
                         std::vector<std::string>* tlsServers, res_params* params,
                         std::vector<ResolverStats>* stats,
                         int* wait_for_pending_req_timeout_count) {
        using android::net::IDnsResolver;
        std::vector<int32_t> params32;
        std::vector<int32_t> stats32;
        std::vector<int32_t> wait_for_pending_req_timeout_count32{0};
        auto rv = mDnsClient.resolvService()->getResolverInfo(
                TEST_NETID, servers, domains, tlsServers, &params32, &stats32,
                &wait_for_pending_req_timeout_count32);

        if (!rv.isOk() ||
            params32.size() != static_cast<size_t>(IDnsResolver::RESOLVER_PARAMS_COUNT)) {
            return false;
        }
        *params = res_params{
                .sample_validity = static_cast<uint16_t>(
                        params32[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY]),
                .success_threshold = static_cast<uint8_t>(
                        params32[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD]),
                .min_samples =
                        static_cast<uint8_t>(params32[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES]),
                .max_samples =
                        static_cast<uint8_t>(params32[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES]),
                .base_timeout_msec = params32[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC],
                .retry_count = params32[IDnsResolver::RESOLVER_PARAMS_RETRY_COUNT],
        };
        *wait_for_pending_req_timeout_count = wait_for_pending_req_timeout_count32[0];
        return ResolverStats::decodeAll(stats32, stats);
    }

    static std::string ToString(const hostent* he) {
        if (he == nullptr) return "<null>";
        char buffer[INET6_ADDRSTRLEN];
        if (!inet_ntop(he->h_addrtype, he->h_addr_list[0], buffer, sizeof(buffer))) {
            return "<invalid>";
        }
        return buffer;
    }

    static std::string ToString(const addrinfo* ai) {
        if (!ai)
            return "<null>";
        for (const auto* aip = ai ; aip != nullptr ; aip = aip->ai_next) {
            char host[NI_MAXHOST];
            int rv = getnameinfo(aip->ai_addr, aip->ai_addrlen, host, sizeof(host), nullptr, 0,
                    NI_NUMERICHOST);
            if (rv != 0)
                return gai_strerror(rv);
            return host;
        }
        return "<invalid>";
    }

    static std::string ToString(const ScopedAddrinfo& ai) { return ToString(ai.get()); }

    static std::vector<std::string> ToStrings(const addrinfo* ai) {
        std::vector<std::string> hosts;
        if (!ai) {
            hosts.push_back("<null>");
            return hosts;
        }
        for (const auto* aip = ai; aip != nullptr; aip = aip->ai_next) {
            char host[NI_MAXHOST];
            int rv = getnameinfo(aip->ai_addr, aip->ai_addrlen, host, sizeof(host), nullptr, 0,
                                 NI_NUMERICHOST);
            if (rv != 0) {
                hosts.clear();
                hosts.push_back(gai_strerror(rv));
                return hosts;
            } else {
                hosts.push_back(host);
            }
        }
        if (hosts.empty()) hosts.push_back("<invalid>");
        return hosts;
    }

    static std::vector<std::string> ToStrings(const ScopedAddrinfo& ai) {
        return ToStrings(ai.get());
    }

    size_t GetNumQueries(const test::DNSResponder& dns, const char* name) const {
        auto queries = dns.queries();
        size_t found = 0;
        for (const auto& p : queries) {
            if (p.first == name) {
                ++found;
            }
        }
        return found;
    }

    size_t GetNumQueriesForType(const test::DNSResponder& dns, ns_type type,
                                const char* name) const {
        auto queries = dns.queries();
        size_t found = 0;
        for (const auto& p : queries) {
            if (p.second == type && p.first == name) {
                ++found;
            }
        }
        return found;
    }

    bool WaitForPrefix64Detected(int netId, int timeoutMs) {
        constexpr int intervalMs = 2;
        const int limit = timeoutMs / intervalMs;
@@ -226,59 +121,6 @@ class ResolverTest : public ::testing::Test {
        return false;
    }

    void RunGetAddrInfoStressTest_Binder(unsigned num_hosts, unsigned num_threads,
            unsigned num_queries) {
        std::vector<std::string> domains = { "example.com" };
        std::vector<std::unique_ptr<test::DNSResponder>> dns;
        std::vector<std::string> servers;
        std::vector<DnsResponderClient::DnsResponderClient::Mapping> mappings;
        ASSERT_NO_FATAL_FAILURE(mDnsClient.SetupMappings(num_hosts, domains, &mappings));
        ASSERT_NO_FATAL_FAILURE(mDnsClient.SetupDNSServers(MAXNS, mappings, &dns, &servers));

        ASSERT_TRUE(mDnsClient.SetResolversForNetwork(servers, domains, kDefaultParams));

        auto t0 = std::chrono::steady_clock::now();
        std::vector<std::thread> threads(num_threads);
        for (std::thread& thread : threads) {
            thread = std::thread([&mappings, num_queries]() {
                for (unsigned i = 0 ; i < num_queries ; ++i) {
                    uint32_t ofs = arc4random_uniform(mappings.size());
                    auto& mapping = mappings[ofs];
                    addrinfo* result = nullptr;
                    int rv = getaddrinfo(mapping.host.c_str(), nullptr, nullptr, &result);
                    EXPECT_EQ(0, rv) << "error [" << rv << "] " << gai_strerror(rv);
                    if (rv == 0) {
                        std::string result_str = ToString(result);
                        EXPECT_TRUE(result_str == mapping.ip4 || result_str == mapping.ip6)
                            << "result='" << result_str << "', ip4='" << mapping.ip4
                            << "', ip6='" << mapping.ip6;
                    }
                    if (result) {
                        freeaddrinfo(result);
                        result = nullptr;
                    }
                }
            });
        }

        for (std::thread& thread : threads) {
            thread.join();
        }
        auto t1 = std::chrono::steady_clock::now();
        ALOGI("%u hosts, %u threads, %u queries, %Es", num_hosts, num_threads, num_queries,
                std::chrono::duration<double>(t1 - t0).count());

        std::vector<std::string> res_servers;
        std::vector<std::string> res_domains;
        std::vector<std::string> res_tls_servers;
        res_params res_params;
        std::vector<ResolverStats> res_stats;
        int wait_for_pending_req_timeout_count;
        ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_tls_servers, &res_params,
                                    &res_stats, &wait_for_pending_req_timeout_count));
        EXPECT_EQ(0, wait_for_pending_req_timeout_count);
    }

    void StartDns(test::DNSResponder& dns, const std::vector<DnsRecord>& records) {
        for (const auto& r : records) {
            dns.addMapping(r.host_name, r.type, r.addr);
@@ -526,7 +368,7 @@ TEST_F(ResolverTest, GetHostByName_Binder) {

    const hostent* result = gethostbyname(mapping.host.c_str());
    const size_t total_queries =
            std::accumulate(dns.begin(), dns.end(), 0, [this, &mapping](size_t total, auto& d) {
            std::accumulate(dns.begin(), dns.end(), 0, [&mapping](size_t total, auto& d) {
                return total + GetNumQueriesForType(*d, ns_type::ns_t_a, mapping.entry.c_str());
            });

@@ -543,8 +385,9 @@ TEST_F(ResolverTest, GetHostByName_Binder) {
    res_params res_params;
    std::vector<ResolverStats> res_stats;
    int wait_for_pending_req_timeout_count;
    ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_tls_servers, &res_params,
                                &res_stats, &wait_for_pending_req_timeout_count));
    ASSERT_TRUE(GetResolverInfo(mDnsClient.resolvService(), TEST_NETID, &res_servers, &res_domains,
                                &res_tls_servers, &res_params, &res_stats,
                                &wait_for_pending_req_timeout_count));
    EXPECT_EQ(servers.size(), res_servers.size());
    EXPECT_EQ(domains.size(), res_domains.size());
    EXPECT_EQ(0U, res_tls_servers.size());
@@ -714,8 +557,9 @@ TEST_F(ResolverTest, GetAddrInfoV4_deferred_resp) {
        res_params res_params;
        std::vector<ResolverStats> res_stats;
        int wait_for_pending_req_timeout_count;
        ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_tls_servers, &res_params,
                                    &res_stats, &wait_for_pending_req_timeout_count));
        ASSERT_TRUE(GetResolverInfo(mDnsClient.resolvService(), TEST_NETID, &res_servers,
                                    &res_domains, &res_tls_servers, &res_params, &res_stats,
                                    &wait_for_pending_req_timeout_count));
        EXPECT_EQ(0, wait_for_pending_req_timeout_count);
    });

@@ -982,25 +826,12 @@ TEST_F(ResolverTest, GetAddrInfoV6_concurrent) {
    res_params res_params;
    std::vector<ResolverStats> res_stats;
    int wait_for_pending_req_timeout_count;
    ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_tls_servers, &res_params,
                                &res_stats, &wait_for_pending_req_timeout_count));
    ASSERT_TRUE(GetResolverInfo(mDnsClient.resolvService(), TEST_NETID, &res_servers, &res_domains,
                                &res_tls_servers, &res_params, &res_stats,
                                &wait_for_pending_req_timeout_count));
    EXPECT_EQ(0, wait_for_pending_req_timeout_count);
}

TEST_F(ResolverTest, GetAddrInfoStressTest_Binder_100) {
    const unsigned num_hosts = 100;
    const unsigned num_threads = 100;
    const unsigned num_queries = 100;
    ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest_Binder(num_hosts, num_threads, num_queries));
}

TEST_F(ResolverTest, GetAddrInfoStressTest_Binder_100000) {
    const unsigned num_hosts = 100000;
    const unsigned num_threads = 100;
    const unsigned num_queries = 100;
    ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest_Binder(num_hosts, num_threads, num_queries));
}

TEST_F(ResolverTest, EmptySetup) {
    using android::net::IDnsResolver;
    std::vector<std::string> servers;
@@ -1012,8 +843,9 @@ TEST_F(ResolverTest, EmptySetup) {
    res_params res_params;
    std::vector<ResolverStats> res_stats;
    int wait_for_pending_req_timeout_count;
    ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_tls_servers, &res_params,
                                &res_stats, &wait_for_pending_req_timeout_count));
    ASSERT_TRUE(GetResolverInfo(mDnsClient.resolvService(), TEST_NETID, &res_servers, &res_domains,
                                &res_tls_servers, &res_params, &res_stats,
                                &wait_for_pending_req_timeout_count));
    EXPECT_EQ(0U, res_servers.size());
    EXPECT_EQ(0U, res_domains.size());
    EXPECT_EQ(0U, res_tls_servers.size());
@@ -1122,8 +954,9 @@ TEST_F(ResolverTest, MaxServerPrune_Binder) {
    res_params res_params;
    std::vector<ResolverStats> res_stats;
    int wait_for_pending_req_timeout_count;
    ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_tls_servers, &res_params,
                                &res_stats, &wait_for_pending_req_timeout_count));
    ASSERT_TRUE(GetResolverInfo(mDnsClient.resolvService(), TEST_NETID, &res_servers, &res_domains,
                                &res_tls_servers, &res_params, &res_stats,
                                &wait_for_pending_req_timeout_count));

    // Check the size of the stats and its contents.
    EXPECT_EQ(static_cast<size_t>(MAXNS), res_servers.size());
@@ -1171,8 +1004,9 @@ TEST_F(ResolverTest, ResolverStats) {
    res_params res_params;
    std::vector<ResolverStats> res_stats;
    int wait_for_pending_req_timeout_count;
    ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_tls_servers, &res_params,
                                &res_stats, &wait_for_pending_req_timeout_count));
    ASSERT_TRUE(GetResolverInfo(mDnsClient.resolvService(), TEST_NETID, &res_servers, &res_domains,
                                &res_tls_servers, &res_params, &res_stats,
                                &wait_for_pending_req_timeout_count));

    EXPECT_EQ(1, res_stats[0].timeouts);
    EXPECT_EQ(1, res_stats[1].errors);

tests/Android.bp

0 → 100644
+36 −0
Original line number Diff line number Diff line
cc_test {
    name: "resolv_stress_test",
    test_suites: ["device-tests"],
    test_config: "resolv_stress_test_config.xml",
    defaults: ["netd_defaults"],
    srcs: [
        "resolv_stress_test.cpp",
        "resolv_test_utils.cpp",
    ],
    include_dirs: [
        "system/netd/resolv",
        "system/netd/resolv/include",
        // TODO: stop including NetdConstants.h, copy ScopedAddrinfo out
        "system/netd/server",
    ],
    shared_libs: [
        "libbase",
        "libbinder",
        // TODO: remove it after making dns_responder use LOG(*) instead of ALOG*
        "liblog",
        "libnetd_client",
        "libutils",
    ],
    static_libs: [
        "libgmock",
        "libnetd_test_dnsresponder",
        "libnetdutils",
        "netd_aidl_interface-V2-cpp",
        "dnsresolver_aidl_interface-V2-cpp",
    ],
    compile_multilib: "both",
    sanitize: {
        address: true,
        recover: ["all"],
    },
}
+111 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#define LOG_TAG "resolv_stress_test"

#include <chrono>
#include <thread>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>

#include "ResolverStats.h"
#include "dns_responder/dns_responder_client.h"
#include "netd_resolv/params.h"  // MAX_NS
#include "resolv_test_utils.h"

using android::base::StringPrintf;
using android::net::ResolverStats;

class ResolverStressTest : public ::testing::Test {
  public:
    ResolverStressTest() { mDnsClient.SetUp(); }
    ~ResolverStressTest() { mDnsClient.TearDown(); }

  protected:
    void RunGetAddrInfoStressTest(unsigned num_hosts, unsigned num_threads,
                                         unsigned num_queries) {
        std::vector<std::string> domains = {"example.com"};
        std::vector<std::unique_ptr<test::DNSResponder>> dns;
        std::vector<std::string> servers;
        std::vector<DnsResponderClient::DnsResponderClient::Mapping> mappings;
        ASSERT_NO_FATAL_FAILURE(mDnsClient.SetupMappings(num_hosts, domains, &mappings));
        ASSERT_NO_FATAL_FAILURE(mDnsClient.SetupDNSServers(MAXNS, mappings, &dns, &servers));

        ASSERT_TRUE(mDnsClient.SetResolversForNetwork(servers, domains, kDefaultParams));

        auto t0 = std::chrono::steady_clock::now();
        std::vector<std::thread> threads(num_threads);
        for (std::thread& thread : threads) {
            thread = std::thread([&mappings, num_queries]() {
                for (unsigned i = 0; i < num_queries; ++i) {
                    uint32_t ofs = arc4random_uniform(mappings.size());
                    auto& mapping = mappings[ofs];
                    addrinfo* result = nullptr;
                    int rv = getaddrinfo(mapping.host.c_str(), nullptr, nullptr, &result);
                    EXPECT_EQ(0, rv) << "error [" << rv << "] " << gai_strerror(rv);
                    if (rv == 0) {
                        std::string result_str = ToString(result);
                        EXPECT_TRUE(result_str == mapping.ip4 || result_str == mapping.ip6)
                                << "result='" << result_str << "', ip4='" << mapping.ip4
                                << "', ip6='" << mapping.ip6;
                    }
                    if (result) {
                        freeaddrinfo(result);
                        result = nullptr;
                    }
                }
            });
        }

        for (std::thread& thread : threads) {
            thread.join();
        }
        auto t1 = std::chrono::steady_clock::now();
        LOG(INFO) << StringPrintf("%u hosts, %u threads, %u queries, %Es", num_hosts, num_threads,
                                  num_queries, std::chrono::duration<double>(t1 - t0).count());

        std::vector<std::string> res_servers;
        std::vector<std::string> res_domains;
        std::vector<std::string> res_tls_servers;
        res_params res_params;
        std::vector<ResolverStats> res_stats;
        int wait_for_pending_req_timeout_count;
        ASSERT_TRUE(GetResolverInfo(mDnsClient.resolvService(), TEST_NETID, &res_servers,
                                    &res_domains, &res_tls_servers, &res_params, &res_stats,
                                    &wait_for_pending_req_timeout_count));
        EXPECT_EQ(0, wait_for_pending_req_timeout_count);
    }

    DnsResponderClient mDnsClient;
};

TEST_F(ResolverStressTest, GetAddrInfoStressTest_100) {
    const unsigned num_hosts = 100;
    const unsigned num_threads = 100;
    const unsigned num_queries = 100;
    ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest(num_hosts, num_threads, num_queries));
}

TEST_F(ResolverStressTest, GetAddrInfoStressTest_100000) {
    const unsigned num_hosts = 100000;
    const unsigned num_threads = 100;
    const unsigned num_queries = 100;
    ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest(num_hosts, num_threads, num_queries));
}
 No newline at end of file
+37 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2019 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<configuration description="Config for resolv_stress_test.">
    <option name="test-suite-tag" value="apct" />
    <option name="test-suite-tag" value="apct-native" />
    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
        <option name="cleanup" value="true" />
        <option name="push" value="resolv_stress_test->/data/local/tmp/resolv_stress_test" />
    </target_preparer>

    <test class="com.android.tradefed.testtype.GTest" >
        <option name="native-test-device-path" value="/data/local/tmp" />
        <option name="module-name" value="resolv_stress_test" />
        <!--
            On 2018-12-12, GetAddrInfoStressTest_Binder_100 suddenly jumped
            from ~1xs to ~70s runtime in APCT continuous integration, causing
            resolv_integration_test to flake with the default 60s timeout.
            We're not sure what caused the regression, but it's not due to a change
            in the Android image and unlikely to affect users.
            Just bump the timeout to 120s for now.
        -->
        <option name="native-test-timeout" value="120000" />
    </test>
</configuration>
Loading