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 org::chromium::flimflam::ManagerProxyMock;
38 using org::chromium::flimflam::ServiceProxyMock;
39 using std::set;
40 using std::string;
41 using testing::Return;
42 using testing::SetArgPointee;
43 using testing::_;
44
45 namespace chromeos_update_engine {
46
47 class ConnectionManagerTest : public ::testing::Test {
48 public:
SetUp()49 void SetUp() override {
50 loop_.SetAsCurrent();
51 fake_system_state_.set_connection_manager(&cmut_);
52 }
53
TearDown()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
SetManagerReply(const char * default_service,bool reply_succeeds)86 void 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
SetServiceReply(const string & service_path,const char * service_type,const char * physical_technology,const char * service_tethering)108 void 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
TestWithServiceType(const char * service_type,const char * physical_technology,NetworkConnectionType expected_type)136 void 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
TestWithServiceTethering(const char * service_tethering,NetworkTethering expected_tethering)154 void 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
TEST_F(ConnectionManagerTest,SimpleTest)169 TEST_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
TEST_F(ConnectionManagerTest,PhysicalTechnologyTest)182 TEST_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
TEST_F(ConnectionManagerTest,TetheringTest)193 TEST_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
TEST_F(ConnectionManagerTest,UnknownTest)204 TEST_F(ConnectionManagerTest, UnknownTest) {
205 TestWithServiceType("foo", nullptr, NetworkConnectionType::kUnknown);
206 }
207
TEST_F(ConnectionManagerTest,AllowUpdatesOverEthernetTest)208 TEST_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
TEST_F(ConnectionManagerTest,AllowUpdatesOverWifiTest)214 TEST_F(ConnectionManagerTest, AllowUpdatesOverWifiTest) {
215 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kWifi,
216 NetworkTethering::kUnknown));
217 }
218
TEST_F(ConnectionManagerTest,AllowUpdatesOverWimaxTest)219 TEST_F(ConnectionManagerTest, AllowUpdatesOverWimaxTest) {
220 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kWimax,
221 NetworkTethering::kUnknown));
222 }
223
TEST_F(ConnectionManagerTest,BlockUpdatesOverBluetoothTest)224 TEST_F(ConnectionManagerTest, BlockUpdatesOverBluetoothTest) {
225 EXPECT_FALSE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kBluetooth,
226 NetworkTethering::kUnknown));
227 }
228
TEST_F(ConnectionManagerTest,AllowUpdatesOnlyOver3GPerPolicyTest)229 TEST_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
TEST_F(ConnectionManagerTest,AllowUpdatesOver3GAndOtherTypesPerPolicyTest)247 TEST_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
TEST_F(ConnectionManagerTest,BlockUpdatesOverCellularByDefaultTest)286 TEST_F(ConnectionManagerTest, BlockUpdatesOverCellularByDefaultTest) {
287 EXPECT_FALSE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kCellular,
288 NetworkTethering::kUnknown));
289 }
290
TEST_F(ConnectionManagerTest,BlockUpdatesOverTetheredNetworkByDefaultTest)291 TEST_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
TEST_F(ConnectionManagerTest,BlockUpdatesOver3GPerPolicyTest)300 TEST_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
TEST_F(ConnectionManagerTest,BlockUpdatesOver3GIfErrorInPolicyFetchTest)323 TEST_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
TEST_F(ConnectionManagerTest,UseUserPrefForUpdatesOverCellularIfNoPolicyTest)343 TEST_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
TEST_F(ConnectionManagerTest,StringForConnectionTypeTest)382 TEST_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
TEST_F(ConnectionManagerTest,MalformedServiceList)401 TEST_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