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