1 //
2 // Copyright (C) 2014 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/update_manager/real_device_policy_provider.h"
18 
19 #include <memory>
20 #include <vector>
21 
22 #include <base/memory/ptr_util.h>
23 #include <brillo/message_loops/fake_message_loop.h>
24 #include <brillo/message_loops/message_loop.h>
25 #include <brillo/message_loops/message_loop_utils.h>
26 #include <gmock/gmock.h>
27 #include <gtest/gtest.h>
28 #include <policy/mock_device_policy.h>
29 #include <policy/mock_libpolicy.h>
30 #if USE_DBUS
31 #include <session_manager/dbus-proxies.h>
32 #include <session_manager/dbus-proxy-mocks.h>
33 #endif  // USE_DBUS
34 
35 #include "update_engine/common/test_utils.h"
36 #if USE_DBUS
37 #include "update_engine/dbus_test_utils.h"
38 #endif  // USE_DBUS
39 #include "update_engine/update_manager/umtest_utils.h"
40 
41 using base::TimeDelta;
42 using brillo::MessageLoop;
43 using chromeos_update_engine::ConnectionType;
44 using policy::DevicePolicy;
45 #if USE_DBUS
46 using chromeos_update_engine::dbus_test_utils::MockSignalHandler;
47 #endif  // USE_DBUS
48 using std::set;
49 using std::string;
50 using std::unique_ptr;
51 using std::vector;
52 using testing::_;
53 using testing::DoAll;
54 using testing::Mock;
55 using testing::Return;
56 using testing::ReturnRef;
57 using testing::SetArgPointee;
58 
59 namespace chromeos_update_manager {
60 
61 class UmRealDevicePolicyProviderTest : public ::testing::Test {
62  protected:
63   void SetUp() override {
64     loop_.SetAsCurrent();
65 #if USE_DBUS
66     auto session_manager_proxy_mock =
67         new org::chromium::SessionManagerInterfaceProxyMock();
68     provider_.reset(new RealDevicePolicyProvider(
69         base::WrapUnique(session_manager_proxy_mock), &mock_policy_provider_));
70 #else
71     provider_.reset(new RealDevicePolicyProvider(&mock_policy_provider_));
72 #endif  // USE_DBUS
73     // By default, we have a device policy loaded. Tests can call
74     // SetUpNonExistentDevicePolicy() to override this.
75     SetUpExistentDevicePolicy();
76 
77 #if USE_DBUS
78     // Setup the session manager_proxy such that it will accept the signal
79     // handler and store it in the |property_change_complete_| once registered.
80     MOCK_SIGNAL_HANDLER_EXPECT_SIGNAL_HANDLER(property_change_complete_,
81                                               *session_manager_proxy_mock,
82                                               PropertyChangeComplete);
83 #endif  // USE_DBUS
84   }
85 
86   void TearDown() override {
87     provider_.reset();
88     // Check for leaked callbacks on the main loop.
89     EXPECT_FALSE(loop_.PendingTasks());
90   }
91 
92   void SetUpNonExistentDevicePolicy() {
93     ON_CALL(mock_policy_provider_, Reload()).WillByDefault(Return(false));
94     ON_CALL(mock_policy_provider_, device_policy_is_loaded())
95         .WillByDefault(Return(false));
96     EXPECT_CALL(mock_policy_provider_, GetDevicePolicy()).Times(0);
97   }
98 
99   void SetUpExistentDevicePolicy() {
100     // Setup the default behavior of the mocked PolicyProvider.
101     ON_CALL(mock_policy_provider_, Reload()).WillByDefault(Return(true));
102     ON_CALL(mock_policy_provider_, device_policy_is_loaded())
103         .WillByDefault(Return(true));
104     ON_CALL(mock_policy_provider_, GetDevicePolicy())
105         .WillByDefault(ReturnRef(mock_device_policy_));
106   }
107 
108   brillo::FakeMessageLoop loop_{nullptr};
109   testing::NiceMock<policy::MockDevicePolicy> mock_device_policy_;
110   testing::NiceMock<policy::MockPolicyProvider> mock_policy_provider_;
111   unique_ptr<RealDevicePolicyProvider> provider_;
112 
113 #if USE_DBUS
114   // The registered signal handler for the signal.
115   MockSignalHandler<void(const string&)> property_change_complete_;
116 #endif  // USE_DBUS
117 };
118 
119 TEST_F(UmRealDevicePolicyProviderTest, RefreshScheduledTest) {
120   // Check that the RefreshPolicy gets scheduled by checking the TaskId.
121   EXPECT_TRUE(provider_->Init());
122   EXPECT_NE(MessageLoop::kTaskIdNull, provider_->scheduled_refresh_);
123   loop_.RunOnce(false);
124 }
125 
126 TEST_F(UmRealDevicePolicyProviderTest, FirstReload) {
127   // Checks that the policy is reloaded and the DevicePolicy is consulted twice:
128   // once on Init() and once again when the signal is connected.
129   EXPECT_CALL(mock_policy_provider_, Reload());
130   EXPECT_TRUE(provider_->Init());
131   Mock::VerifyAndClearExpectations(&mock_policy_provider_);
132   // We won't be notified that signal is connected without DBus.
133 #if USE_DBUS
134   EXPECT_CALL(mock_policy_provider_, Reload());
135 #endif  // USE_DBUS
136   loop_.RunOnce(false);
137 }
138 
139 TEST_F(UmRealDevicePolicyProviderTest, NonExistentDevicePolicyReloaded) {
140   // Checks that the policy is reloaded by RefreshDevicePolicy().
141   SetUpNonExistentDevicePolicy();
142   // We won't be notified that signal is connected without DBus.
143 #if USE_DBUS
144   EXPECT_CALL(mock_policy_provider_, Reload()).Times(3);
145 #else
146   EXPECT_CALL(mock_policy_provider_, Reload()).Times(2);
147 #endif  // USE_DBUS
148   EXPECT_TRUE(provider_->Init());
149   loop_.RunOnce(false);
150   // Force the policy refresh.
151   provider_->RefreshDevicePolicy();
152 }
153 
154 #if USE_DBUS
155 TEST_F(UmRealDevicePolicyProviderTest, SessionManagerSignalForcesReload) {
156   // Checks that a signal from the SessionManager forces a reload.
157   SetUpNonExistentDevicePolicy();
158   EXPECT_CALL(mock_policy_provider_, Reload()).Times(2);
159   EXPECT_TRUE(provider_->Init());
160   loop_.RunOnce(false);
161   Mock::VerifyAndClearExpectations(&mock_policy_provider_);
162 
163   EXPECT_CALL(mock_policy_provider_, Reload());
164   ASSERT_TRUE(property_change_complete_.IsHandlerRegistered());
165   property_change_complete_.signal_callback().Run("success");
166 }
167 #endif  // USE_DBUS
168 
169 TEST_F(UmRealDevicePolicyProviderTest, NonExistentDevicePolicyEmptyVariables) {
170   SetUpNonExistentDevicePolicy();
171   EXPECT_CALL(mock_policy_provider_, GetDevicePolicy()).Times(0);
172   EXPECT_TRUE(provider_->Init());
173   loop_.RunOnce(false);
174 
175   UmTestUtils::ExpectVariableHasValue(false,
176                                       provider_->var_device_policy_is_loaded());
177 
178   UmTestUtils::ExpectVariableNotSet(provider_->var_release_channel());
179   UmTestUtils::ExpectVariableNotSet(provider_->var_release_channel_delegated());
180   UmTestUtils::ExpectVariableNotSet(provider_->var_update_disabled());
181   UmTestUtils::ExpectVariableNotSet(provider_->var_target_version_prefix());
182   UmTestUtils::ExpectVariableNotSet(
183       provider_->var_rollback_to_target_version());
184   UmTestUtils::ExpectVariableNotSet(
185       provider_->var_rollback_allowed_milestones());
186   UmTestUtils::ExpectVariableNotSet(provider_->var_scatter_factor());
187   UmTestUtils::ExpectVariableNotSet(
188       provider_->var_allowed_connection_types_for_update());
189   UmTestUtils::ExpectVariableNotSet(provider_->var_owner());
190   UmTestUtils::ExpectVariableNotSet(provider_->var_http_downloads_enabled());
191   UmTestUtils::ExpectVariableNotSet(provider_->var_au_p2p_enabled());
192   UmTestUtils::ExpectVariableNotSet(
193       provider_->var_allow_kiosk_app_control_chrome_version());
194   UmTestUtils::ExpectVariableNotSet(
195       provider_->var_auto_launched_kiosk_app_id());
196   UmTestUtils::ExpectVariableNotSet(provider_->var_disallowed_time_intervals());
197 }
198 
199 TEST_F(UmRealDevicePolicyProviderTest, ValuesUpdated) {
200   SetUpNonExistentDevicePolicy();
201   EXPECT_TRUE(provider_->Init());
202   loop_.RunOnce(false);
203   Mock::VerifyAndClearExpectations(&mock_policy_provider_);
204 
205   // Reload the policy with a good one and set some values as present. The
206   // remaining values are false.
207   SetUpExistentDevicePolicy();
208   EXPECT_CALL(mock_device_policy_, GetReleaseChannel(_))
209       .WillOnce(DoAll(SetArgPointee<0>(string("mychannel")), Return(true)));
210   EXPECT_CALL(mock_device_policy_, GetAllowedConnectionTypesForUpdate(_))
211       .WillOnce(Return(false));
212   EXPECT_CALL(mock_device_policy_, GetAllowKioskAppControlChromeVersion(_))
213       .WillOnce(DoAll(SetArgPointee<0>(true), Return(true)));
214   EXPECT_CALL(mock_device_policy_, GetAutoLaunchedKioskAppId(_))
215       .WillOnce(DoAll(SetArgPointee<0>(string("myapp")), Return(true)));
216 
217   provider_->RefreshDevicePolicy();
218 
219   UmTestUtils::ExpectVariableHasValue(true,
220                                       provider_->var_device_policy_is_loaded());
221 
222   // Test that at least one variable is set, to ensure the refresh occurred.
223   UmTestUtils::ExpectVariableHasValue(string("mychannel"),
224                                       provider_->var_release_channel());
225   UmTestUtils::ExpectVariableNotSet(
226       provider_->var_allowed_connection_types_for_update());
227   UmTestUtils::ExpectVariableHasValue(
228       true, provider_->var_allow_kiosk_app_control_chrome_version());
229   UmTestUtils::ExpectVariableHasValue(
230       string("myapp"), provider_->var_auto_launched_kiosk_app_id());
231 }
232 
233 TEST_F(UmRealDevicePolicyProviderTest, RollbackToTargetVersionConverted) {
234   SetUpExistentDevicePolicy();
235   EXPECT_CALL(mock_device_policy_, GetRollbackToTargetVersion(_))
236 #if USE_DBUS
237       .Times(2)
238 #else
239       .Times(1)
240 #endif  // USE_DBUS
241       .WillRepeatedly(DoAll(SetArgPointee<0>(2), Return(true)));
242   EXPECT_TRUE(provider_->Init());
243   loop_.RunOnce(false);
244 
245   UmTestUtils::ExpectVariableHasValue(
246       RollbackToTargetVersion::kRollbackAndPowerwash,
247       provider_->var_rollback_to_target_version());
248 }
249 
250 TEST_F(UmRealDevicePolicyProviderTest, RollbackAllowedMilestonesOobe) {
251   SetUpNonExistentDevicePolicy();
252   EXPECT_CALL(mock_device_policy_, GetRollbackAllowedMilestones(_)).Times(0);
253   ON_CALL(mock_policy_provider_, IsConsumerDevice())
254       .WillByDefault(Return(false));
255   EXPECT_TRUE(provider_->Init());
256   loop_.RunOnce(false);
257 
258   UmTestUtils::ExpectVariableNotSet(
259       provider_->var_rollback_allowed_milestones());
260 }
261 
262 TEST_F(UmRealDevicePolicyProviderTest, RollbackAllowedMilestonesConsumer) {
263   SetUpNonExistentDevicePolicy();
264   EXPECT_CALL(mock_device_policy_, GetRollbackAllowedMilestones(_)).Times(0);
265   ON_CALL(mock_policy_provider_, IsConsumerDevice())
266       .WillByDefault(Return(true));
267   EXPECT_TRUE(provider_->Init());
268   loop_.RunOnce(false);
269 
270   UmTestUtils::ExpectVariableHasValue(
271       0, provider_->var_rollback_allowed_milestones());
272 }
273 
274 TEST_F(UmRealDevicePolicyProviderTest,
275        RollbackAllowedMilestonesEnterprisePolicySet) {
276   SetUpExistentDevicePolicy();
277   ON_CALL(mock_device_policy_, GetRollbackAllowedMilestones(_))
278       .WillByDefault(DoAll(SetArgPointee<0>(2), Return(true)));
279   ON_CALL(mock_policy_provider_, IsConsumerDevice())
280       .WillByDefault(Return(false));
281   EXPECT_TRUE(provider_->Init());
282   loop_.RunOnce(false);
283 
284   UmTestUtils::ExpectVariableHasValue(
285       2, provider_->var_rollback_allowed_milestones());
286 }
287 
288 TEST_F(UmRealDevicePolicyProviderTest, ScatterFactorConverted) {
289   SetUpExistentDevicePolicy();
290   EXPECT_CALL(mock_device_policy_, GetScatterFactorInSeconds(_))
291 #if USE_DBUS
292       .Times(2)
293 #else
294       .Times(1)
295 #endif  // USE_DBUS
296       .WillRepeatedly(DoAll(SetArgPointee<0>(1234), Return(true)));
297   EXPECT_TRUE(provider_->Init());
298   loop_.RunOnce(false);
299 
300   UmTestUtils::ExpectVariableHasValue(TimeDelta::FromSeconds(1234),
301                                       provider_->var_scatter_factor());
302 }
303 
304 TEST_F(UmRealDevicePolicyProviderTest, NegativeScatterFactorIgnored) {
305   SetUpExistentDevicePolicy();
306   EXPECT_CALL(mock_device_policy_, GetScatterFactorInSeconds(_))
307 #if USE_DBUS
308       .Times(2)
309 #else
310       .Times(1)
311 #endif  // USE_DBUS
312       .WillRepeatedly(DoAll(SetArgPointee<0>(-1), Return(true)));
313   EXPECT_TRUE(provider_->Init());
314   loop_.RunOnce(false);
315 
316   UmTestUtils::ExpectVariableNotSet(provider_->var_scatter_factor());
317 }
318 
319 TEST_F(UmRealDevicePolicyProviderTest, AllowedTypesConverted) {
320   SetUpExistentDevicePolicy();
321   EXPECT_CALL(mock_device_policy_, GetAllowedConnectionTypesForUpdate(_))
322 #if USE_DBUS
323       .Times(2)
324 #else
325       .Times(1)
326 #endif  // USE_DBUS
327       .WillRepeatedly(DoAll(
328           SetArgPointee<0>(set<string>{"bluetooth", "wifi", "not-a-type"}),
329           Return(true)));
330   EXPECT_TRUE(provider_->Init());
331   loop_.RunOnce(false);
332 
333   UmTestUtils::ExpectVariableHasValue(
334       set<ConnectionType>{ConnectionType::kWifi, ConnectionType::kBluetooth},
335       provider_->var_allowed_connection_types_for_update());
336 }
337 
338 TEST_F(UmRealDevicePolicyProviderTest, DisallowedIntervalsConverted) {
339   SetUpExistentDevicePolicy();
340 
341   vector<DevicePolicy::WeeklyTimeInterval> intervals = {
342       {5, TimeDelta::FromHours(5), 6, TimeDelta::FromHours(8)},
343       {1, TimeDelta::FromHours(1), 3, TimeDelta::FromHours(10)}};
344 
345   EXPECT_CALL(mock_device_policy_, GetDisallowedTimeIntervals(_))
346       .WillRepeatedly(DoAll(SetArgPointee<0>(intervals), Return(true)));
347   EXPECT_TRUE(provider_->Init());
348   loop_.RunOnce(false);
349 
350   UmTestUtils::ExpectVariableHasValue(
351       WeeklyTimeIntervalVector{
352           WeeklyTimeInterval(WeeklyTime(5, TimeDelta::FromHours(5)),
353                              WeeklyTime(6, TimeDelta::FromHours(8))),
354           WeeklyTimeInterval(WeeklyTime(1, TimeDelta::FromHours(1)),
355                              WeeklyTime(3, TimeDelta::FromHours(10)))},
356       provider_->var_disallowed_time_intervals());
357 }
358 
359 }  // namespace chromeos_update_manager
360