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 "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"
16
17namespace chrome_browser_net {
18
19class NetworkStatsTest : public PlatformTest {
20 public:
21  NetworkStatsTest() {}
22
23 protected:
24
25  virtual void SetUp() {
26    net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
27    base::MessageLoop::current()->RunUntilIdle();
28    mock_writes_.clear();
29    mock_reads_.clear();
30  }
31
32  virtual void TearDown() {
33    net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
34    // Empty the current queue.
35    base::MessageLoop::current()->RunUntilIdle();
36    PlatformTest::TearDown();
37  }
38
39  void CreateToken(uint64 timestamp_micros,
40                   const string& hash,
41                   ProbePacket_Token* token) {
42    token->set_timestamp_micros(timestamp_micros);
43    token->mutable_hash()->assign(hash);
44  }
45
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,
51                                 uint32 probe_bytes,
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);
55    outputs_.resize(10);
56    ProbePacket probe_packet;
57    ProbeMessage probe_message;
58    probe_message.SetPacketHeader(ProbePacket_Type_HELLO_REQUEST,
59                                  &probe_packet);
60    probe_packet.set_group_id(0);
61    outputs_[0] = probe_message.MakeEncodedPacket(probe_packet);
62    mock_writes_.clear();
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));
74
75    inputs_.resize(10);
76    mock_reads_.clear();
77    // Add a hello reply.
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));
85
86    for (uint32 i = 0; i < max_probe_packets; ++i) {
87      // Add a probe reply.
88      probe_packet = ProbePacket();  // Clear all content.
89      probe_message.SetPacketHeader(ProbePacket_Type_PROBE_REPLY,
90                                    &probe_packet);
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));
100    }
101  }
102
103  // Test NetworkStats::Start(...) method.
104  void TestStart(bool has_proxy,
105                 uint32 max_tests,
106                 uint32 max_probe_packets,
107                 uint32 bytes,
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;
118
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(),
124                                        host_port_pair,
125                                        9999,
126                                        has_proxy,
127                                        bytes,
128                                        bytes,
129                                        cb.callback()));
130    int num_packets_run = (max_tests + 1) * 2 + max_probe_packets - 1;
131    test_data.RunFor(num_packets_run);
132    int rv = cb.WaitForResult();
133    // Check there were no errors during connect/write/read to echo UDP server.
134    EXPECT_EQ(0, rv);
135  }
136
137  // Make one write and then |max_probe_packets| reads.
138  void MakeDelayedMockData(NetworkStats::TestType test_type,
139                           uint32 probe_bytes,
140                           uint32 pacing_interval_micros,
141                           uint32 max_probe_packets,
142                           net::IoMode io_mode) {
143    outputs_.resize(1);
144    ProbePacket probe_packet;
145    ProbeMessage probe_message;
146    mock_writes_.clear();
147    ProbePacket_Token token;
148    CreateToken(2L, "2a2b", &token);
149    switch (test_type) {
150      case NetworkStats::PACKET_SIZE_TEST:
151      case NetworkStats::NON_PACED_PACKET_TEST:
152        pacing_interval_micros = 0;
153        break;
154      case NetworkStats::NAT_BIND_TEST:
155        // For NAT_BIND_TEST, we always set this to 1000000 to avoid the
156        // randomness in NetworkStats::SendProbeRequest() and to match
157        // the value chosen in TestStartOneTest() below.
158        pacing_interval_micros = 1000000;
159        break;
160      default: {}  // Do nothing here.
161    }
162    probe_message.GenerateProbeRequest(token,
163                                       1,  // current_test_index_ = 1.
164                                       probe_bytes,
165                                       pacing_interval_micros,
166                                       max_probe_packets,
167                                       &probe_packet);
168    outputs_[0] = probe_message.MakeEncodedPacket(probe_packet);
169    mock_writes_.push_back(
170        net::MockWrite(io_mode, &outputs_[0][0], outputs_[0].size()));
171
172    inputs_.resize(max_probe_packets);
173    mock_reads_.clear();
174    for (uint32 i = 0; i < max_probe_packets; ++i) {
175      // Add a probe reply.
176      probe_packet = ProbePacket();  // Clear all content.
177      probe_message.SetPacketHeader(ProbePacket_Type_PROBE_REPLY,
178                                    &probe_packet);
179      int padding_size = probe_bytes - probe_packet.ByteSize() - 8;
180      probe_packet.mutable_padding()->append(
181          std::string(std::max(0, padding_size), 0));
182      probe_packet.mutable_header()->set_checksum(0);
183      probe_packet.set_group_id(1);
184      probe_packet.set_packet_index(i);
185      inputs_[i] = probe_message.MakeEncodedPacket(probe_packet);
186      mock_reads_.push_back(
187          net::MockRead(io_mode, &inputs_[i][0], inputs_[i].size()));
188    }
189  }
190
191  // Test NetworkStats::StartOneTest(...) method.
192  void TestStartOneTest(bool has_proxy,
193                        NetworkStats::TestType test_type,
194                        uint32 bytes,
195                        uint32 interval_micros,
196                        uint32 max_probe_packets,
197                        net::IoMode io_mode) {
198
199    net::MockClientSocketFactory mock_socket_factory;
200    MakeDelayedMockData(
201        test_type, bytes, interval_micros, max_probe_packets, io_mode);
202    net::DelayedSocketData test_data(1,
203                                     &mock_reads_[0],
204                                     mock_reads_.size(),
205                                     &mock_writes_[0],
206                                     mock_writes_.size());
207    mock_socket_factory.AddSocketDataProvider(&test_data);
208    NetworkStats* udp_stats_client = new NetworkStats(&mock_socket_factory);
209    udp_stats_client->maximum_tests_ = 1;  // Only do one probe at a time.
210    udp_stats_client->maximum_sequential_packets_ = max_probe_packets;
211    udp_stats_client->maximum_NAT_packets_ = max_probe_packets;
212    // For NAT_BIND_TEST, we always set this to 1 (second) to avoid the
213    // randomness in NetworkStats::SendProbeRequest().
214    udp_stats_client->maximum_NAT_idle_seconds_ = 1;
215    udp_stats_client->start_test_after_connect_ = false;
216    udp_stats_client->inter_arrival_time_ =
217        base::TimeDelta::FromMicroseconds(interval_micros);
218    CreateToken(2L, "2a2b", &udp_stats_client->token_);
219
220    net::TestCompletionCallback cb;
221    scoped_ptr<net::MockHostResolver> host_resolver(
222        new net::MockHostResolver());
223    net::HostPortPair host_port_pair;
224    EXPECT_TRUE(udp_stats_client->Start(host_resolver.get(),
225                                        host_port_pair,
226                                        9999,
227                                        has_proxy,
228                                        bytes,
229                                        bytes,
230                                        cb.callback()));
231    // Test need to be added after Start() because Start() will reset
232    // test_sequence_
233    udp_stats_client->test_sequence_.push_back(test_type);
234    udp_stats_client->current_test_index_ = 1;
235    // Wait for host resolving and check if there were no errors during
236    // connect/write/read to UDP server.
237    int rv = cb.WaitForResult();
238    EXPECT_EQ(0, rv);
239    udp_stats_client->ReadData();
240    udp_stats_client->StartOneTest();
241    rv = cb.WaitForResult();
242    EXPECT_EQ(0, rv);
243  }
244
245  base::MessageLoopForIO message_loop_;
246  std::vector<std::string> inputs_;
247  std::vector<std::string> outputs_;
248  std::vector<net::MockRead> mock_reads_;
249  std::vector<net::MockWrite> mock_writes_;
250};
251
252TEST_F(NetworkStatsTest, ProbeTest100BHasProxyGetToken) {
253  TestStart(true, 0, 1, 100, net::ASYNC);
254}
255
256TEST_F(NetworkStatsTest, ProbeTest500BHasNoProxyGetTokenSync) {
257  TestStart(false, 0, 1, 500, net::SYNCHRONOUS);
258}
259
260TEST_F(NetworkStatsTest, ProbeTest100BHasNoProxyOneTest) {
261  TestStart(false, 1, 1, 100, net::ASYNC);
262}
263
264TEST_F(NetworkStatsTest, ProbeTest100BHasNoProxyOneTestSync) {
265  TestStart(false, 1, 1, 100, net::SYNCHRONOUS);
266}
267
268TEST_F(NetworkStatsTest, ProbeTest100BHasProxyOneTest) {
269  TestStart(true, 1, 1, 100, net::ASYNC);
270}
271
272TEST_F(NetworkStatsTest, ProbeTest100BHasProxyOneTestSync) {
273  TestStart(true, 1, 1, 100, net::SYNCHRONOUS);
274}
275
276TEST_F(NetworkStatsTest, ProbeTest500BHasProxyOneTest) {
277  TestStart(true, 1, 1, 500, net::ASYNC);
278}
279
280TEST_F(NetworkStatsTest, ProbeTest500BHasNoProxyOneTestSync) {
281  TestStart(false, 1, 1, 500, net::SYNCHRONOUS);
282}
283
284TEST_F(NetworkStatsTest, ProbeTest500BHasNoProxyOneTest) {
285  TestStart(false, 1, 1, 500, net::ASYNC);
286}
287
288TEST_F(NetworkStatsTest, ProbeTest500BHasProxyOneTestSync) {
289  TestStart(true, 1, 1, 500, net::SYNCHRONOUS);
290}
291
292TEST_F(NetworkStatsTest, ProbeTest1200BHasProxyOneTest) {
293  TestStart(true, 1, 1, 1200, net::ASYNC);
294}
295
296TEST_F(NetworkStatsTest, ProbeTest1200BHasNoProxyOneTestSync) {
297  TestStart(false, 1, 1, 1200, net::SYNCHRONOUS);
298}
299
300TEST_F(NetworkStatsTest, ProbeTest1200BHasNoProxyOneTest) {
301  TestStart(false, 1, 1, 1200, net::ASYNC);
302}
303
304TEST_F(NetworkStatsTest, ProbeTest1200BHasProxyOneTestSync) {
305  TestStart(true, 1, 1, 1200, net::SYNCHRONOUS);
306}
307
308TEST_F(NetworkStatsTest, ProbeTest100BHasNoProxyOneTestMultiPackets) {
309  TestStart(false, 1, 4, 100, net::ASYNC);
310}
311
312TEST_F(NetworkStatsTest, ProbeTest1200BHasProxyOneTestMultiPacketsSync) {
313  TestStart(true, 1, 4, 1200, net::SYNCHRONOUS);
314}
315
316TEST_F(NetworkStatsTest, StartNonPacedTest100BHasProxy) {
317  TestStartOneTest(
318      true, NetworkStats::NON_PACED_PACKET_TEST, 100, 0, 1, net::ASYNC);
319}
320
321TEST_F(NetworkStatsTest, StartNonPacedTest100BHasNoProxySync) {
322  TestStartOneTest(
323      false, NetworkStats::NON_PACED_PACKET_TEST, 100, 0, 1, net::SYNCHRONOUS);
324}
325
326TEST_F(NetworkStatsTest, StartNonPacedTest500BHasNoProxy) {
327  TestStartOneTest(
328      false, NetworkStats::NON_PACED_PACKET_TEST, 500, 3, 1, net::ASYNC);
329}
330
331TEST_F(NetworkStatsTest, StartNonPacedTest1200BHasProxySync) {
332  TestStartOneTest(
333      true, NetworkStats::NON_PACED_PACKET_TEST, 1200, 1, 1, net::SYNCHRONOUS);
334}
335
336TEST_F(NetworkStatsTest, StartNonPacedTest500BHasNoProxyMulti) {
337  TestStartOneTest(
338      false, NetworkStats::NON_PACED_PACKET_TEST, 500, 2, 3, net::ASYNC);
339}
340
341TEST_F(NetworkStatsTest, StartNonPacedTest1200BHasProxySyncMulti) {
342  TestStartOneTest(
343      true, NetworkStats::NON_PACED_PACKET_TEST, 1200, 1, 4, net::SYNCHRONOUS);
344}
345
346TEST_F(NetworkStatsTest, StartPacedTest100BHasProxy) {
347  TestStartOneTest(
348      true, NetworkStats::PACED_PACKET_TEST, 100, 0, 1, net::ASYNC);
349}
350
351TEST_F(NetworkStatsTest, StartPacedTest100BHasNoProxySync) {
352  TestStartOneTest(
353      false, NetworkStats::PACED_PACKET_TEST, 100, 0, 1, net::SYNCHRONOUS);
354}
355
356TEST_F(NetworkStatsTest, StartPacedTest500BHasNoProxy) {
357  TestStartOneTest(
358      false, NetworkStats::PACED_PACKET_TEST, 500, 3, 1, net::ASYNC);
359}
360
361TEST_F(NetworkStatsTest, StartPacedTest1200BHasProxySync) {
362  TestStartOneTest(
363      true, NetworkStats::PACED_PACKET_TEST, 1200, 1, 1, net::SYNCHRONOUS);
364}
365
366TEST_F(NetworkStatsTest, StartPacedTest500BHasNoProxyMulti) {
367  TestStartOneTest(
368      false, NetworkStats::PACED_PACKET_TEST, 500, 2, 3, net::ASYNC);
369}
370
371TEST_F(NetworkStatsTest, StartPacedTest1200BHasProxySyncMulti) {
372  TestStartOneTest(
373      true, NetworkStats::PACED_PACKET_TEST, 1200, 1, 4, net::SYNCHRONOUS);
374}
375
376TEST_F(NetworkStatsTest, StartNATBindTest100BHasProxy) {
377  TestStartOneTest(true, NetworkStats::NAT_BIND_TEST, 100, 0, 1, net::ASYNC);
378}
379
380TEST_F(NetworkStatsTest, StartNATBindTest100BHasNoProxySync) {
381  TestStartOneTest(
382      false, NetworkStats::NAT_BIND_TEST, 100, 3, 1, net::SYNCHRONOUS);
383}
384
385TEST_F(NetworkStatsTest, StartNATBindTest500BHasNoProxy) {
386  TestStartOneTest(false, NetworkStats::NAT_BIND_TEST, 500, 0, 2, net::ASYNC);
387}
388
389TEST_F(NetworkStatsTest, StartNATBindTest1200BHasProxySync) {
390  TestStartOneTest(
391      true, NetworkStats::NAT_BIND_TEST, 1200, 3, 2, net::SYNCHRONOUS);
392}
393
394TEST_F(NetworkStatsTest, StartPacketSizeTest1500BHasProxy) {
395  TestStartOneTest(
396      true, NetworkStats::PACKET_SIZE_TEST, 1500, 0, 1, net::ASYNC);
397}
398
399TEST_F(NetworkStatsTest, StartPacketSizeTest1500HasNoProxySync) {
400  TestStartOneTest(
401      false, NetworkStats::PACKET_SIZE_TEST, 1500, 0, 1, net::SYNCHRONOUS);
402}
403
404TEST_F(NetworkStatsTest, StartPacketSizeTest1500BHasNoProxy) {
405  TestStartOneTest(
406      false, NetworkStats::PACKET_SIZE_TEST, 1500, 0, 1, net::ASYNC);
407}
408
409}  // namespace chrome_browser_net
410