• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ConnectionManagerTest()50   ConnectionManagerTest() : fake_shill_proxy_(new FakeShillProxy()) {}
51 
SetUp()52   void SetUp() override {
53     loop_.SetAsCurrent();
54     fake_system_state_.set_connection_manager(&cmut_);
55   }
56 
TearDown()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 
SetManagerReply(const char * default_service,bool reply_succeeds)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 
SetServiceReply(const string & service_path,const char * service_type,const char * physical_technology,const char * service_tethering)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 
TestWithServiceType(const char * service_type,const char * physical_technology,ConnectionType expected_type)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 
TestWithServiceTethering(const char * service_tethering,ConnectionTethering expected_tethering)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 
TEST_F(ConnectionManagerTest,SimpleTest)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 
TEST_F(ConnectionManagerTest,PhysicalTechnologyTest)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 
TEST_F(ConnectionManagerTest,TetheringTest)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 
TEST_F(ConnectionManagerTest,UnknownTest)201 TEST_F(ConnectionManagerTest, UnknownTest) {
202   TestWithServiceType("foo", nullptr, ConnectionType::kUnknown);
203 }
204 
TEST_F(ConnectionManagerTest,AllowUpdatesOverEthernetTest)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 
TEST_F(ConnectionManagerTest,AllowUpdatesOverWifiTest)211 TEST_F(ConnectionManagerTest, AllowUpdatesOverWifiTest) {
212   EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
213                                         ConnectionTethering::kUnknown));
214 }
215 
TEST_F(ConnectionManagerTest,AllowUpdatesOverWimaxTest)216 TEST_F(ConnectionManagerTest, AllowUpdatesOverWimaxTest) {
217   EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWimax,
218                                         ConnectionTethering::kUnknown));
219 }
220 
TEST_F(ConnectionManagerTest,BlockUpdatesOverBluetoothTest)221 TEST_F(ConnectionManagerTest, BlockUpdatesOverBluetoothTest) {
222   EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kBluetooth,
223                                          ConnectionTethering::kUnknown));
224 }
225 
TEST_F(ConnectionManagerTest,AllowUpdatesOnlyOver3GPerPolicyTest)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 
TEST_F(ConnectionManagerTest,AllowUpdatesOver3GAndOtherTypesPerPolicyTest)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 
TEST_F(ConnectionManagerTest,BlockUpdatesOverCellularByDefaultTest)280 TEST_F(ConnectionManagerTest, BlockUpdatesOverCellularByDefaultTest) {
281   EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
282                                          ConnectionTethering::kUnknown));
283 }
284 
TEST_F(ConnectionManagerTest,BlockUpdatesOverTetheredNetworkByDefaultTest)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 
TEST_F(ConnectionManagerTest,BlockUpdatesOver3GPerPolicyTest)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 
TEST_F(ConnectionManagerTest,BlockUpdatesOver3GIfErrorInPolicyFetchTest)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 
TEST_F(ConnectionManagerTest,UseUserPrefForUpdatesOverCellularIfNoPolicyTest)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 
TEST_F(ConnectionManagerTest,StringForConnectionTypeTest)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 
TEST_F(ConnectionManagerTest,MalformedServiceList)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