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