root/chrome/browser/net/network_stats_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SetUp
  2. TearDown
  3. CreateToken
  4. MakeDeterministicMockData
  5. TestStart
  6. MakeDelayedMockData
  7. TestStartOneTest
  8. TEST_F
  9. TEST_F
  10. TEST_F
  11. TEST_F
  12. TEST_F
  13. TEST_F
  14. TEST_F
  15. TEST_F
  16. TEST_F
  17. TEST_F
  18. TEST_F
  19. TEST_F
  20. TEST_F
  21. TEST_F
  22. TEST_F
  23. TEST_F
  24. TEST_F
  25. TEST_F
  26. TEST_F
  27. TEST_F
  28. TEST_F
  29. TEST_F
  30. TEST_F
  31. TEST_F
  32. TEST_F
  33. TEST_F
  34. TEST_F
  35. TEST_F
  36. TEST_F
  37. TEST_F
  38. TEST_F
  39. TEST_F
  40. TEST_F
  41. TEST_F
  42. TEST_F

// 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 "base/basictypes.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/net/network_stats.h"
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/host_resolver.h"
#include "net/dns/mock_host_resolver.h"
#include "net/socket/socket_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

namespace chrome_browser_net {

class NetworkStatsTest : public PlatformTest {
 public:
  NetworkStatsTest() {}

 protected:

  virtual void SetUp() {
    net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
    base::MessageLoop::current()->RunUntilIdle();
    mock_writes_.clear();
    mock_reads_.clear();
  }

  virtual void TearDown() {
    net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
    // Empty the current queue.
    base::MessageLoop::current()->RunUntilIdle();
    PlatformTest::TearDown();
  }

  void CreateToken(uint64 timestamp_micros,
                   const string& hash,
                   ProbePacket_Token* token) {
    token->set_timestamp_micros(timestamp_micros);
    token->mutable_hash()->assign(hash);
  }

  // DeterministicMockData defines the exact sequence of the read/write
  // operations (specified by the last parameter of MockRead/MockWrite).
  // |io_mode_write| is the IO mode for writing only. Reading is always async.
  void MakeDeterministicMockData(uint32 max_tests,
                                 uint32 max_probe_packets,
                                 uint32 probe_bytes,
                                 net::IoMode io_mode_write) {
    // Only allow 0 or 1 test because the test 2 in NetworkStats is random.
    DCHECK_LT(max_tests, 2U);
    outputs_.resize(10);
    ProbePacket probe_packet;
    ProbeMessage probe_message;
    probe_message.SetPacketHeader(ProbePacket_Type_HELLO_REQUEST,
                                  &probe_packet);
    probe_packet.set_group_id(0);
    outputs_[0] = probe_message.MakeEncodedPacket(probe_packet);
    mock_writes_.clear();
    mock_writes_.push_back(net::MockWrite(
        io_mode_write, &outputs_[0][0], outputs_[0].size(), 0));
    // Add one probe_request.
    probe_packet = ProbePacket();  // Clear all content.
    ProbePacket_Token token;
    CreateToken(1L, "1010", &token);
    probe_message.GenerateProbeRequest(
        token, 1, probe_bytes, 0, max_probe_packets, &probe_packet);
    outputs_[1] = probe_message.MakeEncodedPacket(probe_packet);
    mock_writes_.push_back(net::MockWrite(
        io_mode_write, &outputs_[1][0], outputs_[1].size(), 2));

    inputs_.resize(10);
    mock_reads_.clear();
    // Add a hello reply.
    probe_packet = ProbePacket();  // Clear all content.
    probe_message.SetPacketHeader(ProbePacket_Type_HELLO_REPLY, &probe_packet);
    probe_packet.set_group_id(0);
    CreateToken(1L, "1010", probe_packet.mutable_token());
    inputs_[0] = probe_message.MakeEncodedPacket(probe_packet);
    mock_reads_.push_back(
        net::MockRead(net::ASYNC, &inputs_[0][0], inputs_[0].size(), 1));

    for (uint32 i = 0; i < max_probe_packets; ++i) {
      // Add a probe reply.
      probe_packet = ProbePacket();  // Clear all content.
      probe_message.SetPacketHeader(ProbePacket_Type_PROBE_REPLY,
                                    &probe_packet);
      int padding_size = probe_bytes - probe_packet.ByteSize() - 8;
      probe_packet.mutable_padding()->append(
          std::string(std::max(0, padding_size), 0));
      probe_packet.mutable_header()->set_checksum(0);
      probe_packet.set_group_id(1);
      probe_packet.set_packet_index(i);
      inputs_[1 + i] = probe_message.MakeEncodedPacket(probe_packet);
      mock_reads_.push_back(net::MockRead(
          net::ASYNC, &inputs_[1 + i][0], inputs_[1 + i].size(), 3 + i));
    }
  }

