| Index: net/dns/dns_session_unittest.cc
 | 
| diff --git a/net/dns/dns_session_unittest.cc b/net/dns/dns_session_unittest.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..d0a12f2636fdd2e0f92dae9fcfd4695089627ddb
 | 
| --- /dev/null
 | 
| +++ b/net/dns/dns_session_unittest.cc
 | 
| @@ -0,0 +1,225 @@
 | 
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 | 
| +// Use of this source code is governed by a BSD-style license that can be
 | 
| +// found in the LICENSE file.
 | 
| +
 | 
| +#include "net/dns/dns_session.h"
 | 
| +
 | 
| +#include <list>
 | 
| +
 | 
| +#include "base/bind.h"
 | 
| +#include "base/memory/scoped_ptr.h"
 | 
| +#include "base/rand_util.h"
 | 
| +#include "base/stl_util.h"
 | 
| +#include "net/base/net_log.h"
 | 
| +#include "net/dns/dns_protocol.h"
 | 
| +#include "net/dns/dns_socket_pool.h"
 | 
| +#include "net/socket/socket_test_util.h"
 | 
| +#include "testing/gtest/include/gtest/gtest.h"
 | 
| +
 | 
| +namespace net {
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +class TestClientSocketFactory : public ClientSocketFactory {
 | 
| + public:
 | 
| +  virtual ~TestClientSocketFactory();
 | 
| +
 | 
| +  virtual DatagramClientSocket* CreateDatagramClientSocket(
 | 
| +      DatagramSocket::BindType bind_type,
 | 
| +      const RandIntCallback& rand_int_cb,
 | 
| +      net::NetLog* net_log,
 | 
| +      const net::NetLog::Source& source) OVERRIDE;
 | 
| +
 | 
| +  virtual StreamSocket* CreateTransportClientSocket(
 | 
| +      const AddressList& addresses,
 | 
| +      NetLog*, const NetLog::Source&) OVERRIDE {
 | 
| +    NOTIMPLEMENTED();
 | 
| +    return NULL;
 | 
| +  }
 | 
| +
 | 
| +  virtual SSLClientSocket* CreateSSLClientSocket(
 | 
| +      ClientSocketHandle* transport_socket,
 | 
| +      const HostPortPair& host_and_port,
 | 
| +      const SSLConfig& ssl_config,
 | 
| +      const SSLClientSocketContext& context) OVERRIDE {
 | 
| +    NOTIMPLEMENTED();
 | 
| +    return NULL;
 | 
| +  }
 | 
| +
 | 
| +  virtual void ClearSSLSessionCache() OVERRIDE {
 | 
| +    NOTIMPLEMENTED();
 | 
| +  }
 | 
| +
 | 
| + private:
 | 
| +  std::list<SocketDataProvider*> data_providers_;
 | 
| +};
 | 
| +
 | 
| +struct PoolEvent {
 | 
| +  enum { ALLOCATE, FREE } action;
 | 
| +  unsigned server_index;
 | 
| +};
 | 
| +
 | 
| +class DnsSessionTest : public testing::Test {
 | 
| + public:
 | 
| +  void OnSocketAllocated(unsigned server_index);
 | 
| +  void OnSocketFreed(unsigned server_index);
 | 
| +
 | 
| + protected:
 | 
| +  void Initialize(unsigned num_servers);
 | 
| +  scoped_ptr<DnsSession::SocketLease> Allocate(unsigned server_index);
 | 
| +  bool DidAllocate(unsigned server_index);
 | 
| +  bool DidFree(unsigned server_index);
 | 
| +  bool NoMoreEvents();
 | 
| +
 | 
| +  DnsConfig config_;
 | 
| +  scoped_ptr<TestClientSocketFactory> test_client_socket_factory_;
 | 
| +  scoped_refptr<DnsSession> session_;
 | 
| +  NetLog::Source source_;
 | 
| +
 | 
| + private:
 | 
| +  bool ExpectEvent(const PoolEvent& event);
 | 
| +  std::list<PoolEvent> events_;
 | 
| +};
 | 
| +
 | 
| +class MockDnsSocketPool : public DnsSocketPool {
 | 
| + public:
 | 
| +  MockDnsSocketPool(ClientSocketFactory* factory, DnsSessionTest* test)
 | 
| +     : DnsSocketPool(factory), test_(test) { }
 | 
| +
 | 
| +  virtual ~MockDnsSocketPool() { }
 | 
| +
 | 
| +  virtual void Initialize(
 | 
| +      const std::vector<IPEndPoint>* nameservers,
 | 
| +      NetLog* net_log) OVERRIDE {
 | 
| +    InitializeInternal(nameservers, net_log);
 | 
| +  }
 | 
| +
 | 
| +  virtual scoped_ptr<DatagramClientSocket> AllocateSocket(
 | 
| +      unsigned server_index) OVERRIDE {
 | 
| +    test_->OnSocketAllocated(server_index);
 | 
| +    return CreateConnectedSocket(server_index);
 | 
| +  }
 | 
| +
 | 
| +  virtual void FreeSocket(
 | 
| +      unsigned server_index,
 | 
| +      scoped_ptr<DatagramClientSocket> socket) OVERRIDE {
 | 
| +    test_->OnSocketFreed(server_index);
 | 
| +  }
 | 
| +
 | 
| + private:
 | 
| +  DnsSessionTest* test_;
 | 
| +};
 | 
| +
 | 
| +void DnsSessionTest::Initialize(unsigned num_servers) {
 | 
| +  CHECK(num_servers < 256u);
 | 
| +  config_.nameservers.clear();
 | 
| +  IPAddressNumber dns_ip;
 | 
| +  bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
 | 
| +  EXPECT_TRUE(rv);
 | 
| +  for (unsigned char i = 0; i < num_servers; ++i) {
 | 
| +    dns_ip[3] = i;
 | 
| +    IPEndPoint dns_endpoint(dns_ip, dns_protocol::kDefaultPort);
 | 
| +    config_.nameservers.push_back(dns_endpoint);
 | 
| +  }
 | 
| +
 | 
| +  test_client_socket_factory_.reset(new TestClientSocketFactory());
 | 
| +
 | 
| +  DnsSocketPool* dns_socket_pool =
 | 
| +      new MockDnsSocketPool(test_client_socket_factory_.get(), this);
 | 
| +
 | 
| +  session_ = new DnsSession(config_,
 | 
| +                            scoped_ptr<DnsSocketPool>(dns_socket_pool),
 | 
| +                            base::Bind(&base::RandInt),
 | 
| +                            NULL /* NetLog */);
 | 
| +
 | 
| +  events_.clear();
 | 
| +}
 | 
| +
 | 
| +scoped_ptr<DnsSession::SocketLease> DnsSessionTest::Allocate(
 | 
| +    unsigned server_index) {
 | 
| +  return session_->AllocateSocket(server_index, source_);
 | 
| +}
 | 
| +
 | 
| +bool DnsSessionTest::DidAllocate(unsigned server_index) {
 | 
| +  PoolEvent expected_event = { PoolEvent::ALLOCATE, server_index };
 | 
| +  return ExpectEvent(expected_event);
 | 
| +}
 | 
| +
 | 
| +bool DnsSessionTest::DidFree(unsigned server_index) {
 | 
| +  PoolEvent expected_event = { PoolEvent::FREE, server_index };
 | 
| +  return ExpectEvent(expected_event);
 | 
| +}
 | 
| +
 | 
| +bool DnsSessionTest::NoMoreEvents() {
 | 
| +  return events_.empty();
 | 
| +}
 | 
| +
 | 
| +void DnsSessionTest::OnSocketAllocated(unsigned server_index) {
 | 
| +  PoolEvent event = { PoolEvent::ALLOCATE, server_index };
 | 
| +  events_.push_back(event);
 | 
| +}
 | 
| +
 | 
| +void DnsSessionTest::OnSocketFreed(unsigned server_index) {
 | 
| +  PoolEvent event = { PoolEvent::FREE, server_index };
 | 
| +  events_.push_back(event);
 | 
| +}
 | 
| +
 | 
| +bool DnsSessionTest::ExpectEvent(const PoolEvent& expected) {
 | 
| +  if (events_.empty()) {
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  const PoolEvent actual = events_.front();
 | 
| +  if ((expected.action != actual.action)
 | 
| +      || (expected.server_index != actual.server_index)) {
 | 
| +    return false;
 | 
| +  }
 | 
| +  events_.pop_front();
 | 
| +
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +DatagramClientSocket* TestClientSocketFactory::CreateDatagramClientSocket(
 | 
| +    DatagramSocket::BindType bind_type,
 | 
| +    const RandIntCallback& rand_int_cb,
 | 
| +    net::NetLog* net_log,
 | 
| +    const net::NetLog::Source& source) {
 | 
| +  // We're not actually expecting to send or receive any data, so use the
 | 
| +  // simplest SocketDataProvider with no data supplied.
 | 
| +  SocketDataProvider* data_provider = new StaticSocketDataProvider();
 | 
| +  data_providers_.push_back(data_provider);
 | 
| +  MockUDPClientSocket* socket = new MockUDPClientSocket(data_provider, net_log);
 | 
| +  data_provider->set_socket(socket);
 | 
| +  return socket;
 | 
| +}
 | 
| +
 | 
| +TestClientSocketFactory::~TestClientSocketFactory() {
 | 
| +  STLDeleteElements(&data_providers_);
 | 
| +}
 | 
| +
 | 
| +TEST_F(DnsSessionTest, AllocateFree) {
 | 
| +  scoped_ptr<DnsSession::SocketLease> lease1, lease2;
 | 
| +
 | 
| +  Initialize(2);
 | 
| +  EXPECT_TRUE(NoMoreEvents());
 | 
| +
 | 
| +  lease1 = Allocate(0);
 | 
| +  EXPECT_TRUE(DidAllocate(0));
 | 
| +  EXPECT_TRUE(NoMoreEvents());
 | 
| +
 | 
| +  lease2 = Allocate(1);
 | 
| +  EXPECT_TRUE(DidAllocate(1));
 | 
| +  EXPECT_TRUE(NoMoreEvents());
 | 
| +
 | 
| +  lease1.reset();
 | 
| +  EXPECT_TRUE(DidFree(0));
 | 
| +  EXPECT_TRUE(NoMoreEvents());
 | 
| +
 | 
| +  lease2.reset();
 | 
| +  EXPECT_TRUE(DidFree(1));
 | 
| +  EXPECT_TRUE(NoMoreEvents());
 | 
| +}
 | 
| +
 | 
| +} // namespace
 | 
| +
 | 
| +} // namespace net
 | 
| 
 |