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 91 : public HostResolver, 92 public base::SupportsWeakPtr<MockHostResolverBase> { 93 private: 94 class RequestImpl; 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, RequestImpl*>; 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 RequestImpl* 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 RequestImpl 419 // object itself. 420 int Resolve(RequestImpl* 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(RequestImpl& 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 462 class MockHostResolver : public MockHostResolverBase { 463 public: 464 explicit MockHostResolver(std::optional<RuleResolver::RuleResultOrError> 465 default_result = std::nullopt) 466 : MockHostResolverBase(/*use_caching=*/false, 467 /*cache_invalidation_num=*/0, RuleResolver(std::move (default_result))468 RuleResolver(std::move(default_result))) {} 469 ~MockHostResolver() override = default; 470 }; 471 472 // Same as MockHostResolver, except internally it uses a host-cache. 473 // 474 // Note that tests are advised to use MockHostResolver instead, since it is 475 // more predictable. (MockHostResolver also can be put into synchronous 476 // operation mode in case that is what you needed from the caching version). 477 class MockCachingHostResolver : public MockHostResolverBase { 478 public: 479 // If > 0, |cache_invalidation_num| is the number of times a cached entry can 480 // be read before it invalidates itself. Useful to force cache expiration 481 // scenarios. 482 explicit MockCachingHostResolver( 483 int cache_invalidation_num = 0, 484 std::optional<RuleResolver::RuleResultOrError> default_result = 485 std::nullopt) MockHostResolverBase(true,cache_invalidation_num,RuleResolver (std::move (default_result)))486 : MockHostResolverBase(/*use_caching=*/true, 487 cache_invalidation_num, 488 RuleResolver(std::move(default_result))) {} 489 ~MockCachingHostResolver() override = default; 490 }; 491 492 // Factory that will always create and return Mock(Caching)HostResolvers. 493 // 494 // The default behavior is to create a non-caching mock, even if the tested code 495 // requests caching enabled (via the |enable_caching| parameter in the creation 496 // methods). A caching mock will only be created if both |use_caching| is set on 497 // factory construction and |enable_caching| is set in the creation method. 498 class MockHostResolverFactory : public HostResolver::Factory { 499 public: 500 explicit MockHostResolverFactory(MockHostResolverBase::RuleResolver rules = 501 MockHostResolverBase::RuleResolver(), 502 bool use_caching = false, 503 int cache_invalidation_num = 0); 504 505 MockHostResolverFactory(const MockHostResolverFactory&) = delete; 506 MockHostResolverFactory& operator=(const MockHostResolverFactory&) = delete; 507 508 ~MockHostResolverFactory() override; 509 510 std::unique_ptr<HostResolver> CreateResolver( 511 HostResolverManager* manager, 512 std::string_view host_mapping_rules, 513 bool enable_caching) override; 514 std::unique_ptr<HostResolver> CreateStandaloneResolver( 515 NetLog* net_log, 516 const HostResolver::ManagerOptions& options, 517 std::string_view host_mapping_rules, 518 bool enable_caching) override; 519 520 private: 521 const MockHostResolverBase::RuleResolver rules_; 522 const bool use_caching_; 523 const int cache_invalidation_num_; 524 }; 525 526 // RuleBasedHostResolverProc applies a set of rules to map a host string to 527 // a replacement host string. It then uses the system host resolver to return 528 // a socket address. Generally the replacement should be an IPv4 literal so 529 // there is no network dependency. 530 // 531 // RuleBasedHostResolverProc is thread-safe, to a limited degree. Rules can be 532 // added or removed on any thread. 533 class RuleBasedHostResolverProc : public HostResolverProc { 534 public: 535 // If `allow_fallback` is false, no Proc fallback is allowed except to 536 // `previous`. 537 explicit RuleBasedHostResolverProc(scoped_refptr<HostResolverProc> previous, 538 bool allow_fallback = true); 539 540 // Any hostname matching the given pattern will be replaced with the given 541 // |ip_literal|. 542 void AddRule(std::string_view host_pattern, std::string_view ip_literal); 543 544 // Same as AddRule(), but further restricts to |address_family|. 545 void AddRuleForAddressFamily(std::string_view host_pattern, 546 AddressFamily address_family, 547 std::string_view ip_literal); 548 549 void AddRuleWithFlags(std::string_view host_pattern, 550 std::string_view ip_literal, 551 HostResolverFlags flags, 552 std::vector<std::string> dns_aliases = {}); 553 554 // Same as AddRule(), but the replacement is expected to be an IPv4 or IPv6 555 // literal. This can be used in place of AddRule() to bypass the system's 556 // host resolver (the address list will be constructed manually). 557 // If |canonical_name| is non-empty, it is copied to the resulting AddressList 558 // but does not impact DNS resolution. 559 // |ip_literal| can be a single IP address like "192.168.1.1" or a comma 560 // separated list of IP addresses, like "::1,192:168.1.2". 561 void AddIPLiteralRule(std::string_view host_pattern, 562 std::string_view ip_literal, 563 std::string_view canonical_name); 564 565 // Same as AddIPLiteralRule, but with a parameter allowing multiple DNS 566 // aliases, such as CNAME aliases, instead of only the canonical name. While 567 // a simulation using HostResolverProc to obtain more than a single DNS alias 568 // is currently unrealistic, this capability is useful for clients of 569 // MockHostResolver who need to be able to obtain aliases and can be 570 // agnostic about how the host resolution took place, as the alternative, 571 // MockDnsClient, is not currently hooked up to MockHostResolver. 572 void AddIPLiteralRuleWithDnsAliases(std::string_view host_pattern, 573 std::string_view ip_literal, 574 std::vector<std::string> dns_aliases); 575 576 void AddRuleWithLatency(std::string_view host_pattern, 577 std::string_view replacement, 578 int latency_ms); 579 580 // Make sure that |host| will not be re-mapped or even processed by underlying 581 // host resolver procedures. It can also be a pattern. 582 void AllowDirectLookup(std::string_view host); 583 584 // Simulate a lookup failure for |host| (it also can be a pattern). 585 void AddSimulatedFailure( 586 std::string_view host, 587 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY); 588 589 // Simulate a lookup timeout failure for |host| (it also can be a pattern). 590 void AddSimulatedTimeoutFailure( 591 std::string_view host, 592 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY); 593 594 // Deletes all the rules that have been added. 595 void ClearRules(); 596 597 // Causes method calls that add or delete rules to assert. 598 // TODO(jam): once this class isn't used by tests that use an out of process 599 // network service, remove this method and make Rule private. 600 void DisableModifications(); 601 602 // HostResolverProc methods: 603 int Resolve(const std::string& host, 604 AddressFamily address_family, 605 HostResolverFlags host_resolver_flags, 606 AddressList* addrlist, 607 int* os_error) override; 608 609 struct Rule { 610 // TODO(https://crbug.com/1298106) Deduplicate this enum's definition. 611 enum ResolverType { 612 kResolverTypeFail, 613 kResolverTypeFailTimeout, 614 // TODO(mmenke): Is it really reasonable for a "mock" host resolver to 615 // fall back to the system resolver? 616 kResolverTypeSystem, 617 kResolverTypeIPLiteral, 618 }; 619 620 Rule(ResolverType resolver_type, 621 std::string_view host_pattern, 622 AddressFamily address_family, 623 HostResolverFlags host_resolver_flags, 624 std::string_view replacement, 625 std::vector<std::string> dns_aliases, 626 int latency_ms); 627 Rule(const Rule& other); 628 ~Rule(); 629 630 ResolverType resolver_type; 631 std::string host_pattern; 632 AddressFamily address_family; 633 HostResolverFlags host_resolver_flags; 634 std::string replacement; 635 std::vector<std::string> dns_aliases; 636 int latency_ms; // In milliseconds. 637 }; 638 639 typedef std::list<Rule> RuleList; 640 641 RuleList GetRules(); 642 643 // Returns the number of calls to Resolve() where |host| matched 644 // |host_pattern|. 645 size_t NumResolvesForHostPattern(std::string_view host_pattern); 646 647 private: 648 ~RuleBasedHostResolverProc() override; 649 650 void AddRuleInternal(const Rule& rule); 651 652 RuleList rules_ GUARDED_BY(rule_lock_); 653 654 // Tracks the number of calls to Resolve() where |host| matches a rule's host 655 // pattern. 656 std::map<std::string_view, size_t> num_resolves_per_host_pattern_ 657 GUARDED_BY(rule_lock_); 658 659 // Must be obtained before writing to or reading from |rules_|. 660 base::Lock rule_lock_; 661 662 // Whether changes are allowed. 663 bool modifications_allowed_ = true; 664 }; 665 666 // Create rules that map all requests to localhost. 667 scoped_refptr<RuleBasedHostResolverProc> CreateCatchAllHostResolverProc(); 668 669 // HangingHostResolver never completes its |Resolve| request. As LOCAL_ONLY 670 // requests are not allowed to complete asynchronously, they will always result 671 // in |ERR_DNS_CACHE_MISS|. 672 class HangingHostResolver : public HostResolver { 673 public: 674 // A set of states in HangingHostResolver. This is used to observe the 675 // internal state variables after destructing a MockHostResolver. 676 class State : public base::RefCounted<State> { 677 public: 678 State(); 679 num_cancellations()680 int num_cancellations() const { return num_cancellations_; } 681 IncrementNumCancellations()682 void IncrementNumCancellations() { ++num_cancellations_; } 683 684 private: 685 friend class RefCounted<State>; 686 687 ~State(); 688 689 int num_cancellations_ = 0; 690 }; 691 692 HangingHostResolver(); 693 ~HangingHostResolver() override; 694 void OnShutdown() override; 695 std::unique_ptr<ResolveHostRequest> CreateRequest( 696 url::SchemeHostPort host, 697 NetworkAnonymizationKey network_anonymization_key, 698 NetLogWithSource net_log, 699 std::optional<ResolveHostParameters> optional_parameters) override; 700 std::unique_ptr<ResolveHostRequest> CreateRequest( 701 const HostPortPair& host, 702 const NetworkAnonymizationKey& network_anonymization_key, 703 const NetLogWithSource& net_log, 704 const std::optional<ResolveHostParameters>& optional_parameters) override; 705 std::unique_ptr<ServiceEndpointRequest> CreateServiceEndpointRequest( 706 Host host, 707 NetworkAnonymizationKey network_anonymization_key, 708 NetLogWithSource net_log, 709 ResolveHostParameters parameters) override; 710 711 std::unique_ptr<ProbeRequest> CreateDohProbeRequest() override; 712 713 void SetRequestContext(URLRequestContext* url_request_context) override; 714 715 // Use to detect cancellations since there's otherwise no externally-visible 716 // differentiation between a cancelled and a hung task. num_cancellations()717 int num_cancellations() const { return state_->num_cancellations(); } 718 719 // Return the corresponding values passed to the most recent call to 720 // CreateRequest() last_host()721 const HostPortPair& last_host() const { return last_host_; } last_network_anonymization_key()722 const NetworkAnonymizationKey& last_network_anonymization_key() const { 723 return last_network_anonymization_key_; 724 } 725 state()726 const scoped_refptr<const State> state() const { return state_; } 727 728 private: 729 class RequestImpl; 730 class ProbeRequestImpl; 731 732 HostPortPair last_host_; 733 NetworkAnonymizationKey last_network_anonymization_key_; 734 735 scoped_refptr<State> state_; 736 bool shutting_down_ = false; 737 base::WeakPtrFactory<HangingHostResolver> weak_ptr_factory_{this}; 738 }; 739 740 // This class sets the default HostResolverProc for a particular scope. The 741 // chain of resolver procs starting at |proc| is placed in front of any existing 742 // default resolver proc(s). This means that if multiple 743 // ScopedDefaultHostResolverProcs are declared, then resolving will start with 744 // the procs given to the last-allocated one, then fall back to the procs given 745 // to the previously-allocated one, and so forth. 746 // 747 // NOTE: Only use this as a catch-all safety net. Individual tests should use 748 // MockHostResolver. 749 class ScopedDefaultHostResolverProc { 750 public: 751 ScopedDefaultHostResolverProc(); 752 explicit ScopedDefaultHostResolverProc(HostResolverProc* proc); 753 754 ~ScopedDefaultHostResolverProc(); 755 756 void Init(HostResolverProc* proc); 757 758 private: 759 scoped_refptr<HostResolverProc> current_proc_; 760 scoped_refptr<HostResolverProc> previous_proc_; 761 }; 762 763 } // namespace net 764 765 #endif // NET_DNS_MOCK_HOST_RESOLVER_H_ 766