1 // 2 // Copyright (C) 2012 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "update_engine/connection_manager.h" 18 19 #include <memory> 20 #include <set> 21 #include <string> 22 #include <utility> 23 24 #include <base/logging.h> 25 #include <brillo/any.h> 26 #include <brillo/message_loops/fake_message_loop.h> 27 #include <brillo/variant_dictionary.h> 28 #include <gmock/gmock.h> 29 #include <gtest/gtest.h> 30 #include <shill/dbus-constants.h> 31 #include <shill/dbus-proxies.h> 32 #include <shill/dbus-proxy-mocks.h> 33 34 #include "update_engine/common/test_utils.h" 35 #include "update_engine/fake_shill_proxy.h" 36 #include "update_engine/fake_system_state.h" 37 38 using chromeos_update_engine::connection_utils::StringForConnectionType; 39 using org::chromium::flimflam::ManagerProxyMock; 40 using org::chromium::flimflam::ServiceProxyMock; 41 using std::set; 42 using std::string; 43 using testing::_; 44 using testing::Return; 45 using testing::SetArgPointee; 46 47 namespace chromeos_update_engine { 48 49 class ConnectionManagerTest : public ::testing::Test { 50 public: 51 ConnectionManagerTest() : fake_shill_proxy_(new FakeShillProxy()) {} 52 53 void SetUp() override { 54 loop_.SetAsCurrent(); 55 fake_system_state_.set_connection_manager(&cmut_); 56 } 57 58 void TearDown() override { EXPECT_FALSE(loop_.PendingTasks()); } 59 60 protected: 61 // Sets the default_service object path in the response from the 62 // ManagerProxyMock instance. 63 void SetManagerReply(const char* default_service, bool reply_succeeds); 64 65 // Sets the |service_type|, |physical_technology| and |service_tethering| 66 // properties in the mocked service |service_path|. If any of the three 67 // const char* is a nullptr, the corresponding property will not be included 68 // in the response. 69 void SetServiceReply(const string& service_path, 70 const char* service_type, 71 const char* physical_technology, 72 const char* service_tethering); 73 74 void TestWithServiceType(const char* service_type, 75 const char* physical_technology, 76 ConnectionType expected_type); 77 78 void TestWithServiceDisconnected(ConnectionType expected_type); 79 80 void TestWithServiceTethering(const char* service_tethering, 81 ConnectionTethering expected_tethering); 82 83 brillo::FakeMessageLoop loop_{nullptr}; 84 FakeSystemState fake_system_state_; 85 FakeShillProxy* fake_shill_proxy_; 86 87 // ConnectionManager under test. 88 ConnectionManager cmut_{fake_shill_proxy_, &fake_system_state_}; 89 }; 90 91 void ConnectionManagerTest::SetManagerReply(const char* default_service, 92 bool reply_succeeds) { 93 ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_->GetManagerProxy(); 94 if (!reply_succeeds) { 95 EXPECT_CALL(*manager_proxy_mock, GetProperties(_, _, _)) 96 .WillOnce(Return(false)); 97 return; 98 } 99 100 // Create a dictionary of properties and optionally include the default 101 // service. 102 brillo::VariantDictionary reply_dict; 103 reply_dict["SomeOtherProperty"] = 0xC0FFEE; 104 105 if (default_service) { 106 reply_dict[shill::kDefaultServiceProperty] = 107 dbus::ObjectPath(default_service); 108 } 109 EXPECT_CALL(*manager_proxy_mock, GetProperties(_, _, _)) 110 .WillOnce(DoAll(SetArgPointee<0>(reply_dict), Return(true))); 111 } 112 113 void ConnectionManagerTest::SetServiceReply(const string& service_path, 114 const char* service_type, 115 const char* physical_technology, 116 const char* service_tethering) { 117 brillo::VariantDictionary reply_dict; 118 reply_dict["SomeOtherProperty"] = 0xC0FFEE; 119 120 if (service_type) 121 reply_dict[shill::kTypeProperty] = string(service_type); 122 123 if (physical_technology) { 124 reply_dict[shill::kPhysicalTechnologyProperty] = 125 string(physical_technology); 126 } 127 128 if (service_tethering) 129 reply_dict[shill::kTetheringProperty] = string(service_tethering); 130 131 std::unique_ptr<ServiceProxyMock> service_proxy_mock(new ServiceProxyMock()); 132 133 // Plumb return value into mock object. 134 EXPECT_CALL(*service_proxy_mock.get(), GetProperties(_, _, _)) 135 .WillOnce(DoAll(SetArgPointee<0>(reply_dict), Return(true))); 136 137 fake_shill_proxy_->SetServiceForPath(dbus::ObjectPath(service_path), 138 std::move(service_proxy_mock)); 139 } 140 141 void ConnectionManagerTest::TestWithServiceType(const char* service_type, 142 const char* physical_technology, 143 ConnectionType expected_type) { 144 SetManagerReply("/service/guest/network", true); 145 SetServiceReply("/service/guest/network", 146 service_type, 147 physical_technology, 148 shill::kTetheringNotDetectedState); 149 150 ConnectionType type; 151 ConnectionTethering tethering; 152 EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering)); 153 EXPECT_EQ(expected_type, type); 154 testing::Mock::VerifyAndClearExpectations( 155 fake_shill_proxy_->GetManagerProxy()); 156 } 157 158 void ConnectionManagerTest::TestWithServiceTethering( 159 const char* service_tethering, ConnectionTethering expected_tethering) { 160 SetManagerReply("/service/guest/network", true); 161 SetServiceReply( 162 "/service/guest/network", shill::kTypeWifi, nullptr, service_tethering); 163 164 ConnectionType type; 165 ConnectionTethering tethering; 166 EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering)); 167 EXPECT_EQ(expected_tethering, tethering); 168 testing::Mock::VerifyAndClearExpectations( 169 fake_shill_proxy_->GetManagerProxy()); 170 } 171 172 void ConnectionManagerTest::TestWithServiceDisconnected( 173 ConnectionType expected_type) { 174 SetManagerReply("/", true); 175 176 ConnectionType type; 177 ConnectionTethering tethering; 178 EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering)); 179 EXPECT_EQ(expected_type, type); 180 testing::Mock::VerifyAndClearExpectations( 181 fake_shill_proxy_->GetManagerProxy()); 182 } 183 184 TEST_F(ConnectionManagerTest, SimpleTest) { 185 TestWithServiceType(shill::kTypeEthernet, nullptr, ConnectionType::kEthernet); 186 TestWithServiceType(shill::kTypeWifi, nullptr, ConnectionType::kWifi); 187 TestWithServiceType(shill::kTypeWimax, nullptr, ConnectionType::kWimax); 188 TestWithServiceType( 189 shill::kTypeBluetooth, nullptr, ConnectionType::kBluetooth); 190 TestWithServiceType(shill::kTypeCellular, nullptr, ConnectionType::kCellular); 191 } 192 193 TEST_F(ConnectionManagerTest, PhysicalTechnologyTest) { 194 TestWithServiceType(shill::kTypeVPN, nullptr, ConnectionType::kUnknown); 195 TestWithServiceType( 196 shill::kTypeVPN, shill::kTypeVPN, ConnectionType::kUnknown); 197 TestWithServiceType(shill::kTypeVPN, shill::kTypeWifi, ConnectionType::kWifi); 198 TestWithServiceType( 199 shill::kTypeVPN, shill::kTypeWimax, ConnectionType::kWimax); 200 } 201 202 TEST_F(ConnectionManagerTest, TetheringTest) { 203 TestWithServiceTethering(shill::kTetheringConfirmedState, 204 ConnectionTethering::kConfirmed); 205 TestWithServiceTethering(shill::kTetheringNotDetectedState, 206 ConnectionTethering::kNotDetected); 207 TestWithServiceTethering(shill::kTetheringSuspectedState, 208 ConnectionTethering::kSuspected); 209 TestWithServiceTethering("I'm not a valid property value =)", 210 ConnectionTethering::kUnknown); 211 } 212 213 TEST_F(ConnectionManagerTest, UnknownTest) { 214 TestWithServiceType("foo", nullptr, ConnectionType::kUnknown); 215 } 216 217 TEST_F(ConnectionManagerTest, DisconnectTest) { 218 TestWithServiceDisconnected(ConnectionType::kDisconnected); 219 } 220 221 TEST_F(ConnectionManagerTest, AllowUpdatesOverEthernetTest) { 222 // Updates over Ethernet are allowed even if there's no policy. 223 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet, 224 ConnectionTethering::kUnknown)); 225 } 226 227 TEST_F(ConnectionManagerTest, AllowUpdatesOverWifiTest) { 228 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi, 229 ConnectionTethering::kUnknown)); 230 } 231 232 TEST_F(ConnectionManagerTest, AllowUpdatesOverWimaxTest) { 233 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWimax, 234 ConnectionTethering::kUnknown)); 235 } 236 237 TEST_F(ConnectionManagerTest, BlockUpdatesOverBluetoothTest) { 238 EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kBluetooth, 239 ConnectionTethering::kUnknown)); 240 } 241 242 TEST_F(ConnectionManagerTest, AllowUpdatesOnlyOver3GPerPolicyTest) { 243 policy::MockDevicePolicy allow_3g_policy; 244 245 fake_system_state_.set_device_policy(&allow_3g_policy); 246 247 // This test tests cellular (3G) being the only connection type being allowed. 248 set<string> allowed_set; 249 allowed_set.insert(StringForConnectionType(ConnectionType::kCellular)); 250 251 EXPECT_CALL(allow_3g_policy, GetAllowedConnectionTypesForUpdate(_)) 252 .Times(1) 253 .WillOnce(DoAll(SetArgPointee<0>(allowed_set), Return(true))); 254 255 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular, 256 ConnectionTethering::kUnknown)); 257 } 258 259 TEST_F(ConnectionManagerTest, AllowUpdatesOver3GAndOtherTypesPerPolicyTest) { 260 policy::MockDevicePolicy allow_3g_policy; 261 262 fake_system_state_.set_device_policy(&allow_3g_policy); 263 264 // This test tests multiple connection types being allowed, with 265 // 3G one among them. Only Cellular is currently enforced by the policy 266 // setting, the others are ignored (see Bluetooth for example). 267 set<string> allowed_set; 268 allowed_set.insert(StringForConnectionType(ConnectionType::kCellular)); 269 allowed_set.insert(StringForConnectionType(ConnectionType::kBluetooth)); 270 271 EXPECT_CALL(allow_3g_policy, GetAllowedConnectionTypesForUpdate(_)) 272 .Times(3) 273 .WillRepeatedly(DoAll(SetArgPointee<0>(allowed_set), Return(true))); 274 275 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet, 276 ConnectionTethering::kUnknown)); 277 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet, 278 ConnectionTethering::kNotDetected)); 279 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular, 280 ConnectionTethering::kUnknown)); 281 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi, 282 ConnectionTethering::kUnknown)); 283 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWimax, 284 ConnectionTethering::kUnknown)); 285 EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kBluetooth, 286 ConnectionTethering::kUnknown)); 287 288 // Tethered networks are treated in the same way as Cellular networks and 289 // thus allowed. 290 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet, 291 ConnectionTethering::kConfirmed)); 292 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi, 293 ConnectionTethering::kConfirmed)); 294 } 295 296 TEST_F(ConnectionManagerTest, AllowUpdatesOverCellularByDefaultTest) { 297 policy::MockDevicePolicy device_policy; 298 // Set an empty device policy. 299 fake_system_state_.set_device_policy(&device_policy); 300 301 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular, 302 ConnectionTethering::kUnknown)); 303 } 304 305 TEST_F(ConnectionManagerTest, AllowUpdatesOverTetheredNetworkByDefaultTest) { 306 policy::MockDevicePolicy device_policy; 307 // Set an empty device policy. 308 fake_system_state_.set_device_policy(&device_policy); 309 310 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi, 311 ConnectionTethering::kConfirmed)); 312 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet, 313 ConnectionTethering::kConfirmed)); 314 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi, 315 ConnectionTethering::kSuspected)); 316 } 317 318 TEST_F(ConnectionManagerTest, BlockUpdatesOver3GPerPolicyTest) { 319 policy::MockDevicePolicy block_3g_policy; 320 321 fake_system_state_.set_device_policy(&block_3g_policy); 322 323 // Test that updates for 3G are blocked while updates are allowed 324 // over several other types. 325 set<string> allowed_set; 326 allowed_set.insert(StringForConnectionType(ConnectionType::kEthernet)); 327 allowed_set.insert(StringForConnectionType(ConnectionType::kWifi)); 328 allowed_set.insert(StringForConnectionType(ConnectionType::kWimax)); 329 330 EXPECT_CALL(block_3g_policy, GetAllowedConnectionTypesForUpdate(_)) 331 .Times(1) 332 .WillOnce(DoAll(SetArgPointee<0>(allowed_set), Return(true))); 333 334 EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular, 335 ConnectionTethering::kUnknown)); 336 } 337 338 TEST_F(ConnectionManagerTest, AllowUpdatesOver3GIfPolicyIsNotSet) { 339 policy::MockDevicePolicy device_policy; 340 341 fake_system_state_.set_device_policy(&device_policy); 342 343 // Return false for GetAllowedConnectionTypesForUpdate and see 344 // that updates are allowed as device policy is not set. Further 345 // check is left to |OmahaRequestAction|. 346 EXPECT_CALL(device_policy, GetAllowedConnectionTypesForUpdate(_)) 347 .Times(1) 348 .WillOnce(Return(false)); 349 350 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular, 351 ConnectionTethering::kUnknown)); 352 } 353 354 TEST_F(ConnectionManagerTest, AllowUpdatesOverCellularIfPolicyFailsToBeLoaded) { 355 fake_system_state_.set_device_policy(nullptr); 356 357 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular, 358 ConnectionTethering::kUnknown)); 359 } 360 361 TEST_F(ConnectionManagerTest, StringForConnectionTypeTest) { 362 EXPECT_STREQ(shill::kTypeEthernet, 363 StringForConnectionType(ConnectionType::kEthernet)); 364 EXPECT_STREQ(shill::kTypeWifi, 365 StringForConnectionType(ConnectionType::kWifi)); 366 EXPECT_STREQ(shill::kTypeWimax, 367 StringForConnectionType(ConnectionType::kWimax)); 368 EXPECT_STREQ(shill::kTypeBluetooth, 369 StringForConnectionType(ConnectionType::kBluetooth)); 370 EXPECT_STREQ(shill::kTypeCellular, 371 StringForConnectionType(ConnectionType::kCellular)); 372 EXPECT_STREQ("Unknown", StringForConnectionType(ConnectionType::kUnknown)); 373 EXPECT_STREQ("Unknown", 374 StringForConnectionType(static_cast<ConnectionType>(999999))); 375 } 376 377 TEST_F(ConnectionManagerTest, MalformedServiceList) { 378 SetManagerReply("/service/guest/network", false); 379 380 ConnectionType type; 381 ConnectionTethering tethering; 382 EXPECT_FALSE(cmut_.GetConnectionProperties(&type, &tethering)); 383 } 384 385 } // namespace chromeos_update_engine 386