• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "shill/power_manager.h"
18 
19 #include <memory>
20 #include <string>
21 
22 #include <base/bind.h>
23 #if defined(__ANDROID__)
24 #include <dbus/service_constants.h>
25 #else
26 #include <chromeos/dbus/service_constants.h>
27 #endif  // __ANDROID__
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30 
31 #include "shill/mock_control.h"
32 #include "shill/mock_event_dispatcher.h"
33 #include "shill/mock_metrics.h"
34 #include "shill/mock_power_manager_proxy.h"
35 #include "shill/power_manager_proxy_interface.h"
36 
37 using base::Bind;
38 using base::Unretained;
39 using std::map;
40 using std::string;
41 using testing::_;
42 using testing::DoAll;
43 using testing::IgnoreResult;
44 using testing::InvokeWithoutArgs;
45 using testing::Mock;
46 using testing::Return;
47 using testing::SetArgumentPointee;
48 using testing::Test;
49 
50 namespace shill {
51 
52 namespace {
53 
54 class FakeControl : public MockControl {
55  public:
FakeControl()56   FakeControl()
57       : delegate_(nullptr),
58         power_manager_proxy_raw_(new MockPowerManagerProxy),
59         power_manager_proxy_(power_manager_proxy_raw_) {}
60 
CreatePowerManagerProxy(PowerManagerProxyDelegate * delegate,const base::Closure & service_appeared_callback,const base::Closure & service_vanished_callback)61   virtual PowerManagerProxyInterface* CreatePowerManagerProxy(
62       PowerManagerProxyDelegate* delegate,
63       const base::Closure& service_appeared_callback,
64       const base::Closure& service_vanished_callback) {
65     CHECK(power_manager_proxy_);
66     delegate_ = delegate;
67     // Passes ownership.
68     return power_manager_proxy_.release();
69   }
70 
delegate() const71   PowerManagerProxyDelegate* delegate() const { return delegate_; }
72   // Can not guarantee that the returned object is alive.
power_manager_proxy() const73   MockPowerManagerProxy* power_manager_proxy() const {
74     return power_manager_proxy_raw_;
75   }
76 
77  private:
78   PowerManagerProxyDelegate* delegate_;
79   MockPowerManagerProxy* const power_manager_proxy_raw_;
80   std::unique_ptr<MockPowerManagerProxy> power_manager_proxy_;
81 };
82 
83 }  // namespace
84 
85 class PowerManagerTest : public Test {
86  public:
87   static const char kDescription[];
88   static const char kDarkDescription[];
89   static const char kPowerManagerDefaultOwner[];
90   static const int kSuspendId1 = 123;
91   static const int kSuspendId2 = 456;
92   static const int kDelayId = 4;
93   static const int kDelayId2 = 5;
94 
PowerManagerTest()95   PowerManagerTest()
96       : kTimeout(base::TimeDelta::FromSeconds(3)),
97         power_manager_(&dispatcher_, &control_),
98         power_manager_proxy_(control_.power_manager_proxy()),
99         delegate_(control_.delegate()) {
100     suspend_imminent_callback_ =
101         Bind(&PowerManagerTest::SuspendImminentAction, Unretained(this));
102     suspend_done_callback_ =
103         Bind(&PowerManagerTest::SuspendDoneAction, Unretained(this));
104     dark_suspend_imminent_callback_ =
105         Bind(&PowerManagerTest::DarkSuspendImminentAction, Unretained(this));
106   }
107 
108   MOCK_METHOD0(SuspendImminentAction, void());
109   MOCK_METHOD0(SuspendDoneAction, void());
110   MOCK_METHOD0(DarkSuspendImminentAction, void());
111 
112  protected:
SetUp()113   virtual void SetUp() {
114     power_manager_.Start(kTimeout, suspend_imminent_callback_,
115                          suspend_done_callback_,
116                          dark_suspend_imminent_callback_);
117   }
118 
TearDown()119   virtual void TearDown() {
120     power_manager_.Stop();
121   }
122 
AddProxyExpectationForRegisterSuspendDelay(int delay_id,bool return_value)123   void AddProxyExpectationForRegisterSuspendDelay(int delay_id,
124                                                   bool return_value) {
125     EXPECT_CALL(*power_manager_proxy_,
126                 RegisterSuspendDelay(kTimeout, kDescription, _))
127         .WillOnce(DoAll(SetArgumentPointee<2>(delay_id), Return(return_value)));
128   }
129 
AddProxyExpectationForUnregisterSuspendDelay(int delay_id,bool return_value)130   void AddProxyExpectationForUnregisterSuspendDelay(int delay_id,
131                                                     bool return_value) {
132     EXPECT_CALL(*power_manager_proxy_, UnregisterSuspendDelay(delay_id))
133         .WillOnce(Return(return_value));
134   }
135 
AddProxyExpectationForReportSuspendReadiness(int delay_id,int suspend_id,bool return_value)136   void AddProxyExpectationForReportSuspendReadiness(int delay_id,
137                                                     int suspend_id,
138                                                     bool return_value) {
139     EXPECT_CALL(*power_manager_proxy_,
140                 ReportSuspendReadiness(delay_id, suspend_id))
141         .WillOnce(Return(return_value));
142   }
143 
AddProxyExpectationForRecordDarkResumeWakeReason(const string & wake_reason,bool return_value)144   void AddProxyExpectationForRecordDarkResumeWakeReason(
145       const string& wake_reason, bool return_value) {
146     EXPECT_CALL(*power_manager_proxy_, RecordDarkResumeWakeReason(wake_reason))
147         .WillOnce(Return(return_value));
148   }
149 
AddProxyExpectationForRegisterDarkSuspendDelay(int delay_id,bool return_value)150   void AddProxyExpectationForRegisterDarkSuspendDelay(int delay_id,
151                                                       bool return_value) {
152     EXPECT_CALL(*power_manager_proxy_,
153                 RegisterDarkSuspendDelay(kTimeout, kDarkDescription, _))
154         .WillOnce(DoAll(SetArgumentPointee<2>(delay_id), Return(return_value)));
155   }
156 
AddProxyExpectationForReportDarkSuspendReadiness(int delay_id,int suspend_id,bool return_value)157   void AddProxyExpectationForReportDarkSuspendReadiness(int delay_id,
158                                                         int suspend_id,
159                                                         bool return_value) {
160     EXPECT_CALL(*power_manager_proxy_,
161                 ReportDarkSuspendReadiness(delay_id, suspend_id))
162         .WillOnce(Return(return_value));
163   }
164 
AddProxyExpectationForUnregisterDarkSuspendDelay(int delay_id,bool return_value)165   void AddProxyExpectationForUnregisterDarkSuspendDelay(int delay_id,
166                                                         bool return_value) {
167     EXPECT_CALL(*power_manager_proxy_, UnregisterDarkSuspendDelay(delay_id))
168         .WillOnce(Return(return_value));
169   }
170 
RegisterSuspendDelays()171   void RegisterSuspendDelays() {
172     AddProxyExpectationForRegisterSuspendDelay(kDelayId, true);
173     AddProxyExpectationForRegisterDarkSuspendDelay(kDelayId, true);
174     OnPowerManagerAppeared();
175     Mock::VerifyAndClearExpectations(power_manager_proxy_);
176   }
177 
OnSuspendImminent(int suspend_id)178   void OnSuspendImminent(int suspend_id) {
179     control_.delegate()->OnSuspendImminent(suspend_id);
180     EXPECT_TRUE(power_manager_.suspending());
181   }
182 
OnSuspendDone(int suspend_id)183   void OnSuspendDone(int suspend_id) {
184     control_.delegate()->OnSuspendDone(suspend_id);
185     EXPECT_FALSE(power_manager_.suspending());
186   }
187 
OnDarkSuspendImminent(int suspend_id)188   void OnDarkSuspendImminent(int suspend_id) {
189     control_.delegate()->OnDarkSuspendImminent(suspend_id);
190   }
191 
OnPowerManagerAppeared()192   void OnPowerManagerAppeared() {
193     power_manager_.OnPowerManagerAppeared();
194   }
195 
OnPowerManagerVanished()196   void OnPowerManagerVanished() {
197     power_manager_.OnPowerManagerVanished();
198   }
199 
200   // This is non-static since it's a non-POD type.
201   const base::TimeDelta kTimeout;
202 
203   MockEventDispatcher dispatcher_;
204   FakeControl control_;
205   PowerManager power_manager_;
206   MockPowerManagerProxy* const power_manager_proxy_;
207   PowerManagerProxyDelegate* const delegate_;
208   PowerManager::SuspendImminentCallback suspend_imminent_callback_;
209   PowerManager::SuspendDoneCallback suspend_done_callback_;
210   PowerManager::DarkSuspendImminentCallback dark_suspend_imminent_callback_;
211 };
212 
213 const char PowerManagerTest::kDescription[] = "shill";
214 const char PowerManagerTest::kDarkDescription[] = "shill";
215 const char PowerManagerTest::kPowerManagerDefaultOwner[] =
216     "PowerManagerDefaultOwner";
217 
TEST_F(PowerManagerTest,SuspendingState)218 TEST_F(PowerManagerTest, SuspendingState) {
219   const int kSuspendId = 3;
220   EXPECT_FALSE(power_manager_.suspending());
221   OnSuspendImminent(kSuspendId);
222   EXPECT_TRUE(power_manager_.suspending());
223   OnSuspendDone(kSuspendId);
224   EXPECT_FALSE(power_manager_.suspending());
225 }
226 
TEST_F(PowerManagerTest,RegisterSuspendDelayFailure)227 TEST_F(PowerManagerTest, RegisterSuspendDelayFailure) {
228   AddProxyExpectationForRegisterSuspendDelay(kDelayId, false);
229   OnPowerManagerAppeared();
230   Mock::VerifyAndClearExpectations(power_manager_proxy_);
231 
232   // Outstanding shill callbacks should still be invoked.
233   // - suspend_done_callback: If powerd died in the middle of a suspend
234   //   we want to wake shill up with suspend_done_action, so this callback
235   //   should be invoked anyway.
236   //   See PowerManagerTest::PowerManagerDiedInSuspend and
237   //   PowerManagerTest::PowerManagerReappearedInSuspend.
238   EXPECT_CALL(*this, SuspendDoneAction());
239   // - suspend_imminent_callback: The only case this can happen is if this
240   //   callback was put on the queue, and then powerd reappeared, but we failed
241   //   to registered a suspend delay with it.
242   //   It is safe to go through the suspend_imminent -> timeout -> suspend_done
243   //   path in this black swan case.
244   EXPECT_CALL(*this, SuspendImminentAction());
245   OnSuspendImminent(kSuspendId1);
246   OnSuspendDone(kSuspendId1);
247   Mock::VerifyAndClearExpectations(this);
248 }
249 
TEST_F(PowerManagerTest,RegisterDarkSuspendDelayFailure)250 TEST_F(PowerManagerTest, RegisterDarkSuspendDelayFailure) {
251   AddProxyExpectationForRegisterDarkSuspendDelay(kDelayId, false);
252   OnPowerManagerAppeared();
253   Mock::VerifyAndClearExpectations(power_manager_proxy_);
254 
255   // Outstanding dark suspend imminent signal should be ignored, since we
256   // probably won't have time to cleanly do dark resume actions. Might as well
257   // ignore the signal.
258   EXPECT_CALL(*this, DarkSuspendImminentAction()).Times(0);
259   OnDarkSuspendImminent(kSuspendId1);
260 }
261 
TEST_F(PowerManagerTest,ReportSuspendReadinessFailure)262 TEST_F(PowerManagerTest, ReportSuspendReadinessFailure) {
263   RegisterSuspendDelays();
264   EXPECT_CALL(*this, SuspendImminentAction());
265   OnSuspendImminent(kSuspendId1);
266   AddProxyExpectationForReportSuspendReadiness(kDelayId, kSuspendId1, false);
267   EXPECT_FALSE(power_manager_.ReportSuspendReadiness());
268 }
269 
TEST_F(PowerManagerTest,RecordDarkResumeWakeReasonFailure)270 TEST_F(PowerManagerTest, RecordDarkResumeWakeReasonFailure) {
271   const string kWakeReason = "WiFi.Disconnect";
272   RegisterSuspendDelays();
273   EXPECT_CALL(*this, DarkSuspendImminentAction());
274   OnDarkSuspendImminent(kSuspendId1);
275   AddProxyExpectationForRecordDarkResumeWakeReason(kWakeReason, false);
276   EXPECT_FALSE(power_manager_.RecordDarkResumeWakeReason(kWakeReason));
277 }
278 
TEST_F(PowerManagerTest,RecordDarkResumeWakeReasonSuccess)279 TEST_F(PowerManagerTest, RecordDarkResumeWakeReasonSuccess) {
280   const string kWakeReason = "WiFi.Disconnect";
281   RegisterSuspendDelays();
282   EXPECT_CALL(*this, DarkSuspendImminentAction());
283   OnDarkSuspendImminent(kSuspendId1);
284   AddProxyExpectationForRecordDarkResumeWakeReason(kWakeReason, true);
285   EXPECT_TRUE(power_manager_.RecordDarkResumeWakeReason(kWakeReason));
286 }
287 
TEST_F(PowerManagerTest,ReportDarkSuspendReadinessFailure)288 TEST_F(PowerManagerTest, ReportDarkSuspendReadinessFailure) {
289   RegisterSuspendDelays();
290   EXPECT_CALL(*this, DarkSuspendImminentAction());
291   OnDarkSuspendImminent(kSuspendId1);
292   AddProxyExpectationForReportDarkSuspendReadiness(kDelayId, kSuspendId1,
293                                                    false);
294   EXPECT_FALSE(power_manager_.ReportDarkSuspendReadiness());
295 }
296 
TEST_F(PowerManagerTest,ReportSuspendReadinessFailsOutsideSuspend)297 TEST_F(PowerManagerTest, ReportSuspendReadinessFailsOutsideSuspend) {
298   RegisterSuspendDelays();
299   EXPECT_CALL(*power_manager_proxy_, ReportSuspendReadiness(_, _)).Times(0);
300   EXPECT_FALSE(power_manager_.ReportSuspendReadiness());
301 }
302 
TEST_F(PowerManagerTest,ReportSuspendReadinessSynchronous)303 TEST_F(PowerManagerTest, ReportSuspendReadinessSynchronous) {
304   // Verifies that a synchronous ReportSuspendReadiness call by shill on a
305   // SuspendImminent callback is routed back to powerd.
306   RegisterSuspendDelays();
307   EXPECT_CALL(*power_manager_proxy_, ReportSuspendReadiness(_, _))
308       .WillOnce(Return(true));
309   EXPECT_CALL(*this, SuspendImminentAction())
310       .WillOnce(IgnoreResult(InvokeWithoutArgs(
311           &power_manager_, &PowerManager::ReportSuspendReadiness)));
312   OnSuspendImminent(kSuspendId1);
313 }
314 
TEST_F(PowerManagerTest,ReportDarkSuspendReadinessSynchronous)315 TEST_F(PowerManagerTest, ReportDarkSuspendReadinessSynchronous) {
316   // Verifies that a synchronous ReportDarkSuspendReadiness call by shill on a
317   // DarkSuspendImminent callback is routed back to powerd.
318   RegisterSuspendDelays();
319   EXPECT_CALL(*power_manager_proxy_, ReportDarkSuspendReadiness(_, _))
320       .WillOnce(Return(true));
321   EXPECT_CALL(*this, DarkSuspendImminentAction())
322       .WillOnce(IgnoreResult(InvokeWithoutArgs(
323           &power_manager_, &PowerManager::ReportDarkSuspendReadiness)));
324   OnDarkSuspendImminent(kSuspendId1);
325 }
326 
TEST_F(PowerManagerTest,Stop)327 TEST_F(PowerManagerTest, Stop) {
328   RegisterSuspendDelays();
329   AddProxyExpectationForUnregisterSuspendDelay(kDelayId, true);
330   AddProxyExpectationForUnregisterDarkSuspendDelay(kDelayId, true);
331   power_manager_.Stop();
332 }
333 
TEST_F(PowerManagerTest,StopFailure)334 TEST_F(PowerManagerTest, StopFailure) {
335   RegisterSuspendDelays();
336 
337   AddProxyExpectationForUnregisterSuspendDelay(kDelayId, false);
338   power_manager_.Stop();
339   Mock::VerifyAndClearExpectations(power_manager_proxy_);
340 
341   // As a result, callbacks should still be invoked.
342   EXPECT_CALL(*this, SuspendImminentAction());
343   EXPECT_CALL(*this, SuspendDoneAction());
344   OnSuspendImminent(kSuspendId1);
345   OnSuspendDone(kSuspendId1);
346 }
347 
TEST_F(PowerManagerTest,OnPowerManagerReappeared)348 TEST_F(PowerManagerTest, OnPowerManagerReappeared) {
349   RegisterSuspendDelays();
350 
351   // Check that we re-register suspend delay on powerd restart.
352   AddProxyExpectationForRegisterSuspendDelay(kDelayId2, true);
353   AddProxyExpectationForRegisterDarkSuspendDelay(kDelayId2, true);
354   OnPowerManagerVanished();
355   OnPowerManagerAppeared();
356   Mock::VerifyAndClearExpectations(power_manager_proxy_);
357 
358   // Check that a |ReportSuspendReadiness| message is sent with the new delay
359   // id.
360   EXPECT_CALL(*this, SuspendImminentAction());
361   OnSuspendImminent(kSuspendId1);
362   AddProxyExpectationForReportSuspendReadiness(kDelayId2, kSuspendId1, true);
363   EXPECT_TRUE(power_manager_.ReportSuspendReadiness());
364   Mock::VerifyAndClearExpectations(power_manager_proxy_);
365 
366   // Check that a |ReportDarkSuspendReadiness| message is sent with the new
367   // delay id.
368   EXPECT_CALL(*this, DarkSuspendImminentAction());
369   OnDarkSuspendImminent(kSuspendId1);
370   AddProxyExpectationForReportDarkSuspendReadiness(kDelayId2, kSuspendId1,
371                                                    true);
372   EXPECT_TRUE(power_manager_.ReportDarkSuspendReadiness());
373 }
374 
TEST_F(PowerManagerTest,PowerManagerDiedInSuspend)375 TEST_F(PowerManagerTest, PowerManagerDiedInSuspend) {
376   RegisterSuspendDelays();
377   EXPECT_CALL(*this, SuspendImminentAction());
378   OnSuspendImminent(kSuspendId1);
379   Mock::VerifyAndClearExpectations(this);
380 
381   EXPECT_CALL(*this, SuspendDoneAction());
382   OnPowerManagerVanished();
383   EXPECT_FALSE(power_manager_.suspending());
384 }
385 
TEST_F(PowerManagerTest,PowerManagerReappearedInSuspend)386 TEST_F(PowerManagerTest, PowerManagerReappearedInSuspend) {
387   RegisterSuspendDelays();
388   EXPECT_CALL(*this, SuspendImminentAction());
389   OnSuspendImminent(kSuspendId1);
390   Mock::VerifyAndClearExpectations(this);
391 
392   AddProxyExpectationForRegisterSuspendDelay(kDelayId2, true);
393   AddProxyExpectationForRegisterDarkSuspendDelay(kDelayId2, true);
394   EXPECT_CALL(*this, SuspendDoneAction());
395   OnPowerManagerVanished();
396   OnPowerManagerAppeared();
397   EXPECT_FALSE(power_manager_.suspending());
398   Mock::VerifyAndClearExpectations(this);
399 
400   // Let's check a normal suspend request after the fact.
401   EXPECT_CALL(*this, SuspendImminentAction());
402   OnSuspendImminent(kSuspendId2);
403 }
404 
405 }  // namespace shill
406