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