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
37using base::Bind;
38using base::Unretained;
39using std::map;
40using std::string;
41using testing::_;
42using testing::DoAll;
43using testing::IgnoreResult;
44using testing::InvokeWithoutArgs;
45using testing::Mock;
46using testing::Return;
47using testing::SetArgumentPointee;
48using testing::Test;
49
50namespace shill {
51
52namespace {
53
54class FakeControl : public MockControl {
55 public:
56  FakeControl()
57      : delegate_(nullptr),
58        power_manager_proxy_raw_(new MockPowerManagerProxy),
59        power_manager_proxy_(power_manager_proxy_raw_) {}
60
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
71  PowerManagerProxyDelegate* delegate() const { return delegate_; }
72  // Can not guarantee that the returned object is alive.
73  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
85class 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
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:
113  virtual void SetUp() {
114    power_manager_.Start(kTimeout, suspend_imminent_callback_,
115                         suspend_done_callback_,
116                         dark_suspend_imminent_callback_);
117  }
118
119  virtual void TearDown() {
120    power_manager_.Stop();
121  }
122
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
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
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
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
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
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
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
171  void RegisterSuspendDelays() {
172    AddProxyExpectationForRegisterSuspendDelay(kDelayId, true);
173    AddProxyExpectationForRegisterDarkSuspendDelay(kDelayId, true);
174    OnPowerManagerAppeared();
175    Mock::VerifyAndClearExpectations(power_manager_proxy_);
176  }
177
178  void OnSuspendImminent(int suspend_id) {
179    control_.delegate()->OnSuspendImminent(suspend_id);
180    EXPECT_TRUE(power_manager_.suspending());
181  }
182
183  void OnSuspendDone(int suspend_id) {
184    control_.delegate()->OnSuspendDone(suspend_id);
185    EXPECT_FALSE(power_manager_.suspending());
186  }
187
188  void OnDarkSuspendImminent(int suspend_id) {
189    control_.delegate()->OnDarkSuspendImminent(suspend_id);
190  }
191
192  void OnPowerManagerAppeared() {
193    power_manager_.OnPowerManagerAppeared();
194  }
195
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
213const char PowerManagerTest::kDescription[] = "shill";
214const char PowerManagerTest::kDarkDescription[] = "shill";
215const char PowerManagerTest::kPowerManagerDefaultOwner[] =
216    "PowerManagerDefaultOwner";
217
218TEST_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
227TEST_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
250TEST_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
262TEST_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
270TEST_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
279TEST_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
288TEST_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
297TEST_F(PowerManagerTest, ReportSuspendReadinessFailsOutsideSuspend) {
298  RegisterSuspendDelays();
299  EXPECT_CALL(*power_manager_proxy_, ReportSuspendReadiness(_, _)).Times(0);
300  EXPECT_FALSE(power_manager_.ReportSuspendReadiness());
301}
302
303TEST_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
315TEST_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
327TEST_F(PowerManagerTest, Stop) {
328  RegisterSuspendDelays();
329  AddProxyExpectationForUnregisterSuspendDelay(kDelayId, true);
330  AddProxyExpectationForUnregisterDarkSuspendDelay(kDelayId, true);
331  power_manager_.Stop();
332}
333
334TEST_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
348TEST_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
375TEST_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
386TEST_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