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/synchronization/lock.h" 22 #include "base/synchronization/waitable_event.h" 23 #include "base/thread_annotations.h" 24 #include "base/threading/thread_checker.h" 25 #include "net/base/address_family.h" 26 #include "net/base/address_list.h" 27 #include "net/base/completion_once_callback.h" 28 #include "net/base/host_port_pair.h" 29 #include "net/base/net_errors.h" 30 #include "net/base/network_anonymization_key.h" 31 #include "net/dns/host_resolver.h" 32 #include "net/dns/host_resolver_proc.h" 33 #include "net/dns/public/dns_query_type.h" 34 #include "net/dns/public/host_resolver_results.h" 35 #include "net/dns/public/host_resolver_source.h" 36 #include "net/dns/public/mdns_listener_update_type.h" 37 #include "net/dns/public/secure_dns_policy.h" 38 #include "net/log/net_log_with_source.h" 39 #include "third_party/abseil-cpp/absl/types/optional.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(base::StringPiece 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 absl::optional<uint16_t> port; 135 absl::optional<DnsQueryType> query_type; 136 absl::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 absl::optional<RuleResultOrError> default_result = absl::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, base::StringPiece ip_literal); 179 180 void AddRule(base::StringPiece hostname_pattern, RuleResultOrError result); 181 void AddRule(base::StringPiece hostname_pattern, 182 base::StringPiece ip_literal); 183 184 void AddRule(base::StringPiece 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(base::StringPiece hostname_pattern, 190 base::StringPiece ip_literal, 191 base::StringPiece canonical_name); 192 void AddIPLiteralRuleWithDnsAliases(base::StringPiece hostname_pattern, 193 base::StringPiece ip_literal, 194 std::vector<std::string> dns_aliases); 195 void AddIPLiteralRuleWithDnsAliases(base::StringPiece hostname_pattern, 196 base::StringPiece ip_literal, 197 std::set<std::string> dns_aliases); 198 void AddSimulatedFailure(base::StringPiece hostname_pattern); 199 void AddSimulatedTimeoutFailure(base::StringPiece hostname_pattern); 200 void AddRuleWithFlags(base::StringPiece host_pattern, 201 base::StringPiece ip_literal, 202 HostResolverFlags flags, 203 std::vector<std::string> dns_aliases = {}); 204 205 private: 206 std::map<RuleKey, RuleResultOrError> rules_; 207 absl::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 absl::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 absl::optional<ResolveHostParameters>& optional_parameters) 290 override; 291 std::unique_ptr<ProbeRequest> CreateDohProbeRequest() override; 292 std::unique_ptr<MdnsListener> CreateMdnsListener( 293 const HostPortPair& host, 294 DnsQueryType query_type) override; 295 HostCache* GetHostCache() override; SetRequestContext(URLRequestContext * request_context)296 void SetRequestContext(URLRequestContext* request_context) override {} 297 298 // Preloads the cache with what would currently be the result of a request 299 // with the given parameters. Returns the net error of the cached result. 300 int LoadIntoCache( 301 absl::variant<url::SchemeHostPort, HostPortPair> endpoint, 302 const NetworkAnonymizationKey& network_anonymization_key, 303 const absl::optional<ResolveHostParameters>& optional_parameters); 304 int LoadIntoCache( 305 const Host& endpoint, 306 const NetworkAnonymizationKey& network_anonymization_key, 307 const absl::optional<ResolveHostParameters>& optional_parameters); 308 309 // Returns true if there are pending requests that can be resolved by invoking 310 // ResolveAllPending(). has_pending_requests()311 bool has_pending_requests() const { return state_->has_pending_requests(); } 312 313 // Resolves all pending requests. It is only valid to invoke this if 314 // set_ondemand_mode was set before. The requests are resolved asynchronously, 315 // after this call returns. 316 void ResolveAllPending(); 317 318 // Each request is assigned an ID when started and stored with the resolver 319 // for async resolution, starting with 1. IDs are not reused. Once a request 320 // completes, it is destroyed, and can no longer be accessed. 321 322 // Returns the ID of the most recently started still-active request. Zero if 323 // no requests are currently active. 324 size_t last_id(); 325 326 // Resolve request stored in |requests_|. Pass rv to callback. 327 void ResolveNow(size_t id); 328 329 // Detach cancelled request. 330 void DetachRequest(size_t id); 331 332 // Returns the hostname of the request with the given id. 333 base::StringPiece request_host(size_t id); 334 335 // Returns the priority of the request with the given id. 336 RequestPriority request_priority(size_t id); 337 338 // Returns NetworkAnonymizationKey of the request with the given id. 339 const NetworkAnonymizationKey& request_network_anonymization_key(size_t id); 340 341 // Like ResolveNow, but doesn't take an ID. DCHECKs if there's more than one 342 // pending request. 343 void ResolveOnlyRequestNow(); 344 345 // The number of times that Resolve() has been called. num_resolve()346 size_t num_resolve() const { return state_->num_resolve(); } 347 348 // The number of times that ResolveFromCache() has been called. num_resolve_from_cache()349 size_t num_resolve_from_cache() const { 350 return state_->num_resolve_from_cache(); 351 } 352 353 // The number of times resolve was attempted non-locally. num_non_local_resolves()354 size_t num_non_local_resolves() const { 355 return state_->num_non_local_resolves(); 356 } 357 358 // Returns the RequestPriority of the last call to Resolve() (or 359 // DEFAULT_PRIORITY if Resolve() hasn't been called yet). last_request_priority()360 RequestPriority last_request_priority() const { 361 return last_request_priority_; 362 } 363 364 // Returns the NetworkAnonymizationKey passed in to the last call to Resolve() 365 // (or absl::nullopt if Resolve() hasn't been called yet). 366 const absl::optional<NetworkAnonymizationKey>& last_request_network_anonymization_key()367 last_request_network_anonymization_key() { 368 return last_request_network_anonymization_key_; 369 } 370 371 // Returns the SecureDnsPolicy of the last call to Resolve() (or 372 // absl::nullopt if Resolve() hasn't been called yet). last_secure_dns_policy()373 SecureDnsPolicy last_secure_dns_policy() const { 374 return last_secure_dns_policy_; 375 } 376 IsDohProbeRunning()377 bool IsDohProbeRunning() const { return state_->IsDohProbeRunning(); } 378 379 void TriggerMdnsListeners(const HostPortPair& host, 380 DnsQueryType query_type, 381 MdnsListenerUpdateType update_type, 382 const IPEndPoint& address_result); 383 void TriggerMdnsListeners(const HostPortPair& host, 384 DnsQueryType query_type, 385 MdnsListenerUpdateType update_type, 386 const std::vector<std::string>& text_result); 387 void TriggerMdnsListeners(const HostPortPair& host, 388 DnsQueryType query_type, 389 MdnsListenerUpdateType update_type, 390 const HostPortPair& host_result); 391 void TriggerMdnsListeners(const HostPortPair& host, 392 DnsQueryType query_type, 393 MdnsListenerUpdateType update_type); 394 set_tick_clock(const base::TickClock * tick_clock)395 void set_tick_clock(const base::TickClock* tick_clock) { 396 tick_clock_ = tick_clock; 397 } 398 399 private: 400 friend class MockHostResolver; 401 friend class MockCachingHostResolver; 402 friend class MockHostResolverFactory; 403 404 // Returns the request with the given id. 405 RequestImpl* request(size_t id); 406 407 // If > 0, |cache_invalidation_num| is the number of times a cached entry can 408 // be read before it invalidates itself. Useful to force cache expiration 409 // scenarios. 410 MockHostResolverBase(bool use_caching, 411 int cache_invalidation_num, 412 RuleResolver rule_resolver); 413 414 // Handle resolution for |request|. Expected to be called only the RequestImpl 415 // object itself. 416 int Resolve(RequestImpl* request); 417 418 // Resolve as IP or from |cache_| return cached error or 419 // DNS_CACHE_MISS if failed. 420 int ResolveFromIPLiteralOrCache( 421 const Host& endpoint, 422 const NetworkAnonymizationKey& network_anonymization_key, 423 DnsQueryType dns_query_type, 424 HostResolverFlags flags, 425 HostResolverSource source, 426 HostResolver::ResolveHostParameters::CacheUsage cache_usage, 427 std::vector<HostResolverEndpointResult>* out_endpoints, 428 std::set<std::string>* out_aliases, 429 absl::optional<HostCache::EntryStaleness>* out_stale_info); 430 int DoSynchronousResolution(RequestImpl& request); 431 432 void AddListener(MdnsListenerImpl* listener); 433 void RemoveCancelledListener(MdnsListenerImpl* listener); 434 435 RequestPriority last_request_priority_ = DEFAULT_PRIORITY; 436 absl::optional<NetworkAnonymizationKey> 437 last_request_network_anonymization_key_; 438 SecureDnsPolicy last_secure_dns_policy_ = SecureDnsPolicy::kAllow; 439 bool synchronous_mode_ = false; 440 bool ondemand_mode_ = false; 441 RuleResolver rule_resolver_; 442 std::unique_ptr<HostCache> cache_; 443 444 const int initial_cache_invalidation_num_; 445 std::map<HostCache::Key, int> cache_invalidation_nums_; 446 447 std::set<MdnsListenerImpl*> listeners_; 448 449 size_t next_request_id_ = 1; 450 451 raw_ptr<const base::TickClock> tick_clock_; 452 453 scoped_refptr<State> state_; 454 455 THREAD_CHECKER(thread_checker_); 456 }; 457 458 class MockHostResolver : public MockHostResolverBase { 459 public: 460 explicit MockHostResolver(absl::optional<RuleResolver::RuleResultOrError> 461 default_result = absl::nullopt) 462 : MockHostResolverBase(/*use_caching=*/false, 463 /*cache_invalidation_num=*/0, RuleResolver(std::move (default_result))464 RuleResolver(std::move(default_result))) {} 465 ~MockHostResolver() override = default; 466 }; 467 468 // Same as MockHostResolver, except internally it uses a host-cache. 469 // 470 // Note that tests are advised to use MockHostResolver instead, since it is 471 // more predictable. (MockHostResolver also can be put into synchronous 472 // operation mode in case that is what you needed from the caching version). 473 class MockCachingHostResolver : public MockHostResolverBase { 474 public: 475 // If > 0, |cache_invalidation_num| is the number of times a cached entry can 476 // be read before it invalidates itself. Useful to force cache expiration 477 // scenarios. 478 explicit MockCachingHostResolver( 479 int cache_invalidation_num = 0, 480 absl::optional<RuleResolver::RuleResultOrError> default_result = 481 absl::nullopt) MockHostResolverBase(true,cache_invalidation_num,RuleResolver (std::move (default_result)))482 : MockHostResolverBase(/*use_caching=*/true, 483 cache_invalidation_num, 484 RuleResolver(std::move(default_result))) {} 485 ~MockCachingHostResolver() override = default; 486 }; 487 488 // Factory that will always create and return Mock(Caching)HostResolvers. 489 // 490 // The default behavior is to create a non-caching mock, even if the tested code 491 // requests caching enabled (via the |enable_caching| parameter in the creation 492 // methods). A caching mock will only be created if both |use_caching| is set on 493 // factory construction and |enable_caching| is set in the creation method. 494 class MockHostResolverFactory : public HostResolver::Factory { 495 public: 496 explicit MockHostResolverFactory(MockHostResolverBase::RuleResolver rules = 497 MockHostResolverBase::RuleResolver(), 498 bool use_caching = false, 499 int cache_invalidation_num = 0); 500 501 MockHostResolverFactory(const MockHostResolverFactory&) = delete; 502 MockHostResolverFactory& operator=(const MockHostResolverFactory&) = delete; 503 504 ~MockHostResolverFactory() override; 505 506 std::unique_ptr<HostResolver> CreateResolver( 507 HostResolverManager* manager, 508 base::StringPiece host_mapping_rules, 509 bool enable_caching) override; 510 std::unique_ptr<HostResolver> CreateStandaloneResolver( 511 NetLog* net_log, 512 const HostResolver::ManagerOptions& options, 513 base::StringPiece host_mapping_rules, 514 bool enable_caching) override; 515 516 private: 517 const MockHostResolverBase::RuleResolver rules_; 518 const bool use_caching_; 519 const int cache_invalidation_num_; 520 }; 521 522 // RuleBasedHostResolverProc applies a set of rules to map a host string to 523 // a replacement host string. It then uses the system host resolver to return 524 // a socket address. Generally the replacement should be an IPv4 literal so 525 // there is no network dependency. 526 // 527 // RuleBasedHostResolverProc is thread-safe, to a limited degree. Rules can be 528 // added or removed on any thread. 529 class RuleBasedHostResolverProc : public HostResolverProc { 530 public: 531 // If `allow_fallback` is false, no Proc fallback is allowed except to 532 // `previous`. 533 explicit RuleBasedHostResolverProc(scoped_refptr<HostResolverProc> previous, 534 bool allow_fallback = true); 535 536 // Any hostname matching the given pattern will be replaced with the given 537 // |ip_literal|. 538 void AddRule(base::StringPiece host_pattern, base::StringPiece ip_literal); 539 540 // Same as AddRule(), but further restricts to |address_family|. 541 void AddRuleForAddressFamily(base::StringPiece host_pattern, 542 AddressFamily address_family, 543 base::StringPiece ip_literal); 544 545 void AddRuleWithFlags(base::StringPiece host_pattern, 546 base::StringPiece ip_literal, 547 HostResolverFlags flags, 548 std::vector<std::string> dns_aliases = {}); 549 550 // Same as AddRule(), but the replacement is expected to be an IPv4 or IPv6 551 // literal. This can be used in place of AddRule() to bypass the system's 552 // host resolver (the address list will be constructed manually). 553 // If |canonical_name| is non-empty, it is copied to the resulting AddressList 554 // but does not impact DNS resolution. 555 // |ip_literal| can be a single IP address like "192.168.1.1" or a comma 556 // separated list of IP addresses, like "::1,192:168.1.2". 557 void AddIPLiteralRule(base::StringPiece host_pattern, 558 base::StringPiece ip_literal, 559 base::StringPiece canonical_name); 560 561 // Same as AddIPLiteralRule, but with a parameter allowing multiple DNS 562 // aliases, such as CNAME aliases, instead of only the canonical name. While 563 // a simulation using HostResolverProc to obtain more than a single DNS alias 564 // is currently unrealistic, this capability is useful for clients of 565 // MockHostResolver who need to be able to obtain aliases and can be 566 // agnostic about how the host resolution took place, as the alternative, 567 // MockDnsClient, is not currently hooked up to MockHostResolver. 568 void AddIPLiteralRuleWithDnsAliases(base::StringPiece host_pattern, 569 base::StringPiece ip_literal, 570 std::vector<std::string> dns_aliases); 571 572 void AddRuleWithLatency(base::StringPiece host_pattern, 573 base::StringPiece replacement, 574 int latency_ms); 575 576 // Make sure that |host| will not be re-mapped or even processed by underlying 577 // host resolver procedures. It can also be a pattern. 578 void AllowDirectLookup(base::StringPiece host); 579 580 // Simulate a lookup failure for |host| (it also can be a pattern). 581 void AddSimulatedFailure( 582 base::StringPiece host, 583 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY); 584 585 // Simulate a lookup timeout failure for |host| (it also can be a pattern). 586 void AddSimulatedTimeoutFailure( 587 base::StringPiece host, 588 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY); 589 590 // Deletes all the rules that have been added. 591 void ClearRules(); 592 593 // Causes method calls that add or delete rules to assert. 594 // TODO(jam): once this class isn't used by tests that use an out of process 595 // network service, remove this method and make Rule private. 596 void DisableModifications(); 597 598 // HostResolverProc methods: 599 int Resolve(const std::string& host, 600 AddressFamily address_family, 601 HostResolverFlags host_resolver_flags, 602 AddressList* addrlist, 603 int* os_error) override; 604 605 struct Rule { 606 // TODO(https://crbug.com/1298106) Deduplicate this enum's definition. 607 enum ResolverType { 608 kResolverTypeFail, 609 kResolverTypeFailTimeout, 610 // TODO(mmenke): Is it really reasonable for a "mock" host resolver to 611 // fall back to the system resolver? 612 kResolverTypeSystem, 613 kResolverTypeIPLiteral, 614 }; 615 616 Rule(ResolverType resolver_type, 617 base::StringPiece host_pattern, 618 AddressFamily address_family, 619 HostResolverFlags host_resolver_flags, 620 base::StringPiece replacement, 621 std::vector<std::string> dns_aliases, 622 int latency_ms); 623 Rule(const Rule& other); 624 ~Rule(); 625 626 ResolverType resolver_type; 627 std::string host_pattern; 628 AddressFamily address_family; 629 HostResolverFlags host_resolver_flags; 630 std::string replacement; 631 std::vector<std::string> dns_aliases; 632 int latency_ms; // In milliseconds. 633 }; 634 635 typedef std::list<Rule> RuleList; 636 637 RuleList GetRules(); 638 639 // Returns the number of calls to Resolve() where |host| matched 640 // |host_pattern|. 641 size_t NumResolvesForHostPattern(base::StringPiece host_pattern); 642 643 private: 644 ~RuleBasedHostResolverProc() override; 645 646 void AddRuleInternal(const Rule& rule); 647 648 RuleList rules_ GUARDED_BY(rule_lock_); 649 650 // Tracks the number of calls to Resolve() where |host| matches a rule's host 651 // pattern. 652 std::map<base::StringPiece, size_t> num_resolves_per_host_pattern_ 653 GUARDED_BY(rule_lock_); 654 655 // Must be obtained before writing to or reading from |rules_|. 656 base::Lock rule_lock_; 657 658 // Whether changes are allowed. 659 bool modifications_allowed_ = true; 660 }; 661 662 // Create rules that map all requests to localhost. 663 scoped_refptr<RuleBasedHostResolverProc> CreateCatchAllHostResolverProc(); 664 665 // HangingHostResolver never completes its |Resolve| request. As LOCAL_ONLY 666 // requests are not allowed to complete asynchronously, they will always result 667 // in |ERR_DNS_CACHE_MISS|. 668 class HangingHostResolver : public HostResolver { 669 public: 670 // A set of states in HangingHostResolver. This is used to observe the 671 // internal state variables after destructing a MockHostResolver. 672 class State : public base::RefCounted<State> { 673 public: 674 State(); 675 num_cancellations()676 int num_cancellations() const { return num_cancellations_; } 677 IncrementNumCancellations()678 void IncrementNumCancellations() { ++num_cancellations_; } 679 680 private: 681 friend class RefCounted<State>; 682 683 ~State(); 684 685 int num_cancellations_ = 0; 686 }; 687 688 HangingHostResolver(); 689 ~HangingHostResolver() override; 690 void OnShutdown() override; 691 std::unique_ptr<ResolveHostRequest> CreateRequest( 692 url::SchemeHostPort host, 693 NetworkAnonymizationKey network_anonymization_key, 694 NetLogWithSource net_log, 695 absl::optional<ResolveHostParameters> optional_parameters) override; 696 std::unique_ptr<ResolveHostRequest> CreateRequest( 697 const HostPortPair& host, 698 const NetworkAnonymizationKey& network_anonymization_key, 699 const NetLogWithSource& net_log, 700 const absl::optional<ResolveHostParameters>& optional_parameters) 701 override; 702 703 std::unique_ptr<ProbeRequest> CreateDohProbeRequest() override; 704 705 void SetRequestContext(URLRequestContext* url_request_context) override; 706 707 // Use to detect cancellations since there's otherwise no externally-visible 708 // differentiation between a cancelled and a hung task. num_cancellations()709 int num_cancellations() const { return state_->num_cancellations(); } 710 711 // Return the corresponding values passed to the most recent call to 712 // CreateRequest() last_host()713 const HostPortPair& last_host() const { return last_host_; } last_network_anonymization_key()714 const NetworkAnonymizationKey& last_network_anonymization_key() const { 715 return last_network_anonymization_key_; 716 } 717 state()718 const scoped_refptr<const State> state() const { return state_; } 719 720 private: 721 class RequestImpl; 722 class ProbeRequestImpl; 723 724 HostPortPair last_host_; 725 NetworkAnonymizationKey last_network_anonymization_key_; 726 727 scoped_refptr<State> state_; 728 bool shutting_down_ = false; 729 base::WeakPtrFactory<HangingHostResolver> weak_ptr_factory_{this}; 730 }; 731 732 // This class sets the default HostResolverProc for a particular scope. The 733 // chain of resolver procs starting at |proc| is placed in front of any existing 734 // default resolver proc(s). This means that if multiple 735 // ScopedDefaultHostResolverProcs are declared, then resolving will start with 736 // the procs given to the last-allocated one, then fall back to the procs given 737 // to the previously-allocated one, and so forth. 738 // 739 // NOTE: Only use this as a catch-all safety net. Individual tests should use 740 // MockHostResolver. 741 class ScopedDefaultHostResolverProc { 742 public: 743 ScopedDefaultHostResolverProc(); 744 explicit ScopedDefaultHostResolverProc(HostResolverProc* proc); 745 746 ~ScopedDefaultHostResolverProc(); 747 748 void Init(HostResolverProc* proc); 749 750 private: 751 scoped_refptr<HostResolverProc> current_proc_; 752 scoped_refptr<HostResolverProc> previous_proc_; 753 }; 754 755 } // namespace net 756 757 #endif // NET_DNS_MOCK_HOST_RESOLVER_H_ 758