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:
38     ResolverStressTest() { mDnsClient.SetUp(); }
39     ~ResolverStressTest() { mDnsClient.TearDown(); }
40 
41   protected:
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 
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 
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 }