  // Test NetworkStats::Start(...) method.
  void TestStart(bool has_proxy,
                 uint32 max_tests,
                 uint32 max_probe_packets,
                 uint32 bytes,
                 net::IoMode io_mode) {
    net::DeterministicMockClientSocketFactory mock_socket_factory;
    MakeDeterministicMockData(max_tests, max_probe_packets, bytes, io_mode);
    net::DeterministicSocketData test_data(
        &mock_reads_[0], mock_reads_.size(),
        &mock_writes_[0], mock_writes_.size());
    mock_socket_factory.AddSocketDataProvider(&test_data);
    NetworkStats* udp_stats_client = new NetworkStats(&mock_socket_factory);
    udp_stats_client->maximum_tests_ = max_tests;
    udp_stats_client->maximum_sequential_packets_ = max_probe_packets;

    net::TestCompletionCallback cb;
    scoped_ptr<net::MockHostResolver> host_resolver(
        new net::MockHostResolver());
    net::HostPortPair host_port_pair;
    EXPECT_TRUE(udp_stats_client->Start(host_resolver.get(),
                                        host_port_pair,
                                        9999,
                                        has_proxy,
                                        bytes,
                                        bytes,
                                        cb.callback()));
    int num_packets_run = (max_tests + 1) * 2 + max_probe_packets - 1;
    test_data.RunFor(num_packets_run);
    int rv = cb.WaitForResult();
    // Check there were no errors during connect/write/read to echo UDP server.
    EXPECT_EQ(0, rv);
  }

  // Make one write and then |max_probe_packets| reads.
  void MakeDelayedMockData(NetworkStats::TestType test_type,
                           uint32 probe_bytes,
                           uint32 pacing_interval_micros,
                           uint32 max_probe_packets,
                           net::IoMode io_mode) {
    outputs_.resize(1);
    ProbePacket probe_packet;
    ProbeMessage probe_message;
    mock_writes_.clear();
    ProbePacket_Token token;
    CreateToken(2L, "2a2b", &token);
    switch (test_type) {
      case NetworkStats::PACKET_SIZE_TEST:
      case NetworkStats::NON_PACED_PACKET_TEST:
        pacing_interval_micros = 0;
        break;
      case NetworkStats::NAT_BIND_TEST:
        // For NAT_BIND_TEST, we always set this to 1000000 to avoid the
        // randomness in NetworkStats::SendProbeRequest() and to match
        // the value chosen in TestStartOneTest() below.
        pacing_interval_micros = 1000000;
        break;
      default: {}  // Do nothing here.
    }
    probe_message.GenerateProbeRequest(token,
                                       1,  // current_test_index_ = 1.
                                       probe_bytes,
                                       pacing_interval_micros,
                                       max_probe_packets,
                                       &probe_packet);
    outputs_[0] = probe_message.MakeEncodedPacket(probe_packet);
    mock_writes_.push_back(
        net::MockWrite(io_mode, &outputs_[0][0], outputs_[0].size()));

    inputs_.resize(max_probe_packets);
    mock_reads_.clear();
    for (uint32 i = 0; i < max_probe_packets; ++i) {
      // Add a probe reply.
      probe_packet = ProbePacket();  // Clear all content.
      probe_message.SetPacketHeader(ProbePacket_Type_PROBE_REPLY,
                                    &probe_packet);
      int padding_size = probe_bytes - probe_packet.ByteSize() - 8;
      probe_packet.mutable_padding()->append(
          std::string(std::max(0, padding_size), 0));
      probe_packet.mutable_header()->set_checksum(0);
      probe_packet.set_group_id(1);
      probe_packet.set_packet_index(i);
      inputs_[i] = probe_message.MakeEncodedPacket(probe_packet);
      mock_reads_.push_back(
          net::MockRead(io_mode, &inputs_[i][0], inputs_[i].size()));
    }
  }

