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