Home | History | Annotate | Download | only in dns
      1 // Copyright (c) 2012 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 #include "net/dns/dns_session.h"
      6 
      7 #include <list>
      8 
      9 #include "base/bind.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/rand_util.h"
     12 #include "base/stl_util.h"
     13 #include "net/base/net_log.h"
     14 #include "net/dns/dns_protocol.h"
     15 #include "net/dns/dns_socket_pool.h"
     16 #include "net/socket/socket_test_util.h"
     17 #include "net/socket/ssl_client_socket.h"
     18 #include "net/socket/stream_socket.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 namespace net {
     22 
     23 namespace {
     24 
     25 class TestClientSocketFactory : public ClientSocketFactory {
     26  public:
     27   virtual ~TestClientSocketFactory();
     28 
     29   virtual scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket(
     30       DatagramSocket::BindType bind_type,
     31       const RandIntCallback& rand_int_cb,
     32       net::NetLog* net_log,
     33       const net::NetLog::Source& source) OVERRIDE;
     34 
     35   virtual scoped_ptr<StreamSocket> CreateTransportClientSocket(
     36       const AddressList& addresses,
     37       NetLog*, const NetLog::Source&) OVERRIDE {
     38     NOTIMPLEMENTED();
     39     return scoped_ptr<StreamSocket>();
     40   }
     41 
     42   virtual scoped_ptr<SSLClientSocket> CreateSSLClientSocket(
     43       scoped_ptr<ClientSocketHandle> transport_socket,
     44       const HostPortPair& host_and_port,
     45       const SSLConfig& ssl_config,
     46       const SSLClientSocketContext& context) OVERRIDE {
     47     NOTIMPLEMENTED();
     48     return scoped_ptr<SSLClientSocket>();
     49   }
     50 
     51   virtual void ClearSSLSessionCache() OVERRIDE {
     52     NOTIMPLEMENTED();
     53   }
     54 
     55  private:
     56   std::list<SocketDataProvider*> data_providers_;
     57 };
     58 
     59 struct PoolEvent {
     60   enum { ALLOCATE, FREE } action;
     61   unsigned server_index;
     62 };
     63 
     64 class DnsSessionTest : public testing::Test {
     65  public:
     66   void OnSocketAllocated(unsigned server_index);
     67   void OnSocketFreed(unsigned server_index);
     68 
     69  protected:
     70   void Initialize(unsigned num_servers);
     71   scoped_ptr<DnsSession::SocketLease> Allocate(unsigned server_index);
     72   bool DidAllocate(unsigned server_index);
     73   bool DidFree(unsigned server_index);
     74   bool NoMoreEvents();
     75 
     76   DnsConfig config_;
     77   scoped_ptr<TestClientSocketFactory> test_client_socket_factory_;
     78   scoped_refptr<DnsSession> session_;
     79   NetLog::Source source_;
     80 
     81  private:
     82   bool ExpectEvent(const PoolEvent& event);
     83   std::list<PoolEvent> events_;
     84 };
     85 
     86 class MockDnsSocketPool : public DnsSocketPool {
     87  public:
     88   MockDnsSocketPool(ClientSocketFactory* factory, DnsSessionTest* test)
     89      : DnsSocketPool(factory), test_(test) { }
     90 
     91   virtual ~MockDnsSocketPool() { }
     92 
     93   virtual void Initialize(
     94       const std::vector<IPEndPoint>* nameservers,
     95       NetLog* net_log) OVERRIDE {
     96     InitializeInternal(nameservers, net_log);
     97   }
     98 
     99   virtual scoped_ptr<DatagramClientSocket> AllocateSocket(
    100       unsigned server_index) OVERRIDE {
    101     test_->OnSocketAllocated(server_index);
    102     return CreateConnectedSocket(server_index);
    103   }
    104 
    105   virtual void FreeSocket(
    106       unsigned server_index,
    107       scoped_ptr<DatagramClientSocket> socket) OVERRIDE {
    108     test_->OnSocketFreed(server_index);
    109   }
    110 
    111  private:
    112   DnsSessionTest* test_;
    113 };
    114 
    115 void DnsSessionTest::Initialize(unsigned num_servers) {
    116   CHECK(num_servers < 256u);
    117   config_.nameservers.clear();
    118   IPAddressNumber dns_ip;
    119   bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
    120   EXPECT_TRUE(rv);
    121   for (unsigned char i = 0; i < num_servers; ++i) {
    122     dns_ip[3] = i;
    123     IPEndPoint dns_endpoint(dns_ip, dns_protocol::kDefaultPort);
    124     config_.nameservers.push_back(dns_endpoint);
    125   }
    126 
    127   test_client_socket_factory_.reset(new TestClientSocketFactory());
    128 
    129   DnsSocketPool* dns_socket_pool =
    130       new MockDnsSocketPool(test_client_socket_factory_.get(), this);
    131 
    132   session_ = new DnsSession(config_,
    133                             scoped_ptr<DnsSocketPool>(dns_socket_pool),
    134                             base::Bind(&base::RandInt),
    135                             NULL /* NetLog */);
    136 
    137   events_.clear();
    138 }
    139 
    140 scoped_ptr<DnsSession::SocketLease> DnsSessionTest::Allocate(
    141     unsigned server_index) {
    142   return session_->AllocateSocket(server_index, source_);
    143 }
    144 
    145 bool DnsSessionTest::DidAllocate(unsigned server_index) {
    146   PoolEvent expected_event = { PoolEvent::ALLOCATE, server_index };
    147   return ExpectEvent(expected_event);
    148 }
    149 
    150 bool DnsSessionTest::DidFree(unsigned server_index) {
    151   PoolEvent expected_event = { PoolEvent::FREE, server_index };
    152   return ExpectEvent(expected_event);
    153 }
    154 
    155 bool DnsSessionTest::NoMoreEvents() {
    156   return events_.empty();
    157 }
    158 
    159 void DnsSessionTest::OnSocketAllocated(unsigned server_index) {
    160   PoolEvent event = { PoolEvent::ALLOCATE, server_index };
    161   events_.push_back(event);
    162 }
    163 
    164 void DnsSessionTest::OnSocketFreed(unsigned server_index) {
    165   PoolEvent event = { PoolEvent::FREE, server_index };
    166   events_.push_back(event);
    167 }
    168 
    169 bool DnsSessionTest::ExpectEvent(const PoolEvent& expected) {
    170   if (events_.empty()) {
    171     return false;
    172   }
    173 
    174   const PoolEvent actual = events_.front();
    175   if ((expected.action != actual.action)
    176       || (expected.server_index != actual.server_index)) {
    177     return false;
    178   }
    179   events_.pop_front();
    180 
    181   return true;
    182 }
    183 
    184 scoped_ptr<DatagramClientSocket>
    185 TestClientSocketFactory::CreateDatagramClientSocket(
    186     DatagramSocket::BindType bind_type,
    187     const RandIntCallback& rand_int_cb,
    188     net::NetLog* net_log,
    189     const net::NetLog::Source& source) {
    190   // We're not actually expecting to send or receive any data, so use the
    191   // simplest SocketDataProvider with no data supplied.
    192   SocketDataProvider* data_provider = new StaticSocketDataProvider();
    193   data_providers_.push_back(data_provider);
    194   scoped_ptr<MockUDPClientSocket> socket(
    195       new MockUDPClientSocket(data_provider, net_log));
    196   data_provider->set_socket(socket.get());
    197   return socket.PassAs<DatagramClientSocket>();
    198 }
    199 
    200 TestClientSocketFactory::~TestClientSocketFactory() {
    201   STLDeleteElements(&data_providers_);
    202 }
    203 
    204 TEST_F(DnsSessionTest, AllocateFree) {
    205   scoped_ptr<DnsSession::SocketLease> lease1, lease2;
    206 
    207   Initialize(2);
    208   EXPECT_TRUE(NoMoreEvents());
    209 
    210   lease1 = Allocate(0);
    211   EXPECT_TRUE(DidAllocate(0));
    212   EXPECT_TRUE(NoMoreEvents());
    213 
    214   lease2 = Allocate(1);
    215   EXPECT_TRUE(DidAllocate(1));
    216   EXPECT_TRUE(NoMoreEvents());
    217 
    218   lease1.reset();
    219   EXPECT_TRUE(DidFree(0));
    220   EXPECT_TRUE(NoMoreEvents());
    221 
    222   lease2.reset();
    223   EXPECT_TRUE(DidFree(1));
    224   EXPECT_TRUE(NoMoreEvents());
    225 }
    226 
    227 // Expect default calculated timeout to be within 10ms of in DnsConfig.
    228 TEST_F(DnsSessionTest, HistogramTimeoutNormal) {
    229   Initialize(2);
    230   base::TimeDelta timeoutDelta = session_->NextTimeout(0, 0) - config_.timeout;
    231   EXPECT_LT(timeoutDelta.InMilliseconds(), 10);
    232 }
    233 
    234 // Expect short calculated timeout to be within 10ms of in DnsConfig.
    235 TEST_F(DnsSessionTest, HistogramTimeoutShort) {
    236   config_.timeout = base::TimeDelta::FromMilliseconds(15);
    237   Initialize(2);
    238   base::TimeDelta timeoutDelta = session_->NextTimeout(0, 0) - config_.timeout;
    239   EXPECT_LT(timeoutDelta.InMilliseconds(), 10);
    240 }
    241 
    242 // Expect long calculated timeout to be equal to one in DnsConfig.
    243 TEST_F(DnsSessionTest, HistogramTimeoutLong) {
    244   config_.timeout = base::TimeDelta::FromSeconds(15);
    245   Initialize(2);
    246   base::TimeDelta timeout = session_->NextTimeout(0, 0);
    247   EXPECT_EQ(config_.timeout.InMilliseconds(), timeout.InMilliseconds());
    248 }
    249 
    250 }  // namespace
    251 
    252 } // namespace net
    253