123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "net/dns/context_host_resolver.h"
- #include <memory>
- #include <utility>
- #include "base/bind.h"
- #include "base/containers/fixed_flat_map.h"
- #include "base/memory/raw_ptr.h"
- #include "base/run_loop.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/test/simple_test_tick_clock.h"
- #include "base/test/task_environment.h"
- #include "base/time/time.h"
- #include "net/base/features.h"
- #include "net/base/host_port_pair.h"
- #include "net/base/ip_address.h"
- #include "net/base/ip_endpoint.h"
- #include "net/base/mock_network_change_notifier.h"
- #include "net/base/net_errors.h"
- #include "net/base/network_isolation_key.h"
- #include "net/base/schemeful_site.h"
- #include "net/base/test_completion_callback.h"
- #include "net/dns/dns_config.h"
- #include "net/dns/dns_test_util.h"
- #include "net/dns/dns_util.h"
- #include "net/dns/host_cache.h"
- #include "net/dns/host_resolver.h"
- #include "net/dns/host_resolver_manager.h"
- #include "net/dns/mock_host_resolver.h"
- #include "net/dns/public/dns_over_https_config.h"
- #include "net/dns/public/dns_protocol.h"
- #include "net/dns/public/host_resolver_source.h"
- #include "net/dns/public/resolve_error_info.h"
- #include "net/dns/resolve_context.h"
- #include "net/log/net_log_with_source.h"
- #include "net/test/gtest_util.h"
- #include "net/test/test_with_task_environment.h"
- #include "net/url_request/url_request_context.h"
- #include "net/url_request/url_request_context_builder.h"
- #include "net/url_request/url_request_test_util.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "url/gurl.h"
- #include "url/scheme_host_port.h"
- #if BUILDFLAG(IS_ANDROID)
- #include "base/android/build_info.h"
- #include "net/android/network_change_notifier_factory_android.h"
- #endif // BUILDFLAG(IS_ANDROID)
- namespace net {
- namespace {
- const IPEndPoint kEndpoint(IPAddress(1, 2, 3, 4), 100);
- }
- class ContextHostResolverTest : public ::testing::Test,
- public WithTaskEnvironment {
- protected:
- // Use mock time to prevent the HostResolverManager's injected IPv6 probe
- // result from timing out.
- ContextHostResolverTest()
- : WithTaskEnvironment(
- base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- ~ContextHostResolverTest() override = default;
- void SetUp() override {
- manager_ = std::make_unique<HostResolverManager>(
- HostResolver::ManagerOptions(),
- nullptr /* system_dns_config_notifier */, nullptr /* net_log */);
- manager_->SetLastIPv6ProbeResultForTesting(true);
- }
- void SetMockDnsRules(MockDnsClientRuleList rules) {
- IPAddress dns_ip(192, 168, 1, 0);
- DnsConfig config;
- config.nameservers.emplace_back(dns_ip, dns_protocol::kDefaultPort);
- config.doh_config = *DnsOverHttpsConfig::FromString("https://example.com");
- EXPECT_TRUE(config.IsValid());
- auto dns_client =
- std::make_unique<MockDnsClient>(std::move(config), std::move(rules));
- dns_client->set_ignore_system_config_changes(true);
- dns_client_ = dns_client.get();
- manager_->SetDnsClientForTesting(std::move(dns_client));
- manager_->SetInsecureDnsClientEnabled(
- /*enabled=*/true,
- /*additional_dns_types_enabled=*/true);
- // Ensure DnsClient is fully usable.
- EXPECT_TRUE(dns_client_->CanUseInsecureDnsTransactions());
- EXPECT_FALSE(dns_client_->FallbackFromInsecureTransactionPreferred());
- EXPECT_TRUE(dns_client_->GetEffectiveConfig());
- scoped_refptr<HostResolverProc> proc = CreateCatchAllHostResolverProc();
- manager_->set_proc_params_for_test(ProcTaskParams(proc, 1u));
- }
- raw_ptr<MockDnsClient> dns_client_;
- std::unique_ptr<HostResolverManager> manager_;
- };
- TEST_F(ContextHostResolverTest, Resolve) {
- auto context = CreateTestURLRequestContextBuilder()->Build();
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", kEndpoint.address())),
- false /* delay */, context.get());
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */, context.get());
- SetMockDnsRules(std::move(rules));
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- EXPECT_THAT(callback.GetResult(rv), test::IsOk());
- EXPECT_THAT(request->GetResolveErrorInfo().error, test::IsError(net::OK));
- EXPECT_THAT(request->GetAddressResults()->endpoints(),
- testing::ElementsAre(kEndpoint));
- }
- TEST_F(ContextHostResolverTest, ResolveWithScheme) {
- auto context = CreateTestURLRequestContextBuilder()->Build();
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", kEndpoint.address())),
- false /* delay */, context.get());
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */, context.get());
- SetMockDnsRules(std::move(rules));
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(
- url::SchemeHostPort(url::kHttpsScheme, "example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- EXPECT_THAT(callback.GetResult(rv), test::IsOk());
- EXPECT_THAT(request->GetResolveErrorInfo().error, test::IsError(net::OK));
- EXPECT_THAT(request->GetAddressResults()->endpoints(),
- testing::ElementsAre(kEndpoint));
- }
- TEST_F(ContextHostResolverTest, ResolveWithSchemeAndIpLiteral) {
- auto context = CreateTestURLRequestContextBuilder()->Build();
- IPAddress expected_address;
- ASSERT_TRUE(expected_address.AssignFromIPLiteral("1234::5678"));
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(
- url::SchemeHostPort(url::kHttpsScheme, "[1234::5678]", 100),
- NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- EXPECT_THAT(callback.GetResult(rv), test::IsOk());
- EXPECT_THAT(request->GetResolveErrorInfo().error, test::IsError(net::OK));
- EXPECT_THAT(request->GetAddressResults()->endpoints(),
- testing::ElementsAre(IPEndPoint(expected_address, 100)));
- }
- // Test that destroying a request silently cancels that request.
- TEST_F(ContextHostResolverTest, DestroyRequest) {
- // Set up delayed results for "example.com".
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", IPAddress(1, 2, 3, 4))),
- true /* delay */);
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- SetMockDnsRules(std::move(rules));
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(),
- std::make_unique<ResolveContext>(nullptr /* url_request_context */,
- false /* enable_caching */));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- // Cancel |request| before allowing delayed result to complete.
- request = nullptr;
- dns_client_->CompleteDelayedTransactions();
- // Ensure |request| never completes.
- base::RunLoop().RunUntilIdle();
- EXPECT_THAT(rv, test::IsError(ERR_IO_PENDING));
- EXPECT_FALSE(callback.have_result());
- }
- TEST_F(ContextHostResolverTest, DohProbeRequest) {
- // Set empty MockDnsClient rules to ensure DnsClient is mocked out.
- MockDnsClientRuleList rules;
- SetMockDnsRules(std::move(rules));
- auto context = CreateTestURLRequestContextBuilder()->Build();
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), true /* enable caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ProbeRequest> request =
- resolver->CreateDohProbeRequest();
- ASSERT_FALSE(dns_client_->factory()->doh_probes_running());
- EXPECT_THAT(request->Start(), test::IsError(ERR_IO_PENDING));
- EXPECT_TRUE(dns_client_->factory()->doh_probes_running());
- request.reset();
- EXPECT_FALSE(dns_client_->factory()->doh_probes_running());
- }
- TEST_F(ContextHostResolverTest, DohProbesFromSeparateContexts) {
- // Set empty MockDnsClient rules to ensure DnsClient is mocked out.
- MockDnsClientRuleList rules;
- SetMockDnsRules(std::move(rules));
- auto resolve_context1 = std::make_unique<ResolveContext>(
- nullptr /* url_request_context */, false /* enable_caching */);
- auto resolver1 = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context1));
- std::unique_ptr<HostResolver::ProbeRequest> request1 =
- resolver1->CreateDohProbeRequest();
- auto resolve_context2 = std::make_unique<ResolveContext>(
- nullptr /* url_request_context */, false /* enable_caching */);
- auto resolver2 = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context2));
- std::unique_ptr<HostResolver::ProbeRequest> request2 =
- resolver2->CreateDohProbeRequest();
- EXPECT_FALSE(dns_client_->factory()->doh_probes_running());
- EXPECT_THAT(request1->Start(), test::IsError(ERR_IO_PENDING));
- EXPECT_THAT(request2->Start(), test::IsError(ERR_IO_PENDING));
- EXPECT_TRUE(dns_client_->factory()->doh_probes_running());
- request1.reset();
- EXPECT_TRUE(dns_client_->factory()->doh_probes_running());
- request2.reset();
- EXPECT_FALSE(dns_client_->factory()->doh_probes_running());
- }
- // Test that cancelling a resolver cancels its (and only its) requests.
- TEST_F(ContextHostResolverTest, DestroyResolver) {
- // Set up delayed results for "example.com" and "google.com".
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", IPAddress(2, 3, 4, 5))),
- true /* delay */);
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- rules.emplace_back("google.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "google.com", kEndpoint.address())),
- true /* delay */);
- rules.emplace_back(
- "google.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- SetMockDnsRules(std::move(rules));
- auto resolver1 = std::make_unique<ContextHostResolver>(
- manager_.get(),
- std::make_unique<ResolveContext>(nullptr /* url_request_context */,
- false /* enable_caching */));
- std::unique_ptr<HostResolver::ResolveHostRequest> request1 =
- resolver1->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- auto resolver2 = std::make_unique<ContextHostResolver>(
- manager_.get(),
- std::make_unique<ResolveContext>(nullptr /* url_request_context */,
- false /* enable_caching */));
- std::unique_ptr<HostResolver::ResolveHostRequest> request2 =
- resolver2->CreateRequest(HostPortPair("google.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- TestCompletionCallback callback1;
- int rv1 = request1->Start(callback1.callback());
- TestCompletionCallback callback2;
- int rv2 = request2->Start(callback2.callback());
- EXPECT_EQ(2u, manager_->num_jobs_for_testing());
- // Cancel |resolver1| before allowing delayed requests to complete.
- resolver1 = nullptr;
- dns_client_->CompleteDelayedTransactions();
- EXPECT_THAT(callback2.GetResult(rv2), test::IsOk());
- EXPECT_THAT(request2->GetAddressResults()->endpoints(),
- testing::ElementsAre(kEndpoint));
- // Ensure |request1| never completes.
- base::RunLoop().RunUntilIdle();
- EXPECT_THAT(rv1, test::IsError(ERR_IO_PENDING));
- EXPECT_FALSE(callback1.have_result());
- }
- TEST_F(ContextHostResolverTest, DestroyResolver_CompletedRequests) {
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", kEndpoint.address())),
- false /* delay */);
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- SetMockDnsRules(std::move(rules));
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(),
- std::make_unique<ResolveContext>(nullptr /* url_request_context */,
- false /* enable_caching */));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- // Complete request and then destroy the resolver.
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- ASSERT_THAT(callback.GetResult(rv), test::IsOk());
- resolver = nullptr;
- // Expect completed results are still available.
- EXPECT_THAT(request->GetResolveErrorInfo().error, test::IsError(net::OK));
- EXPECT_THAT(request->GetAddressResults()->endpoints(),
- testing::ElementsAre(kEndpoint));
- }
- // Test a request created before resolver destruction but not yet started.
- TEST_F(ContextHostResolverTest, DestroyResolver_DelayedStartRequest) {
- // Set up delayed result for "example.com".
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", IPAddress(2, 3, 4, 5))),
- true /* delay */);
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(),
- std::make_unique<ResolveContext>(nullptr /* url_request_context */,
- false /* enable_caching */));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- resolver = nullptr;
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- EXPECT_THAT(callback.GetResult(rv), test::IsError(ERR_NAME_NOT_RESOLVED));
- EXPECT_THAT(request->GetResolveErrorInfo().error,
- test::IsError(ERR_CONTEXT_SHUT_DOWN));
- EXPECT_FALSE(request->GetAddressResults());
- }
- TEST_F(ContextHostResolverTest, DestroyResolver_DelayedStartDohProbeRequest) {
- // Set empty MockDnsClient rules to ensure DnsClient is mocked out.
- MockDnsClientRuleList rules;
- SetMockDnsRules(std::move(rules));
- auto context = CreateTestURLRequestContextBuilder()->Build();
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ProbeRequest> request =
- resolver->CreateDohProbeRequest();
- resolver = nullptr;
- EXPECT_THAT(request->Start(), test::IsError(ERR_CONTEXT_SHUT_DOWN));
- EXPECT_FALSE(dns_client_->factory()->doh_probes_running());
- }
- TEST_F(ContextHostResolverTest, OnShutdown_PendingRequest) {
- // Set up delayed result for "example.com".
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", IPAddress(2, 3, 4, 5))),
- true /* delay */);
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- SetMockDnsRules(std::move(rules));
- auto context = CreateTestURLRequestContextBuilder()->Build();
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- // Trigger shutdown before allowing request to complete.
- resolver->OnShutdown();
- dns_client_->CompleteDelayedTransactions();
- // Ensure request never completes.
- base::RunLoop().RunUntilIdle();
- EXPECT_THAT(rv, test::IsError(ERR_IO_PENDING));
- EXPECT_FALSE(callback.have_result());
- }
- TEST_F(ContextHostResolverTest, OnShutdown_CompletedRequests) {
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", kEndpoint.address())),
- false /* delay */);
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- SetMockDnsRules(std::move(rules));
- auto context = CreateTestURLRequestContextBuilder()->Build();
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- // Complete request and then shutdown the resolver.
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- ASSERT_THAT(callback.GetResult(rv), test::IsOk());
- resolver->OnShutdown();
- // Expect completed results are still available.
- EXPECT_THAT(request->GetResolveErrorInfo().error, test::IsError(net::OK));
- EXPECT_THAT(request->GetAddressResults()->endpoints(),
- testing::ElementsAre(kEndpoint));
- }
- TEST_F(ContextHostResolverTest, OnShutdown_SubsequentRequests) {
- auto context = CreateTestURLRequestContextBuilder()->Build();
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- resolver->OnShutdown();
- std::unique_ptr<HostResolver::ResolveHostRequest> request1 =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- std::unique_ptr<HostResolver::ResolveHostRequest> request2 =
- resolver->CreateRequest(HostPortPair("127.0.0.1", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- TestCompletionCallback callback1;
- int rv1 = request1->Start(callback1.callback());
- TestCompletionCallback callback2;
- int rv2 = request2->Start(callback2.callback());
- EXPECT_THAT(callback1.GetResult(rv1), test::IsError(ERR_CONTEXT_SHUT_DOWN));
- EXPECT_THAT(request1->GetResolveErrorInfo().error,
- test::IsError(ERR_CONTEXT_SHUT_DOWN));
- EXPECT_FALSE(request1->GetAddressResults());
- EXPECT_THAT(callback2.GetResult(rv2), test::IsError(ERR_CONTEXT_SHUT_DOWN));
- EXPECT_THAT(request2->GetResolveErrorInfo().error,
- test::IsError(ERR_CONTEXT_SHUT_DOWN));
- EXPECT_FALSE(request2->GetAddressResults());
- }
- TEST_F(ContextHostResolverTest, OnShutdown_SubsequentDohProbeRequest) {
- // Set empty MockDnsClient rules to ensure DnsClient is mocked out.
- MockDnsClientRuleList rules;
- SetMockDnsRules(std::move(rules));
- auto context = CreateTestURLRequestContextBuilder()->Build();
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- resolver->OnShutdown();
- std::unique_ptr<HostResolver::ProbeRequest> request =
- resolver->CreateDohProbeRequest();
- EXPECT_THAT(request->Start(), test::IsError(ERR_CONTEXT_SHUT_DOWN));
- EXPECT_FALSE(dns_client_->factory()->doh_probes_running());
- }
- // Test a request created before shutdown but not yet started.
- TEST_F(ContextHostResolverTest, OnShutdown_DelayedStartRequest) {
- // Set up delayed result for "example.com".
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", IPAddress(2, 3, 4, 5))),
- true /* delay */);
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- auto context = CreateTestURLRequestContextBuilder()->Build();
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- resolver->OnShutdown();
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- EXPECT_THAT(callback.GetResult(rv), test::IsError(ERR_NAME_NOT_RESOLVED));
- EXPECT_THAT(request->GetResolveErrorInfo().error,
- test::IsError(ERR_CONTEXT_SHUT_DOWN));
- EXPECT_FALSE(request->GetAddressResults());
- }
- TEST_F(ContextHostResolverTest, OnShutdown_DelayedStartDohProbeRequest) {
- // Set empty MockDnsClient rules to ensure DnsClient is mocked out.
- MockDnsClientRuleList rules;
- SetMockDnsRules(std::move(rules));
- auto context = CreateTestURLRequestContextBuilder()->Build();
- auto resolve_context = std::make_unique<ResolveContext>(
- context.get(), false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ProbeRequest> request =
- resolver->CreateDohProbeRequest();
- resolver->OnShutdown();
- EXPECT_THAT(request->Start(), test::IsError(ERR_CONTEXT_SHUT_DOWN));
- EXPECT_FALSE(dns_client_->factory()->doh_probes_running());
- }
- TEST_F(ContextHostResolverTest, ResolveFromCache) {
- auto resolve_context = std::make_unique<ResolveContext>(
- nullptr /* url_request_context */, true /* enable_caching */);
- HostCache* host_cache = resolve_context->host_cache();
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- // Create the cache entry after creating the ContextHostResolver, as
- // registering into the HostResolverManager initializes and invalidates the
- // cache.
- base::SimpleTestTickClock clock;
- clock.Advance(base::Days(62)); // Arbitrary non-zero time.
- std::vector<IPEndPoint> expected({kEndpoint});
- host_cache->Set(
- HostCache::Key("example.com", DnsQueryType::UNSPECIFIED,
- 0 /* host_resolver_flags */, HostResolverSource::ANY,
- NetworkIsolationKey()),
- HostCache::Entry(OK, expected,
- /*aliases=*/std::set<std::string>({"example.com"}),
- HostCache::Entry::SOURCE_DNS, base::Days(1)),
- clock.NowTicks(), base::Days(1));
- resolver->SetTickClockForTesting(&clock);
- // Allow stale results and then confirm the result is not stale in order to
- // make the issue more clear if something is invalidating the cache.
- HostResolver::ResolveHostParameters parameters;
- parameters.source = HostResolverSource::LOCAL_ONLY;
- parameters.cache_usage =
- HostResolver::ResolveHostParameters::CacheUsage::STALE_ALLOWED;
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- parameters);
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- EXPECT_THAT(callback.GetResult(rv), test::IsOk());
- EXPECT_THAT(request->GetResolveErrorInfo().error, test::IsError(net::OK));
- EXPECT_THAT(request->GetAddressResults()->endpoints(),
- testing::ElementsAre(kEndpoint));
- ASSERT_TRUE(request->GetStaleInfo());
- EXPECT_EQ(0, request->GetStaleInfo().value().network_changes);
- EXPECT_FALSE(request->GetStaleInfo().value().is_stale());
- }
- TEST_F(ContextHostResolverTest, ResultsAddedToCache) {
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", kEndpoint.address())),
- false /* delay */);
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- SetMockDnsRules(std::move(rules));
- auto resolve_context = std::make_unique<ResolveContext>(
- nullptr /* url_request_context */, true /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> caching_request =
- resolver->CreateRequest(HostPortPair("example.com", 103),
- NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- TestCompletionCallback caching_callback;
- int rv = caching_request->Start(caching_callback.callback());
- EXPECT_THAT(caching_callback.GetResult(rv), test::IsOk());
- HostResolver::ResolveHostParameters local_resolve_parameters;
- local_resolve_parameters.source = HostResolverSource::LOCAL_ONLY;
- std::unique_ptr<HostResolver::ResolveHostRequest> cached_request =
- resolver->CreateRequest(HostPortPair("example.com", 100),
- NetworkIsolationKey(), NetLogWithSource(),
- local_resolve_parameters);
- TestCompletionCallback callback;
- rv = cached_request->Start(callback.callback());
- EXPECT_THAT(callback.GetResult(rv), test::IsOk());
- EXPECT_THAT(cached_request->GetResolveErrorInfo().error,
- test::IsError(net::OK));
- EXPECT_THAT(cached_request->GetAddressResults()->endpoints(),
- testing::ElementsAre(kEndpoint));
- }
- // Do a lookup with a NetworkIsolationKey, and then make sure the entry added to
- // the cache is in fact using that NetworkIsolationKey.
- TEST_F(ContextHostResolverTest, ResultsAddedToCacheWithNetworkIsolationKey) {
- const SchemefulSite kSite(GURL("https://origin.test/"));
- const NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- features::kSplitHostCacheByNetworkIsolationKey);
- MockDnsClientRuleList rules;
- rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
- MockDnsClientRule::Result(BuildTestDnsAddressResponse(
- "example.com", kEndpoint.address())),
- false /* delay */);
- rules.emplace_back(
- "example.com", dns_protocol::kTypeAAAA, false /* secure */,
- MockDnsClientRule::Result(MockDnsClientRule::ResultType::kEmpty),
- false /* delay */);
- SetMockDnsRules(std::move(rules));
- auto resolve_context = std::make_unique<ResolveContext>(
- nullptr /* url_request_context */, true /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> caching_request =
- resolver->CreateRequest(HostPortPair("example.com", 103),
- kNetworkIsolationKey, NetLogWithSource(),
- absl::nullopt);
- TestCompletionCallback caching_callback;
- int rv = caching_request->Start(caching_callback.callback());
- EXPECT_THAT(caching_callback.GetResult(rv), test::IsOk());
- HostCache::Key cache_key("example.com", DnsQueryType::UNSPECIFIED,
- 0 /* host_resolver_flags */, HostResolverSource::ANY,
- kNetworkIsolationKey);
- EXPECT_TRUE(
- resolver->GetHostCache()->Lookup(cache_key, base::TimeTicks::Now()));
- HostCache::Key cache_key_with_empty_nik(
- "example.com", DnsQueryType::UNSPECIFIED, 0 /* host_resolver_flags */,
- HostResolverSource::ANY, NetworkIsolationKey());
- EXPECT_FALSE(resolver->GetHostCache()->Lookup(cache_key_with_empty_nik,
- base::TimeTicks::Now()));
- }
- // Test that the underlying HostCache can receive invalidations from the manager
- // and that it safely does not receive invalidations after the resolver (and the
- // HostCache) is destroyed.
- TEST_F(ContextHostResolverTest, HostCacheInvalidation) {
- // Set empty MockDnsClient rules to ensure DnsClient is mocked out.
- MockDnsClientRuleList rules;
- SetMockDnsRules(std::move(rules));
- auto resolve_context = std::make_unique<ResolveContext>(
- nullptr /* url_request_context */, true /* enable_caching */);
- ResolveContext* resolve_context_ptr = resolve_context.get();
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- // No invalidations yet (other than the initialization "invalidation" from
- // registering the context).
- ASSERT_EQ(resolve_context_ptr->current_session_for_testing(),
- dns_client_->GetCurrentSession());
- ASSERT_EQ(resolve_context_ptr->host_cache()->network_changes(), 1);
- manager_->InvalidateCachesForTesting();
- EXPECT_EQ(resolve_context_ptr->current_session_for_testing(),
- dns_client_->GetCurrentSession());
- EXPECT_EQ(resolve_context_ptr->host_cache()->network_changes(), 2);
- // Expect manager to be able to safely do invalidations after an individual
- // ContextHostResolver has been destroyed (and deregisters its ResolveContext)
- resolver = nullptr;
- manager_->InvalidateCachesForTesting();
- }
- class NetworkBoundResolveContext : public ResolveContext {
- public:
- NetworkBoundResolveContext(URLRequestContext* url_request_context,
- bool enable_caching,
- handles::NetworkHandle target_network)
- : ResolveContext(url_request_context, enable_caching),
- target_network_(target_network) {}
- handles::NetworkHandle GetTargetNetwork() const override {
- return target_network_;
- }
- private:
- const handles::NetworkHandle target_network_;
- };
- // A mock HostResolverProc which returns different IP addresses based on the
- // `network` parameter received.
- class NetworkAwareHostResolverProc : public HostResolverProc {
- public:
- NetworkAwareHostResolverProc() : HostResolverProc(nullptr) {}
- NetworkAwareHostResolverProc(const NetworkAwareHostResolverProc&) = delete;
- NetworkAwareHostResolverProc& operator=(const NetworkAwareHostResolverProc&) =
- delete;
- int Resolve(const std::string& host,
- AddressFamily address_family,
- HostResolverFlags host_resolver_flags,
- AddressList* addrlist,
- int* os_error,
- handles::NetworkHandle network) override {
- // Presume failure
- *os_error = 1;
- const auto* iter = kResults.find(network);
- if (iter == kResults.end())
- return ERR_NETWORK_CHANGED;
- *os_error = 0;
- *addrlist = AddressList();
- addrlist->push_back(ToIPEndPoint(iter->second));
- return OK;
- }
- int Resolve(const std::string& host,
- AddressFamily address_family,
- HostResolverFlags host_resolver_flags,
- AddressList* addrlist,
- int* os_error) override {
- return Resolve(host, address_family, host_resolver_flags, addrlist,
- os_error, handles::kInvalidNetworkHandle);
- }
- struct IPv4 {
- uint8_t a;
- uint8_t b;
- uint8_t c;
- uint8_t d;
- };
- static constexpr int kPort = 100;
- static constexpr auto kResults =
- base::MakeFixedFlatMap<handles::NetworkHandle, IPv4>(
- {{1, IPv4{1, 2, 3, 4}}, {2, IPv4{8, 8, 8, 8}}});
- static IPEndPoint ToIPEndPoint(const IPv4& ipv4) {
- return IPEndPoint(IPAddress(ipv4.a, ipv4.b, ipv4.c, ipv4.d), kPort);
- }
- protected:
- ~NetworkAwareHostResolverProc() override = default;
- };
- TEST_F(ContextHostResolverTest, ExistingNetworkBoundLookup) {
- #if BUILDFLAG(IS_ANDROID)
- auto scoped_mock_network_change_notifier =
- std::make_unique<test::ScopedMockNetworkChangeNotifier>();
- scoped_mock_network_change_notifier->mock_network_change_notifier()
- ->ForceNetworkHandlesSupported();
- const url::SchemeHostPort host(url::kHttpsScheme, "example.com",
- NetworkAwareHostResolverProc::kPort);
- auto resolver_proc = base::MakeRefCounted<NetworkAwareHostResolverProc>();
- ScopedDefaultHostResolverProc scoped_default_host_resolver;
- scoped_default_host_resolver.Init(resolver_proc.get());
- // ResolveContexts bound to a specific network should end up in a call to
- // Resolve with `network` == context.GetTargetNetwork(). Confirm that we do
- // indeed receive the IP address associated with that network.
- for (const auto& iter : NetworkAwareHostResolverProc::kResults) {
- auto network = iter.first;
- auto expected_ipv4 = iter.second;
- auto resolve_context = std::make_unique<NetworkBoundResolveContext>(
- nullptr /* url_request_context */, false /* enable_caching */, network);
- // DNS lookups originated from network-bound ResolveContexts must be
- // resolved through a HostResolverManager bound to the same network.
- auto manager = HostResolverManager::CreateNetworkBoundHostResolverManager(
- HostResolver::ManagerOptions(), network, nullptr /* net_log */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(host, NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- EXPECT_THAT(callback.GetResult(rv), test::IsOk());
- EXPECT_THAT(request->GetResolveErrorInfo().error, test::IsError(net::OK));
- ASSERT_EQ(1u, request->GetAddressResults()->endpoints().size());
- EXPECT_THAT(request->GetAddressResults()->endpoints(),
- testing::ElementsAre(
- NetworkAwareHostResolverProc::ToIPEndPoint(expected_ipv4)));
- }
- #else // !BUILDFLAG(IS_ANDROID)
- GTEST_SKIP()
- << "Network-bound HostResolverManager are supported only on Android.";
- #endif // BUILDFLAG(IS_ANDROID)
- }
- TEST_F(ContextHostResolverTest, NotExistingNetworkBoundLookup) {
- const url::SchemeHostPort host(url::kHttpsScheme, "example.com",
- NetworkAwareHostResolverProc::kPort);
- auto resolver_proc = base::MakeRefCounted<NetworkAwareHostResolverProc>();
- ScopedDefaultHostResolverProc scoped_default_host_resolver;
- scoped_default_host_resolver.Init(resolver_proc.get());
- // Non-bound ResolveContexts should end up with a call to Resolve with
- // `network` == kInvalidNetwork, which NetworkAwareHostResolverProc fails to
- // resolve.
- auto resolve_context = std::make_unique<ResolveContext>(
- nullptr /* url_request_context */, false /* enable_caching */);
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- std::unique_ptr<HostResolver::ResolveHostRequest> request =
- resolver->CreateRequest(host, NetworkIsolationKey(), NetLogWithSource(),
- absl::nullopt);
- TestCompletionCallback callback;
- int rv = request->Start(callback.callback());
- EXPECT_THAT(callback.GetResult(rv),
- test::IsError(net::ERR_NAME_NOT_RESOLVED));
- EXPECT_THAT(request->GetResolveErrorInfo().error,
- test::IsError(net::ERR_NETWORK_CHANGED));
- }
- // Test that the underlying HostCache does not receive invalidations when its
- // ResolveContext/HostResolverManager is bound to a network.
- TEST_F(ContextHostResolverTest, NetworkBoundResolverCacheInvalidation) {
- #if BUILDFLAG(IS_ANDROID)
- auto scoped_mock_network_change_notifier =
- std::make_unique<test::ScopedMockNetworkChangeNotifier>();
- test::MockNetworkChangeNotifier* mock_ncn =
- scoped_mock_network_change_notifier->mock_network_change_notifier();
- mock_ncn->ForceNetworkHandlesSupported();
- // The actual network handle doesn't really matter, this test just wants to
- // check that all the pieces are in place and configured correctly.
- constexpr handles::NetworkHandle network = 2;
- manager_ = HostResolverManager::CreateNetworkBoundHostResolverManager(
- HostResolver::ManagerOptions(), network, nullptr /* net_log */);
- manager_->SetLastIPv6ProbeResultForTesting(true);
- // Set empty MockDnsClient rules to ensure DnsClient is mocked out.
- MockDnsClientRuleList rules;
- SetMockDnsRules(std::move(rules));
- auto resolve_context = std::make_unique<NetworkBoundResolveContext>(
- nullptr /* url_request_context */, true /* enable_caching */, network);
- ResolveContext* resolve_context_ptr = resolve_context.get();
- auto resolver = std::make_unique<ContextHostResolver>(
- manager_.get(), std::move(resolve_context));
- // Network events should not trigger cache invalidations
- auto network_changes_before_events =
- resolve_context_ptr->host_cache()->network_changes();
- NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
- NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
- NetworkChangeNotifier::CONNECTION_NONE);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(network_changes_before_events,
- resolve_context_ptr->host_cache()->network_changes());
- #else // !BUILDFLAG(IS_ANDROID)
- GTEST_SKIP()
- << "Network-bound HostResolverManagers are supported only on Android";
- #endif // BUILDFLAG(IS_ANDROID)
- }
- } // namespace net
|