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