Home | History | Annotate | Download | only in update_engine
      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