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