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:
ConnectionManagerTest()51 ConnectionManagerTest() : fake_shill_proxy_(new FakeShillProxy()) {}
52
SetUp()53 void SetUp() override {
54 loop_.SetAsCurrent();
55 fake_system_state_.set_connection_manager(&cmut_);
56 }
57
TearDown()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
SetManagerReply(const char * default_service,bool reply_succeeds)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
SetServiceReply(const string & service_path,const char * service_type,const char * physical_technology,const char * service_tethering)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
TestWithServiceType(const char * service_type,const char * physical_technology,ConnectionType expected_type)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
TestWithServiceTethering(const char * service_tethering,ConnectionTethering expected_tethering)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
TestWithServiceDisconnected(ConnectionType expected_type)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
TEST_F(ConnectionManagerTest,SimpleTest)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
TEST_F(ConnectionManagerTest,PhysicalTechnologyTest)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
TEST_F(ConnectionManagerTest,TetheringTest)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
TEST_F(ConnectionManagerTest,UnknownTest)213 TEST_F(ConnectionManagerTest, UnknownTest) {
214 TestWithServiceType("foo", nullptr, ConnectionType::kUnknown);
215 }
216
TEST_F(ConnectionManagerTest,DisconnectTest)217 TEST_F(ConnectionManagerTest, DisconnectTest) {
218 TestWithServiceDisconnected(ConnectionType::kDisconnected);
219 }
220
TEST_F(ConnectionManagerTest,AllowUpdatesOverEthernetTest)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
TEST_F(ConnectionManagerTest,AllowUpdatesOverWifiTest)227 TEST_F(ConnectionManagerTest, AllowUpdatesOverWifiTest) {
228 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
229 ConnectionTethering::kUnknown));
230 }
231
TEST_F(ConnectionManagerTest,AllowUpdatesOverWimaxTest)232 TEST_F(ConnectionManagerTest, AllowUpdatesOverWimaxTest) {
233 EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWimax,
234 ConnectionTethering::kUnknown));
235 }
236
TEST_F(ConnectionManagerTest,BlockUpdatesOverBluetoothTest)237 TEST_F(ConnectionManagerTest, BlockUpdatesOverBluetoothTest) {
238 EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kBluetooth,
239 ConnectionTethering::kUnknown));
240 }
241
TEST_F(ConnectionManagerTest,AllowUpdatesOnlyOver3GPerPolicyTest)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
TEST_F(ConnectionManagerTest,AllowUpdatesOver3GAndOtherTypesPerPolicyTest)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
TEST_F(ConnectionManagerTest,AllowUpdatesOverCellularByDefaultTest)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
TEST_F(ConnectionManagerTest,AllowUpdatesOverTetheredNetworkByDefaultTest)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
TEST_F(ConnectionManagerTest,BlockUpdatesOver3GPerPolicyTest)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
TEST_F(ConnectionManagerTest,AllowUpdatesOver3GIfPolicyIsNotSet)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
TEST_F(ConnectionManagerTest,AllowUpdatesOverCellularIfPolicyFailsToBeLoaded)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
TEST_F(ConnectionManagerTest,StringForConnectionTypeTest)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
TEST_F(ConnectionManagerTest,MalformedServiceList)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