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

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

Issue 2792483002: [CrOS Tether] Create TetherConnector, which attempts to connect to a nearby tether host. (Closed)
Patch Set: hansberry@ comment. Created 3 years, 8 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/tether_connector.h"
6
7 #include "base/memory/ptr_util.h"
8 #include "base/message_loop/message_loop.h"
9 #include "chromeos/components/tether/connect_tethering_operation.h"
10 #include "chromeos/components/tether/device_id_tether_network_guid_map.h"
11 #include "chromeos/components/tether/fake_active_host.h"
12 #include "chromeos/components/tether/fake_ble_connection_manager.h"
13 #include "chromeos/components/tether/fake_tether_host_fetcher.h"
14 #include "chromeos/components/tether/fake_wifi_hotspot_connector.h"
15 #include "chromeos/components/tether/mock_host_scan_device_prioritizer.h"
16 #include "chromeos/components/tether/tether_connector.h"
17 #include "chromeos/dbus/dbus_thread_manager.h"
18 #include "chromeos/network/network_connect.h"
19 #include "chromeos/network/network_state.h"
20 #include "chromeos/network/network_state_handler.h"
21 #include "chromeos/network/network_state_test.h"
22 #include "components/cryptauth/remote_device.h"
23 #include "components/cryptauth/remote_device_test_util.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
27
28 namespace chromeos {
29
30 namespace tether {
31
32 namespace {
33
34 const char kSsid[] = "ssid";
35 const char kPassword[] = "password";
36
37 const char kWifiNetworkGuid[] = "wifiNetworkGuid";
38
39 const char kTetherNetwork1Name[] = "tetherNetwork1Name";
40 const char kTetherNetwork2Name[] = "tetherNetwork2Name";
41
42 std::string CreateWifiConfigurationJsonString() {
43 std::stringstream ss;
44 ss << "{"
45 << " \"GUID\": \"" << kWifiNetworkGuid << "\","
46 << " \"Type\": \"" << shill::kTypeWifi << "\","
47 << " \"State\": \"" << shill::kStateIdle << "\""
48 << "}";
49 return ss.str();
50 }
51
52 class TestNetworkConnect : public NetworkConnect {
53 public:
54 TestNetworkConnect() : tether_delegate_(nullptr) {}
55 ~TestNetworkConnect() override {}
56
57 void CallTetherDelegate(const std::string& tether_network_guid) {
58 tether_delegate_->ConnectToNetwork(tether_network_guid);
59 }
60
61 // NetworkConnect:
62 void SetTetherDelegate(
63 NetworkConnect::TetherDelegate* tether_delegate) override {
64 tether_delegate_ = tether_delegate;
65 }
66
67 void DisconnectFromNetworkId(const std::string& network_id) override {}
68 bool MaybeShowConfigureUI(const std::string& network_id,
69 const std::string& connect_error) override {
70 return false;
71 }
72 void SetTechnologyEnabled(const chromeos::NetworkTypePattern& technology,
73 bool enabled_state) override {}
74 void ShowMobileSetup(const std::string& network_id) override {}
75 void ConfigureNetworkIdAndConnect(
76 const std::string& network_id,
77 const base::DictionaryValue& shill_properties,
78 bool shared) override {}
79 void CreateConfigurationAndConnect(base::DictionaryValue* shill_properties,
80 bool shared) override {}
81 void CreateConfiguration(base::DictionaryValue* shill_properties,
82 bool shared) override {}
83 void ConnectToNetworkId(const std::string& network_id) override {}
84
85 private:
86 NetworkConnect::TetherDelegate* tether_delegate_;
87 };
88
89 class FakeConnectTetheringOperation : public ConnectTetheringOperation {
90 public:
91 FakeConnectTetheringOperation(
92 const cryptauth::RemoteDevice& device_to_connect,
93 BleConnectionManager* connection_manager,
94 HostScanDevicePrioritizer* host_scan_device_prioritizer)
95 : ConnectTetheringOperation(device_to_connect,
96 connection_manager,
97 host_scan_device_prioritizer) {}
98
99 ~FakeConnectTetheringOperation() override {}
100
101 void SendSuccessfulResponse(const std::string& ssid,
102 const std::string& password) {
103 NotifyObserversOfSuccessfulResponse(ssid, password);
104 }
105
106 void SendFailedResponse(ConnectTetheringResponse_ResponseCode error_code) {
107 NotifyObserversOfConnectionFailure(error_code);
108 }
109
110 cryptauth::RemoteDevice GetRemoteDevice() {
111 EXPECT_EQ(1u, remote_devices().size());
112 return remote_devices()[0];
113 }
114 };
115
116 class FakeConnectTetheringOperationFactory
117 : public ConnectTetheringOperation::Factory {
118 public:
119 FakeConnectTetheringOperationFactory() {}
120 virtual ~FakeConnectTetheringOperationFactory() {}
121
122 std::vector<FakeConnectTetheringOperation*>& created_operations() {
123 return created_operations_;
124 }
125
126 protected:
127 // ConnectTetheringOperation::Factory:
128 std::unique_ptr<ConnectTetheringOperation> BuildInstance(
129 const cryptauth::RemoteDevice& device_to_connect,
130 BleConnectionManager* connection_manager,
131 HostScanDevicePrioritizer* host_scan_device_prioritizer) override {
132 FakeConnectTetheringOperation* operation =
133 new FakeConnectTetheringOperation(device_to_connect, connection_manager,
134 host_scan_device_prioritizer);
135 created_operations_.push_back(operation);
136 return base::WrapUnique(operation);
137 }
138
139 private:
140 std::vector<FakeConnectTetheringOperation*> created_operations_;
141 };
142
143 } // namespace
144
145 class TetherConnectorTest : public NetworkStateTest {
146 public:
147 TetherConnectorTest()
148 : test_devices_(cryptauth::GenerateTestRemoteDevices(2u)) {}
149 ~TetherConnectorTest() override {}
150
151 void SetUp() override {
152 DBusThreadManager::Initialize();
153 NetworkStateTest::SetUp();
154
155 fake_operation_factory_ =
156 base::WrapUnique(new FakeConnectTetheringOperationFactory());
157 ConnectTetheringOperation::Factory::SetInstanceForTesting(
158 fake_operation_factory_.get());
159
160 test_network_connect_ = base::WrapUnique(new TestNetworkConnect());
161 fake_wifi_hotspot_connector_ =
162 base::MakeUnique<FakeWifiHotspotConnector>(network_state_handler());
163 fake_active_host_ = base::MakeUnique<FakeActiveHost>();
164 fake_tether_host_fetcher_ = base::MakeUnique<FakeTetherHostFetcher>(
165 test_devices_, false /* synchronously_reply_with_results */);
166 fake_ble_connection_manager_ = base::MakeUnique<FakeBleConnectionManager>();
167 mock_host_scan_device_prioritizer_ =
168 base::MakeUnique<MockHostScanDevicePrioritizer>();
169 device_id_tether_network_guid_map_ =
170 base::MakeUnique<DeviceIdTetherNetworkGuidMap>();
171
172 tether_connector_ = base::WrapUnique(new TetherConnector(
173 test_network_connect_.get(), network_state_handler(),
174 fake_wifi_hotspot_connector_.get(), fake_active_host_.get(),
175 fake_tether_host_fetcher_.get(), fake_ble_connection_manager_.get(),
176 mock_host_scan_device_prioritizer_.get(),
177 device_id_tether_network_guid_map_.get()));
178
179 SetUpTetherNetworks();
180 }
181
182 void TearDown() override {
183 // Must delete |fake_wifi_hotspot_connector_| before NetworkStateHandler is
184 // destroyed to ensure that NetworkStateHandler has zero observers by the
185 // time it reaches its destructor.
186 fake_wifi_hotspot_connector_.reset();
187
188 ShutdownNetworkState();
189 NetworkStateTest::TearDown();
190 DBusThreadManager::Shutdown();
191 }
192
193 std::string GetTetherNetworkGuid(const std::string& device_id) {
194 return device_id_tether_network_guid_map_->GetTetherNetworkGuidForDeviceId(
195 device_id);
196 }
197
198 void SetUpTetherNetworks() {
199 // Add a tether network corresponding to both of the test devices. These
200 // networks are expected to be added already before TetherConnector receives
201 // its ConnectToNetwork() callback.
202 network_state_handler()->AddTetherNetworkState(
203 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()),
204 kTetherNetwork1Name);
205 network_state_handler()->AddTetherNetworkState(
206 GetTetherNetworkGuid(test_devices_[1].GetDeviceId()),
207 kTetherNetwork2Name);
208 }
209
210 void SuccessfullyJoinWifiNetwork() {
211 ConfigureService(CreateWifiConfigurationJsonString());
212 fake_wifi_hotspot_connector_->CallMostRecentCallback(kWifiNetworkGuid);
213 }
214
215 void VerifyTetherAndWifiNetworkAssociation(
216 const std::string& tether_network_guid) {
217 const NetworkState* tether_network_state =
218 network_state_handler()->GetNetworkStateFromGuid(tether_network_guid);
219 EXPECT_TRUE(tether_network_state);
220 EXPECT_EQ(kWifiNetworkGuid, tether_network_state->tether_guid());
221
222 const NetworkState* wifi_network_state =
223 network_state_handler()->GetNetworkStateFromGuid(kWifiNetworkGuid);
224 EXPECT_TRUE(wifi_network_state);
225 EXPECT_EQ(tether_network_guid, wifi_network_state->tether_guid());
226 }
227
228 const std::vector<cryptauth::RemoteDevice> test_devices_;
229 const base::MessageLoop message_loop_;
230
231 std::unique_ptr<FakeConnectTetheringOperationFactory> fake_operation_factory_;
232 std::unique_ptr<TestNetworkConnect> test_network_connect_;
233 std::unique_ptr<FakeWifiHotspotConnector> fake_wifi_hotspot_connector_;
234 std::unique_ptr<FakeActiveHost> fake_active_host_;
235 std::unique_ptr<FakeTetherHostFetcher> fake_tether_host_fetcher_;
236 std::unique_ptr<FakeBleConnectionManager> fake_ble_connection_manager_;
237 std::unique_ptr<MockHostScanDevicePrioritizer>
238 mock_host_scan_device_prioritizer_;
239 // TODO(hansberry): Use a fake for this when a real mapping scheme is created.
240 std::unique_ptr<DeviceIdTetherNetworkGuidMap>
241 device_id_tether_network_guid_map_;
242
243 std::unique_ptr<TetherConnector> tether_connector_;
244
245 private:
246 DISALLOW_COPY_AND_ASSIGN(TetherConnectorTest);
247 };
248
249 TEST_F(TetherConnectorTest, TestCannotFetchDevice) {
250 test_network_connect_->CallTetherDelegate(
251 GetTetherNetworkGuid("nonexistentDeviceId"));
252 fake_tether_host_fetcher_->InvokePendingCallbacks();
253
254 // Since an invalid device ID was used, no connection should have been
255 // started.
256 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED,
257 fake_active_host_->GetActiveHostStatus());
258 }
259
260 TEST_F(TetherConnectorTest, TestConnectTetheringOperationFails) {
261 test_network_connect_->CallTetherDelegate(
262 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()));
263 fake_tether_host_fetcher_->InvokePendingCallbacks();
264
265 // The connection should have started.
266 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
267 fake_active_host_->GetActiveHostStatus());
268 EXPECT_EQ(test_devices_[0].GetDeviceId(),
269 fake_active_host_->GetActiveHostDeviceId());
270 EXPECT_EQ(GetTetherNetworkGuid(test_devices_[0].GetDeviceId()),
271 fake_active_host_->GetTetherNetworkGuid());
272 EXPECT_TRUE(fake_active_host_->GetWifiNetworkGuid().empty());
273
274 // Simulate a failed connection attempt (either the host cannot provide
275 // tethering at this time or a timeout occurs).
276 EXPECT_EQ(1u, fake_operation_factory_->created_operations().size());
277 fake_operation_factory_->created_operations()[0]->SendFailedResponse(
278 ConnectTetheringResponse_ResponseCode::
279 ConnectTetheringResponse_ResponseCode_UNKNOWN_ERROR);
280
281 // The failure should have resulted in the host being disconnected.
282 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED,
283 fake_active_host_->GetActiveHostStatus());
284 }
285
286 TEST_F(TetherConnectorTest, TestConnectingToWifiFails) {
287 test_network_connect_->CallTetherDelegate(
288 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()));
289 fake_tether_host_fetcher_->InvokePendingCallbacks();
290
291 // The connection should have started.
292 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
293 fake_active_host_->GetActiveHostStatus());
294 EXPECT_EQ(test_devices_[0].GetDeviceId(),
295 fake_active_host_->GetActiveHostDeviceId());
296 EXPECT_EQ(GetTetherNetworkGuid(test_devices_[0].GetDeviceId()),
297 fake_active_host_->GetTetherNetworkGuid());
298 EXPECT_TRUE(fake_active_host_->GetWifiNetworkGuid().empty());
299
300 // Receive a successful response. We should still be connecting.
301 EXPECT_EQ(1u, fake_operation_factory_->created_operations().size());
302 fake_operation_factory_->created_operations()[0]->SendSuccessfulResponse(
303 kSsid, kPassword);
304 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
305 fake_active_host_->GetActiveHostStatus());
306
307 // |fake_wifi_hotspot_connector_| should have received the SSID and password
308 // above. Verify this, then return an empty string, signaling a failure to
309 // connect.
310 EXPECT_EQ(kSsid, fake_wifi_hotspot_connector_->most_recent_ssid());
311 EXPECT_EQ(kPassword, fake_wifi_hotspot_connector_->most_recent_password());
312 fake_wifi_hotspot_connector_->CallMostRecentCallback("");
313
314 // The failure should have resulted in the host being disconnected.
315 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED,
316 fake_active_host_->GetActiveHostStatus());
317 }
318
319 TEST_F(TetherConnectorTest, TestSuccessfulConnection) {
320 test_network_connect_->CallTetherDelegate(
321 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()));
322 fake_tether_host_fetcher_->InvokePendingCallbacks();
323
324 // The connection should have started.
325 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
326 fake_active_host_->GetActiveHostStatus());
327 EXPECT_EQ(test_devices_[0].GetDeviceId(),
328 fake_active_host_->GetActiveHostDeviceId());
329 EXPECT_EQ(GetTetherNetworkGuid(test_devices_[0].GetDeviceId()),
330 fake_active_host_->GetTetherNetworkGuid());
331 EXPECT_TRUE(fake_active_host_->GetWifiNetworkGuid().empty());
332
333 // Receive a successful response. We should still be connecting.
334 EXPECT_EQ(1u, fake_operation_factory_->created_operations().size());
335 fake_operation_factory_->created_operations()[0]->SendSuccessfulResponse(
336 kSsid, kPassword);
337 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
338 fake_active_host_->GetActiveHostStatus());
339
340 // |fake_wifi_hotspot_connector_| should have received the SSID and password
341 // above. Verify this, then return the GUID corresponding to the connected
342 // Wi-Fi network.
343 EXPECT_EQ(kSsid, fake_wifi_hotspot_connector_->most_recent_ssid());
344 EXPECT_EQ(kPassword, fake_wifi_hotspot_connector_->most_recent_password());
345 SuccessfullyJoinWifiNetwork();
346
347 // The active host should now be connected, and the tether and Wi-Fi networks
348 // should be associated.
349 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTED,
350 fake_active_host_->GetActiveHostStatus());
351 EXPECT_EQ(test_devices_[0].GetDeviceId(),
352 fake_active_host_->GetActiveHostDeviceId());
353 EXPECT_EQ(GetTetherNetworkGuid(test_devices_[0].GetDeviceId()),
354 fake_active_host_->GetTetherNetworkGuid());
355 EXPECT_EQ(kWifiNetworkGuid, fake_active_host_->GetWifiNetworkGuid());
356 VerifyTetherAndWifiNetworkAssociation(
357 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()));
358 }
359
360 TEST_F(TetherConnectorTest, TestNewConnectionAttemptDuringFetch_SameDevice) {
361 test_network_connect_->CallTetherDelegate(
362 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()));
363
364 // Instead of invoking the pending callbacks on |fake_tether_host_fetcher_|,
365 // attempt another connection attempt.
366 test_network_connect_->CallTetherDelegate(
367 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()));
368
369 // Now invoke the callbacks. Only one operation should have been created,
370 // even though the callback occurred twice.
371 fake_tether_host_fetcher_->InvokePendingCallbacks();
372 EXPECT_EQ(1u, fake_operation_factory_->created_operations().size());
373 }
374
375 TEST_F(TetherConnectorTest,
376 TestNewConnectionAttemptDuringFetch_DifferentDevice) {
377 test_network_connect_->CallTetherDelegate(
378 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()));
379
380 // Instead of invoking the pending callbacks on |fake_tether_host_fetcher_|,
381 // attempt another connection attempt, this time to another device.
382 test_network_connect_->CallTetherDelegate(
383 GetTetherNetworkGuid(test_devices_[1].GetDeviceId()));
384
385 // Now invoke the callbacks. An operation should have been created for the
386 // device 1, not device 0.
387 fake_tether_host_fetcher_->InvokePendingCallbacks();
388 EXPECT_EQ(1u, fake_operation_factory_->created_operations().size());
389 EXPECT_EQ(
390 test_devices_[1],
391 fake_operation_factory_->created_operations()[0]->GetRemoteDevice());
392 }
393
394 TEST_F(TetherConnectorTest,
395 TestNewConnectionAttemptDuringOperation_DifferentDevice) {
396 test_network_connect_->CallTetherDelegate(
397 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()));
398 fake_tether_host_fetcher_->InvokePendingCallbacks();
399
400 // The active host should be device 0.
401 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
402 fake_active_host_->GetActiveHostStatus());
403 EXPECT_EQ(test_devices_[0].GetDeviceId(),
404 fake_active_host_->GetActiveHostDeviceId());
405 EXPECT_EQ(GetTetherNetworkGuid(test_devices_[0].GetDeviceId()),
406 fake_active_host_->GetTetherNetworkGuid());
407 EXPECT_TRUE(fake_active_host_->GetWifiNetworkGuid().empty());
408
409 // An operation should have been created.
410 EXPECT_EQ(1u, fake_operation_factory_->created_operations().size());
411
412 // Before the created operation replies, start a new connection to device 1.
413 test_network_connect_->CallTetherDelegate(
414 GetTetherNetworkGuid(test_devices_[1].GetDeviceId()));
415 fake_tether_host_fetcher_->InvokePendingCallbacks();
416
417 // Now, the active host should be the second device.
418 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
419 fake_active_host_->GetActiveHostStatus());
420 EXPECT_EQ(test_devices_[1].GetDeviceId(),
421 fake_active_host_->GetActiveHostDeviceId());
422 EXPECT_EQ(GetTetherNetworkGuid(test_devices_[1].GetDeviceId()),
423 fake_active_host_->GetTetherNetworkGuid());
424 EXPECT_TRUE(fake_active_host_->GetWifiNetworkGuid().empty());
425
426 // A second operation should have been created.
427 EXPECT_EQ(2u, fake_operation_factory_->created_operations().size());
428
429 // The first operation replies successfully, but this response should be
430 // ignored since the active host has changed.
431 fake_operation_factory_->created_operations()[0]->SendSuccessfulResponse(
432 kSsid, kPassword);
433 EXPECT_EQ(test_devices_[1].GetDeviceId(),
434 fake_active_host_->GetActiveHostDeviceId());
435
436 // No connection should have been started.
437 EXPECT_TRUE(fake_wifi_hotspot_connector_->most_recent_ssid().empty());
438 EXPECT_TRUE(fake_wifi_hotspot_connector_->most_recent_password().empty());
439
440 // The second operation replies successfully, and this response should
441 // result in a Wi-Fi connection attempt.
442 fake_operation_factory_->created_operations()[1]->SendSuccessfulResponse(
443 kSsid, kPassword);
444 EXPECT_EQ(kSsid, fake_wifi_hotspot_connector_->most_recent_ssid());
445 EXPECT_EQ(kPassword, fake_wifi_hotspot_connector_->most_recent_password());
446 }
447
448 TEST_F(TetherConnectorTest,
449 TestNewConnectionAttemptDuringWifiConnection_DifferentDevice) {
450 test_network_connect_->CallTetherDelegate(
451 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()));
452 fake_tether_host_fetcher_->InvokePendingCallbacks();
453 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
454 fake_active_host_->GetActiveHostStatus());
455 EXPECT_EQ(test_devices_[0].GetDeviceId(),
456 fake_active_host_->GetActiveHostDeviceId());
457 EXPECT_EQ(1u, fake_operation_factory_->created_operations().size());
458
459 fake_operation_factory_->created_operations()[0]->SendSuccessfulResponse(
460 kSsid, kPassword);
461 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
462 fake_active_host_->GetActiveHostStatus());
463 EXPECT_EQ(kSsid, fake_wifi_hotspot_connector_->most_recent_ssid());
464 EXPECT_EQ(kPassword, fake_wifi_hotspot_connector_->most_recent_password());
465
466 // While the connection to the Wi-Fi network is in progress, start a new
467 // connection attempt.
468 test_network_connect_->CallTetherDelegate(
469 GetTetherNetworkGuid(test_devices_[1].GetDeviceId()));
470 fake_tether_host_fetcher_->InvokePendingCallbacks();
471
472 // Connect successfully to the first Wi-Fi network. Even though a temporary
473 // connection has succeeded, the active host should be CONNECTING to device 1.
474 SuccessfullyJoinWifiNetwork();
475 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
476 fake_active_host_->GetActiveHostStatus());
477 EXPECT_EQ(test_devices_[1].GetDeviceId(),
478 fake_active_host_->GetActiveHostDeviceId());
479 EXPECT_EQ(GetTetherNetworkGuid(test_devices_[1].GetDeviceId()),
480 fake_active_host_->GetTetherNetworkGuid());
481 EXPECT_TRUE(fake_active_host_->GetWifiNetworkGuid().empty());
482 }
483
484 } // namespace tether
485
486 } // namespace cryptauth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698