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
15namespace net {
16
17class 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.
40class 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
83class 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).
94class 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.
104class 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.
155class 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.
183class 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