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
18 #define LOG_TAG "resolv_stress_test"
19
20 #include <chrono>
21 #include <thread>
22
23 #include <android-base/logging.h>
24 #include <android-base/stringprintf.h>
25 #include <gmock/gmock-matchers.h>
26 #include <gtest/gtest.h>
27
28 #include "ResolverStats.h"
29 #include "dns_responder/dns_responder_client_ndk.h"
30 #include "params.h" // MAX_NS
31 #include "resolv_test_utils.h"
32
33 using android::base::StringPrintf;
34 using android::net::ResolverStats;
35
36 class ResolverStressTest : public ::testing::Test {
37 public:
ResolverStressTest()38 ResolverStressTest() { mDnsClient.SetUp(); }
~ResolverStressTest()39 ~ResolverStressTest() { mDnsClient.TearDown(); }
40
41 protected:
RunGetAddrInfoStressTest(unsigned num_hosts,unsigned num_threads,unsigned num_queries)42 void RunGetAddrInfoStressTest(unsigned num_hosts, unsigned num_threads,
43 unsigned num_queries) {
44 std::vector<std::string> domains = {"example.com"};
45 std::vector<std::unique_ptr<test::DNSResponder>> dns;
46 std::vector<std::string> servers;
47 std::vector<DnsResponderClient::DnsResponderClient::Mapping> mappings;
48 ASSERT_NO_FATAL_FAILURE(mDnsClient.SetupMappings(num_hosts, domains, &mappings));
49 ASSERT_NO_FATAL_FAILURE(mDnsClient.SetupDNSServers(MAXNS, mappings, &dns, &servers));
50
51 ASSERT_TRUE(mDnsClient.SetResolversForNetwork(servers, domains, kDefaultParams));
52
53 auto t0 = std::chrono::steady_clock::now();
54 std::vector<std::thread> threads(num_threads);
55 for (std::thread& thread : threads) {
56 thread = std::thread([&mappings, num_queries]() {
57 for (unsigned i = 0; i < num_queries; ++i) {
58 uint32_t ofs = arc4random_uniform(mappings.size());
59 auto& mapping = mappings[ofs];
60 addrinfo* result = nullptr;
61 int rv = getaddrinfo(mapping.host.c_str(), nullptr, nullptr, &result);
62 EXPECT_EQ(0, rv) << "error [" << rv << "] " << gai_strerror(rv);
63 if (rv == 0) {
64 std::string result_str = ToString(result);
65 EXPECT_TRUE(result_str == mapping.ip4 || result_str == mapping.ip6)
66 << "result='" << result_str << "', ip4='" << mapping.ip4
67 << "', ip6='" << mapping.ip6;
68 }
69 if (result) {
70 freeaddrinfo(result);
71 result = nullptr;
72 }
73 }
74 });
75 }
76
77 for (std::thread& thread : threads) {
78 thread.join();
79 }
80 auto t1 = std::chrono::steady_clock::now();
81 LOG(INFO) << StringPrintf("%u hosts, %u threads, %u queries, %Es", num_hosts, num_threads,
82 num_queries, std::chrono::duration<double>(t1 - t0).count());
83
84 std::vector<std::string> res_servers;
85 std::vector<std::string> res_domains;
86 std::vector<std::string> res_tls_servers;
87 res_params res_params;
88 std::vector<ResolverStats> res_stats;
89 int wait_for_pending_req_timeout_count;
90 ASSERT_TRUE(DnsResponderClient::GetResolverInfo(
91 mDnsClient.resolvService(), TEST_NETID, &res_servers, &res_domains,
92 &res_tls_servers, &res_params, &res_stats, &wait_for_pending_req_timeout_count));
93 EXPECT_EQ(0, wait_for_pending_req_timeout_count);
94 }
95
96 DnsResponderClient mDnsClient;
97 };
98
TEST_F(ResolverStressTest,GetAddrInfoStressTest_100)99 TEST_F(ResolverStressTest, GetAddrInfoStressTest_100) {
100 const unsigned num_hosts = 100;
101 const unsigned num_threads = 100;
102 const unsigned num_queries = 100;
103 ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest(num_hosts, num_threads, num_queries));
104 }
105
TEST_F(ResolverStressTest,GetAddrInfoStressTest_100000)106 TEST_F(ResolverStressTest, GetAddrInfoStressTest_100000) {
107 const unsigned num_hosts = 100000;
108 const unsigned num_threads = 100;
109 const unsigned num_queries = 100;
110 ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest(num_hosts, num_threads, num_queries));
111 }