hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 1 | // Copyright (c) 2013 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/network/network_connect.h" |
| 6 | |
| 7 | #include <memory> |
| 8 | |
| 9 | #include "base/macros.h" |
| 10 | #include "base/memory/ptr_util.h" |
| 11 | #include "base/run_loop.h" |
fdoray | c85e9b8 | 2017-04-06 15:37:22 | [diff] [blame] | 12 | #include "base/test/scoped_task_environment.h" |
Steven Bennetts | b4bf6cd | 2019-04-05 17:02:57 | [diff] [blame] | 13 | #include "chromeos/dbus/shill/shill_clients.h" |
Steven Bennetts | d11e440f | 2019-04-04 01:09:00 | [diff] [blame] | 14 | #include "chromeos/dbus/shill/shill_device_client.h" |
| 15 | #include "chromeos/dbus/shill/shill_service_client.h" |
Steven Bennetts | 4bea303 | 2019-01-03 19:33:18 | [diff] [blame] | 16 | #include "chromeos/login/login_state/login_state.h" |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 17 | #include "chromeos/network/network_connect.h" |
| 18 | #include "chromeos/network/network_connection_handler.h" |
| 19 | #include "chromeos/network/network_handler.h" |
varkha | c6eefbe | 2017-03-23 23:26:10 | [diff] [blame] | 20 | #include "chromeos/network/network_state.h" |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 21 | #include "chromeos/network/network_state_handler.h" |
| 22 | #include "testing/gmock/include/gmock/gmock.h" |
| 23 | #include "testing/gtest/include/gtest/gtest.h" |
| 24 | #include "testing/platform_test.h" |
| 25 | #include "third_party/cros_system_api/dbus/service_constants.h" |
| 26 | |
| 27 | using testing::_; |
| 28 | using testing::AnyNumber; |
| 29 | using testing::NiceMock; |
| 30 | using testing::Return; |
| 31 | |
| 32 | namespace chromeos { |
| 33 | |
| 34 | namespace { |
| 35 | |
| 36 | const char kWiFi1ServicePath[] = "/service/wifi1"; |
| 37 | const char kWiFi1Guid[] = "wifi1_guid"; |
| 38 | |
| 39 | const char kCellular1DevicePath[] = "/device/stub_cellular_device1"; |
| 40 | const char kCellular1ServicePath[] = "/service/cellular1"; |
| 41 | const char kCellular1Guid[] = "cellular1_guid"; |
| 42 | |
khorimoto | 00bbba5 | 2017-05-03 00:18:48 | [diff] [blame] | 43 | const char kTetherGuid[] = "tether_guid"; |
| 44 | |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 45 | class MockDelegate : public NetworkConnect::Delegate { |
| 46 | public: |
Chris Watkins | 2c529d6 | 2017-11-29 02:14:41 | [diff] [blame] | 47 | MockDelegate() = default; |
| 48 | ~MockDelegate() override = default; |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 49 | |
| 50 | MOCK_METHOD1(ShowNetworkConfigure, void(const std::string& network_id)); |
| 51 | MOCK_METHOD1(ShowNetworkSettings, void(const std::string& network_id)); |
| 52 | MOCK_METHOD1(ShowEnrollNetwork, bool(const std::string& network_id)); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 53 | MOCK_METHOD1(ShowMobileSetupDialog, void(const std::string& network_id)); |
| 54 | MOCK_METHOD2(ShowNetworkConnectError, |
| 55 | void(const std::string& error_name, |
| 56 | const std::string& network_id)); |
| 57 | MOCK_METHOD1(ShowMobileActivationError, void(const std::string& network_id)); |
| 58 | }; |
| 59 | |
khorimoto | 00bbba5 | 2017-05-03 00:18:48 | [diff] [blame] | 60 | class FakeTetherDelegate : public NetworkConnectionHandler::TetherDelegate { |
| 61 | public: |
Chris Watkins | 2c529d6 | 2017-11-29 02:14:41 | [diff] [blame] | 62 | FakeTetherDelegate() = default; |
| 63 | ~FakeTetherDelegate() override = default; |
khorimoto | 00bbba5 | 2017-05-03 00:18:48 | [diff] [blame] | 64 | |
| 65 | std::string last_connected_tether_network_guid() { |
| 66 | return last_connected_tether_network_guid_; |
| 67 | } |
| 68 | |
| 69 | // NetworkConnectionHandler::TetherDelegate: |
| 70 | void ConnectToNetwork( |
| 71 | const std::string& tether_network_guid, |
| 72 | const base::Closure& success_callback, |
| 73 | const network_handler::StringResultCallback& error_callback) override { |
| 74 | last_connected_tether_network_guid_ = tether_network_guid; |
| 75 | success_callback.Run(); |
| 76 | } |
khorimoto | d46b48b | 2017-05-04 04:17:36 | [diff] [blame] | 77 | void DisconnectFromNetwork( |
| 78 | const std::string& tether_network_guid, |
| 79 | const base::Closure& success_callback, |
| 80 | const network_handler::StringResultCallback& error_callback) override {} |
khorimoto | 00bbba5 | 2017-05-03 00:18:48 | [diff] [blame] | 81 | |
| 82 | private: |
| 83 | std::string last_connected_tether_network_guid_; |
| 84 | }; |
| 85 | |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 86 | } // namespace |
| 87 | |
| 88 | class NetworkConnectTest : public testing::Test { |
| 89 | public: |
Chris Watkins | 2c529d6 | 2017-11-29 02:14:41 | [diff] [blame] | 90 | NetworkConnectTest() = default; |
| 91 | ~NetworkConnectTest() override = default; |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 92 | |
| 93 | void SetUp() override { |
| 94 | testing::Test::SetUp(); |
Steven Bennetts | b4bf6cd | 2019-04-05 17:02:57 | [diff] [blame] | 95 | shill_clients::InitializeFakes(); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 96 | LoginState::Initialize(); |
| 97 | SetupDefaultShillState(); |
| 98 | NetworkHandler::Initialize(); |
| 99 | base::RunLoop().RunUntilIdle(); |
| 100 | |
| 101 | mock_delegate_.reset(new MockDelegate()); |
| 102 | ON_CALL(*mock_delegate_, ShowEnrollNetwork(_)).WillByDefault(Return(true)); |
| 103 | |
khorimoto | 00bbba5 | 2017-05-03 00:18:48 | [diff] [blame] | 104 | fake_tether_delegate_.reset(new FakeTetherDelegate()); |
| 105 | NetworkHandler::Get()->network_connection_handler()->SetTetherDelegate( |
| 106 | fake_tether_delegate_.get()); |
| 107 | |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 108 | NetworkConnect::Initialize(mock_delegate_.get()); |
| 109 | } |
| 110 | |
| 111 | void TearDown() override { |
| 112 | NetworkConnect::Shutdown(); |
| 113 | mock_delegate_.reset(); |
| 114 | LoginState::Shutdown(); |
| 115 | NetworkHandler::Shutdown(); |
Steven Bennetts | b4bf6cd | 2019-04-05 17:02:57 | [diff] [blame] | 116 | shill_clients::Shutdown(); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 117 | testing::Test::TearDown(); |
| 118 | } |
| 119 | |
| 120 | protected: |
| 121 | void SetupDefaultShillState() { |
| 122 | base::RunLoop().RunUntilIdle(); |
Steven Bennetts | b4bf6cd | 2019-04-05 17:02:57 | [diff] [blame] | 123 | device_test_ = ShillDeviceClient::Get()->GetTestInterface(); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 124 | device_test_->ClearDevices(); |
| 125 | device_test_->AddDevice("/device/stub_wifi_device1", shill::kTypeWifi, |
| 126 | "stub_wifi_device1"); |
| 127 | device_test_->AddDevice(kCellular1DevicePath, shill::kTypeCellular, |
| 128 | "stub_cellular_device1"); |
Steven Bennetts | b06cf2b | 2018-04-26 18:33:59 | [diff] [blame] | 129 | device_test_->SetDeviceProperty( |
| 130 | kCellular1DevicePath, shill::kTechnologyFamilyProperty, |
| 131 | base::Value(shill::kNetworkTechnologyGsm), /*notify_changed=*/true); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 132 | |
Steven Bennetts | b4bf6cd | 2019-04-05 17:02:57 | [diff] [blame] | 133 | service_test_ = ShillServiceClient::Get()->GetTestInterface(); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 134 | service_test_->ClearServices(); |
| 135 | const bool add_to_visible = true; |
| 136 | |
| 137 | // Create a wifi network and set to online. |
| 138 | service_test_->AddService(kWiFi1ServicePath, kWiFi1Guid, "wifi1", |
| 139 | shill::kTypeWifi, shill::kStateIdle, |
| 140 | add_to_visible); |
| 141 | service_test_->SetServiceProperty(kWiFi1ServicePath, |
| 142 | shill::kSecurityClassProperty, |
jdoerrie | 122c4da | 2017-03-06 11:12:04 | [diff] [blame] | 143 | base::Value(shill::kSecurityWep)); |
jdoerrie | 23972357 | 2017-03-02 12:09:19 | [diff] [blame] | 144 | service_test_->SetServiceProperty( |
| 145 | kWiFi1ServicePath, shill::kConnectableProperty, base::Value(true)); |
jdoerrie | 122c4da | 2017-03-06 11:12:04 | [diff] [blame] | 146 | service_test_->SetServiceProperty( |
| 147 | kWiFi1ServicePath, shill::kPassphraseProperty, base::Value("password")); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 148 | |
| 149 | // Create a cellular network. |
| 150 | service_test_->AddService(kCellular1ServicePath, kCellular1Guid, |
| 151 | "cellular1", shill::kTypeCellular, |
| 152 | shill::kStateIdle, add_to_visible); |
jdoerrie | 23972357 | 2017-03-02 12:09:19 | [diff] [blame] | 153 | service_test_->SetServiceProperty( |
| 154 | kCellular1ServicePath, shill::kConnectableProperty, base::Value(true)); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 155 | service_test_->SetServiceProperty( |
| 156 | kCellular1ServicePath, shill::kActivationStateProperty, |
jdoerrie | 122c4da | 2017-03-06 11:12:04 | [diff] [blame] | 157 | base::Value(shill::kActivationStateActivated)); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 158 | service_test_->SetServiceProperty(kCellular1ServicePath, |
| 159 | shill::kOutOfCreditsProperty, |
jdoerrie | 23972357 | 2017-03-02 12:09:19 | [diff] [blame] | 160 | base::Value(false)); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 161 | |
| 162 | base::RunLoop().RunUntilIdle(); |
| 163 | } |
| 164 | |
khorimoto | 00bbba5 | 2017-05-03 00:18:48 | [diff] [blame] | 165 | void AddTetherNetwork(bool has_connected_to_host) { |
| 166 | NetworkStateHandler* handler = |
| 167 | NetworkHandler::Get()->network_state_handler(); |
| 168 | handler->SetTetherTechnologyState( |
| 169 | NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED); |
| 170 | handler->AddTetherNetworkState(kTetherGuid, "TetherName", "TetherCarrier", |
| 171 | 100 /* battery_percentage */, |
| 172 | 100 /* signal_strength */, |
| 173 | has_connected_to_host); |
| 174 | } |
| 175 | |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 176 | std::unique_ptr<MockDelegate> mock_delegate_; |
khorimoto | 00bbba5 | 2017-05-03 00:18:48 | [diff] [blame] | 177 | std::unique_ptr<FakeTetherDelegate> fake_tether_delegate_; |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 178 | base::test::TaskEnvironment task_environment_; |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 179 | ShillDeviceClient::TestInterface* device_test_; |
| 180 | ShillServiceClient::TestInterface* service_test_; |
| 181 | |
| 182 | private: |
| 183 | DISALLOW_COPY_AND_ASSIGN(NetworkConnectTest); |
| 184 | }; |
| 185 | |
| 186 | TEST_F(NetworkConnectTest, ConnectToNetworkId_NoConfiguration) { |
| 187 | EXPECT_CALL(*mock_delegate_, ShowNetworkConfigure(_)).Times(0); |
| 188 | EXPECT_CALL(*mock_delegate_, ShowNetworkConnectError(_, _)).Times(0); |
| 189 | |
| 190 | NetworkConnect::Get()->ConnectToNetworkId("bad guid"); |
| 191 | } |
| 192 | |
| 193 | TEST_F(NetworkConnectTest, ConfigureAndConnectToNetwork_NoConfiguration) { |
| 194 | EXPECT_CALL(*mock_delegate_, |
| 195 | ShowNetworkConnectError(NetworkConnectionHandler::kErrorNotFound, |
| 196 | "bad guid")); |
| 197 | |
| 198 | base::DictionaryValue properties; |
| 199 | NetworkConnect::Get()->ConfigureNetworkIdAndConnect("bad guid", properties, |
| 200 | true); |
| 201 | } |
| 202 | |
| 203 | TEST_F(NetworkConnectTest, |
| 204 | ConfigureAndConnectToNetwork_NotSharedButNoProfilePath) { |
| 205 | EXPECT_CALL(*mock_delegate_, |
| 206 | ShowNetworkConnectError( |
| 207 | NetworkConnectionHandler::kErrorConfigureFailed, kWiFi1Guid)); |
| 208 | |
| 209 | base::DictionaryValue properties; |
| 210 | NetworkConnect::Get()->ConfigureNetworkIdAndConnect(kWiFi1Guid, properties, |
| 211 | false); |
| 212 | } |
| 213 | |
varkha | c6eefbe | 2017-03-23 23:26:10 | [diff] [blame] | 214 | TEST_F(NetworkConnectTest, ConnectThenDisconnectWiFiNetwork) { |
| 215 | const NetworkState* network = |
| 216 | NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid( |
| 217 | kWiFi1Guid); |
| 218 | |
| 219 | NetworkConnect::Get()->ConnectToNetworkId(kWiFi1Guid); |
| 220 | base::RunLoop().RunUntilIdle(); |
| 221 | EXPECT_TRUE(network->IsConnectedState()); |
| 222 | |
| 223 | NetworkConnect::Get()->DisconnectFromNetworkId(kWiFi1Guid); |
| 224 | base::RunLoop().RunUntilIdle(); |
| 225 | EXPECT_FALSE(network->IsConnectedState()); |
| 226 | EXPECT_FALSE(network->IsConnectingState()); |
| 227 | } |
| 228 | |
khorimoto | 00bbba5 | 2017-05-03 00:18:48 | [diff] [blame] | 229 | TEST_F(NetworkConnectTest, ConnectToTetherNetwork_HasConnectedToHost) { |
| 230 | EXPECT_CALL(*mock_delegate_, ShowNetworkConfigure(_)).Times(0); |
| 231 | |
| 232 | AddTetherNetwork(true /* has_connected_to_host */); |
| 233 | |
| 234 | NetworkConnect::Get()->ConnectToNetworkId(kTetherGuid); |
| 235 | EXPECT_EQ(kTetherGuid, |
| 236 | fake_tether_delegate_->last_connected_tether_network_guid()); |
| 237 | } |
| 238 | |
| 239 | TEST_F(NetworkConnectTest, ConnectToTetherNetwork_HasNotConnectedToHost) { |
| 240 | EXPECT_CALL(*mock_delegate_, ShowNetworkConfigure(_)); |
| 241 | |
| 242 | AddTetherNetwork(false /* has_connected_to_host */); |
| 243 | |
| 244 | NetworkConnect::Get()->ConnectToNetworkId(kTetherGuid); |
| 245 | EXPECT_TRUE( |
| 246 | fake_tether_delegate_->last_connected_tether_network_guid().empty()); |
| 247 | } |
| 248 | |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 249 | TEST_F(NetworkConnectTest, ActivateCellular) { |
| 250 | EXPECT_CALL(*mock_delegate_, ShowMobileSetupDialog(kCellular1Guid)); |
| 251 | |
| 252 | service_test_->SetServiceProperty( |
| 253 | kCellular1ServicePath, shill::kActivationStateProperty, |
jdoerrie | 122c4da | 2017-03-06 11:12:04 | [diff] [blame] | 254 | base::Value(shill::kActivationStateNotActivated)); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 255 | base::RunLoop().RunUntilIdle(); |
| 256 | |
| 257 | NetworkConnect::Get()->ConnectToNetworkId(kCellular1Guid); |
| 258 | } |
| 259 | |
| 260 | TEST_F(NetworkConnectTest, ActivateCellular_Error) { |
| 261 | EXPECT_CALL(*mock_delegate_, ShowMobileActivationError(kCellular1Guid)); |
| 262 | |
| 263 | service_test_->SetServiceProperty( |
| 264 | kCellular1ServicePath, shill::kActivationStateProperty, |
jdoerrie | 122c4da | 2017-03-06 11:12:04 | [diff] [blame] | 265 | base::Value(shill::kActivationStateNotActivated)); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 266 | service_test_->SetServiceProperty( |
| 267 | kCellular1ServicePath, shill::kActivationTypeProperty, |
jdoerrie | 122c4da | 2017-03-06 11:12:04 | [diff] [blame] | 268 | base::Value(shill::kActivationTypeNonCellular)); |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 269 | base::RunLoop().RunUntilIdle(); |
| 270 | |
| 271 | NetworkConnect::Get()->ConnectToNetworkId(kCellular1Guid); |
| 272 | } |
| 273 | |
hansberry | 67d781c | 2017-03-02 01:51:50 | [diff] [blame] | 274 | } // namespace chromeos |