Home | History | Annotate | Download | only in base
      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 
     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 
     73 class 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).
     86 class 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.
     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:
    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.
    177 class 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