  // Test NetworkStats::StartOneTest(...) method.
  void TestStartOneTest(bool has_proxy,
                        NetworkStats::TestType test_type,
                        uint32 bytes,
                        uint32 interval_micros,
                        uint32 max_probe_packets,
                        net::IoMode io_mode) {

    net::MockClientSocketFactory mock_socket_factory;
    MakeDelayedMockData(
        test_type, bytes, interval_micros, max_probe_packets, io_mode);
    net::DelayedSocketData test_data(1,
                                     &mock_reads_[0],
                                     mock_reads_.size(),
                                     &mock_writes_[0],
                                     mock_writes_.size());
    mock_socket_factory.AddSocketDataProvider(&test_data);
    NetworkStats* udp_stats_client = new NetworkStats(&mock_socket_factory);
    udp_stats_client->maximum_tests_ = 1;  // Only do one probe at a time.
    udp_stats_client->maximum_sequential_packets_ = max_probe_packets;
    udp_stats_client->maximum_NAT_packets_ = max_probe_packets;
    // For NAT_BIND_TEST, we always set this to 1 (second) to avoid the
    // randomness in NetworkStats::SendProbeRequest().
    udp_stats_client->maximum_NAT_idle_seconds_ = 1;
    udp_stats_client->start_test_after_connect_ = false;
    udp_stats_client->inter_arrival_time_ =
        base::TimeDelta::FromMicroseconds(interval_micros);
    CreateToken(2L, "2a2b", &udp_stats_client->token_);

    net::TestCompletionCallback cb;
    scoped_ptr<net::MockHostResolver> host_resolver(
        new net::MockHostResolver());
    net::HostPortPair host_port_pair;
    EXPECT_TRUE(udp_stats_client->Start(host_resolver.get(),
                                        host_port_pair,
                                        9999,
                                        has_proxy,
                                        bytes,
                                        bytes,
                                        cb.callback()));
    // Test need to be added after Start() because Start() will reset
    // test_sequence_
    udp_stats_client->test_sequence_.push_back(test_type);
    udp_stats_client->current_test_index_ = 1;
    // Wait for host resolving and check if there were no errors during
    // connect/write/read to UDP server.
    int rv = cb.WaitForResult();
    EXPECT_EQ(0, rv);
    udp_stats_client->ReadData();
    udp_stats_client->StartOneTest();
    rv = cb.WaitForResult();
    EXPECT_EQ(0, rv);
  }

