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 <gmock/gmock-matchers.h>
25 #include <gtest/gtest.h>
26 #include <netdutils/NetNativeTestBase.h>
27 
28 #include "dns_responder/dns_responder_client_ndk.h"
29 #include "resolv_test_utils.h"
30 
31 class ResolverStressTest : public NetNativeTestBase {
32   public:
ResolverStressTest()33     ResolverStressTest() { mDnsClient.SetUp(); }
~ResolverStressTest()34     ~ResolverStressTest() { mDnsClient.TearDown(); }
35 
36   protected:
RunGetAddrInfoStressTest(unsigned num_hosts,unsigned num_threads,unsigned num_queries)37     void RunGetAddrInfoStressTest(unsigned num_hosts, unsigned num_threads, unsigned num_queries) {
38         std::vector<std::string> domains = {"example.com"};
39         std::vector<std::unique_ptr<test::DNSResponder>> dns;
40         std::vector<std::string> servers;
41         std::vector<DnsResponderClient::DnsResponderClient::Mapping> mappings;
42         ASSERT_NO_FATAL_FAILURE(mDnsClient.SetupMappings(num_hosts, domains, &mappings));
43         ASSERT_NO_FATAL_FAILURE(mDnsClient.SetupDNSServers(MAXNS, mappings, &dns, &servers));
44 
45         ASSERT_TRUE(mDnsClient.SetResolversForNetwork(servers));
46 
47         auto t0 = std::chrono::steady_clock::now();
48         std::vector<std::thread> threads(num_threads);
49         for (std::thread& thread : threads) {
50             thread = std::thread([&mappings, num_queries]() {
51                 for (unsigned i = 0; i < num_queries; ++i) {
52                     uint32_t ofs = arc4random_uniform(mappings.size());
53                     auto& mapping = mappings[ofs];
54                     addrinfo* result = nullptr;
55                     int rv = getaddrinfo(mapping.host.c_str(), nullptr, nullptr, &result);
56                     EXPECT_EQ(0, rv) << "error [" << rv << "] " << gai_strerror(rv);
57                     if (rv == 0) {
58                         std::string result_str = ToString(result);
59                         EXPECT_TRUE(result_str == mapping.ip4 || result_str == mapping.ip6)
60                                 << "result='" << result_str << "', ip4='" << mapping.ip4
61                                 << "', ip6='" << mapping.ip6;
62                     }
63                     if (result) {
64                         freeaddrinfo(result);
65                         result = nullptr;
66                     }
67                 }
68             });
69         }
70 
71         for (std::thread& thread : threads) {
72             thread.join();
73         }
74         auto t1 = std::chrono::steady_clock::now();
75         LOG(INFO) << fmt::format("{} hosts, {} threads, {} queries, {:E}s", num_hosts, num_threads,
76                                  num_queries, std::chrono::duration<double>(t1 - t0).count());
77 
78         const auto resolvInfo = mDnsClient.getResolverInfo();
79         ASSERT_RESULT_OK(resolvInfo);
80         EXPECT_EQ(0, resolvInfo.value().waitForPendingReqTimeoutCount);
81     }
82 
83     DnsResponderClient mDnsClient;
84 };
85 
TEST_F(ResolverStressTest,GetAddrInfoStressTest_100)86 TEST_F(ResolverStressTest, GetAddrInfoStressTest_100) {
87     const unsigned num_hosts = 100;
88     const unsigned num_threads = 100;
89     const unsigned num_queries = 100;
90     ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest(num_hosts, num_threads, num_queries));
91 }
92 
TEST_F(ResolverStressTest,GetAddrInfoStressTest_100000)93 TEST_F(ResolverStressTest, GetAddrInfoStressTest_100000) {
94     const unsigned num_hosts = 100000;
95     const unsigned num_threads = 100;
96     const unsigned num_queries = 100;
97     ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest(num_hosts, num_threads, num_queries));
98 }
99