Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: chromeos/components/tether/host_scan_cache_unittest.cc

Issue 2852693004: [CrOS Tether] Create HostScanCache, which caches scan results and inserts them into the network sta… (Closed)
Patch Set: stevenjb@ comments. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 "chromeos/components/tether/host_scan_cache.h"
6
7 #include <memory>
8 #include <unordered_map>
9 #include <vector>
10
11 #include "base/callback.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/test/scoped_task_environment.h"
14 #include "base/timer/mock_timer.h"
15 #include "chromeos/components/tether/device_id_tether_network_guid_map.h"
16 #include "chromeos/components/tether/fake_active_host.h"
17 #include "chromeos/components/tether/fake_host_scan_cache.h"
18 #include "chromeos/components/tether/mock_tether_host_response_recorder.h"
19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/network/network_state.h"
21 #include "chromeos/network/network_state_handler.h"
22 #include "chromeos/network/network_state_test.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 using testing::NiceMock;
27 using testing::Invoke;
28
29 namespace chromeos {
30
31 namespace tether {
32
33 namespace {
34
35 const char kTetherGuid0[] = "kTetherGuid0";
36 const char kTetherGuid1[] = "kTetherGuid1";
37 const char kTetherGuid2[] = "kTetherGuid2";
38 const char kTetherGuid3[] = "kTetherGuid3";
39
40 const char kTetherDeviceName0[] = "kDeviceName1";
41 const char kTetherDeviceName1[] = "kDeviceName2";
42 const char kTetherDeviceName2[] = "kDeviceName3";
43 const char kTetherDeviceName3[] = "kDeviceName4";
44
45 const char kTetherCarrier0[] = "kTetherCarrier0";
46 const char kTetherCarrier1[] = "kTetherCarrier1";
47 const char kTetherCarrier2[] = "kTetherCarrier2";
48 const char kTetherCarrier3[] = "kTetherCarrier3";
49
50 const int kTetherBatteryPercentage0 = 20;
51 const int kTetherBatteryPercentage1 = 40;
52 const int kTetherBatteryPercentage2 = 60;
53 const int kTetherBatteryPercentage3 = 80;
54
55 const int kTetherSignalStrength0 = 25;
56 const int kTetherSignalStrength1 = 50;
57 const int kTetherSignalStrength2 = 75;
58 const int kTetherSignalStrength3 = 100;
59
60 // MockTimer which invokes a callback in its destructor.
61 class ExtendedMockTimer : public base::MockTimer {
62 public:
63 explicit ExtendedMockTimer(const base::Closure& destructor_callback)
64 : base::MockTimer(true /* retain_user_task */, false /* is_repeating */),
65 destructor_callback_(destructor_callback) {}
66
67 ~ExtendedMockTimer() override { destructor_callback_.Run(); }
68
69 private:
70 base::Closure destructor_callback_;
71 };
72
73 } // namespace
74
75 // TODO(khorimoto): The test uses a FakeHostScanCache to keep an in-memory
76 // cache of expected values. This has the potential to be confusing, since this
77 // is the test for HostScanCache. Clean this up to avoid using FakeHostScanCache
78 // if possible.
79 class HostScanCacheTest : public NetworkStateTest {
80 protected:
81 class TestTimerFactory : public HostScanCache::TimerFactory {
82 public:
83 TestTimerFactory() {}
84 ~TestTimerFactory() {}
85
86 std::unordered_map<std::string, ExtendedMockTimer*>&
87 tether_network_guid_to_timer_map() {
88 return tether_network_guid_to_timer_map_;
89 }
90
91 void set_tether_network_guid_for_next_timer(
92 const std::string& tether_network_guid_for_next_timer) {
93 tether_network_guid_for_next_timer_ = tether_network_guid_for_next_timer;
94 }
stevenjb 2017/05/01 22:13:01 This is definitely a better solution IMHO. An extr
Kyle Horimoto 2017/05/02 00:02:18 Yay! It actually didn't end up being as hard as I
95
96 // HostScanCache::TimerFactory:
97 std::unique_ptr<base::Timer> CreateOneShotTimer() override {
98 EXPECT_FALSE(tether_network_guid_for_next_timer_.empty());
99 ExtendedMockTimer* mock_timer = new ExtendedMockTimer(base::Bind(
100 &TestTimerFactory::OnActiveTimerDestructor, base::Unretained(this),
101 tether_network_guid_for_next_timer_));
102 tether_network_guid_to_timer_map_[tether_network_guid_for_next_timer_] =
103 mock_timer;
104 return base::WrapUnique(mock_timer);
105 }
106
107 private:
108 void OnActiveTimerDestructor(const std::string& tether_network_guid) {
109 tether_network_guid_to_timer_map_.erase(
110 tether_network_guid_to_timer_map_.find(tether_network_guid));
111 }
112
113 std::string tether_network_guid_for_next_timer_;
114 std::unordered_map<std::string, ExtendedMockTimer*>
115 tether_network_guid_to_timer_map_;
116 };
117
118 HostScanCacheTest() {}
119
120 void SetUp() override {
121 DBusThreadManager::Initialize();
122 NetworkStateTest::SetUp();
123 network_state_handler()->SetTetherTechnologyState(
124 NetworkStateHandler::TECHNOLOGY_ENABLED);
125
126 test_timer_factory_ = new TestTimerFactory();
127 fake_active_host_ = base::MakeUnique<FakeActiveHost>();
128 mock_tether_host_response_recorder_ =
129 base::MakeUnique<NiceMock<MockTetherHostResponseRecorder>>();
130 device_id_tether_network_guid_map_ =
131 base::MakeUnique<DeviceIdTetherNetworkGuidMap>();
132
133 ON_CALL(*mock_tether_host_response_recorder_,
134 GetPreviouslyConnectedHostIds())
135 .WillByDefault(
136 Invoke(this, &HostScanCacheTest::GetPreviouslyConnectedHostIds));
137
138 host_scan_cache_ = base::WrapUnique(new HostScanCache(
139 base::WrapUnique(test_timer_factory_), network_state_handler(),
140 fake_active_host_.get(), mock_tether_host_response_recorder_.get(),
141 device_id_tether_network_guid_map_.get()));
142
143 // To track what is expected to be contained in the cache, maintain a
144 // FakeHostScanCache in memory and update it alongside |host_scan_cache_|.
145 // Use a std::vector to track which device IDs correspond to devices whose
146 // Tether networks' HasConnectedToHost fields are expected to be set.
147 expected_cache_ = base::MakeUnique<FakeHostScanCache>();
148 has_connected_to_host_device_ids_.clear();
149 }
150
151 void TearDown() override {
152 ShutdownNetworkState();
153 NetworkStateTest::TearDown();
154 DBusThreadManager::Shutdown();
155 }
156
157 void FireTimer(const std::string& tether_network_guid) {
158 ExtendedMockTimer* timer =
159 test_timer_factory_
160 ->tether_network_guid_to_timer_map()[tether_network_guid];
161 ASSERT_TRUE(timer);
162 timer->Fire();
163
164 // If the device whose correlated timer has fired is not the active host, it
165 // is expected to be removed from the cache.
166 EXPECT_EQ(fake_active_host_->GetTetherNetworkGuid(),
167 expected_cache_->active_host_tether_network_guid());
168 if (fake_active_host_->GetTetherNetworkGuid() != tether_network_guid) {
169 expected_cache_->RemoveHostScanResult(tether_network_guid);
170 }
171 }
172
173 std::vector<std::string> GetPreviouslyConnectedHostIds() const {
174 return has_connected_to_host_device_ids_;
175 }
176
177 void SetActiveHost(const std::string& tether_network_guid) {
178 fake_active_host_->SetActiveHostConnected(
179 device_id_tether_network_guid_map_->GetDeviceIdForTetherNetworkGuid(
180 tether_network_guid),
181 tether_network_guid, "wifiNetworkGuid");
182 expected_cache_->set_active_host_tether_network_guid(tether_network_guid);
183 }
184
185 void SetHasConnectedToHost(const std::string& tether_network_guid) {
186 has_connected_to_host_device_ids_.push_back(
187 device_id_tether_network_guid_map_->GetDeviceIdForTetherNetworkGuid(
188 tether_network_guid));
189 mock_tether_host_response_recorder_
190 ->NotifyObserversPreviouslyConnectedHostIdsChanged();
191 }
192
193 // Sets host scan results in the cache for the device at index |index|. Index
194 // can be from 0 to 3 and corresponds to the index of the constants declared
195 // at the top of this test file.
196 void SetCacheScanResultForDeviceIndex(int32_t index) {
197 // There are 4 sets of test constants.
198 ASSERT_TRUE(index >= 0 && index <= 3);
199
200 std::string tether_network_guid;
201 std::string device_name;
202 std::string carrier;
203 int battery_percentage;
204 int signal_strength;
205
206 switch (index) {
207 case 0:
208 tether_network_guid = kTetherGuid0;
209 device_name = kTetherDeviceName0;
210 carrier = kTetherCarrier0;
211 battery_percentage = kTetherBatteryPercentage0;
212 signal_strength = kTetherSignalStrength0;
213 break;
214 case 1:
215 tether_network_guid = kTetherGuid1;
216 device_name = kTetherDeviceName1;
217 carrier = kTetherCarrier1;
218 battery_percentage = kTetherBatteryPercentage1;
219 signal_strength = kTetherSignalStrength1;
220 break;
221 case 2:
222 tether_network_guid = kTetherGuid2;
223 device_name = kTetherDeviceName2;
224 carrier = kTetherCarrier2;
225 battery_percentage = kTetherBatteryPercentage2;
226 signal_strength = kTetherSignalStrength2;
227 break;
228 case 3:
229 tether_network_guid = kTetherGuid3;
230 device_name = kTetherDeviceName3;
231 carrier = kTetherCarrier3;
232 battery_percentage = kTetherBatteryPercentage3;
233 signal_strength = kTetherSignalStrength3;
234 break;
235 default:
236 NOTREACHED();
237 // Set values for |battery_percentage| and |signal_strength| here to
238 // prevent a compiler warning which says that they may be unset at this
239 // point.
240 battery_percentage = 0;
241 signal_strength = 0;
242 break;
243 }
244
245 SetHostScanResult(tether_network_guid, device_name, carrier,
246 battery_percentage, signal_strength);
247 }
248
249 void SetHostScanResult(const std::string& tether_network_guid,
250 const std::string& device_name,
251 const std::string& carrier,
252 int battery_percentage,
253 int signal_strength) {
254 test_timer_factory_->set_tether_network_guid_for_next_timer(
255 tether_network_guid);
256 host_scan_cache_->SetHostScanResult(tether_network_guid, device_name,
257 carrier, battery_percentage,
258 signal_strength);
259 expected_cache_->SetHostScanResult(tether_network_guid, device_name,
260 carrier, battery_percentage,
261 signal_strength);
262 }
263
264 void RemoveHostScanResult(const std::string& tether_network_guid) {
265 host_scan_cache_->RemoveHostScanResult(tether_network_guid);
266 expected_cache_->RemoveHostScanResult(tether_network_guid);
267 }
268
269 void ClearCacheExceptForActiveHost() {
270 host_scan_cache_->ClearCacheExceptForActiveHost();
271 expected_cache_->ClearCacheExceptForActiveHost();
272 }
273
274 bool HasConnectedToHost(const std::string& tether_network_guid) {
275 auto it =
276 std::find(has_connected_to_host_device_ids_.begin(),
277 has_connected_to_host_device_ids_.end(), tether_network_guid);
278 return it != has_connected_to_host_device_ids_.end();
279 }
280
281 // Verifies that the information present in |expected_cache_| and
282 // |has_connected_to_host_device_ids_| mirrors what |host_scan_cache_| has set
283 // in NetworkStateHandler.
284 void VerifyCacheMatchesNetworkStack() {
285 for (auto& it : expected_cache_->cache()) {
286 const std::string tether_network_guid = it.first;
287 const FakeHostScanCache::CacheEntry cache_entry = it.second;
288
289 // Ensure that each entry in |expected_cache_| matches the
290 // corresponding entry in NetworkStateHandler.
291 const NetworkState* tether_network_state =
292 network_state_handler()->GetNetworkStateFromGuid(tether_network_guid);
293 ASSERT_TRUE(tether_network_state);
294 EXPECT_EQ(cache_entry.device_name, tether_network_state->name());
295 EXPECT_EQ(cache_entry.carrier, tether_network_state->carrier());
296 EXPECT_EQ(cache_entry.battery_percentage,
297 tether_network_state->battery_percentage());
298 EXPECT_EQ(cache_entry.signal_strength,
299 tether_network_state->signal_strength());
300 EXPECT_EQ(HasConnectedToHost(tether_network_guid),
301 tether_network_state->tether_has_connected_to_host());
302
303 // Ensure that each entry has an actively-running Timer.
304 auto timer_map_it =
305 test_timer_factory_->tether_network_guid_to_timer_map().begin();
306 EXPECT_NE(timer_map_it,
307 test_timer_factory_->tether_network_guid_to_timer_map().end());
308 EXPECT_TRUE(timer_map_it->second->IsRunning());
309 }
310 }
311
312 const base::test::ScopedTaskEnvironment scoped_task_environment_;
313
314 TestTimerFactory* test_timer_factory_;
315 std::unique_ptr<FakeActiveHost> fake_active_host_;
316 std::unique_ptr<NiceMock<MockTetherHostResponseRecorder>>
317 mock_tether_host_response_recorder_;
318 // TODO(hansberry): Use a fake for this when a real mapping scheme is created.
319 std::unique_ptr<DeviceIdTetherNetworkGuidMap>
320 device_id_tether_network_guid_map_;
321
322 std::vector<std::string> has_connected_to_host_device_ids_;
323 std::unique_ptr<FakeHostScanCache> expected_cache_;
324
325 std::unique_ptr<HostScanCache> host_scan_cache_;
326
327 private:
328 DISALLOW_COPY_AND_ASSIGN(HostScanCacheTest);
329 };
330
331 TEST_F(HostScanCacheTest, TestSetScanResultsAndLetThemExpire) {
332 SetCacheScanResultForDeviceIndex(0);
333 EXPECT_EQ(1u, expected_cache_->size());
334 VerifyCacheMatchesNetworkStack();
335
336 SetCacheScanResultForDeviceIndex(1);
337 EXPECT_EQ(2u, expected_cache_->size());
338 VerifyCacheMatchesNetworkStack();
339
340 SetCacheScanResultForDeviceIndex(2);
341 EXPECT_EQ(3u, expected_cache_->size());
342 VerifyCacheMatchesNetworkStack();
343
344 SetCacheScanResultForDeviceIndex(3);
345 EXPECT_EQ(4u, expected_cache_->size());
346 VerifyCacheMatchesNetworkStack();
347
348 FireTimer(kTetherGuid0);
349 EXPECT_EQ(3u, expected_cache_->size());
350 VerifyCacheMatchesNetworkStack();
351
352 FireTimer(kTetherGuid1);
353 EXPECT_EQ(2u, expected_cache_->size());
354 VerifyCacheMatchesNetworkStack();
355
356 FireTimer(kTetherGuid2);
357 EXPECT_EQ(1u, expected_cache_->size());
358 VerifyCacheMatchesNetworkStack();
359
360 FireTimer(kTetherGuid3);
361 EXPECT_TRUE(expected_cache_->empty());
362 VerifyCacheMatchesNetworkStack();
363 }
364
365 TEST_F(HostScanCacheTest, TestSetScanResultThenUpdateAndRemove) {
366 SetCacheScanResultForDeviceIndex(0);
367 EXPECT_EQ(1u, expected_cache_->size());
368 VerifyCacheMatchesNetworkStack();
369
370 // Change the fields for tether network with GUID |kTetherGuid0| to the
371 // fields corresponding to |kTetherGuid1|.
372 SetHostScanResult(kTetherGuid0, kTetherDeviceName0, kTetherCarrier1,
373 kTetherBatteryPercentage1, kTetherSignalStrength1);
374 EXPECT_EQ(1u, expected_cache_->size());
375 VerifyCacheMatchesNetworkStack();
376
377 // Now, remove that result.
378 RemoveHostScanResult(kTetherGuid0);
379 EXPECT_TRUE(expected_cache_->empty());
380 VerifyCacheMatchesNetworkStack();
381 }
382
383 TEST_F(HostScanCacheTest, TestSetScanResult_SetActiveHost_ThenClear) {
384 SetCacheScanResultForDeviceIndex(0);
385 EXPECT_EQ(1u, expected_cache_->size());
386 VerifyCacheMatchesNetworkStack();
387
388 SetCacheScanResultForDeviceIndex(1);
389 EXPECT_EQ(2u, expected_cache_->size());
390 VerifyCacheMatchesNetworkStack();
391
392 SetCacheScanResultForDeviceIndex(2);
393 EXPECT_EQ(3u, expected_cache_->size());
394 VerifyCacheMatchesNetworkStack();
395
396 // Now, set the active host to be the device 0.
397 SetActiveHost(kTetherGuid0);
398
399 // Clear the cache except for the active host.
400 ClearCacheExceptForActiveHost();
401 EXPECT_EQ(1u, expected_cache_->size());
402 VerifyCacheMatchesNetworkStack();
403
404 // Attempt to remove the active host. This operation should fail since
405 // removing the active host from the cache is not allowed.
406 RemoveHostScanResult(kTetherGuid0);
407 EXPECT_EQ(1u, expected_cache_->size());
408 VerifyCacheMatchesNetworkStack();
409
410 // Fire the timer for the active host. Likewise, this should not result in the
411 // cache entry being removed.
412 FireTimer(kTetherGuid0);
413 EXPECT_EQ(1u, expected_cache_->size());
414 VerifyCacheMatchesNetworkStack();
415
416 // Now, unset the active host.
417 SetActiveHost("");
418
419 // Removing the device should now succeed.
420 RemoveHostScanResult(kTetherGuid0);
421 EXPECT_TRUE(expected_cache_->empty());
422 VerifyCacheMatchesNetworkStack();
423 }
424
425 TEST_F(HostScanCacheTest, TestHasConnectedToHost) {
426 // Before the test starts, set device 0 as having already connected.
427 SetHasConnectedToHost(kTetherGuid0);
428
429 SetCacheScanResultForDeviceIndex(0);
430 EXPECT_EQ(1u, expected_cache_->size());
431 VerifyCacheMatchesNetworkStack();
432
433 SetCacheScanResultForDeviceIndex(1);
434 EXPECT_EQ(2u, expected_cache_->size());
435 VerifyCacheMatchesNetworkStack();
436
437 // Simulate a connection to device 1.
438 SetActiveHost(kTetherGuid1);
439 SetHasConnectedToHost(kTetherGuid1);
440 VerifyCacheMatchesNetworkStack();
441 }
442
443 } // namespace tether
444
445 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698