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.
5 #include "net/dns/dns_session.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/rand_util.h"
12 #include "base/stl_util.h"
13 #include "net/dns/dns_protocol.h"
14 #include "net/dns/dns_socket_pool.h"
15 #include "net/log/net_log.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"
25 class TestClientSocketFactory
: public ClientSocketFactory
{
27 ~TestClientSocketFactory() override
;
29 scoped_ptr
<DatagramClientSocket
> CreateDatagramClientSocket(
30 DatagramSocket::BindType bind_type
,
31 const RandIntCallback
& rand_int_cb
,
33 const NetLog::Source
& source
) override
;
35 scoped_ptr
<StreamSocket
> CreateTransportClientSocket(
36 const AddressList
& addresses
,
38 const NetLog::Source
&) override
{
40 return scoped_ptr
<StreamSocket
>();
43 scoped_ptr
<SSLClientSocket
> CreateSSLClientSocket(
44 scoped_ptr
<ClientSocketHandle
> transport_socket
,
45 const HostPortPair
& host_and_port
,
46 const SSLConfig
& ssl_config
,
47 const SSLClientSocketContext
& context
) override
{
49 return scoped_ptr
<SSLClientSocket
>();
52 void ClearSSLSessionCache() override
{ NOTIMPLEMENTED(); }
55 std::list
<SocketDataProvider
*> data_providers_
;
59 enum { ALLOCATE
, FREE
} action
;
60 unsigned server_index
;
63 class DnsSessionTest
: public testing::Test
{
65 void OnSocketAllocated(unsigned server_index
);
66 void OnSocketFreed(unsigned server_index
);
69 void Initialize(unsigned num_servers
);
70 scoped_ptr
<DnsSession::SocketLease
> Allocate(unsigned server_index
);
71 bool DidAllocate(unsigned server_index
);
72 bool DidFree(unsigned server_index
);
76 scoped_ptr
<TestClientSocketFactory
> test_client_socket_factory_
;
77 scoped_refptr
<DnsSession
> session_
;
78 NetLog::Source source_
;
81 bool ExpectEvent(const PoolEvent
& event
);
82 std::list
<PoolEvent
> events_
;
85 class MockDnsSocketPool
: public DnsSocketPool
{
87 MockDnsSocketPool(ClientSocketFactory
* factory
, DnsSessionTest
* test
)
88 : DnsSocketPool(factory
), test_(test
) { }
90 ~MockDnsSocketPool() override
{}
92 void Initialize(const std::vector
<IPEndPoint
>* nameservers
,
93 NetLog
* net_log
) override
{
94 InitializeInternal(nameservers
, net_log
);
97 scoped_ptr
<DatagramClientSocket
> AllocateSocket(
98 unsigned server_index
) override
{
99 test_
->OnSocketAllocated(server_index
);
100 return CreateConnectedSocket(server_index
);
103 void FreeSocket(unsigned server_index
,
104 scoped_ptr
<DatagramClientSocket
> socket
) override
{
105 test_
->OnSocketFreed(server_index
);
109 DnsSessionTest
* test_
;
112 void DnsSessionTest::Initialize(unsigned num_servers
) {
113 CHECK(num_servers
< 256u);
114 config_
.nameservers
.clear();
115 IPAddressNumber dns_ip
;
116 bool rv
= ParseIPLiteralToNumber("192.168.1.0", &dns_ip
);
118 for (unsigned char i
= 0; i
< num_servers
; ++i
) {
120 IPEndPoint
dns_endpoint(dns_ip
, dns_protocol::kDefaultPort
);
121 config_
.nameservers
.push_back(dns_endpoint
);
124 test_client_socket_factory_
.reset(new TestClientSocketFactory());
126 DnsSocketPool
* dns_socket_pool
=
127 new MockDnsSocketPool(test_client_socket_factory_
.get(), this);
129 session_
= new DnsSession(config_
,
130 scoped_ptr
<DnsSocketPool
>(dns_socket_pool
),
131 base::Bind(&base::RandInt
),
137 scoped_ptr
<DnsSession::SocketLease
> DnsSessionTest::Allocate(
138 unsigned server_index
) {
139 return session_
->AllocateSocket(server_index
, source_
);
142 bool DnsSessionTest::DidAllocate(unsigned server_index
) {
143 PoolEvent expected_event
= { PoolEvent::ALLOCATE
, server_index
};
144 return ExpectEvent(expected_event
);
147 bool DnsSessionTest::DidFree(unsigned server_index
) {
148 PoolEvent expected_event
= { PoolEvent::FREE
, server_index
};
149 return ExpectEvent(expected_event
);
152 bool DnsSessionTest::NoMoreEvents() {
153 return events_
.empty();
156 void DnsSessionTest::OnSocketAllocated(unsigned server_index
) {
157 PoolEvent event
= { PoolEvent::ALLOCATE
, server_index
};
158 events_
.push_back(event
);
161 void DnsSessionTest::OnSocketFreed(unsigned server_index
) {
162 PoolEvent event
= { PoolEvent::FREE
, server_index
};
163 events_
.push_back(event
);
166 bool DnsSessionTest::ExpectEvent(const PoolEvent
& expected
) {
167 if (events_
.empty()) {
171 const PoolEvent actual
= events_
.front();
172 if ((expected
.action
!= actual
.action
)
173 || (expected
.server_index
!= actual
.server_index
)) {
181 scoped_ptr
<DatagramClientSocket
>
182 TestClientSocketFactory::CreateDatagramClientSocket(
183 DatagramSocket::BindType bind_type
,
184 const RandIntCallback
& rand_int_cb
,
186 const NetLog::Source
& source
) {
187 // We're not actually expecting to send or receive any data, so use the
188 // simplest SocketDataProvider with no data supplied.
189 SocketDataProvider
* data_provider
= new StaticSocketDataProvider();
190 data_providers_
.push_back(data_provider
);
191 scoped_ptr
<MockUDPClientSocket
> socket(
192 new MockUDPClientSocket(data_provider
, net_log
));
193 data_provider
->set_socket(socket
.get());
194 return socket
.Pass();
197 TestClientSocketFactory::~TestClientSocketFactory() {
198 STLDeleteElements(&data_providers_
);
201 TEST_F(DnsSessionTest
, AllocateFree
) {
202 scoped_ptr
<DnsSession::SocketLease
> lease1
, lease2
;
205 EXPECT_TRUE(NoMoreEvents());
207 lease1
= Allocate(0);
208 EXPECT_TRUE(DidAllocate(0));
209 EXPECT_TRUE(NoMoreEvents());
211 lease2
= Allocate(1);
212 EXPECT_TRUE(DidAllocate(1));
213 EXPECT_TRUE(NoMoreEvents());
216 EXPECT_TRUE(DidFree(0));
217 EXPECT_TRUE(NoMoreEvents());
220 EXPECT_TRUE(DidFree(1));
221 EXPECT_TRUE(NoMoreEvents());
224 // Expect default calculated timeout to be within 10ms of in DnsConfig.
225 TEST_F(DnsSessionTest
, HistogramTimeoutNormal
) {
227 base::TimeDelta timeoutDelta
= session_
->NextTimeout(0, 0) - config_
.timeout
;
228 EXPECT_LT(timeoutDelta
.InMilliseconds(), 10);
231 // Expect short calculated timeout to be within 10ms of in DnsConfig.
232 TEST_F(DnsSessionTest
, HistogramTimeoutShort
) {
233 config_
.timeout
= base::TimeDelta::FromMilliseconds(15);
235 base::TimeDelta timeoutDelta
= session_
->NextTimeout(0, 0) - config_
.timeout
;
236 EXPECT_LT(timeoutDelta
.InMilliseconds(), 10);
239 // Expect long calculated timeout to be equal to one in DnsConfig.
240 TEST_F(DnsSessionTest
, HistogramTimeoutLong
) {
241 config_
.timeout
= base::TimeDelta::FromSeconds(15);
243 base::TimeDelta timeout
= session_
->NextTimeout(0, 0);
244 EXPECT_EQ(config_
.timeout
.InMilliseconds(), timeout
.InMilliseconds());