mock_host_resolver.h revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 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_BASE_MOCK_HOST_RESOLVER_H_ 6#define NET_BASE_MOCK_HOST_RESOLVER_H_ 7 8#include <list> 9 10#include "base/waitable_event.h" 11#include "net/base/host_resolver_impl.h" 12#include "net/base/host_resolver_proc.h" 13 14namespace net { 15 16class RuleBasedHostResolverProc; 17 18// In most cases, it is important that unit tests avoid making actual DNS 19// queries since the resulting tests can be flaky, especially if the network is 20// unreliable for some reason. To simplify writing tests that avoid making 21// actual DNS queries, pass a MockHostResolver as the HostResolver dependency. 22// The socket addresses returned can be configured using the 23// RuleBasedHostResolverProc: 24// 25// host_resolver->rules()->AddRule("foo.com", "1.2.3.4"); 26// host_resolver->rules()->AddRule("bar.com", "2.3.4.5"); 27// 28// The above rules define a static mapping from hostnames to IP address 29// literals. The first parameter to AddRule specifies a host pattern to match 30// against, and the second parameter indicates what value should be used to 31// replace the given hostname. So, the following is also supported: 32// 33// host_mapper->AddRule("*.com", "127.0.0.1"); 34// 35// Replacement doesn't have to be string representing an IP address. It can 36// re-map one hostname to another as well. 37 38// Base class shared by MockHostResolver and MockCachingHostResolver. 39class MockHostResolverBase : public HostResolver { 40 public: 41 // HostResolver methods: 42 virtual int Resolve(const RequestInfo& info, 43 AddressList* addresses, 44 CompletionCallback* callback, 45 RequestHandle* out_req, 46 LoadLog* load_log); 47 virtual void CancelRequest(RequestHandle req); 48 virtual void AddObserver(Observer* observer); 49 virtual void RemoveObserver(Observer* observer); 50 // TODO(eroman): temp hack for http://crbug.com/18373 51 virtual void Shutdown(); 52 53 RuleBasedHostResolverProc* rules() { return rules_; } 54 55 // Controls whether resolutions complete synchronously or asynchronously. 56 void set_synchronous_mode(bool is_synchronous) { 57 synchronous_mode_ = is_synchronous; 58 } 59 60 // Resets the mock. 61 void Reset(HostResolverProc* interceptor); 62 63 protected: 64 MockHostResolverBase(bool use_caching); 65 virtual ~MockHostResolverBase() {} 66 67 scoped_refptr<HostResolverImpl> impl_; 68 scoped_refptr<RuleBasedHostResolverProc> rules_; 69 bool synchronous_mode_; 70 bool use_caching_; 71}; 72 73class MockHostResolver : public MockHostResolverBase { 74 public: 75 MockHostResolver() : MockHostResolverBase(false /*use_caching*/) {} 76 77 private: 78 virtual ~MockHostResolver() {} 79}; 80 81// Same as MockHostResolver, except internally it uses a host-cache. 82// 83// Note that tests are advised to use MockHostResolver instead, since it is 84// more predictable. (MockHostResolver also can be put into synchronous 85// operation mode in case that is what you needed from the caching version). 86class MockCachingHostResolver : public MockHostResolverBase { 87 public: 88 MockCachingHostResolver() : MockHostResolverBase(true /*use_caching*/) {} 89 90 private: 91 ~MockCachingHostResolver() {} 92}; 93 94// RuleBasedHostResolverProc applies a set of rules to map a host string to 95// a replacement host string. It then uses the system host resolver to return 96// a socket address. Generally the replacement should be an IPv4 literal so 97// there is no network dependency. 98class RuleBasedHostResolverProc : public HostResolverProc { 99 public: 100 explicit RuleBasedHostResolverProc(HostResolverProc* previous); 101 102 // Any hostname matching the given pattern will be replaced with the given 103 // replacement value. Usually, replacement should be an IP address literal. 104 void AddRule(const std::string& host_pattern, 105 const std::string& replacement); 106 107 // Same as AddRule(), but further restricts to |address_family|. 108 void AddRuleForAddressFamily(const std::string& host_pattern, 109 AddressFamily address_family, 110 const std::string& replacement); 111 112 // Same as AddRule(), but the replacement is expected to be an IPV6 literal. 113 // You should use this in place of AddRule(), since the system's host resolver 114 // may not support IPv6 literals on all systems. Whereas this variant 115 // constructs the socket address directly so it will always work. 116 void AddIPv6Rule(const std::string& host_pattern, 117 const std::string& ipv6_literal); 118 119 void AddRuleWithLatency(const std::string& host_pattern, 120 const std::string& replacement, 121 int latency_ms); 122 123 // Make sure that |host| will not be re-mapped or even processed by underlying 124 // host resolver procedures. It can also be a pattern. 125 void AllowDirectLookup(const std::string& host); 126 127 // Simulate a lookup failure for |host| (it also can be a pattern). 128 void AddSimulatedFailure(const std::string& host); 129 130 // HostResolverProc methods: 131 virtual int Resolve(const std::string& host, 132 AddressFamily address_family, 133 AddressList* addrlist); 134 135 private: 136 ~RuleBasedHostResolverProc(); 137 138 struct Rule; 139 typedef std::list<Rule> RuleList; 140 141 RuleList rules_; 142}; 143 144// Using WaitingHostResolverProc you can simulate very long lookups. 145class WaitingHostResolverProc : public HostResolverProc { 146 public: 147 explicit WaitingHostResolverProc(HostResolverProc* previous) 148 : HostResolverProc(previous), event_(false, false) {} 149 150 void Signal() { 151 event_.Signal(); 152 } 153 154 // HostResolverProc methods: 155 virtual int Resolve(const std::string& host, 156 AddressFamily address_family, 157 AddressList* addrlist) { 158 event_.Wait(); 159 return ResolveUsingPrevious(host, address_family, addrlist); 160 } 161 162 private: 163 ~WaitingHostResolverProc() {} 164 165 base::WaitableEvent event_; 166}; 167 168// This class sets the default HostResolverProc for a particular scope. The 169// chain of resolver procs starting at |proc| is placed in front of any existing 170// default resolver proc(s). This means that if multiple 171// ScopedDefaultHostResolverProcs are declared, then resolving will start with 172// the procs given to the last-allocated one, then fall back to the procs given 173// to the previously-allocated one, and so forth. 174// 175// NOTE: Only use this as a catch-all safety net. Individual tests should use 176// MockHostResolver. 177class ScopedDefaultHostResolverProc { 178 public: 179 ScopedDefaultHostResolverProc() {} 180 explicit ScopedDefaultHostResolverProc(HostResolverProc* proc); 181 182 ~ScopedDefaultHostResolverProc(); 183 184 void Init(HostResolverProc* proc); 185 186 private: 187 scoped_refptr<HostResolverProc> current_proc_; 188 scoped_refptr<HostResolverProc> previous_proc_; 189}; 190 191} // namespace net 192 193#endif // NET_BASE_MOCK_HOST_RESOLVER_H_ 194