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/network_quality_store.h"
6
7 #include "base/strings/string_number_conversions.h"
8 #include "base/test/simple_test_tick_clock.h"
9 #include "base/time/time.h"
10 #include "net/base/network_change_notifier.h"
11 #include "net/nqe/cached_network_quality.h"
12 #include "net/nqe/effective_connection_type.h"
13 #include "net/nqe/network_id.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace net {
17
18 namespace {
19
TEST(NetworkQualityStoreTest,TestCaching)20 TEST(NetworkQualityStoreTest, TestCaching) {
21 nqe::internal::NetworkQualityStore network_quality_store;
22 base::SimpleTestTickClock tick_clock;
23
24 // Cached network quality for network with NetworkID (2G, "test1").
25 const nqe::internal::CachedNetworkQuality cached_network_quality_2g_test1(
26 tick_clock.NowTicks(),
27 nqe::internal::NetworkQuality(base::Seconds(1), base::Seconds(1), 1),
28 EFFECTIVE_CONNECTION_TYPE_2G);
29
30 {
31 // When ECT is UNKNOWN, then the network quality is not cached.
32 nqe::internal::CachedNetworkQuality cached_network_quality_unknown(
33 tick_clock.NowTicks(),
34 nqe::internal::NetworkQuality(base::Seconds(1), base::Seconds(1), 1),
35 EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
36
37 // Entry should not be added.
38 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
39 "test1", 0);
40 nqe::internal::CachedNetworkQuality read_network_quality;
41 network_quality_store.Add(network_id, cached_network_quality_unknown);
42 EXPECT_FALSE(
43 network_quality_store.GetById(network_id, &read_network_quality));
44 }
45
46 {
47 // Entry will be added for (2G, "test1").
48 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
49 "test1", 0);
50 nqe::internal::CachedNetworkQuality read_network_quality;
51 network_quality_store.Add(network_id, cached_network_quality_2g_test1);
52 EXPECT_TRUE(
53 network_quality_store.GetById(network_id, &read_network_quality));
54 EXPECT_EQ(cached_network_quality_2g_test1.network_quality(),
55 read_network_quality.network_quality());
56 }
57
58 {
59 // Entry will be added for (2G, "test2").
60 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
61 "test2", 0);
62 nqe::internal::CachedNetworkQuality read_network_quality;
63 nqe::internal::CachedNetworkQuality cached_network_quality(
64 tick_clock.NowTicks(),
65 nqe::internal::NetworkQuality(base::Seconds(2), base::Seconds(2), 2),
66 EFFECTIVE_CONNECTION_TYPE_2G);
67 network_quality_store.Add(network_id, cached_network_quality);
68 EXPECT_TRUE(
69 network_quality_store.GetById(network_id, &read_network_quality));
70 EXPECT_EQ(read_network_quality.network_quality(),
71 cached_network_quality.network_quality());
72 }
73
74 {
75 // Entry will be added for (3G, "test3").
76 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_3G,
77 "test3", 0);
78 nqe::internal::CachedNetworkQuality read_network_quality;
79 nqe::internal::CachedNetworkQuality cached_network_quality(
80 tick_clock.NowTicks(),
81 nqe::internal::NetworkQuality(base::Seconds(3), base::Seconds(3), 3),
82 EFFECTIVE_CONNECTION_TYPE_3G);
83 network_quality_store.Add(network_id, cached_network_quality);
84 EXPECT_TRUE(
85 network_quality_store.GetById(network_id, &read_network_quality));
86 EXPECT_EQ(read_network_quality.network_quality(),
87 cached_network_quality.network_quality());
88 }
89
90 {
91 // Entry will be added for (Unknown, "").
92 nqe::internal::NetworkID network_id(
93 NetworkChangeNotifier::CONNECTION_UNKNOWN, "", 0);
94 nqe::internal::CachedNetworkQuality read_network_quality;
95 nqe::internal::CachedNetworkQuality set_network_quality(
96 tick_clock.NowTicks(),
97 nqe::internal::NetworkQuality(base::Seconds(4), base::Seconds(4), 4),
98 EFFECTIVE_CONNECTION_TYPE_4G);
99 network_quality_store.Add(network_id, set_network_quality);
100 EXPECT_TRUE(
101 network_quality_store.GetById(network_id, &read_network_quality));
102 }
103
104 {
105 // Existing entry will be read for (2G, "test1").
106 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
107 "test1", 0);
108 nqe::internal::CachedNetworkQuality read_network_quality;
109 EXPECT_TRUE(
110 network_quality_store.GetById(network_id, &read_network_quality));
111 EXPECT_EQ(cached_network_quality_2g_test1.network_quality(),
112 read_network_quality.network_quality());
113 }
114
115 {
116 // Existing entry will be overwritten for (2G, "test1").
117 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
118 "test1", 0);
119 nqe::internal::CachedNetworkQuality read_network_quality;
120 const nqe::internal::CachedNetworkQuality cached_network_quality(
121 tick_clock.NowTicks(),
122 nqe::internal::NetworkQuality(base::Seconds(5), base::Seconds(5), 5),
123 EFFECTIVE_CONNECTION_TYPE_4G);
124 network_quality_store.Add(network_id, cached_network_quality);
125 EXPECT_TRUE(
126 network_quality_store.GetById(network_id, &read_network_quality));
127 EXPECT_EQ(cached_network_quality.network_quality(),
128 read_network_quality.network_quality());
129 }
130
131 {
132 // No entry should exist for (2G, "test4").
133 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
134 "test4", 0);
135 nqe::internal::CachedNetworkQuality read_network_quality;
136 EXPECT_FALSE(
137 network_quality_store.GetById(network_id, &read_network_quality));
138 }
139 }
140
TEST(NetworkQualityStoreTest,TestCachingClosestSignalStrength)141 TEST(NetworkQualityStoreTest, TestCachingClosestSignalStrength) {
142 nqe::internal::NetworkQualityStore network_quality_store;
143 base::SimpleTestTickClock tick_clock;
144
145 // Cached network quality for network with NetworkID (2G, "test1").
146 const nqe::internal::CachedNetworkQuality cached_network_quality_strength_1(
147 tick_clock.NowTicks(),
148 nqe::internal::NetworkQuality(base::Seconds(1), base::Seconds(1), 1),
149 EFFECTIVE_CONNECTION_TYPE_2G);
150
151 const nqe::internal::CachedNetworkQuality cached_network_quality_strength_3(
152 tick_clock.NowTicks(),
153 nqe::internal::NetworkQuality(base::Seconds(3), base::Seconds(3), 3),
154 EFFECTIVE_CONNECTION_TYPE_2G);
155
156 {
157 // Entry will be added for (2G, "test1") with signal strength value of 1.
158 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
159 "test1", 1);
160 nqe::internal::CachedNetworkQuality read_network_quality;
161 network_quality_store.Add(network_id, cached_network_quality_strength_1);
162 EXPECT_TRUE(
163 network_quality_store.GetById(network_id, &read_network_quality));
164 EXPECT_EQ(cached_network_quality_strength_1.network_quality(),
165 read_network_quality.network_quality());
166 }
167
168 {
169 // Entry will be added for (2G, "test1") with signal strength value of 3.
170 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
171 "test1", 3);
172 nqe::internal::CachedNetworkQuality read_network_quality;
173 network_quality_store.Add(network_id, cached_network_quality_strength_3);
174 EXPECT_TRUE(
175 network_quality_store.GetById(network_id, &read_network_quality));
176 EXPECT_EQ(cached_network_quality_strength_3.network_quality(),
177 read_network_quality.network_quality());
178 }
179
180 {
181 // Now with cached entries for signal strengths 1 and 3, verify across the
182 // range of strength values that the closest value match will be returned
183 // when looking up (2G, "test1", signal_strength).
184 for (int32_t signal_strength = 0; signal_strength <= 4; ++signal_strength) {
185 nqe::internal::CachedNetworkQuality expected_cached_network_quality =
186 signal_strength <= 2 ? cached_network_quality_strength_1
187 : cached_network_quality_strength_3;
188 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
189 "test1", signal_strength);
190 nqe::internal::CachedNetworkQuality read_network_quality;
191 EXPECT_TRUE(
192 network_quality_store.GetById(network_id, &read_network_quality));
193 EXPECT_EQ(expected_cached_network_quality.network_quality(),
194 read_network_quality.network_quality());
195 }
196 }
197
198 {
199 // When the current network does not have signal strength available, then
200 // the cached value that corresponds to maximum signal strength should be
201 // returned.
202 int32_t signal_strength = INT32_MIN;
203 nqe::internal::CachedNetworkQuality expected_cached_network_quality =
204 cached_network_quality_strength_3;
205 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
206 "test1", signal_strength);
207 nqe::internal::CachedNetworkQuality read_network_quality;
208 EXPECT_TRUE(
209 network_quality_store.GetById(network_id, &read_network_quality));
210 EXPECT_EQ(expected_cached_network_quality.network_quality(),
211 read_network_quality.network_quality());
212 }
213
214 {
215 // No entry should exist for (2G, "test4").
216 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
217 "test4", 0);
218 nqe::internal::CachedNetworkQuality read_network_quality;
219 EXPECT_FALSE(
220 network_quality_store.GetById(network_id, &read_network_quality));
221 }
222 }
223
TEST(NetworkQualityStoreTest,TestCachingUnknownSignalStrength)224 TEST(NetworkQualityStoreTest, TestCachingUnknownSignalStrength) {
225 nqe::internal::NetworkQualityStore network_quality_store;
226 base::SimpleTestTickClock tick_clock;
227
228 // Cached network quality for network with NetworkID (2G, "test1").
229 const nqe::internal::CachedNetworkQuality
230 cached_network_quality_strength_unknown(
231 tick_clock.NowTicks(),
232 nqe::internal::NetworkQuality(base::Seconds(1), base::Seconds(1), 1),
233 EFFECTIVE_CONNECTION_TYPE_2G);
234
235 const nqe::internal::CachedNetworkQuality cached_network_quality_strength_3(
236 tick_clock.NowTicks(),
237 nqe::internal::NetworkQuality(base::Seconds(3), base::Seconds(3), 3),
238 EFFECTIVE_CONNECTION_TYPE_2G);
239
240 {
241 // Entry will be added for (2G, "test1") with signal strength value of
242 // INT32_MIN.
243 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
244 "test1", INT32_MIN);
245 nqe::internal::CachedNetworkQuality read_network_quality;
246 network_quality_store.Add(network_id,
247 cached_network_quality_strength_unknown);
248 EXPECT_TRUE(
249 network_quality_store.GetById(network_id, &read_network_quality));
250 EXPECT_EQ(cached_network_quality_strength_unknown.network_quality(),
251 read_network_quality.network_quality());
252 }
253
254 {
255 // Entry will be added for (2G, "test1") with signal strength value of 3.
256 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
257 "test1", 3);
258 nqe::internal::CachedNetworkQuality read_network_quality;
259 network_quality_store.Add(network_id, cached_network_quality_strength_3);
260 EXPECT_TRUE(
261 network_quality_store.GetById(network_id, &read_network_quality));
262 EXPECT_EQ(cached_network_quality_strength_3.network_quality(),
263 read_network_quality.network_quality());
264 }
265
266 {
267 // Now with cached entries for signal strengths INT32_MIN and 3, verify
268 // across the range of strength values that the closest value match will be
269 // returned when looking up (2G, "test1", signal_strength).
270 for (int32_t signal_strength = 0; signal_strength <= 4; ++signal_strength) {
271 nqe::internal::CachedNetworkQuality expected_cached_network_quality =
272 cached_network_quality_strength_3;
273 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
274 "test1", signal_strength);
275 nqe::internal::CachedNetworkQuality read_network_quality;
276 EXPECT_TRUE(
277 network_quality_store.GetById(network_id, &read_network_quality));
278 EXPECT_EQ(expected_cached_network_quality.network_quality(),
279 read_network_quality.network_quality());
280 }
281 }
282
283 {
284 // When the current network does not have signal strength available, then
285 // the cached value that corresponds to unknown signal strength should be
286 // returned.
287 int32_t signal_strength = INT32_MIN;
288 nqe::internal::CachedNetworkQuality expected_cached_network_quality =
289 cached_network_quality_strength_unknown;
290 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
291 "test1", signal_strength);
292 nqe::internal::CachedNetworkQuality read_network_quality;
293 EXPECT_TRUE(
294 network_quality_store.GetById(network_id, &read_network_quality));
295 EXPECT_EQ(expected_cached_network_quality.network_quality(),
296 read_network_quality.network_quality());
297 }
298 }
299
300 // Tests if the cache size remains bounded. Also, ensure that the cache is
301 // LRU.
TEST(NetworkQualityStoreTest,TestLRUCacheMaximumSize)302 TEST(NetworkQualityStoreTest, TestLRUCacheMaximumSize) {
303 nqe::internal::NetworkQualityStore network_quality_store;
304 base::SimpleTestTickClock tick_clock;
305
306 // Add more networks than the maximum size of the cache.
307 const size_t network_count = 21;
308
309 nqe::internal::CachedNetworkQuality read_network_quality(
310 tick_clock.NowTicks(),
311 nqe::internal::NetworkQuality(base::Seconds(0), base::Seconds(0), 0),
312 EFFECTIVE_CONNECTION_TYPE_2G);
313
314 for (size_t i = 0; i < network_count; ++i) {
315 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
316 "test" + base::NumberToString(i), 0);
317
318 const nqe::internal::CachedNetworkQuality network_quality(
319 tick_clock.NowTicks(),
320 nqe::internal::NetworkQuality(base::Seconds(1), base::Seconds(1), 1),
321 EFFECTIVE_CONNECTION_TYPE_2G);
322 network_quality_store.Add(network_id, network_quality);
323 tick_clock.Advance(base::Seconds(1));
324 }
325
326 base::TimeTicks earliest_last_update_time = tick_clock.NowTicks();
327 size_t cache_match_count = 0;
328 for (size_t i = 0; i < network_count; ++i) {
329 nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G,
330 "test" + base::NumberToString(i), 0);
331
332 nqe::internal::CachedNetworkQuality network_quality(
333 tick_clock.NowTicks(),
334 nqe::internal::NetworkQuality(base::Seconds(0), base::Seconds(0), 0),
335 EFFECTIVE_CONNECTION_TYPE_2G);
336 if (network_quality_store.GetById(network_id, &network_quality)) {
337 cache_match_count++;
338 earliest_last_update_time = std::min(earliest_last_update_time,
339 network_quality.last_update_time());
340 }
341 }
342
343 // Ensure that the number of entries in cache are fewer than |network_count|.
344 EXPECT_LT(cache_match_count, network_count);
345 EXPECT_GT(cache_match_count, 0u);
346
347 // Ensure that only LRU entries are cached by comparing the
348 // |earliest_last_update_time|.
349 EXPECT_EQ(tick_clock.NowTicks() - base::Seconds(cache_match_count),
350 earliest_last_update_time);
351 }
352
353 } // namespace
354
355 } // namespace net
356