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 14 namespace net { 15 16 class 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. 39 class 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 rules()53 RuleBasedHostResolverProc* rules() { return rules_; } 54 55 // Controls whether resolutions complete synchronously or asynchronously. set_synchronous_mode(bool is_synchronous)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); ~MockHostResolverBase()65 virtual ~MockHostResolverBase() {} 66 67 scoped_refptr<HostResolverImpl> impl_; 68 scoped_refptr<RuleBasedHostResolverProc> rules_; 69 bool synchronous_mode_; 70 bool use_caching_; 71 }; 72 73 class MockHostResolver : public MockHostResolverBase { 74 public: MockHostResolver()75 MockHostResolver() : MockHostResolverBase(false /*use_caching*/) {} 76 77 private: ~MockHostResolver()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). 86 class MockCachingHostResolver : public MockHostResolverBase { 87 public: MockCachingHostResolver()88 MockCachingHostResolver() : MockHostResolverBase(true /*use_caching*/) {} 89 90 private: ~MockCachingHostResolver()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. 98 class 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. 145 class WaitingHostResolverProc : public HostResolverProc { 146 public: WaitingHostResolverProc(HostResolverProc * previous)147 explicit WaitingHostResolverProc(HostResolverProc* previous) 148 : HostResolverProc(previous), event_(false, false) {} 149 Signal()150 void Signal() { 151 event_.Signal(); 152 } 153 154 // HostResolverProc methods: Resolve(const std::string & host,AddressFamily address_family,AddressList * addrlist)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: ~WaitingHostResolverProc()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. 177 class ScopedDefaultHostResolverProc { 178 public: ScopedDefaultHostResolverProc()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