| OLD | NEW |
| (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_disconnector.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_network_configuration_remover.h" | |
| 14 #include "chromeos/components/tether/fake_tether_host_fetcher.h" | |
| 15 #include "chromeos/components/tether/fake_wifi_hotspot_connector.h" | |
| 16 #include "chromeos/components/tether/mock_tether_host_response_recorder.h" | |
| 17 #include "chromeos/components/tether/tether_connector.h" | |
| 18 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 19 #include "chromeos/network/network_connection_handler.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 "components/cryptauth/remote_device.h" | |
| 24 #include "components/cryptauth/remote_device_test_util.h" | |
| 25 #include "testing/gmock/include/gmock/gmock.h" | |
| 26 #include "testing/gtest/include/gtest/gtest.h" | |
| 27 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h" | |
| 28 | |
| 29 namespace chromeos { | |
| 30 | |
| 31 namespace tether { | |
| 32 | |
| 33 namespace { | |
| 34 | |
| 35 const char kSuccessResult[] = "success"; | |
| 36 | |
| 37 const char kWifiNetworkGuid[] = "wifiNetworkGuid"; | |
| 38 | |
| 39 std::string CreateConnectedWifiConfigurationJsonString() { | |
| 40 std::stringstream ss; | |
| 41 ss << "{" | |
| 42 << " \"GUID\": \"" << kWifiNetworkGuid << "\"," | |
| 43 << " \"Type\": \"" << shill::kTypeWifi << "\"," | |
| 44 << " \"State\": \"" << shill::kStateOnline << "\"" | |
| 45 << "}"; | |
| 46 return ss.str(); | |
| 47 } | |
| 48 | |
| 49 class TestNetworkConnectionHandler : public NetworkConnectionHandler { | |
| 50 public: | |
| 51 explicit TestNetworkConnectionHandler(base::Closure disconnect_callback) | |
| 52 : disconnect_callback_(disconnect_callback) {} | |
| 53 ~TestNetworkConnectionHandler() override {} | |
| 54 | |
| 55 std::string last_disconnect_service_path() { | |
| 56 return last_disconnect_service_path_; | |
| 57 } | |
| 58 | |
| 59 base::Closure last_disconnect_success_callback() { | |
| 60 return last_disconnect_success_callback_; | |
| 61 } | |
| 62 | |
| 63 network_handler::ErrorCallback last_disconnect_error_callback() { | |
| 64 return last_disconnect_error_callback_; | |
| 65 } | |
| 66 | |
| 67 // NetworkConnectionHandler: | |
| 68 void DisconnectNetwork( | |
| 69 const std::string& service_path, | |
| 70 const base::Closure& success_callback, | |
| 71 const network_handler::ErrorCallback& error_callback) override { | |
| 72 last_disconnect_service_path_ = service_path; | |
| 73 last_disconnect_success_callback_ = success_callback; | |
| 74 last_disconnect_error_callback_ = error_callback; | |
| 75 | |
| 76 disconnect_callback_.Run(); | |
| 77 } | |
| 78 void ConnectToNetwork(const std::string& service_path, | |
| 79 const base::Closure& success_callback, | |
| 80 const network_handler::ErrorCallback& error_callback, | |
| 81 bool check_error_state) override {} | |
| 82 bool HasConnectingNetwork(const std::string& service_path) override { | |
| 83 return false; | |
| 84 } | |
| 85 bool HasPendingConnectRequest() override { return false; } | |
| 86 void Init(NetworkStateHandler* network_state_handler, | |
| 87 NetworkConfigurationHandler* network_configuration_handler, | |
| 88 ManagedNetworkConfigurationHandler* | |
| 89 managed_network_configuration_handler) override {} | |
| 90 | |
| 91 private: | |
| 92 base::Closure disconnect_callback_; | |
| 93 | |
| 94 std::string last_disconnect_service_path_; | |
| 95 base::Closure last_disconnect_success_callback_; | |
| 96 network_handler::ErrorCallback last_disconnect_error_callback_; | |
| 97 }; | |
| 98 | |
| 99 class TestTetherConnector : public TetherConnector { | |
| 100 public: | |
| 101 TestTetherConnector() | |
| 102 : TetherConnector(nullptr /* network_state_handler */, | |
| 103 nullptr /* wifi_hotspot_connector */, | |
| 104 nullptr /* active_host */, | |
| 105 nullptr /* tether_host_fetcher */, | |
| 106 nullptr /* connection_manager */, | |
| 107 nullptr /* tether_host_response_recorder */, | |
| 108 nullptr /* device_id_tether_network_guid_map */, | |
| 109 nullptr /* host_scan_cache */, | |
| 110 nullptr /* notification_presenter */), | |
| 111 should_cancel_successfully_(true) {} | |
| 112 ~TestTetherConnector() override {} | |
| 113 | |
| 114 void set_should_cancel_successfully(bool should_cancel_successfully) { | |
| 115 should_cancel_successfully_ = should_cancel_successfully; | |
| 116 } | |
| 117 | |
| 118 std::string last_canceled_tether_network_guid() { | |
| 119 return last_canceled_tether_network_guid_; | |
| 120 } | |
| 121 | |
| 122 // TetherConnector: | |
| 123 bool CancelConnectionAttempt( | |
| 124 const std::string& tether_network_guid) override { | |
| 125 last_canceled_tether_network_guid_ = tether_network_guid; | |
| 126 return should_cancel_successfully_; | |
| 127 } | |
| 128 | |
| 129 private: | |
| 130 bool should_cancel_successfully_; | |
| 131 std::string last_canceled_tether_network_guid_; | |
| 132 }; | |
| 133 | |
| 134 class FakeDisconnectTetheringOperation : public DisconnectTetheringOperation { | |
| 135 public: | |
| 136 FakeDisconnectTetheringOperation( | |
| 137 const cryptauth::RemoteDevice& device_to_connect, | |
| 138 BleConnectionManager* connection_manager) | |
| 139 : DisconnectTetheringOperation(device_to_connect, connection_manager) {} | |
| 140 | |
| 141 ~FakeDisconnectTetheringOperation() override {} | |
| 142 | |
| 143 void NotifyFinished(bool success) { | |
| 144 NotifyObserversOperationFinished(success); | |
| 145 } | |
| 146 | |
| 147 cryptauth::RemoteDevice GetRemoteDevice() { | |
| 148 EXPECT_EQ(1u, remote_devices().size()); | |
| 149 return remote_devices()[0]; | |
| 150 } | |
| 151 }; | |
| 152 | |
| 153 class FakeDisconnectTetheringOperationFactory | |
| 154 : public DisconnectTetheringOperation::Factory { | |
| 155 public: | |
| 156 FakeDisconnectTetheringOperationFactory() {} | |
| 157 virtual ~FakeDisconnectTetheringOperationFactory() {} | |
| 158 | |
| 159 std::vector<FakeDisconnectTetheringOperation*>& created_operations() { | |
| 160 return created_operations_; | |
| 161 } | |
| 162 | |
| 163 protected: | |
| 164 // DisconnectTetheringOperation::Factory: | |
| 165 std::unique_ptr<DisconnectTetheringOperation> BuildInstance( | |
| 166 const cryptauth::RemoteDevice& device_to_connect, | |
| 167 BleConnectionManager* connection_manager) override { | |
| 168 FakeDisconnectTetheringOperation* operation = | |
| 169 new FakeDisconnectTetheringOperation(device_to_connect, | |
| 170 connection_manager); | |
| 171 created_operations_.push_back(operation); | |
| 172 return base::WrapUnique(operation); | |
| 173 } | |
| 174 | |
| 175 private: | |
| 176 std::vector<FakeDisconnectTetheringOperation*> created_operations_; | |
| 177 }; | |
| 178 | |
| 179 } // namespace | |
| 180 | |
| 181 class TetherDisconnectorTest : public NetworkStateTest { | |
| 182 public: | |
| 183 TetherDisconnectorTest() | |
| 184 : test_devices_(cryptauth::GenerateTestRemoteDevices(2u)) {} | |
| 185 ~TetherDisconnectorTest() override {} | |
| 186 | |
| 187 void SetUp() override { | |
| 188 DBusThreadManager::Initialize(); | |
| 189 NetworkStateTest::SetUp(); | |
| 190 | |
| 191 should_disconnect_successfully_ = true; | |
| 192 | |
| 193 test_network_connection_handler_ = | |
| 194 base::WrapUnique(new TestNetworkConnectionHandler(base::Bind( | |
| 195 &TetherDisconnectorTest::OnNetworkConnectionManagerDisconnect, | |
| 196 base::Unretained(this)))); | |
| 197 fake_active_host_ = base::MakeUnique<FakeActiveHost>(); | |
| 198 fake_ble_connection_manager_ = base::MakeUnique<FakeBleConnectionManager>(); | |
| 199 fake_network_configuration_remover_ = | |
| 200 base::MakeUnique<FakeNetworkConfigurationRemover>(); | |
| 201 test_tether_connector_ = base::WrapUnique(new TestTetherConnector()); | |
| 202 device_id_tether_network_guid_map_ = | |
| 203 base::MakeUnique<DeviceIdTetherNetworkGuidMap>(); | |
| 204 fake_tether_host_fetcher_ = base::MakeUnique<FakeTetherHostFetcher>( | |
| 205 test_devices_, true /* synchronously_reply_with_results */); | |
| 206 | |
| 207 fake_operation_factory_ = | |
| 208 base::WrapUnique(new FakeDisconnectTetheringOperationFactory()); | |
| 209 DisconnectTetheringOperation::Factory::SetInstanceForTesting( | |
| 210 fake_operation_factory_.get()); | |
| 211 | |
| 212 SetUpTetherNetworks(); | |
| 213 | |
| 214 tether_disconnector_ = base::MakeUnique<TetherDisconnector>( | |
| 215 test_network_connection_handler_.get(), network_state_handler(), | |
| 216 fake_active_host_.get(), fake_ble_connection_manager_.get(), | |
| 217 fake_network_configuration_remover_.get(), test_tether_connector_.get(), | |
| 218 device_id_tether_network_guid_map_.get(), | |
| 219 fake_tether_host_fetcher_.get()); | |
| 220 } | |
| 221 | |
| 222 void TearDown() override { | |
| 223 ShutdownNetworkState(); | |
| 224 NetworkStateTest::TearDown(); | |
| 225 DBusThreadManager::Shutdown(); | |
| 226 } | |
| 227 | |
| 228 std::string GetTetherNetworkGuid(const std::string& device_id) { | |
| 229 return device_id_tether_network_guid_map_->GetTetherNetworkGuidForDeviceId( | |
| 230 device_id); | |
| 231 } | |
| 232 | |
| 233 void SetUpTetherNetworks() { | |
| 234 network_state_handler()->SetTetherTechnologyState( | |
| 235 NetworkStateHandler::TECHNOLOGY_ENABLED); | |
| 236 | |
| 237 // Add a tether network corresponding to both of the test devices. These | |
| 238 // networks are expected to be added already before | |
| 239 // TetherDisconnector::DisconnectFromNetwork() is called. | |
| 240 network_state_handler()->AddTetherNetworkState( | |
| 241 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), | |
| 242 "TetherNetworkName1", "TetherNetworkCarrier1", | |
| 243 85 /* battery_percentage */, 75 /* signal_strength */, | |
| 244 true /* has_connected_to_host */); | |
| 245 network_state_handler()->AddTetherNetworkState( | |
| 246 GetTetherNetworkGuid(test_devices_[1].GetDeviceId()), | |
| 247 "TetherNetworkName2", "TetherNetworkCarrier2", | |
| 248 90 /* battery_percentage */, 50 /* signal_strength */, | |
| 249 true /* has_connected_to_host */); | |
| 250 } | |
| 251 | |
| 252 void SimulateConnectionToWifiNetwork() { | |
| 253 wifi_service_path_ = | |
| 254 ConfigureService(CreateConnectedWifiConfigurationJsonString()); | |
| 255 EXPECT_FALSE(wifi_service_path_.empty()); | |
| 256 } | |
| 257 | |
| 258 void SuccessCallback() { disconnection_result_ = kSuccessResult; } | |
| 259 | |
| 260 void ErrorCallback(const std::string& error_name) { | |
| 261 disconnection_result_ = error_name; | |
| 262 } | |
| 263 | |
| 264 void CallDisconnect(const std::string& tether_network_guid) { | |
| 265 tether_disconnector_->DisconnectFromNetwork( | |
| 266 tether_network_guid, | |
| 267 base::Bind(&TetherDisconnectorTest::SuccessCallback, | |
| 268 base::Unretained(this)), | |
| 269 base::Bind(&TetherDisconnectorTest::ErrorCallback, | |
| 270 base::Unretained(this))); | |
| 271 } | |
| 272 | |
| 273 // This function is called by | |
| 274 // TestNetworkConnectionHandler::DisconnectFromNetwork(). | |
| 275 void OnNetworkConnectionManagerDisconnect() { | |
| 276 EXPECT_EQ(wifi_service_path_, | |
| 277 test_network_connection_handler_->last_disconnect_service_path()); | |
| 278 | |
| 279 if (should_disconnect_successfully_) { | |
| 280 SetServiceProperty(wifi_service_path_, shill::kStateProperty, | |
| 281 base::Value(shill::kStateIdle)); | |
| 282 EXPECT_FALSE( | |
| 283 test_network_connection_handler_->last_disconnect_success_callback() | |
| 284 .is_null()); | |
| 285 test_network_connection_handler_->last_disconnect_success_callback() | |
| 286 .Run(); | |
| 287 } else { | |
| 288 EXPECT_FALSE( | |
| 289 test_network_connection_handler_->last_disconnect_error_callback() | |
| 290 .is_null()); | |
| 291 network_handler::RunErrorCallback( | |
| 292 test_network_connection_handler_->last_disconnect_error_callback(), | |
| 293 wifi_service_path_, NetworkConnectionHandler::kErrorDisconnectFailed, | |
| 294 "" /* error_detail */); | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 std::string GetResultAndReset() { | |
| 299 std::string result; | |
| 300 result.swap(disconnection_result_); | |
| 301 return result; | |
| 302 } | |
| 303 | |
| 304 const std::vector<cryptauth::RemoteDevice> test_devices_; | |
| 305 const base::MessageLoop message_loop_; | |
| 306 | |
| 307 std::unique_ptr<TestNetworkConnectionHandler> | |
| 308 test_network_connection_handler_; | |
| 309 std::unique_ptr<FakeActiveHost> fake_active_host_; | |
| 310 std::unique_ptr<FakeBleConnectionManager> fake_ble_connection_manager_; | |
| 311 std::unique_ptr<FakeNetworkConfigurationRemover> | |
| 312 fake_network_configuration_remover_; | |
| 313 std::unique_ptr<TestTetherConnector> test_tether_connector_; | |
| 314 // TODO(hansberry): Use a fake for this when a real mapping scheme is created. | |
| 315 std::unique_ptr<DeviceIdTetherNetworkGuidMap> | |
| 316 device_id_tether_network_guid_map_; | |
| 317 std::unique_ptr<FakeTetherHostFetcher> fake_tether_host_fetcher_; | |
| 318 | |
| 319 std::unique_ptr<FakeDisconnectTetheringOperationFactory> | |
| 320 fake_operation_factory_; | |
| 321 | |
| 322 std::string wifi_service_path_; | |
| 323 std::string disconnection_result_; | |
| 324 bool should_disconnect_successfully_; | |
| 325 | |
| 326 std::unique_ptr<TetherDisconnector> tether_disconnector_; | |
| 327 | |
| 328 private: | |
| 329 DISALLOW_COPY_AND_ASSIGN(TetherDisconnectorTest); | |
| 330 }; | |
| 331 | |
| 332 TEST_F(TetherDisconnectorTest, DisconnectWhenAlreadyDisconnected) { | |
| 333 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 334 EXPECT_EQ(NetworkConnectionHandler::kErrorNotConnected, GetResultAndReset()); | |
| 335 | |
| 336 // Should still be disconnected. | |
| 337 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED, | |
| 338 fake_active_host_->GetActiveHostStatus()); | |
| 339 } | |
| 340 | |
| 341 TEST_F(TetherDisconnectorTest, DisconnectWhenOtherDeviceConnected) { | |
| 342 fake_active_host_->SetActiveHostConnected( | |
| 343 test_devices_[1].GetDeviceId(), | |
| 344 GetTetherNetworkGuid(test_devices_[1].GetDeviceId()), | |
| 345 "otherWifiNetworkGuid"); | |
| 346 | |
| 347 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 348 EXPECT_EQ(NetworkConnectionHandler::kErrorNotConnected, GetResultAndReset()); | |
| 349 | |
| 350 // Should still be connected to the other host. | |
| 351 EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTED, | |
| 352 fake_active_host_->GetActiveHostStatus()); | |
| 353 EXPECT_EQ(test_devices_[1].GetDeviceId(), | |
| 354 fake_active_host_->GetActiveHostDeviceId()); | |
| 355 } | |
| 356 | |
| 357 TEST_F(TetherDisconnectorTest, DisconnectWhenConnecting_CancelFails) { | |
| 358 fake_active_host_->SetActiveHostConnecting( | |
| 359 test_devices_[0].GetDeviceId(), | |
| 360 GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 361 test_tether_connector_->set_should_cancel_successfully(false); | |
| 362 | |
| 363 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 364 EXPECT_EQ(NetworkConnectionHandler::kErrorDisconnectFailed, | |
| 365 GetResultAndReset()); | |
| 366 EXPECT_EQ(GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), | |
| 367 test_tether_connector_->last_canceled_tether_network_guid()); | |
| 368 | |
| 369 // Note: This test does not check the active host's status because it will be | |
| 370 // changed by TetherConnector. | |
| 371 } | |
| 372 | |
| 373 TEST_F(TetherDisconnectorTest, DisconnectWhenConnecting_CancelSucceeds) { | |
| 374 fake_active_host_->SetActiveHostConnecting( | |
| 375 test_devices_[0].GetDeviceId(), | |
| 376 GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 377 test_tether_connector_->set_should_cancel_successfully(true); | |
| 378 | |
| 379 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 380 EXPECT_EQ(kSuccessResult, GetResultAndReset()); | |
| 381 EXPECT_EQ(GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), | |
| 382 test_tether_connector_->last_canceled_tether_network_guid()); | |
| 383 | |
| 384 // Note: This test does not check the active host's status because it will be | |
| 385 // changed by TetherConnector. | |
| 386 } | |
| 387 | |
| 388 TEST_F(TetherDisconnectorTest, DisconnectWhenConnected_NotActuallyConnected) { | |
| 389 fake_active_host_->SetActiveHostConnected( | |
| 390 test_devices_[0].GetDeviceId(), | |
| 391 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), | |
| 392 "nonExistentWifiGuid"); | |
| 393 | |
| 394 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 395 EXPECT_EQ(NetworkConnectionHandler::kErrorDisconnectFailed, | |
| 396 GetResultAndReset()); | |
| 397 | |
| 398 // Should be disconnected. | |
| 399 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED, | |
| 400 fake_active_host_->GetActiveHostStatus()); | |
| 401 } | |
| 402 | |
| 403 TEST_F(TetherDisconnectorTest, | |
| 404 DisconnectWhenConnected_WifiConnectionFails_CannotFetchHost) { | |
| 405 fake_active_host_->SetActiveHostConnected( | |
| 406 test_devices_[0].GetDeviceId(), | |
| 407 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), kWifiNetworkGuid); | |
| 408 SimulateConnectionToWifiNetwork(); | |
| 409 | |
| 410 // Remove hosts from |fake_tether_host_fetcher_|; this will cause the fetcher | |
| 411 // to return a null RemoteDevice. | |
| 412 fake_tether_host_fetcher_->SetTetherHosts( | |
| 413 std::vector<cryptauth::RemoteDevice>()); | |
| 414 | |
| 415 should_disconnect_successfully_ = false; | |
| 416 | |
| 417 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 418 EXPECT_EQ(NetworkConnectionHandler::kErrorDisconnectFailed, | |
| 419 GetResultAndReset()); | |
| 420 | |
| 421 // The Wi-Fi network should still be connected since disconnection failed. | |
| 422 EXPECT_EQ( | |
| 423 shill::kStateOnline, | |
| 424 GetServiceStringProperty(wifi_service_path_, shill::kStateProperty)); | |
| 425 | |
| 426 // Should not have created any operations since the fetch failed. | |
| 427 EXPECT_TRUE(fake_operation_factory_->created_operations().empty()); | |
| 428 | |
| 429 // Should be disconnected. | |
| 430 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED, | |
| 431 fake_active_host_->GetActiveHostStatus()); | |
| 432 } | |
| 433 | |
| 434 TEST_F(TetherDisconnectorTest, | |
| 435 DisconnectWhenConnected_WifiConnectionSucceeds_CannotFetchHost) { | |
| 436 fake_active_host_->SetActiveHostConnected( | |
| 437 test_devices_[0].GetDeviceId(), | |
| 438 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), kWifiNetworkGuid); | |
| 439 SimulateConnectionToWifiNetwork(); | |
| 440 | |
| 441 // Remove hosts from |fake_tether_host_fetcher_|; this will cause the fetcher | |
| 442 // to return a null RemoteDevice. | |
| 443 fake_tether_host_fetcher_->SetTetherHosts( | |
| 444 std::vector<cryptauth::RemoteDevice>()); | |
| 445 | |
| 446 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 447 EXPECT_EQ(kSuccessResult, GetResultAndReset()); | |
| 448 | |
| 449 // The Wi-Fi network should be disconnected since disconnection failed. | |
| 450 EXPECT_EQ(shill::kStateIdle, GetServiceStringProperty(wifi_service_path_, | |
| 451 shill::kStateProperty)); | |
| 452 | |
| 453 // Should not have created any operations since the fetch failed. | |
| 454 EXPECT_TRUE(fake_operation_factory_->created_operations().empty()); | |
| 455 | |
| 456 // Should be disconnected. | |
| 457 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED, | |
| 458 fake_active_host_->GetActiveHostStatus()); | |
| 459 } | |
| 460 | |
| 461 TEST_F(TetherDisconnectorTest, | |
| 462 DisconnectWhenConnected_WifiConnectionFails_OperationFails) { | |
| 463 fake_active_host_->SetActiveHostConnected( | |
| 464 test_devices_[0].GetDeviceId(), | |
| 465 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), kWifiNetworkGuid); | |
| 466 SimulateConnectionToWifiNetwork(); | |
| 467 | |
| 468 should_disconnect_successfully_ = false; | |
| 469 | |
| 470 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 471 EXPECT_EQ(NetworkConnectionHandler::kErrorDisconnectFailed, | |
| 472 GetResultAndReset()); | |
| 473 | |
| 474 // The Wi-Fi network should still be connected since disconnection failed. | |
| 475 EXPECT_EQ( | |
| 476 shill::kStateOnline, | |
| 477 GetServiceStringProperty(wifi_service_path_, shill::kStateProperty)); | |
| 478 | |
| 479 // Fail the operation. | |
| 480 ASSERT_EQ(1u, fake_operation_factory_->created_operations().size()); | |
| 481 EXPECT_EQ( | |
| 482 test_devices_[0], | |
| 483 fake_operation_factory_->created_operations()[0]->GetRemoteDevice()); | |
| 484 fake_operation_factory_->created_operations()[0]->NotifyFinished( | |
| 485 false /* success */); | |
| 486 | |
| 487 // Should be disconnected. | |
| 488 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED, | |
| 489 fake_active_host_->GetActiveHostStatus()); | |
| 490 } | |
| 491 | |
| 492 TEST_F(TetherDisconnectorTest, | |
| 493 DisconnectWhenConnected_WifiConnectionSucceeds_OperationFails) { | |
| 494 fake_active_host_->SetActiveHostConnected( | |
| 495 test_devices_[0].GetDeviceId(), | |
| 496 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), kWifiNetworkGuid); | |
| 497 SimulateConnectionToWifiNetwork(); | |
| 498 | |
| 499 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 500 EXPECT_EQ(kSuccessResult, GetResultAndReset()); | |
| 501 | |
| 502 // The Wi-Fi network should be disconnected since disconnection failed. | |
| 503 EXPECT_EQ(shill::kStateIdle, GetServiceStringProperty(wifi_service_path_, | |
| 504 shill::kStateProperty)); | |
| 505 | |
| 506 ASSERT_EQ(1u, fake_operation_factory_->created_operations().size()); | |
| 507 EXPECT_EQ( | |
| 508 test_devices_[0], | |
| 509 fake_operation_factory_->created_operations()[0]->GetRemoteDevice()); | |
| 510 fake_operation_factory_->created_operations()[0]->NotifyFinished( | |
| 511 false /* success */); | |
| 512 | |
| 513 // Should be disconnected. | |
| 514 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED, | |
| 515 fake_active_host_->GetActiveHostStatus()); | |
| 516 } | |
| 517 | |
| 518 TEST_F(TetherDisconnectorTest, | |
| 519 DisconnectWhenConnected_WifiConnectionFails_OperationSucceeds) { | |
| 520 fake_active_host_->SetActiveHostConnected( | |
| 521 test_devices_[0].GetDeviceId(), | |
| 522 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), kWifiNetworkGuid); | |
| 523 SimulateConnectionToWifiNetwork(); | |
| 524 | |
| 525 should_disconnect_successfully_ = false; | |
| 526 | |
| 527 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 528 EXPECT_EQ(NetworkConnectionHandler::kErrorDisconnectFailed, | |
| 529 GetResultAndReset()); | |
| 530 | |
| 531 // The Wi-Fi network should still be connected since disconnection failed. | |
| 532 EXPECT_EQ( | |
| 533 shill::kStateOnline, | |
| 534 GetServiceStringProperty(wifi_service_path_, shill::kStateProperty)); | |
| 535 | |
| 536 // Fail the operation. | |
| 537 ASSERT_EQ(1u, fake_operation_factory_->created_operations().size()); | |
| 538 EXPECT_EQ( | |
| 539 test_devices_[0], | |
| 540 fake_operation_factory_->created_operations()[0]->GetRemoteDevice()); | |
| 541 fake_operation_factory_->created_operations()[0]->NotifyFinished( | |
| 542 true /* success */); | |
| 543 | |
| 544 // Should be disconnected. | |
| 545 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED, | |
| 546 fake_active_host_->GetActiveHostStatus()); | |
| 547 } | |
| 548 | |
| 549 TEST_F(TetherDisconnectorTest, | |
| 550 DisconnectWhenConnected_WifiConnectionSucceeds_OperationSucceeds) { | |
| 551 fake_active_host_->SetActiveHostConnected( | |
| 552 test_devices_[0].GetDeviceId(), | |
| 553 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), kWifiNetworkGuid); | |
| 554 SimulateConnectionToWifiNetwork(); | |
| 555 | |
| 556 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 557 EXPECT_EQ(kSuccessResult, GetResultAndReset()); | |
| 558 | |
| 559 // The Wi-Fi network should be disconnected since disconnection failed. | |
| 560 EXPECT_EQ(shill::kStateIdle, GetServiceStringProperty(wifi_service_path_, | |
| 561 shill::kStateProperty)); | |
| 562 | |
| 563 ASSERT_EQ(1u, fake_operation_factory_->created_operations().size()); | |
| 564 EXPECT_EQ( | |
| 565 test_devices_[0], | |
| 566 fake_operation_factory_->created_operations()[0]->GetRemoteDevice()); | |
| 567 fake_operation_factory_->created_operations()[0]->NotifyFinished( | |
| 568 true /* success */); | |
| 569 | |
| 570 // Should be disconnected. | |
| 571 EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED, | |
| 572 fake_active_host_->GetActiveHostStatus()); | |
| 573 } | |
| 574 | |
| 575 TEST_F(TetherDisconnectorTest, | |
| 576 DisconnectWhenConnected_DestroyBeforeOperationComplete) { | |
| 577 fake_active_host_->SetActiveHostConnected( | |
| 578 test_devices_[0].GetDeviceId(), | |
| 579 GetTetherNetworkGuid(test_devices_[0].GetDeviceId()), kWifiNetworkGuid); | |
| 580 SimulateConnectionToWifiNetwork(); | |
| 581 | |
| 582 CallDisconnect(GetTetherNetworkGuid(test_devices_[0].GetDeviceId())); | |
| 583 EXPECT_EQ(kSuccessResult, GetResultAndReset()); | |
| 584 | |
| 585 // Stop the test here, before the operation responds in any way. This test | |
| 586 // ensures that TetherDisconnector properly removes existing listeners if it | |
| 587 // is destroyed while there are still active operations. | |
| 588 } | |
| 589 | |
| 590 } // namespace tether | |
| 591 | |
| 592 } // namespace chromeos | |
| OLD | NEW |