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