• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors
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 "net/nqe/observation_buffer.h"
6 
7 #include <stddef.h>
8 
9 #include <map>
10 #include <string>
11 #include <utility>
12 #include <vector>
13 
14 #include "base/test/simple_test_tick_clock.h"
15 #include "base/time/time.h"
16 #include "net/nqe/network_quality_estimator_params.h"
17 #include "net/nqe/network_quality_observation.h"
18 #include "net/nqe/network_quality_observation_source.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 
21 namespace net::nqe::internal {
22 
23 namespace {
24 
25 // Verify that the buffer size is never exceeded.
TEST(NetworkQualityObservationBufferTest,BoundedBuffer)26 TEST(NetworkQualityObservationBufferTest, BoundedBuffer) {
27   std::map<std::string, std::string> variation_params;
28   NetworkQualityEstimatorParams params(variation_params);
29   base::SimpleTestTickClock tick_clock;
30   tick_clock.Advance(base::Minutes(1));
31   ObservationBuffer observation_buffer(&params, &tick_clock, 1.0, 1.0);
32   const base::TimeTicks now = base::TimeTicks() + base::Seconds(1);
33   for (int i = 1; i <= 1000; ++i) {
34     observation_buffer.AddObservation(
35         Observation(i, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
36     // The number of entries should be at most the maximum buffer size.
37     EXPECT_GE(300u, observation_buffer.Size());
38   }
39 }
40 
41 // Verify that the percentiles are monotonically non-decreasing when a weight is
42 // applied.
TEST(NetworkQualityObservationBufferTest,GetPercentileWithWeights)43 TEST(NetworkQualityObservationBufferTest, GetPercentileWithWeights) {
44   std::map<std::string, std::string> variation_params;
45   NetworkQualityEstimatorParams params(variation_params);
46   base::SimpleTestTickClock tick_clock;
47   tick_clock.Advance(base::Minutes(1));
48 
49   ObservationBuffer observation_buffer(&params, &tick_clock, 0.98, 1.0);
50   const base::TimeTicks now = tick_clock.NowTicks();
51   for (int i = 1; i <= 100; ++i) {
52     tick_clock.Advance(base::Seconds(1));
53     observation_buffer.AddObservation(
54         Observation(i, tick_clock.NowTicks(), INT32_MIN,
55                     NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
56   }
57   EXPECT_EQ(100U, observation_buffer.Size());
58 
59   int32_t result_lowest = INT32_MAX;
60   int32_t result_highest = INT32_MIN;
61 
62   for (int i = 1; i <= 100; ++i) {
63     size_t observations_count = 0;
64     // Verify that i'th percentile is more than i-1'th percentile.
65     absl::optional<int32_t> result_i = observation_buffer.GetPercentile(
66         now, INT32_MIN, i, &observations_count);
67     EXPECT_EQ(100u, observations_count);
68     ASSERT_TRUE(result_i.has_value());
69     result_lowest = std::min(result_lowest, result_i.value());
70 
71     result_highest = std::max(result_highest, result_i.value());
72 
73     absl::optional<int32_t> result_i_1 = observation_buffer.GetPercentile(
74         now, INT32_MIN, i - 1, &observations_count);
75     EXPECT_EQ(100u, observations_count);
76     ASSERT_TRUE(result_i_1.has_value());
77 
78     EXPECT_LE(result_i_1.value(), result_i.value());
79   }
80   EXPECT_LT(result_lowest, result_highest);
81 }
82 
83 // Verifies that the percentiles are correctly computed. All observations have
84 // the same timestamp.
TEST(NetworkQualityObservationBufferTest,PercentileSameTimestamps)85 TEST(NetworkQualityObservationBufferTest, PercentileSameTimestamps) {
86   std::map<std::string, std::string> variation_params;
87   NetworkQualityEstimatorParams params(variation_params);
88   base::SimpleTestTickClock tick_clock;
89   tick_clock.Advance(base::Minutes(1));
90   ObservationBuffer buffer(&params, &tick_clock, 0.5, 1.0);
91   ASSERT_EQ(0u, buffer.Size());
92   ASSERT_LT(0u, buffer.Capacity());
93 
94   const base::TimeTicks now = tick_clock.NowTicks();
95 
96   size_t observations_count = 0;
97   // Percentiles should be unavailable when no observations are available.
98   EXPECT_FALSE(
99       buffer
100           .GetPercentile(base::TimeTicks(), INT32_MIN, 50,
101                          &observations_count)
102           .has_value());
103   EXPECT_EQ(0u, observations_count);
104 
105   // Insert samples from {1,2,3,..., 100}. First insert odd samples, then even
106   // samples. This helps in verifying that the order of samples does not matter.
107   for (int i = 1; i <= 99; i += 2) {
108     buffer.AddObservation(Observation(i, now, INT32_MIN,
109                                       NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
110     EXPECT_TRUE(buffer.GetPercentile(base::TimeTicks(), INT32_MIN, 50, nullptr)
111                     .has_value());
112     ASSERT_EQ(static_cast<size_t>(i / 2 + 1), buffer.Size());
113   }
114 
115   for (int i = 2; i <= 100; i += 2) {
116     buffer.AddObservation(Observation(i, now, INT32_MIN,
117                                       NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
118     EXPECT_TRUE(buffer.GetPercentile(base::TimeTicks(), INT32_MIN, 50, nullptr)
119                     .has_value());
120     ASSERT_EQ(static_cast<size_t>(i / 2 + 50), buffer.Size());
121   }
122 
123   ASSERT_EQ(100u, buffer.Size());
124 
125   for (int i = 0; i <= 100; ++i) {
126     // Checks if the difference between actual result and the computed result is
127     // less than 1. This is required because computed percentiles may be
128     // slightly different from what is expected due to floating point
129     // computation errors and integer rounding off errors.
130     absl::optional<int32_t> result = buffer.GetPercentile(
131         base::TimeTicks(), INT32_MIN, i, &observations_count);
132     EXPECT_EQ(100u, observations_count);
133     EXPECT_TRUE(result.has_value());
134     EXPECT_NEAR(result.value(), i, 1.0);
135   }
136 
137   EXPECT_FALSE(buffer
138                    .GetPercentile(now + base::Seconds(1), INT32_MIN, 50,
139                                   &observations_count)
140                    .has_value());
141   EXPECT_EQ(0u, observations_count);
142 
143   // Percentiles should be unavailable when no observations are available.
144   buffer.Clear();
145   EXPECT_FALSE(
146       buffer
147           .GetPercentile(base::TimeTicks(), INT32_MIN, 50,
148                          &observations_count)
149           .has_value());
150   EXPECT_EQ(0u, observations_count);
151 }
152 
153 // Verifies that the percentiles are correctly computed. Observations have
154 // different timestamps with half the observations being very old and the rest
155 // of them being very recent. Percentiles should factor in recent observations
156 // much more heavily than older samples.
TEST(NetworkQualityObservationBufferTest,PercentileDifferentTimestamps)157 TEST(NetworkQualityObservationBufferTest, PercentileDifferentTimestamps) {
158   std::map<std::string, std::string> variation_params;
159   NetworkQualityEstimatorParams params(variation_params);
160   base::SimpleTestTickClock tick_clock;
161   tick_clock.Advance(base::Minutes(1));
162   ObservationBuffer buffer(&params, &tick_clock, 0.5, 1.0);
163   const base::TimeTicks now = tick_clock.NowTicks();
164   const base::TimeTicks very_old = now - base::Days(7);
165 
166   size_t observations_count;
167 
168   // Network quality should be unavailable when no observations are available.
169   EXPECT_FALSE(
170       buffer
171           .GetPercentile(base::TimeTicks(), INT32_MIN, 50,
172                          &observations_count)
173           .has_value());
174   EXPECT_EQ(0u, observations_count);
175 
176   // First 50 samples have very old timestamps.
177   for (int i = 1; i <= 50; ++i) {
178     buffer.AddObservation(Observation(i, very_old, INT32_MIN,
179                                       NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
180   }
181 
182   // Next 50 (i.e., from 51 to 100) have recent timestamps.
183   for (int i = 51; i <= 100; ++i) {
184     buffer.AddObservation(Observation(i, now, INT32_MIN,
185                                       NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
186   }
187 
188   // Older samples have very little weight. So, all percentiles are >= 51
189   // (lowest value among recent observations).
190   for (int i = 1; i < 100; ++i) {
191     // Checks if the difference between the two integers is less than 1. This is
192     // required because computed percentiles may be slightly different from
193     // what is expected due to floating point computation errors and integer
194     // rounding off errors.
195     absl::optional<int32_t> result =
196         buffer.GetPercentile(very_old, INT32_MIN, i, &observations_count);
197     EXPECT_TRUE(result.has_value());
198     EXPECT_NEAR(result.value(), 51 + 0.49 * i, 1);
199     EXPECT_EQ(100u, observations_count);
200   }
201 
202   EXPECT_FALSE(buffer.GetPercentile(now + base::Seconds(1), INT32_MIN, 50,
203                                     &observations_count));
204   EXPECT_EQ(0u, observations_count);
205 }
206 
207 // Verifies that the percentiles are correctly computed. All observations have
208 // same timestamp with half the observations taken at low RSSI, and half the
209 // observations with high RSSI. Percentiles should be computed based on the
210 // current RSSI and the RSSI of the observations.
TEST(NetworkQualityObservationBufferTest,PercentileDifferentRSSI)211 TEST(NetworkQualityObservationBufferTest, PercentileDifferentRSSI) {
212   std::map<std::string, std::string> variation_params;
213   NetworkQualityEstimatorParams params(variation_params);
214   base::SimpleTestTickClock tick_clock;
215   tick_clock.Advance(base::Minutes(1));
216   ObservationBuffer buffer(&params, &tick_clock, 1.0, 0.25);
217   const base::TimeTicks now = tick_clock.NowTicks();
218   int32_t high_rssi = 4;
219   int32_t low_rssi = 0;
220 
221   // Network quality should be unavailable when no observations are available.
222   EXPECT_FALSE(buffer.GetPercentile(base::TimeTicks(), INT32_MIN, 50, nullptr)
223                    .has_value());
224 
225   // First 50 samples have very low RSSI.
226   for (int i = 1; i <= 50; ++i) {
227     buffer.AddObservation(
228         Observation(i, now, low_rssi, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
229   }
230 
231   // Next 50 (i.e., from 51 to 100) have high RSSI.
232   for (int i = 51; i <= 100; ++i) {
233     buffer.AddObservation(Observation(i, now, high_rssi,
234                                       NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
235   }
236 
237   // When the current RSSI is |high_rssi|, higher weight should be assigned
238   // to observations that were taken at |high_rssi|.
239   for (int i = 1; i < 100; ++i) {
240     absl::optional<int32_t> result =
241         buffer.GetPercentile(now, high_rssi, i, nullptr);
242     EXPECT_TRUE(result.has_value());
243     EXPECT_NEAR(result.value(), 51 + 0.49 * i, 2);
244   }
245 
246   // When the current RSSI is |low_rssi|, higher weight should be assigned
247   // to observations that were taken at |low_rssi|.
248   for (int i = 1; i < 100; ++i) {
249     absl::optional<int32_t> result =
250         buffer.GetPercentile(now, low_rssi, i, nullptr);
251     EXPECT_TRUE(result.has_value());
252     EXPECT_NEAR(result.value(), i / 2, 2);
253   }
254 }
255 
256 // Verifies that the percentiles are correctly computed when some of the
257 // observation sources are disallowed. All observations have the same timestamp.
TEST(NetworkQualityObservationBufferTest,RemoveObservations)258 TEST(NetworkQualityObservationBufferTest, RemoveObservations) {
259   std::map<std::string, std::string> variation_params;
260   NetworkQualityEstimatorParams params(variation_params);
261   base::SimpleTestTickClock tick_clock;
262   tick_clock.Advance(base::Minutes(1));
263 
264   ObservationBuffer buffer(&params, &tick_clock, 0.5, 1.0);
265   const base::TimeTicks now = tick_clock.NowTicks();
266 
267   // Insert samples from {1,2,3,..., 100}. First insert odd samples, then even
268   // samples. This helps in verifying that the order of samples does not matter.
269   for (int i = 1; i <= 99; i += 2) {
270     buffer.AddObservation(Observation(i, now, INT32_MIN,
271                                       NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
272   }
273   EXPECT_EQ(50u, buffer.Size());
274 
275   // Add samples for TCP and QUIC observations which should not be taken into
276   // account when computing the percentile.
277   for (int i = 1; i <= 99; i += 2) {
278     buffer.AddObservation(Observation(10000, now, INT32_MIN,
279                                       NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
280     buffer.AddObservation(Observation(10000, now, INT32_MIN,
281                                       NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC));
282   }
283   EXPECT_EQ(150u, buffer.Size());
284 
285   for (int i = 2; i <= 100; i += 2) {
286     buffer.AddObservation(Observation(i, now, INT32_MIN,
287                                       NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
288   }
289   EXPECT_EQ(200u, buffer.Size());
290 
291   bool deleted_observation_sources[NETWORK_QUALITY_OBSERVATION_SOURCE_MAX] = {
292       false};
293 
294   // Since all entries in |deleted_observation_sources| are set to false, no
295   // observations should be deleted.
296   buffer.RemoveObservationsWithSource(deleted_observation_sources);
297   EXPECT_EQ(200u, buffer.Size());
298 
299   // 50 TCP and 50 QUIC observations should be deleted.
300   deleted_observation_sources[NETWORK_QUALITY_OBSERVATION_SOURCE_TCP] = true;
301   deleted_observation_sources[NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC] = true;
302   buffer.RemoveObservationsWithSource(deleted_observation_sources);
303   EXPECT_EQ(100u, buffer.Size());
304 
305   for (int i = 0; i <= 100; ++i) {
306     // Checks if the difference between the two integers is less than 1. This is
307     // required because computed percentiles may be slightly different from
308     // what is expected due to floating point computation errors and integer
309     // rounding off errors.
310     absl::optional<int32_t> result =
311         buffer.GetPercentile(base::TimeTicks(), INT32_MIN, i, nullptr);
312     EXPECT_TRUE(result.has_value());
313     EXPECT_NEAR(result.value(), i, 1);
314   }
315 
316   deleted_observation_sources[NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP] = true;
317   buffer.RemoveObservationsWithSource(deleted_observation_sources);
318   EXPECT_EQ(0u, buffer.Size());
319 }
320 
TEST(NetworkQualityObservationBufferTest,TestGetMedianRTTSince)321 TEST(NetworkQualityObservationBufferTest, TestGetMedianRTTSince) {
322   std::map<std::string, std::string> variation_params;
323   NetworkQualityEstimatorParams params(variation_params);
324   base::SimpleTestTickClock tick_clock;
325   tick_clock.Advance(base::Minutes(1));
326   ObservationBuffer buffer(&params, &tick_clock, 0.5, 1.0);
327   base::TimeTicks now = tick_clock.NowTicks();
328   base::TimeTicks old = now - base::Milliseconds(1);
329   ASSERT_NE(old, now);
330 
331   // First sample has very old timestamp.
332   buffer.AddObservation(
333       Observation(1, old, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
334 
335   buffer.AddObservation(Observation(100, now, INT32_MIN,
336                                     NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
337 
338   const struct {
339     base::TimeTicks start_timestamp;
340     bool expect_network_quality_available;
341     base::TimeDelta expected_url_request_rtt;
342   } tests[] = {
343       {now + base::Seconds(10), false, base::Milliseconds(0)},
344       {now, true, base::Milliseconds(100)},
345       {now - base::Microseconds(500), true, base::Milliseconds(100)},
346 
347   };
348 
349   for (const auto& test : tests) {
350     absl::optional<int32_t> url_request_rtt =
351         buffer.GetPercentile(test.start_timestamp, INT32_MIN, 50, nullptr);
352     EXPECT_EQ(test.expect_network_quality_available,
353               url_request_rtt.has_value());
354 
355     if (test.expect_network_quality_available) {
356       EXPECT_EQ(test.expected_url_request_rtt.InMillisecondsF(),
357                 url_request_rtt.value());
358     }
359   }
360 }
361 
362 
363 }  // namespace
364 
365 }  // namespace net::nqe::internal
366