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 }