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 "base/basictypes.h"
6 #include "base/message_loop/message_loop.h"
7 #include "chrome/browser/net/network_stats.h"
8 #include "net/base/net_errors.h"
9 #include "net/base/network_change_notifier.h"
10 #include "net/base/test_completion_callback.h"
11 #include "net/dns/host_resolver.h"
12 #include "net/dns/mock_host_resolver.h"
13 #include "net/socket/socket_test_util.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "testing/platform_test.h"
17 namespace chrome_browser_net {
19 class NetworkStatsTest : public PlatformTest {
25 virtual void SetUp() {
26 net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
27 base::MessageLoop::current()->RunUntilIdle();
32 virtual void TearDown() {
33 net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
34 // Empty the current queue.
35 base::MessageLoop::current()->RunUntilIdle();
36 PlatformTest::TearDown();
39 void CreateToken(uint64 timestamp_micros,
41 ProbePacket_Token* token) {
42 token->set_timestamp_micros(timestamp_micros);
43 token->mutable_hash()->assign(hash);
46 // DeterministicMockData defines the exact sequence of the read/write
47 // operations (specified by the last parameter of MockRead/MockWrite).
48 // |io_mode_write| is the IO mode for writing only. Reading is always async.
49 void MakeDeterministicMockData(uint32 max_tests,
50 uint32 max_probe_packets,
52 net::IoMode io_mode_write) {
53 // Only allow 0 or 1 test because the test 2 in NetworkStats is random.
54 DCHECK_LT(max_tests, 2U);
56 ProbePacket probe_packet;
57 ProbeMessage probe_message;
58 probe_message.SetPacketHeader(ProbePacket_Type_HELLO_REQUEST,
60 probe_packet.set_group_id(0);
61 outputs_[0] = probe_message.MakeEncodedPacket(probe_packet);
63 mock_writes_.push_back(net::MockWrite(
64 io_mode_write, &outputs_[0][0], outputs_[0].size(), 0));
65 // Add one probe_request.
66 probe_packet = ProbePacket(); // Clear all content.
67 ProbePacket_Token token;
68 CreateToken(1L, "1010", &token);
69 probe_message.GenerateProbeRequest(
70 token, 1, probe_bytes, 0, max_probe_packets, &probe_packet);
71 outputs_[1] = probe_message.MakeEncodedPacket(probe_packet);
72 mock_writes_.push_back(net::MockWrite(
73 io_mode_write, &outputs_[1][0], outputs_[1].size(), 2));
78 probe_packet = ProbePacket(); // Clear all content.
79 probe_message.SetPacketHeader(ProbePacket_Type_HELLO_REPLY, &probe_packet);
80 probe_packet.set_group_id(0);
81 CreateToken(1L, "1010", probe_packet.mutable_token());
82 inputs_[0] = probe_message.MakeEncodedPacket(probe_packet);
83 mock_reads_.push_back(
84 net::MockRead(net::ASYNC, &inputs_[0][0], inputs_[0].size(), 1));
86 for (uint32 i = 0; i < max_probe_packets; ++i) {
88 probe_packet = ProbePacket(); // Clear all content.
89 probe_message.SetPacketHeader(ProbePacket_Type_PROBE_REPLY,
91 int padding_size = probe_bytes - probe_packet.ByteSize() - 8;
92 probe_packet.mutable_padding()->append(
93 std::string(std::max(0, padding_size), 0));
94 probe_packet.mutable_header()->set_checksum(0);
95 probe_packet.set_group_id(1);
96 probe_packet.set_packet_index(i);
97 inputs_[1 + i] = probe_message.MakeEncodedPacket(probe_packet);
98 mock_reads_.push_back(net::MockRead(
99 net::ASYNC, &inputs_[1 + i][0], inputs_[1 + i].size(), 3 + i));
103 // Test NetworkStats::Start(...) method.
104 void TestStart(bool has_proxy,
106 uint32 max_probe_packets,
108 net::IoMode io_mode) {
109 net::DeterministicMockClientSocketFactory mock_socket_factory;
110 MakeDeterministicMockData(max_tests, max_probe_packets, bytes, io_mode);
111 net::DeterministicSocketData test_data(
112 &mock_reads_[0], mock_reads_.size(),
113 &mock_writes_[0], mock_writes_.size());
114 mock_socket_factory.AddSocketDataProvider(&test_data);
115 NetworkStats* udp_stats_client = new NetworkStats(&mock_socket_factory);
116 udp_stats_client->maximum_tests_ = max_tests;
117 udp_stats_client->maximum_sequential_packets_ = max_probe_packets;
119 net::TestCompletionCallback cb;
120 scoped_ptr<net::MockHostResolver> host_resolver(
121 new net::MockHostResolver());
122 net::HostPortPair host_port_pair;
123 EXPECT_TRUE(udp_stats_client->Start(host_resolver.get(),
129 int num_packets_run = (max_tests + 1) * 2 + max_probe_packets - 1;
130 test_data.RunFor(num_packets_run);
131 int rv = cb.WaitForResult();
132 // Check there were no errors during connect/write/read to echo UDP server.
136 // Make one write and then |max_probe_packets| reads.
137 void MakeDelayedMockData(NetworkStats::TestType test_type,
139 uint32 pacing_interval_micros,
140 uint32 max_probe_packets,
141 net::IoMode io_mode) {
143 ProbePacket probe_packet;
144 ProbeMessage probe_message;
145 mock_writes_.clear();
146 ProbePacket_Token token;
147 CreateToken(2L, "2a2b", &token);
149 case NetworkStats::NON_PACED_PACKET_TEST:
150 pacing_interval_micros = 0;
152 case NetworkStats::NAT_BIND_TEST:
153 // For NAT_BIND_TEST, we always set this to 1000000 to avoid the
154 // randomness in NetworkStats::SendProbeRequest() and to match
155 // the value chosen in TestStartOneTest() below.
156 pacing_interval_micros = 1000000;
158 default: {} // Do nothing here.
160 probe_message.GenerateProbeRequest(token,
161 1, // current_test_index_ = 1.
163 pacing_interval_micros,
166 outputs_[0] = probe_message.MakeEncodedPacket(probe_packet);
167 mock_writes_.push_back(
168 net::MockWrite(io_mode, &outputs_[0][0], outputs_[0].size()));
170 inputs_.resize(max_probe_packets);
172 for (uint32 i = 0; i < max_probe_packets; ++i) {
173 // Add a probe reply.
174 probe_packet = ProbePacket(); // Clear all content.
175 probe_message.SetPacketHeader(ProbePacket_Type_PROBE_REPLY,
177 int padding_size = probe_bytes - probe_packet.ByteSize() - 8;
178 probe_packet.mutable_padding()->append(
179 std::string(std::max(0, padding_size), 0));
180 probe_packet.mutable_header()->set_checksum(0);
181 probe_packet.set_group_id(1);
182 probe_packet.set_packet_index(i);
183 inputs_[i] = probe_message.MakeEncodedPacket(probe_packet);
184 mock_reads_.push_back(
185 net::MockRead(io_mode, &inputs_[i][0], inputs_[i].size()));
189 // Test NetworkStats::StartOneTest(...) method.
190 void TestStartOneTest(bool has_proxy,
191 NetworkStats::TestType test_type,
193 uint32 interval_micros,
194 uint32 max_probe_packets,
195 net::IoMode io_mode) {
197 net::MockClientSocketFactory mock_socket_factory;
199 test_type, bytes, interval_micros, max_probe_packets, io_mode);
200 net::DelayedSocketData test_data(1,
204 mock_writes_.size());
205 mock_socket_factory.AddSocketDataProvider(&test_data);
206 NetworkStats* udp_stats_client = new NetworkStats(&mock_socket_factory);
207 udp_stats_client->maximum_tests_ = 1; // Only do one probe at a time.
208 udp_stats_client->maximum_sequential_packets_ = max_probe_packets;
209 udp_stats_client->maximum_NAT_packets_ = max_probe_packets;
210 // For NAT_BIND_TEST, we always set this to 1 (second) to avoid the
211 // randomness in NetworkStats::SendProbeRequest().
212 udp_stats_client->maximum_NAT_idle_seconds_ = 1;
213 udp_stats_client->start_test_after_connect_ = false;
214 udp_stats_client->inter_arrival_time_ =
215 base::TimeDelta::FromMicroseconds(interval_micros);
216 CreateToken(2L, "2a2b", &udp_stats_client->token_);
218 net::TestCompletionCallback cb;
219 scoped_ptr<net::MockHostResolver> host_resolver(
220 new net::MockHostResolver());
221 net::HostPortPair host_port_pair;
222 EXPECT_TRUE(udp_stats_client->Start(host_resolver.get(),
228 // Test need to be added after Start() because Start() will reset
230 udp_stats_client->test_sequence_.push_back(test_type);
231 udp_stats_client->current_test_index_ = 1;
232 // Wait for host resolving and check if there were no errors during
233 // connect/write/read to UDP server.
234 int rv = cb.WaitForResult();
236 udp_stats_client->ReadData();
237 udp_stats_client->StartOneTest();
238 rv = cb.WaitForResult();
242 base::MessageLoopForIO message_loop_;
243 std::vector<std::string> inputs_;
244 std::vector<std::string> outputs_;
245 std::vector<net::MockRead> mock_reads_;
246 std::vector<net::MockWrite> mock_writes_;
249 TEST_F(NetworkStatsTest, ProbeTest100BHasProxyGetToken) {
250 TestStart(true, 0, 1, 100, net::ASYNC);
253 TEST_F(NetworkStatsTest, ProbeTest500BHasNoProxyGetTokenSync) {
254 TestStart(false, 0, 1, 500, net::SYNCHRONOUS);
257 TEST_F(NetworkStatsTest, ProbeTest100BHasNoProxyOneTest) {
258 TestStart(false, 1, 1, 100, net::ASYNC);
261 TEST_F(NetworkStatsTest, ProbeTest100BHasNoProxyOneTestSync) {
262 TestStart(false, 1, 1, 100, net::SYNCHRONOUS);
265 TEST_F(NetworkStatsTest, ProbeTest100BHasProxyOneTest) {
266 TestStart(true, 1, 1, 100, net::ASYNC);
269 TEST_F(NetworkStatsTest, ProbeTest100BHasProxyOneTestSync) {
270 TestStart(true, 1, 1, 100, net::SYNCHRONOUS);
273 TEST_F(NetworkStatsTest, ProbeTest500BHasProxyOneTest) {
274 TestStart(true, 1, 1, 500, net::ASYNC);
277 TEST_F(NetworkStatsTest, ProbeTest500BHasNoProxyOneTestSync) {
278 TestStart(false, 1, 1, 500, net::SYNCHRONOUS);
281 TEST_F(NetworkStatsTest, ProbeTest500BHasNoProxyOneTest) {
282 TestStart(false, 1, 1, 500, net::ASYNC);
285 TEST_F(NetworkStatsTest, ProbeTest500BHasProxyOneTestSync) {
286 TestStart(true, 1, 1, 500, net::SYNCHRONOUS);
289 TEST_F(NetworkStatsTest, ProbeTest1200BHasProxyOneTest) {
290 TestStart(true, 1, 1, 1200, net::ASYNC);
293 TEST_F(NetworkStatsTest, ProbeTest1200BHasNoProxyOneTestSync) {
294 TestStart(false, 1, 1, 1200, net::SYNCHRONOUS);
297 TEST_F(NetworkStatsTest, ProbeTest1200BHasNoProxyOneTest) {
298 TestStart(false, 1, 1, 1200, net::ASYNC);
301 TEST_F(NetworkStatsTest, ProbeTest1200BHasProxyOneTestSync) {
302 TestStart(true, 1, 1, 1200, net::SYNCHRONOUS);
305 TEST_F(NetworkStatsTest, ProbeTest100BHasNoProxyOneTestMultiPackets) {
306 TestStart(false, 1, 4, 100, net::ASYNC);
309 TEST_F(NetworkStatsTest, ProbeTest1200BHasProxyOneTestMultiPacketsSync) {
310 TestStart(true, 1, 4, 1200, net::SYNCHRONOUS);
313 TEST_F(NetworkStatsTest, StartNonPacedTest100BHasProxy) {
315 true, NetworkStats::NON_PACED_PACKET_TEST, 100, 0, 1, net::ASYNC);
318 TEST_F(NetworkStatsTest, StartNonPacedTest100BHasNoProxySync) {
320 false, NetworkStats::NON_PACED_PACKET_TEST, 100, 0, 1, net::SYNCHRONOUS);
323 TEST_F(NetworkStatsTest, StartNonPacedTest500BHasNoProxy) {
325 false, NetworkStats::NON_PACED_PACKET_TEST, 500, 3, 1, net::ASYNC);
328 TEST_F(NetworkStatsTest, StartNonPacedTest1200BHasProxySync) {
330 true, NetworkStats::NON_PACED_PACKET_TEST, 1200, 1, 1, net::SYNCHRONOUS);
333 TEST_F(NetworkStatsTest, StartNonPacedTest500BHasNoProxyMulti) {
335 false, NetworkStats::NON_PACED_PACKET_TEST, 500, 2, 3, net::ASYNC);
338 TEST_F(NetworkStatsTest, StartNonPacedTest1200BHasProxySyncMulti) {
340 true, NetworkStats::NON_PACED_PACKET_TEST, 1200, 1, 4, net::SYNCHRONOUS);
343 TEST_F(NetworkStatsTest, StartPacedTest100BHasProxy) {
345 true, NetworkStats::PACED_PACKET_TEST, 100, 0, 1, net::ASYNC);
348 TEST_F(NetworkStatsTest, StartPacedTest100BHasNoProxySync) {
350 false, NetworkStats::PACED_PACKET_TEST, 100, 0, 1, net::SYNCHRONOUS);
353 TEST_F(NetworkStatsTest, StartPacedTest500BHasNoProxy) {
355 false, NetworkStats::PACED_PACKET_TEST, 500, 3, 1, net::ASYNC);
358 TEST_F(NetworkStatsTest, StartPacedTest1200BHasProxySync) {
360 true, NetworkStats::PACED_PACKET_TEST, 1200, 1, 1, net::SYNCHRONOUS);
363 TEST_F(NetworkStatsTest, StartPacedTest500BHasNoProxyMulti) {
365 false, NetworkStats::PACED_PACKET_TEST, 500, 2, 3, net::ASYNC);
368 TEST_F(NetworkStatsTest, StartPacedTest1200BHasProxySyncMulti) {
370 true, NetworkStats::PACED_PACKET_TEST, 1200, 1, 4, net::SYNCHRONOUS);
373 TEST_F(NetworkStatsTest, StartNATBindTest100BHasProxy) {
374 TestStartOneTest(true, NetworkStats::NAT_BIND_TEST, 100, 0, 1, net::ASYNC);
377 TEST_F(NetworkStatsTest, StartNATBindTest100BHasNoProxySync) {
379 false, NetworkStats::NAT_BIND_TEST, 100, 3, 1, net::SYNCHRONOUS);
382 TEST_F(NetworkStatsTest, StartNATBindTest500BHasNoProxy) {
383 TestStartOneTest(false, NetworkStats::NAT_BIND_TEST, 500, 0, 2, net::ASYNC);
386 TEST_F(NetworkStatsTest, StartNATBindTest1200BHasProxySync) {
388 true, NetworkStats::NAT_BIND_TEST, 1200, 3, 2, net::SYNCHRONOUS);
391 } // namespace chrome_browser_net