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