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