1 // Copyright 2015 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 "net/base/network_quality_estimator.h"
10 #include "base/basictypes.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/run_loop.h"
14 #include "base/test/histogram_tester.h"
15 #include "base/time/time.h"
16 #include "build/build_config.h"
17 #include "net/base/network_change_notifier.h"
18 #include "net/base/network_quality.h"
19 #include "net/test/embedded_test_server/embedded_test_server.h"
20 #include "net/url_request/url_request_test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
26 TEST(NetworkQualityEstimatorTest
, TestPeakKbpsFastestRTTUpdates
) {
27 net::test_server::EmbeddedTestServer embedded_test_server
;
28 embedded_test_server
.ServeFilesFromDirectory(
29 base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
30 ASSERT_TRUE(embedded_test_server
.InitializeAndWaitUntilReady());
32 // Enable requests to local host to be used for network quality estimation.
33 std::map
<std::string
, std::string
> variation_params
;
34 NetworkQualityEstimator
estimator(variation_params
, true, true);
36 NetworkQuality network_quality
= estimator
.GetPeakEstimate();
37 EXPECT_EQ(NetworkQuality::InvalidRTT(), network_quality
.rtt());
38 EXPECT_EQ(NetworkQuality::kInvalidThroughput
,
39 network_quality
.downstream_throughput_kbps());
42 TestDelegate test_delegate
;
43 TestURLRequestContext
context(false);
45 scoped_ptr
<URLRequest
> request(
46 context
.CreateRequest(embedded_test_server
.GetURL("/echo.html"),
47 DEFAULT_PRIORITY
, &test_delegate
));
50 base::RunLoop().Run();
52 // Both RTT and downstream throughput should be updated.
53 estimator
.NotifyDataReceived(*request
, 1000, 1000);
55 NetworkQuality network_quality
= estimator
.GetPeakEstimate();
56 EXPECT_LT(network_quality
.rtt(), base::TimeDelta::Max());
57 EXPECT_GE(network_quality
.downstream_throughput_kbps(), 1);
60 // Check UMA histograms.
61 base::HistogramTester histogram_tester
;
62 histogram_tester
.ExpectTotalCount("NQE.PeakKbps.Unknown", 0);
63 histogram_tester
.ExpectTotalCount("NQE.FastestRTT.Unknown", 0);
65 estimator
.OnConnectionTypeChanged(
66 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI
);
67 histogram_tester
.ExpectTotalCount("NQE.PeakKbps.Unknown", 1);
68 histogram_tester
.ExpectTotalCount("NQE.FastestRTT.Unknown", 1);
70 NetworkQuality network_quality
= estimator
.GetPeakEstimate();
71 EXPECT_EQ(estimator
.current_connection_type_
,
72 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI
);
73 EXPECT_EQ(NetworkQuality::InvalidRTT(), network_quality
.rtt());
74 EXPECT_EQ(NetworkQuality::kInvalidThroughput
,
75 network_quality
.downstream_throughput_kbps());
79 TEST(NetworkQualityEstimatorTest
, StoreObservations
) {
80 net::test_server::EmbeddedTestServer embedded_test_server
;
81 embedded_test_server
.ServeFilesFromDirectory(
82 base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
83 ASSERT_TRUE(embedded_test_server
.InitializeAndWaitUntilReady());
85 std::map
<std::string
, std::string
> variation_params
;
86 NetworkQualityEstimator
estimator(variation_params
, true, true);
87 TestDelegate test_delegate
;
88 TestURLRequestContext
context(false);
90 // Push 10 more observations than the maximum buffer size.
92 i
< estimator
.GetMaximumObservationBufferSizeForTests() + 10U; ++i
) {
93 scoped_ptr
<URLRequest
> request(
94 context
.CreateRequest(embedded_test_server
.GetURL("/echo.html"),
95 DEFAULT_PRIORITY
, &test_delegate
));
97 base::RunLoop().Run();
99 estimator
.NotifyDataReceived(*request
, 1000, 1000);
102 EXPECT_TRUE(estimator
.VerifyBufferSizeForTests(
103 estimator
.GetMaximumObservationBufferSizeForTests()));
105 // Verify that the stored observations are cleared on network change.
106 estimator
.OnConnectionTypeChanged(
107 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI
);
108 EXPECT_TRUE(estimator
.VerifyBufferSizeForTests(0U));
110 scoped_ptr
<URLRequest
> request(
111 context
.CreateRequest(embedded_test_server
.GetURL("/echo.html"),
112 DEFAULT_PRIORITY
, &test_delegate
));
114 // Verify that overflow protection works.
116 base::RunLoop().Run();
117 estimator
.NotifyDataReceived(*request
, std::numeric_limits
<int64_t>::max(),
118 std::numeric_limits
<int64_t>::max());
120 NetworkQuality network_quality
= estimator
.GetPeakEstimate();
121 EXPECT_EQ(std::numeric_limits
<int32_t>::max() - 1,
122 network_quality
.downstream_throughput_kbps());
126 // Verifies that the percentiles are correctly computed. All observations have
127 // the same timestamp. Kbps percentiles must be in decreasing order. RTT
128 // percentiles must be in increasing order.
129 TEST(NetworkQualityEstimatorTest
, PercentileSameTimestamps
) {
130 std::map
<std::string
, std::string
> variation_params
;
131 NetworkQualityEstimator
estimator(variation_params
);
132 base::TimeTicks now
= base::TimeTicks::Now();
134 // Network quality should be unavailable when no observations are available.
135 NetworkQuality network_quality
;
136 EXPECT_FALSE(estimator
.GetEstimate(&network_quality
));
138 // Insert samples from {1,2,3,..., 100}. First insert odd samples, then even
139 // samples. This helps in verifying that the order of samples does not matter.
140 for (int i
= 1; i
<= 99; i
+= 2) {
141 estimator
.kbps_observations_
.AddObservation(
142 NetworkQualityEstimator::Observation(i
, now
));
143 estimator
.rtt_msec_observations_
.AddObservation(
144 NetworkQualityEstimator::Observation(i
, now
));
145 EXPECT_TRUE(estimator
.GetEstimate(&network_quality
));
148 for (int i
= 2; i
<= 100; i
+= 2) {
149 estimator
.kbps_observations_
.AddObservation(
150 NetworkQualityEstimator::Observation(i
, now
));
151 estimator
.rtt_msec_observations_
.AddObservation(
152 NetworkQualityEstimator::Observation(i
, now
));
153 EXPECT_TRUE(estimator
.GetEstimate(&network_quality
));
156 for (int i
= 0; i
<= 100; ++i
) {
157 // Checks if the difference between the two integers is less than 1. This is
158 // required because computed percentiles may be slightly different from
159 // what is expected due to floating point computation errors and integer
160 // rounding off errors.
161 EXPECT_NEAR(estimator
.GetEstimate(i
).downstream_throughput_kbps(), 100 - i
,
163 EXPECT_NEAR(estimator
.GetEstimate(i
).rtt().InMilliseconds(), i
, 1);
166 EXPECT_TRUE(estimator
.GetEstimate(&network_quality
));
167 // |network_quality| should be equal to the 50 percentile value.
168 EXPECT_EQ(estimator
.GetEstimate(50).downstream_throughput_kbps(),
169 network_quality
.downstream_throughput_kbps());
170 EXPECT_EQ(estimator
.GetEstimate(50).rtt(), network_quality
.rtt());
173 // Verifies that the percentiles are correctly computed. Observations have
174 // different timestamps with half the observations being very old and the rest
175 // of them being very recent. Percentiles should factor in recent observations
176 // much more heavily than older samples. Kbps percentiles must be in decreasing
177 // order. RTT percentiles must be in increasing order.
178 TEST(NetworkQualityEstimatorTest
, PercentileDifferentTimestamps
) {
179 std::map
<std::string
, std::string
> variation_params
;
180 NetworkQualityEstimator
estimator(variation_params
);
181 base::TimeTicks now
= base::TimeTicks::Now();
182 base::TimeTicks very_old
= base::TimeTicks::UnixEpoch();
184 // First 50 samples have very old timestamp.
185 for (int i
= 1; i
<= 50; ++i
) {
186 estimator
.kbps_observations_
.AddObservation(
187 NetworkQualityEstimator::Observation(i
, very_old
));
188 estimator
.rtt_msec_observations_
.AddObservation(
189 NetworkQualityEstimator::Observation(i
, very_old
));
192 // Next 50 (i.e., from 51 to 100) have recent timestamp.
193 for (int i
= 51; i
<= 100; ++i
) {
194 estimator
.kbps_observations_
.AddObservation(
195 NetworkQualityEstimator::Observation(i
, now
));
196 estimator
.rtt_msec_observations_
.AddObservation(
197 NetworkQualityEstimator::Observation(i
, now
));
200 // Older samples have very little weight. So, all percentiles are >= 51
201 // (lowest value among recent observations).
202 for (int i
= 1; i
< 100; ++i
) {
203 // Checks if the difference between the two integers is less than 1. This is
204 // required because computed percentiles may be slightly different from
205 // what is expected due to floating point computation errors and integer
206 // rounding off errors.
207 EXPECT_NEAR(estimator
.GetEstimate(i
).downstream_throughput_kbps(),
208 51 + 0.49 * (100 - i
), 1);
209 EXPECT_NEAR(estimator
.GetEstimate(i
).rtt().InMilliseconds(), 51 + 0.49 * i
,
214 // This test notifies NetworkQualityEstimator of received data. Next,
215 // throughput and RTT percentiles are checked for correctness by doing simple
217 TEST(NetworkQualityEstimatorTest
, ComputedPercentiles
) {
218 net::test_server::EmbeddedTestServer embedded_test_server
;
219 embedded_test_server
.ServeFilesFromDirectory(
220 base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
221 ASSERT_TRUE(embedded_test_server
.InitializeAndWaitUntilReady());
223 std::map
<std::string
, std::string
> variation_params
;
224 NetworkQualityEstimator
estimator(variation_params
, true, true);
225 NetworkQuality network_quality
= estimator
.GetPeakEstimate();
226 EXPECT_EQ(NetworkQuality::InvalidRTT(), network_quality
.rtt());
227 EXPECT_EQ(NetworkQuality::kInvalidThroughput
,
228 network_quality
.downstream_throughput_kbps());
230 TestDelegate test_delegate
;
231 TestURLRequestContext
context(false);
233 uint64 min_transfer_size_in_bytes
=
234 NetworkQualityEstimator::kMinTransferSizeInBytes
;
236 // Number of observations are more than the maximum buffer size.
238 i
< estimator
.GetMaximumObservationBufferSizeForTests() + 100U; ++i
) {
239 scoped_ptr
<URLRequest
> request(
240 context
.CreateRequest(embedded_test_server
.GetURL("/echo.html"),
241 DEFAULT_PRIORITY
, &test_delegate
));
243 base::RunLoop().Run();
245 // Use different number of bytes to create variation.
246 estimator
.NotifyDataReceived(*request
, min_transfer_size_in_bytes
+ i
* 100,
247 min_transfer_size_in_bytes
+ i
* 100);
250 // Verify the percentiles through simple tests.
251 for (int i
= 0; i
<= 100; ++i
) {
252 EXPECT_GT(estimator
.GetEstimate(i
).downstream_throughput_kbps(), 0);
253 EXPECT_LT(estimator
.GetEstimate(i
).rtt(), base::TimeDelta::Max());
256 // Throughput percentiles are in decreasing order.
257 EXPECT_LE(estimator
.GetEstimate(i
).downstream_throughput_kbps(),
258 estimator
.GetEstimate(i
- 1).downstream_throughput_kbps());
260 // RTT percentiles are in increasing order.
261 EXPECT_GE(estimator
.GetEstimate(i
).rtt(),
262 estimator
.GetEstimate(i
- 1).rtt());
267 TEST(NetworkQualityEstimatorTest
, ObtainOperatingParams
) {
268 std::map
<std::string
, std::string
> variation_params
;
269 variation_params
["Unknown.DefaultMedianKbps"] = "100";
270 variation_params
["WiFi.DefaultMedianKbps"] = "200";
271 variation_params
["2G.DefaultMedianKbps"] = "300";
273 variation_params
["Unknown.DefaultMedianRTTMsec"] = "1000";
274 variation_params
["WiFi.DefaultMedianRTTMsec"] = "2000";
275 // Negative variation value should not be used.
276 variation_params
["2G.DefaultMedianRTTMsec"] = "-5";
278 NetworkQualityEstimator
estimator(variation_params
, true, true);
279 EXPECT_EQ(1U, estimator
.kbps_observations_
.Size());
280 EXPECT_EQ(1U, estimator
.rtt_msec_observations_
.Size());
281 NetworkQuality network_quality
;
282 EXPECT_TRUE(estimator
.GetEstimate(&network_quality
));
283 EXPECT_EQ(100, network_quality
.downstream_throughput_kbps());
284 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), network_quality
.rtt());
285 auto it
= estimator
.kbps_observations_
.observations_
.begin();
286 EXPECT_EQ(100, (*it
).value
);
287 it
= estimator
.rtt_msec_observations_
.observations_
.begin();
288 EXPECT_EQ(1000, (*it
).value
);
290 // Simulate network change to Wi-Fi.
291 estimator
.OnConnectionTypeChanged(
292 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI
);
293 EXPECT_EQ(1U, estimator
.kbps_observations_
.Size());
294 EXPECT_EQ(1U, estimator
.rtt_msec_observations_
.Size());
295 EXPECT_TRUE(estimator
.GetEstimate(&network_quality
));
296 EXPECT_EQ(200, network_quality
.downstream_throughput_kbps());
297 EXPECT_EQ(base::TimeDelta::FromMilliseconds(2000), network_quality
.rtt());
298 it
= estimator
.kbps_observations_
.observations_
.begin();
299 EXPECT_EQ(200, (*it
).value
);
300 it
= estimator
.rtt_msec_observations_
.observations_
.begin();
301 EXPECT_EQ(2000, (*it
).value
);
303 // Peak network quality should not be affected by the network quality
304 // estimator field trial.
305 EXPECT_EQ(NetworkQuality::InvalidRTT(),
306 estimator
.fastest_rtt_since_last_connection_change_
);
307 EXPECT_EQ(NetworkQuality::kInvalidThroughput
,
308 estimator
.peak_kbps_since_last_connection_change_
);
310 // Simulate network change to 2G. Only the Kbps default estimate should be
312 estimator
.OnConnectionTypeChanged(
313 NetworkChangeNotifier::ConnectionType::CONNECTION_2G
);
314 EXPECT_EQ(1U, estimator
.kbps_observations_
.Size());
315 EXPECT_EQ(0U, estimator
.rtt_msec_observations_
.Size());
316 // For GetEstimate() to return true, at least one observation must be
317 // available for both RTT and downstream throughput.
318 EXPECT_FALSE(estimator
.GetEstimate(&network_quality
));
319 it
= estimator
.kbps_observations_
.observations_
.begin();
320 EXPECT_EQ(300, (*it
).value
);
322 // Simulate network change to 3G. Default estimates should be unavailable.
323 estimator
.OnConnectionTypeChanged(
324 NetworkChangeNotifier::ConnectionType::CONNECTION_3G
);
325 EXPECT_FALSE(estimator
.GetEstimate(&network_quality
));
326 EXPECT_EQ(0U, estimator
.kbps_observations_
.Size());
327 EXPECT_EQ(0U, estimator
.rtt_msec_observations_
.Size());
330 TEST(NetworkQualityEstimatorTest
, HalfLifeParam
) {
331 // Verifies if |weight_multiplier_per_second_| is set to correct value for
332 // various values of half life parameter.
333 std::map
<std::string
, std::string
> variation_params
;
335 // Half life parameter is not set. Default value of
336 // |weight_multiplier_per_second_| should be used.
337 NetworkQualityEstimator
estimator(variation_params
, true, true);
339 estimator
.kbps_observations_
.weight_multiplier_per_second_
,
343 variation_params
["HalfLifeSeconds"] = "-100";
345 // Half life parameter is set to a negative value. Default value of
346 // |weight_multiplier_per_second_| should be used.
347 NetworkQualityEstimator
estimator(variation_params
, true, true);
349 estimator
.kbps_observations_
.weight_multiplier_per_second_
,
353 variation_params
["HalfLifeSeconds"] = "0";
355 // Half life parameter is set to zero. Default value of
356 // |weight_multiplier_per_second_| should be used.
357 NetworkQualityEstimator
estimator(variation_params
, true, true);
359 estimator
.kbps_observations_
.weight_multiplier_per_second_
,
363 variation_params
["HalfLifeSeconds"] = "10";
365 // Half life parameter is set to a valid value.
366 NetworkQualityEstimator
estimator(variation_params
, true, true);
368 estimator
.kbps_observations_
.weight_multiplier_per_second_
,