1 // Copyright 2011 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_DNS_MOCK_HOST_RESOLVER_H_ 6 #define NET_DNS_MOCK_HOST_RESOLVER_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <list> 12 #include <map> 13 #include <memory> 14 #include <optional> 15 #include <set> 16 #include <string> 17 #include <string_view> 18 #include <vector> 19 20 #include "base/memory/raw_ptr.h" 21 #include "base/memory/weak_ptr.h" 22 #include "base/synchronization/lock.h" 23 #include "base/synchronization/waitable_event.h" 24 #include "base/thread_annotations.h" 25 #include "base/threading/thread_checker.h" 26 #include "net/base/address_family.h" 27 #include "net/base/address_list.h" 28 #include "net/base/completion_once_callback.h" 29 #include "net/base/host_port_pair.h" 30 #include "net/base/net_errors.h" 31 #include "net/base/network_anonymization_key.h" 32 #include "net/dns/host_resolver.h" 33 #include "net/dns/host_resolver_proc.h" 34 #include "net/dns/public/dns_query_type.h" 35 #include "net/dns/public/host_resolver_results.h" 36 #include "net/dns/public/host_resolver_source.h" 37 #include "net/dns/public/mdns_listener_update_type.h" 38 #include "net/dns/public/secure_dns_policy.h" 39 #include "net/log/net_log_with_source.h" 40 #include "third_party/abseil-cpp/absl/types/variant.h" 41 #include "url/scheme_host_port.h" 42 43 namespace base { 44 class TickClock; 45 } // namespace base 46 47 namespace net { 48 49 class HostCache; 50 class IPEndPoint; 51 class URLRequestContext; 52 53 // Fills `ip_endpoints` with a socket address for `host_list` which should be a 54 // comma-separated list of IPv4 or IPv6 literal(s) without enclosing brackets. 55 int ParseAddressList(std::string_view host_list, 56 std::vector<net::IPEndPoint>* ip_endpoints); 57 58 // In most cases, it is important that unit tests avoid relying on making actual 59 // DNS queries since the resulting tests can be flaky, especially if the network 60 // is unreliable for some reason. To simplify writing tests that avoid making 61 // actual DNS queries, pass a MockHostResolver as the HostResolver dependency. 62 // The socket addresses returned can be configured using the 63 // MockHostResolverBase::RuleResolver: 64 // 65 // host_resolver->rules()->AddRule("foo.com", "1.2.3.4"); 66 // host_resolver->rules()->AddRule("bar.com", "2.3.4.5"); 67 // 68 // The above rules define a static mapping from hostnames to IP address 69 // literals. The first parameter to AddRule specifies a host pattern to match 70 // against, and the second parameter indicates what IP address should be used to 71 // replace the given hostname. So, the following is also supported: 72 // 73 // host_mapper->AddRule("*.com", "127.0.0.1"); 74 // 75 // For more advanced matching, the first parameter may be replaced with a 76 // MockHostResolverBase::RuleResolver::RuleKey. For more advanced responses, the 77 // second parameter may be replaced with a 78 // MockHostResolverBase::RuleResolver::RuleResultOrError. 79 // 80 // MockHostResolvers may optionally be created with a default result: 81 // 82 // MockHostResolver(ERR_NAME_NOT_RESOLVED); 83 // MockHostResolver(AddressList(ip_endpoint)); 84 // MockHostResolver(MockHostResolverBase::RuleResolver::GetLocalhostResult()); 85 // 86 // If no default result is given, every resolve request must match a configured 87 // rule, otherwise DCHECKs will fire. 88 89 // Base class shared by MockHostResolver and MockCachingHostResolver. 90 class MockHostResolverBase : public HostResolver { 91 private: 92 class RequestBase; 93 class RequestImpl; 94 class ServiceEndpointRequestImpl; 95 class ProbeRequestImpl; 96 class MdnsListenerImpl; 97 98 public: 99 class RuleResolver { 100 public: 101 struct RuleKey { 102 struct WildcardScheme : absl::monostate {}; 103 struct NoScheme : absl::monostate {}; 104 using Scheme = std::string; 105 106 RuleKey(); 107 ~RuleKey(); 108 109 RuleKey(const RuleKey&); 110 RuleKey& operator=(const RuleKey&); 111 RuleKey(RuleKey&&); 112 RuleKey& operator=(RuleKey&&); 113 GetTupleRuleKey114 auto GetTuple() const { 115 return std::tie(scheme, hostname_pattern, port, query_type, 116 query_source); 117 } 118 119 bool operator<(const RuleKey& other) const { 120 return GetTuple() < other.GetTuple(); 121 } 122 123 // If `WildcardScheme`, scheme is wildcard and any query will match, 124 // whether made with url::SchemeHostPort or HostPortPair. If `NoScheme`, 125 // queries will only match if made using HostPortPair. Else, queries will 126 // only match if made using url::SchemeHostPort with matching scheme 127 // value. 128 absl::variant<WildcardScheme, NoScheme, Scheme> scheme = WildcardScheme(); 129 130 // Pattern matched via `base::MatchPattern()`. 131 std::string hostname_pattern = "*"; 132 133 // `nullopt` represents wildcard and all queries will match. 134 std::optional<uint16_t> port; 135 std::optional<DnsQueryType> query_type; 136 std::optional<HostResolverSource> query_source; 137 }; 138 139 struct RuleResult { 140 RuleResult(); 141 explicit RuleResult( 142 std::vector<HostResolverEndpointResult> endpoints, 143 std::set<std::string> aliases = std::set<std::string>()); 144 145 ~RuleResult(); 146 147 RuleResult(const RuleResult&); 148 RuleResult& operator=(const RuleResult&); 149 RuleResult(RuleResult&&); 150 RuleResult& operator=(RuleResult&&); 151 152 std::vector<HostResolverEndpointResult> endpoints; 153 std::set<std::string> aliases; 154 }; 155 156 using ErrorResult = Error; 157 using RuleResultOrError = absl::variant<RuleResult, ErrorResult>; 158 159 // If `default_result` is nullopt, every resolve must match an added rule. 160 explicit RuleResolver( 161 std::optional<RuleResultOrError> default_result = std::nullopt); 162 ~RuleResolver(); 163 164 RuleResolver(const RuleResolver&); 165 RuleResolver& operator=(const RuleResolver&); 166 RuleResolver(RuleResolver&&); 167 RuleResolver& operator=(RuleResolver&&); 168 169 const RuleResultOrError& Resolve(const Host& request_endpoint, 170 DnsQueryTypeSet request_types, 171 HostResolverSource request_source) const; 172 173 void ClearRules(); 174 175 static RuleResultOrError GetLocalhostResult(); 176 177 void AddRule(RuleKey key, RuleResultOrError result); 178 void AddRule(RuleKey key, std::string_view ip_literal); 179 180 void AddRule(std::string_view hostname_pattern, RuleResultOrError result); 181 void AddRule(std::string_view hostname_pattern, 182 std::string_view ip_literal); 183 184 void AddRule(std::string_view hostname_pattern, Error error); 185 186 // Legacy rule creation. Only for compatibility with tests written for use 187 // with RuleBasedHostResolverProc. New code should use the AddRule() calls 188 // above. 189 void AddIPLiteralRule(std::string_view hostname_pattern, 190 std::string_view ip_literal, 191 std::string_view canonical_name); 192 void AddIPLiteralRuleWithDnsAliases(std::string_view hostname_pattern, 193 std::string_view ip_literal, 194 std::vector<std::string> dns_aliases); 195 void AddIPLiteralRuleWithDnsAliases(std::string_view hostname_pattern, 196 std::string_view ip_literal, 197 std::set<std::string> dns_aliases); 198 void AddSimulatedFailure(std::string_view hostname_pattern); 199 void AddSimulatedTimeoutFailure(std::string_view hostname_pattern); 200 void AddRuleWithFlags(std::string_view host_pattern, 201 std::string_view ip_literal, 202 HostResolverFlags flags, 203 std::vector<std::string> dns_aliases = {}); 204 205 private: 206 std::map<RuleKey, RuleResultOrError> rules_; 207 std::optional<RuleResultOrError> default_result_; 208 }; 209 210 using RequestMap = std::map<size_t, raw_ptr<RequestBase, CtnExperimental>>; 211 212 // A set of states in MockHostResolver. This is used to observe the internal 213 // state variables after destructing a MockHostResolver. 214 class State : public base::RefCounted<State> { 215 public: 216 State(); 217 has_pending_requests()218 bool has_pending_requests() const { return !requests_.empty(); } IsDohProbeRunning()219 bool IsDohProbeRunning() const { return !!doh_probe_request_; } num_resolve()220 size_t num_resolve() const { return num_resolve_; } num_resolve_from_cache()221 size_t num_resolve_from_cache() const { return num_resolve_from_cache_; } num_non_local_resolves()222 size_t num_non_local_resolves() const { return num_non_local_resolves_; } 223 mutable_requests()224 RequestMap& mutable_requests() { return requests_; } IncrementNumResolve()225 void IncrementNumResolve() { ++num_resolve_; } IncrementNumResolveFromCache()226 void IncrementNumResolveFromCache() { ++num_resolve_from_cache_; } IncrementNumNonLocalResolves()227 void IncrementNumNonLocalResolves() { ++num_non_local_resolves_; } ClearDohProbeRequest()228 void ClearDohProbeRequest() { doh_probe_request_ = nullptr; } ClearDohProbeRequestIfMatching(ProbeRequestImpl * request)229 void ClearDohProbeRequestIfMatching(ProbeRequestImpl* request) { 230 if (request == doh_probe_request_) { 231 doh_probe_request_ = nullptr; 232 } 233 } set_doh_probe_request(ProbeRequestImpl * request)234 void set_doh_probe_request(ProbeRequestImpl* request) { 235 DCHECK(request); 236 DCHECK(!doh_probe_request_); 237 doh_probe_request_ = request; 238 } 239 240 private: 241 friend class RefCounted<State>; 242 243 ~State(); 244 245 // Maintain non-owning pointers to outstanding requests and listeners to 246 // allow completing/notifying them. The objects are owned by callers, and 247 // should be removed from |this| on destruction by calling DetachRequest() 248 // or RemoveCancelledListener(). 249 RequestMap requests_; 250 raw_ptr<ProbeRequestImpl> doh_probe_request_ = nullptr; 251 size_t num_resolve_ = 0; 252 size_t num_resolve_from_cache_ = 0; 253 size_t num_non_local_resolves_ = 0; 254 }; 255 256 MockHostResolverBase(const MockHostResolverBase&) = delete; 257 MockHostResolverBase& operator=(const MockHostResolverBase&) = delete; 258 259 ~MockHostResolverBase() override; 260 rules()261 RuleResolver* rules() { return &rule_resolver_; } 262 state()263 scoped_refptr<const State> state() const { return state_; } 264 265 // Controls whether resolutions complete synchronously or asynchronously. set_synchronous_mode(bool is_synchronous)266 void set_synchronous_mode(bool is_synchronous) { 267 synchronous_mode_ = is_synchronous; 268 } 269 270 // Asynchronous requests are automatically resolved by default. 271 // If set_ondemand_mode() is set then Resolve() returns IO_PENDING and 272 // ResolveAllPending() must be explicitly invoked to resolve all requests 273 // that are pending. set_ondemand_mode(bool is_ondemand)274 void set_ondemand_mode(bool is_ondemand) { 275 ondemand_mode_ = is_ondemand; 276 } 277 278 // HostResolver methods: 279 void OnShutdown() override; 280 std::unique_ptr<ResolveHostRequest> CreateRequest( 281 url::SchemeHostPort host, 282 NetworkAnonymizationKey network_anonymization_key, 283 NetLogWithSource net_log, 284 std::optional<ResolveHostParameters> optional_parameters) override; 285 std::unique_ptr<ResolveHostRequest> CreateRequest( 286 const HostPortPair& host, 287 const NetworkAnonymizationKey& network_anonymization_key, 288 const NetLogWithSource& net_log, 289 const std::optional<ResolveHostParameters>& optional_parameters) override; 290 std::unique_ptr<ServiceEndpointRequest> CreateServiceEndpointRequest( 291 Host host, 292 NetworkAnonymizationKey network_anonymization_key, 293 NetLogWithSource net_log, 294 ResolveHostParameters parameters) override; 295 std::unique_ptr<ProbeRequest> CreateDohProbeRequest() override; 296 std::unique_ptr<MdnsListener> CreateMdnsListener( 297 const HostPortPair& host, 298 DnsQueryType query_type) override; 299 HostCache* GetHostCache() override; SetRequestContext(URLRequestContext * request_context)300 void SetRequestContext(URLRequestContext* request_context) override {} 301 302 // Preloads the cache with what would currently be the result of a request 303 // with the given parameters. Returns the net error of the cached result. 304 int LoadIntoCache( 305 absl::variant<url::SchemeHostPort, HostPortPair> endpoint, 306 const NetworkAnonymizationKey& network_anonymization_key, 307 const std::optional<ResolveHostParameters>& optional_parameters); 308 int LoadIntoCache( 309 const Host& endpoint, 310 const NetworkAnonymizationKey& network_anonymization_key, 311 const std::optional<ResolveHostParameters>& optional_parameters); 312 313 // Returns true if there are pending requests that can be resolved by invoking 314 // ResolveAllPending(). has_pending_requests()315 bool has_pending_requests() const { return state_->has_pending_requests(); } 316 317 // Resolves all pending requests. It is only valid to invoke this if 318 // set_ondemand_mode was set before. The requests are resolved asynchronously, 319 // after this call returns. 320 void ResolveAllPending(); 321 322 // Each request is assigned an ID when started and stored with the resolver 323 // for async resolution, starting with 1. IDs are not reused. Once a request 324 // completes, it is destroyed, and can no longer be accessed. 325 326 // Returns the ID of the most recently started still-active request. Zero if 327 // no requests are currently active. 328 size_t last_id(); 329 330 // Resolve request stored in |requests_|. Pass rv to callback. 331 void ResolveNow(size_t id); 332 333 // Detach cancelled request. 334 void DetachRequest(size_t id); 335 336 // Returns the hostname of the request with the given id. 337 std::string_view request_host(size_t id); 338 339 // Returns the priority of the request with the given id. 340 RequestPriority request_priority(size_t id); 341 342 // Returns NetworkAnonymizationKey of the request with the given id. 343 const NetworkAnonymizationKey& request_network_anonymization_key(size_t id); 344 345 // Like ResolveNow, but doesn't take an ID. DCHECKs if there's more than one 346 // pending request. 347 void ResolveOnlyRequestNow(); 348 349 // The number of times that Resolve() has been called. num_resolve()350 size_t num_resolve() const { return state_->num_resolve(); } 351 352 // The number of times that ResolveFromCache() has been called. num_resolve_from_cache()353 size_t num_resolve_from_cache() const { 354 return state_->num_resolve_from_cache(); 355 } 356 357 // The number of times resolve was attempted non-locally. num_non_local_resolves()358 size_t num_non_local_resolves() const { 359 return state_->num_non_local_resolves(); 360 } 361 362 // Returns the RequestPriority of the last call to Resolve() (or 363 // DEFAULT_PRIORITY if Resolve() hasn't been called yet). last_request_priority()364 RequestPriority last_request_priority() const { 365 return last_request_priority_; 366 } 367 368 // Returns the NetworkAnonymizationKey passed in to the last call to Resolve() 369 // (or std::nullopt if Resolve() hasn't been called yet). 370 const std::optional<NetworkAnonymizationKey>& last_request_network_anonymization_key()371 last_request_network_anonymization_key() { 372 return last_request_network_anonymization_key_; 373 } 374 375 // Returns the SecureDnsPolicy of the last call to Resolve() (or 376 // std::nullopt if Resolve() hasn't been called yet). last_secure_dns_policy()377 SecureDnsPolicy last_secure_dns_policy() const { 378 return last_secure_dns_policy_; 379 } 380 IsDohProbeRunning()381 bool IsDohProbeRunning() const { return state_->IsDohProbeRunning(); } 382 383 void TriggerMdnsListeners(const HostPortPair& host, 384 DnsQueryType query_type, 385 MdnsListenerUpdateType update_type, 386 const IPEndPoint& address_result); 387 void TriggerMdnsListeners(const HostPortPair& host, 388 DnsQueryType query_type, 389 MdnsListenerUpdateType update_type, 390 const std::vector<std::string>& text_result); 391 void TriggerMdnsListeners(const HostPortPair& host, 392 DnsQueryType query_type, 393 MdnsListenerUpdateType update_type, 394 const HostPortPair& host_result); 395 void TriggerMdnsListeners(const HostPortPair& host, 396 DnsQueryType query_type, 397 MdnsListenerUpdateType update_type); 398 set_tick_clock(const base::TickClock * tick_clock)399 void set_tick_clock(const base::TickClock* tick_clock) { 400 tick_clock_ = tick_clock; 401 } 402 403 private: 404 friend class MockHostResolver; 405 friend class MockCachingHostResolver; 406 friend class MockHostResolverFactory; 407 408 // Returns the request with the given id. 409 RequestBase* request(size_t id); 410 411 // If > 0, |cache_invalidation_num| is the number of times a cached entry can 412 // be read before it invalidates itself. Useful to force cache expiration 413 // scenarios. 414 MockHostResolverBase(bool use_caching, 415 int cache_invalidation_num, 416 RuleResolver rule_resolver); 417 418 // Handle resolution for |request|. Expected to be called only the RequestBase 419 // object itself. 420 int Resolve(RequestBase* request); 421 422 // Resolve as IP or from |cache_| return cached error or 423 // DNS_CACHE_MISS if failed. 424 int ResolveFromIPLiteralOrCache( 425 const Host& endpoint, 426 const NetworkAnonymizationKey& network_anonymization_key, 427 DnsQueryType dns_query_type, 428 HostResolverFlags flags, 429 HostResolverSource source, 430 HostResolver::ResolveHostParameters::CacheUsage cache_usage, 431 std::vector<HostResolverEndpointResult>* out_endpoints, 432 std::set<std::string>* out_aliases, 433 std::optional<HostCache::EntryStaleness>* out_stale_info); 434 int DoSynchronousResolution(RequestBase& request); 435 436 void AddListener(MdnsListenerImpl* listener); 437 void RemoveCancelledListener(MdnsListenerImpl* listener); 438 439 RequestPriority last_request_priority_ = DEFAULT_PRIORITY; 440 std::optional<NetworkAnonymizationKey> 441 last_request_network_anonymization_key_; 442 SecureDnsPolicy last_secure_dns_policy_ = SecureDnsPolicy::kAllow; 443 bool synchronous_mode_ = false; 444 bool ondemand_mode_ = false; 445 RuleResolver rule_resolver_; 446 std::unique_ptr<HostCache> cache_; 447 448 const int initial_cache_invalidation_num_; 449 std::map<HostCache::Key, int> cache_invalidation_nums_; 450 451 std::set<raw_ptr<MdnsListenerImpl, SetExperimental>> listeners_; 452 453 size_t next_request_id_ = 1; 454 455 raw_ptr<const base::TickClock> tick_clock_; 456 457 scoped_refptr<State> state_; 458 459 THREAD_CHECKER(thread_checker_); 460 461 base::WeakPtrFactory<MockHostResolverBase> weak_ptr_factory_{this}; 462 }; 463 464 class MockHostResolver : public MockHostResolverBase { 465 public: 466 explicit MockHostResolver(std::optional<RuleResolver::RuleResultOrError> 467 default_result = std::nullopt) 468 : MockHostResolverBase(/*use_caching=*/false, 469 /*cache_invalidation_num=*/0, RuleResolver(std::move (default_result))470 RuleResolver(std::move(default_result))) {} 471 ~MockHostResolver() override = default; 472 }; 473 474 // Same as MockHostResolver, except internally it uses a host-cache. 475 // 476 // Note that tests are advised to use MockHostResolver instead, since it is 477 // more predictable. (MockHostResolver also can be put into synchronous 478 // operation mode in case that is what you needed from the caching version). 479 class MockCachingHostResolver : public MockHostResolverBase { 480 public: 481 // If > 0, |cache_invalidation_num| is the number of times a cached entry can 482 // be read before it invalidates itself. Useful to force cache expiration 483 // scenarios. 484 explicit MockCachingHostResolver( 485 int cache_invalidation_num = 0, 486 std::optional<RuleResolver::RuleResultOrError> default_result = 487 std::nullopt) MockHostResolverBase(true,cache_invalidation_num,RuleResolver (std::move (default_result)))488 : MockHostResolverBase(/*use_caching=*/true, 489 cache_invalidation_num, 490 RuleResolver(std::move(default_result))) {} 491 ~MockCachingHostResolver() override = default; 492 }; 493 494 // Factory that will always create and return Mock(Caching)HostResolvers. 495 // 496 // The default behavior is to create a non-caching mock, even if the tested code 497 // requests caching enabled (via the |enable_caching| parameter in the creation 498 // methods). A caching mock will only be created if both |use_caching| is set on 499 // factory construction and |enable_caching| is set in the creation method. 500 class MockHostResolverFactory : public HostResolver::Factory { 501 public: 502 explicit MockHostResolverFactory(MockHostResolverBase::RuleResolver rules = 503 MockHostResolverBase::RuleResolver(), 504 bool use_caching = false, 505 int cache_invalidation_num = 0); 506 507 MockHostResolverFactory(const MockHostResolverFactory&) = delete; 508 MockHostResolverFactory& operator=(const MockHostResolverFactory&) = delete; 509 510 ~MockHostResolverFactory() override; 511 512 std::unique_ptr<HostResolver> CreateResolver( 513 HostResolverManager* manager, 514 std::string_view host_mapping_rules, 515 bool enable_caching) override; 516 std::unique_ptr<HostResolver> CreateStandaloneResolver( 517 NetLog* net_log, 518 const HostResolver::ManagerOptions& options, 519 std::string_view host_mapping_rules, 520 bool enable_caching) override; 521 522 private: 523 const MockHostResolverBase::RuleResolver rules_; 524 const bool use_caching_; 525 const int cache_invalidation_num_; 526 }; 527 528 // RuleBasedHostResolverProc applies a set of rules to map a host string to 529 // a replacement host string. It then uses the system host resolver to return 530 // a socket address. Generally the replacement should be an IPv4 literal so 531 // there is no network dependency. 532 // 533 // RuleBasedHostResolverProc is thread-safe, to a limited degree. Rules can be 534 // added or removed on any thread. 535 class RuleBasedHostResolverProc : public HostResolverProc { 536 public: 537 // If `allow_fallback` is false, no Proc fallback is allowed except to 538 // `previous`. 539 explicit RuleBasedHostResolverProc(scoped_refptr<HostResolverProc> previous, 540 bool allow_fallback = true); 541 542 // Any hostname matching the given pattern will be replaced with the given 543 // |ip_literal|. 544 void AddRule(std::string_view host_pattern, std::string_view ip_literal); 545 546 // Same as AddRule(), but further restricts to |address_family|. 547 void AddRuleForAddressFamily(std::string_view host_pattern, 548 AddressFamily address_family, 549 std::string_view ip_literal); 550 551 void AddRuleWithFlags(std::string_view host_pattern, 552 std::string_view ip_literal, 553 HostResolverFlags flags, 554 std::vector<std::string> dns_aliases = {}); 555 556 // Same as AddRule(), but the replacement is expected to be an IPv4 or IPv6 557 // literal. This can be used in place of AddRule() to bypass the system's 558 // host resolver (the address list will be constructed manually). 559 // If |canonical_name| is non-empty, it is copied to the resulting AddressList 560 // but does not impact DNS resolution. 561 // |ip_literal| can be a single IP address like "192.168.1.1" or a comma 562 // separated list of IP addresses, like "::1,192:168.1.2". 563 void AddIPLiteralRule(std::string_view host_pattern, 564 std::string_view ip_literal, 565 std::string_view canonical_name); 566 567 // Same as AddIPLiteralRule, but with a parameter allowing multiple DNS 568 // aliases, such as CNAME aliases, instead of only the canonical name. While 569 // a simulation using HostResolverProc to obtain more than a single DNS alias 570 // is currently unrealistic, this capability is useful for clients of 571 // MockHostResolver who need to be able to obtain aliases and can be 572 // agnostic about how the host resolution took place, as the alternative, 573 // MockDnsClient, is not currently hooked up to MockHostResolver. 574 void AddIPLiteralRuleWithDnsAliases(std::string_view host_pattern, 575 std::string_view ip_literal, 576 std::vector<std::string> dns_aliases); 577 578 void AddRuleWithLatency(std::string_view host_pattern, 579 std::string_view replacement, 580 int latency_ms); 581 582 // Make sure that |host| will not be re-mapped or even processed by underlying 583 // host resolver procedures. It can also be a pattern. 584 void AllowDirectLookup(std::string_view host); 585 586 // Simulate a lookup failure for |host| (it also can be a pattern). 587 void AddSimulatedFailure( 588 std::string_view host, 589 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY); 590 591 // Simulate a lookup timeout failure for |host| (it also can be a pattern). 592 void AddSimulatedTimeoutFailure( 593 std::string_view host, 594 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY); 595 596 // Deletes all the rules that have been added. 597 void ClearRules(); 598 599 // Causes method calls that add or delete rules to assert. 600 // TODO(jam): once this class isn't used by tests that use an out of process 601 // network service, remove this method and make Rule private. 602 void DisableModifications(); 603 604 // HostResolverProc methods: 605 int Resolve(const std::string& host, 606 AddressFamily address_family, 607 HostResolverFlags host_resolver_flags, 608 AddressList* addrlist, 609 int* os_error) override; 610 611 struct Rule { 612 // TODO(crbug.com/40822747) Deduplicate this enum's definition. 613 enum ResolverType { 614 kResolverTypeFail, 615 kResolverTypeFailTimeout, 616 // TODO(mmenke): Is it really reasonable for a "mock" host resolver to 617 // fall back to the system resolver? 618 kResolverTypeSystem, 619 kResolverTypeIPLiteral, 620 }; 621 622 Rule(ResolverType resolver_type, 623 std::string_view host_pattern, 624 AddressFamily address_family, 625 HostResolverFlags host_resolver_flags, 626 std::string_view replacement, 627 std::vector<std::string> dns_aliases, 628 int latency_ms); 629 Rule(const Rule& other); 630 ~Rule(); 631 632 ResolverType resolver_type; 633 std::string host_pattern; 634 AddressFamily address_family; 635 HostResolverFlags host_resolver_flags; 636 std::string replacement; 637 std::vector<std::string> dns_aliases; 638 int latency_ms; // In milliseconds. 639 }; 640 641 typedef std::list<Rule> RuleList; 642 643 RuleList GetRules(); 644 645 // Returns the number of calls to Resolve() where |host| matched 646 // |host_pattern|. 647 size_t NumResolvesForHostPattern(std::string_view host_pattern); 648 649 private: 650 ~RuleBasedHostResolverProc() override; 651 652 void AddRuleInternal(const Rule& rule); 653 654 RuleList rules_ GUARDED_BY(rule_lock_); 655 656 // Tracks the number of calls to Resolve() where |host| matches a rule's host 657 // pattern. 658 std::map<std::string_view, size_t> num_resolves_per_host_pattern_ 659 GUARDED_BY(rule_lock_); 660 661 // Must be obtained before writing to or reading from |rules_|. 662 base::Lock rule_lock_; 663 664 // Whether changes are allowed. 665 bool modifications_allowed_ = true; 666 }; 667 668 // Create rules that map all requests to localhost. 669 scoped_refptr<RuleBasedHostResolverProc> CreateCatchAllHostResolverProc(); 670 671 // HangingHostResolver never completes its |Resolve| request. As LOCAL_ONLY 672 // requests are not allowed to complete asynchronously, they will always result 673 // in |ERR_DNS_CACHE_MISS|. 674 class HangingHostResolver : public HostResolver { 675 public: 676 // A set of states in HangingHostResolver. This is used to observe the 677 // internal state variables after destructing a MockHostResolver. 678 class State : public base::RefCounted<State> { 679 public: 680 State(); 681 num_cancellations()682 int num_cancellations() const { return num_cancellations_; } 683 IncrementNumCancellations()684 void IncrementNumCancellations() { ++num_cancellations_; } 685 686 private: 687 friend class RefCounted<State>; 688 689 ~State(); 690 691 int num_cancellations_ = 0; 692 }; 693 694 HangingHostResolver(); 695 ~HangingHostResolver() override; 696 void OnShutdown() override; 697 std::unique_ptr<ResolveHostRequest> CreateRequest( 698 url::SchemeHostPort host, 699 NetworkAnonymizationKey network_anonymization_key, 700 NetLogWithSource net_log, 701 std::optional<ResolveHostParameters> optional_parameters) override; 702 std::unique_ptr<ResolveHostRequest> CreateRequest( 703 const HostPortPair& host, 704 const NetworkAnonymizationKey& network_anonymization_key, 705 const NetLogWithSource& net_log, 706 const std::optional<ResolveHostParameters>& optional_parameters) override; 707 std::unique_ptr<ServiceEndpointRequest> CreateServiceEndpointRequest( 708 Host host, 709 NetworkAnonymizationKey network_anonymization_key, 710 NetLogWithSource net_log, 711 ResolveHostParameters parameters) override; 712 713 std::unique_ptr<ProbeRequest> CreateDohProbeRequest() override; 714 715 void SetRequestContext(URLRequestContext* url_request_context) override; 716 717 // Use to detect cancellations since there's otherwise no externally-visible 718 // differentiation between a cancelled and a hung task. num_cancellations()719 int num_cancellations() const { return state_->num_cancellations(); } 720 721 // Return the corresponding values passed to the most recent call to 722 // CreateRequest() last_host()723 const HostPortPair& last_host() const { return last_host_; } last_network_anonymization_key()724 const NetworkAnonymizationKey& last_network_anonymization_key() const { 725 return last_network_anonymization_key_; 726 } 727 state()728 const scoped_refptr<const State> state() const { return state_; } 729 730 private: 731 class RequestImpl; 732 class ProbeRequestImpl; 733 734 HostPortPair last_host_; 735 NetworkAnonymizationKey last_network_anonymization_key_; 736 737 scoped_refptr<State> state_; 738 bool shutting_down_ = false; 739 base::WeakPtrFactory<HangingHostResolver> weak_ptr_factory_{this}; 740 }; 741 742 // This class sets the default HostResolverProc for a particular scope. The 743 // chain of resolver procs starting at |proc| is placed in front of any existing 744 // default resolver proc(s). This means that if multiple 745 // ScopedDefaultHostResolverProcs are declared, then resolving will start with 746 // the procs given to the last-allocated one, then fall back to the procs given 747 // to the previously-allocated one, and so forth. 748 // 749 // NOTE: Only use this as a catch-all safety net. Individual tests should use 750 // MockHostResolver. 751 class ScopedDefaultHostResolverProc { 752 public: 753 ScopedDefaultHostResolverProc(); 754 explicit ScopedDefaultHostResolverProc(HostResolverProc* proc); 755 756 ~ScopedDefaultHostResolverProc(); 757 758 void Init(HostResolverProc* proc); 759 760 private: 761 scoped_refptr<HostResolverProc> current_proc_; 762 scoped_refptr<HostResolverProc> previous_proc_; 763 }; 764 765 } // namespace net 766 767 #endif // NET_DNS_MOCK_HOST_RESOLVER_H_ 768