  base::MessageLoopForIO message_loop_;
  std::vector<std::string> inputs_;
  std::vector<std::string> outputs_;
  std::vector<net::MockRead> mock_reads_;
  std::vector<net::MockWrite> mock_writes_;
};

TEST_F(NetworkStatsTest, ProbeTest100BHasProxyGetToken) {
  TestStart(true, 0, 1, 100, net::ASYNC);
}

TEST_F(NetworkStatsTest, ProbeTest500BHasNoProxyGetTokenSync) {
  TestStart(false, 0, 1, 500, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, ProbeTest100BHasNoProxyOneTest) {
  TestStart(false, 1, 1, 100, net::ASYNC);
}

TEST_F(NetworkStatsTest, ProbeTest100BHasNoProxyOneTestSync) {
  TestStart(false, 1, 1, 100, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, ProbeTest100BHasProxyOneTest) {
  TestStart(true, 1, 1, 100, net::ASYNC);
}

TEST_F(NetworkStatsTest, ProbeTest100BHasProxyOneTestSync) {
  TestStart(true, 1, 1, 100, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, ProbeTest500BHasProxyOneTest) {
  TestStart(true, 1, 1, 500, net::ASYNC);
}

TEST_F(NetworkStatsTest, ProbeTest500BHasNoProxyOneTestSync) {
  TestStart(false, 1, 1, 500, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, ProbeTest500BHasNoProxyOneTest) {
  TestStart(false, 1, 1, 500, net::ASYNC);
}

TEST_F(NetworkStatsTest, ProbeTest500BHasProxyOneTestSync) {
  TestStart(true, 1, 1, 500, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, ProbeTest1200BHasProxyOneTest) {
  TestStart(true, 1, 1, 1200, net::ASYNC);
}

TEST_F(NetworkStatsTest, ProbeTest1200BHasNoProxyOneTestSync) {
  TestStart(false, 1, 1, 1200, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, ProbeTest1200BHasNoProxyOneTest) {
  TestStart(false, 1, 1, 1200, net::ASYNC);
}

TEST_F(NetworkStatsTest, ProbeTest1200BHasProxyOneTestSync) {
  TestStart(true, 1, 1, 1200, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, ProbeTest100BHasNoProxyOneTestMultiPackets) {
  TestStart(false, 1, 4, 100, net::ASYNC);
}

TEST_F(NetworkStatsTest, ProbeTest1200BHasProxyOneTestMultiPacketsSync) {
  TestStart(true, 1, 4, 1200, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartNonPacedTest100BHasProxy) {
  TestStartOneTest(
      true, NetworkStats::NON_PACED_PACKET_TEST, 100, 0, 1, net::ASYNC);
}

TEST_F(NetworkStatsTest, StartNonPacedTest100BHasNoProxySync) {
  TestStartOneTest(
      false, NetworkStats::NON_PACED_PACKET_TEST, 100, 0, 1, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartNonPacedTest500BHasNoProxy) {
  TestStartOneTest(
      false, NetworkStats::NON_PACED_PACKET_TEST, 500, 3, 1, net::ASYNC);
}

TEST_F(NetworkStatsTest, StartNonPacedTest1200BHasProxySync) {
  TestStartOneTest(
      true, NetworkStats::NON_PACED_PACKET_TEST, 1200, 1, 1, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartNonPacedTest500BHasNoProxyMulti) {
  TestStartOneTest(
      false, NetworkStats::NON_PACED_PACKET_TEST, 500, 2, 3, net::ASYNC);
}

TEST_F(NetworkStatsTest, StartNonPacedTest1200BHasProxySyncMulti) {
  TestStartOneTest(
      true, NetworkStats::NON_PACED_PACKET_TEST, 1200, 1, 4, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartPacedTest100BHasProxy) {
  TestStartOneTest(
      true, NetworkStats::PACED_PACKET_TEST, 100, 0, 1, net::ASYNC);
}

TEST_F(NetworkStatsTest, StartPacedTest100BHasNoProxySync) {
  TestStartOneTest(
      false, NetworkStats::PACED_PACKET_TEST, 100, 0, 1, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartPacedTest500BHasNoProxy) {
  TestStartOneTest(
      false, NetworkStats::PACED_PACKET_TEST, 500, 3, 1, net::ASYNC);
}

TEST_F(NetworkStatsTest, StartPacedTest1200BHasProxySync) {
  TestStartOneTest(
      true, NetworkStats::PACED_PACKET_TEST, 1200, 1, 1, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartPacedTest500BHasNoProxyMulti) {
  TestStartOneTest(
      false, NetworkStats::PACED_PACKET_TEST, 500, 2, 3, net::ASYNC);
}

TEST_F(NetworkStatsTest, StartPacedTest1200BHasProxySyncMulti) {
  TestStartOneTest(
      true, NetworkStats::PACED_PACKET_TEST, 1200, 1, 4, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartNATBindTest100BHasProxy) {
  TestStartOneTest(true, NetworkStats::NAT_BIND_TEST, 100, 0, 1, net::ASYNC);
}

TEST_F(NetworkStatsTest, StartNATBindTest100BHasNoProxySync) {
  TestStartOneTest(
      false, NetworkStats::NAT_BIND_TEST, 100, 3, 1, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartNATBindTest500BHasNoProxy) {
  TestStartOneTest(false, NetworkStats::NAT_BIND_TEST, 500, 0, 2, net::ASYNC);
}

TEST_F(NetworkStatsTest, StartNATBindTest1200BHasProxySync) {
  TestStartOneTest(
      true, NetworkStats::NAT_BIND_TEST, 1200, 3, 2, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartPacketSizeTest1500BHasProxy) {
  TestStartOneTest(
      true, NetworkStats::PACKET_SIZE_TEST, 1500, 0, 1, net::ASYNC);
}

TEST_F(NetworkStatsTest, StartPacketSizeTest1500HasNoProxySync) {
  TestStartOneTest(
      false, NetworkStats::PACKET_SIZE_TEST, 1500, 0, 1, net::SYNCHRONOUS);
}

TEST_F(NetworkStatsTest, StartPacketSizeTest1500BHasNoProxy) {
  TestStartOneTest(
      false, NetworkStats::PACKET_SIZE_TEST, 1500, 0, 1, net::ASYNC);
}

}  // namespace chrome_browser_net

/* [<][>][^][v][top][bottom][index][help] */