| Index: chromeos/dbus/power_manager_client_unittest.cc
|
| diff --git a/chromeos/dbus/power_manager_client_unittest.cc b/chromeos/dbus/power_manager_client_unittest.cc
|
| index eabdd3029f78361fcb3830b4b4c8161500fd34be..6614d6c7da76ca620cea404f079f4532ed78c3a5 100644
|
| --- a/chromeos/dbus/power_manager_client_unittest.cc
|
| +++ b/chromeos/dbus/power_manager_client_unittest.cc
|
| @@ -32,8 +32,11 @@ namespace {
|
| // Shorthand for a few commonly-used constants.
|
| const char* kInterface = power_manager::kPowerManagerInterface;
|
| const char* kSuspendImminent = power_manager::kSuspendImminentSignal;
|
| +const char* kDarkSuspendImminent = power_manager::kDarkSuspendImminentSignal;
|
| const char* kHandleSuspendReadiness =
|
| power_manager::kHandleSuspendReadinessMethod;
|
| +const char* kHandleDarkSuspendReadiness =
|
| + power_manager::kHandleDarkSuspendReadinessMethod;
|
|
|
| // Matcher that verifies that a dbus::Message has member |name|.
|
| MATCHER_P(HasMember, name, "") {
|
| @@ -85,6 +88,10 @@ class TestObserver : public PowerManagerClient::Observer {
|
|
|
| int num_suspend_imminent() const { return num_suspend_imminent_; }
|
| int num_suspend_done() const { return num_suspend_done_; }
|
| + int num_dark_suspend_imminent() const { return num_dark_suspend_imminent_; }
|
| + base::Closure suspend_readiness_callback() const {
|
| + return suspend_readiness_callback_;
|
| + }
|
|
|
| void set_take_suspend_readiness_callback(bool take_callback) {
|
| take_suspend_readiness_callback_ = take_callback;
|
| @@ -110,16 +117,23 @@ class TestObserver : public PowerManagerClient::Observer {
|
| void SuspendDone(const base::TimeDelta& sleep_duration) override {
|
| num_suspend_done_++;
|
| }
|
| + void DarkSuspendImminent() override {
|
| + num_dark_suspend_imminent_++;
|
| + if (take_suspend_readiness_callback_)
|
| + suspend_readiness_callback_ = client_->GetSuspendReadinessCallback();
|
| + }
|
|
|
| private:
|
| PowerManagerClient* client_; // Not owned.
|
|
|
| - // Number of times SuspendImminent() and SuspendDone() have been called.
|
| + // Number of times SuspendImminent(), SuspendDone(), and DarkSuspendImminent()
|
| + // have been called.
|
| int num_suspend_imminent_ = 0;
|
| int num_suspend_done_ = 0;
|
| + int num_dark_suspend_imminent_ = 0;
|
|
|
| - // Should SuspendImminent() call |client_|'s GetSuspendReadinessCallback()
|
| - // method?
|
| + // Should SuspendImminent() and DarkSuspendImminent() call |client_|'s
|
| + // GetSuspendReadinessCallback() method?
|
| bool take_suspend_readiness_callback_ = false;
|
|
|
| // Callback returned by |client_|'s GetSuspendReadinessCallback() method.
|
| @@ -305,7 +319,8 @@ class PowerManagerClientTest : public testing::Test {
|
| DISALLOW_COPY_AND_ASSIGN(PowerManagerClientTest);
|
| };
|
|
|
| -// Suspend readiness should be reported immediately when there are no observers.
|
| +// Tests that suspend readiness is reported immediately when there are no
|
| +// observers.
|
| TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutObservers) {
|
| const int kSuspendId = 1;
|
| ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
|
| @@ -313,13 +328,15 @@ TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutObservers) {
|
| EmitSuspendDoneSignal(kSuspendId);
|
| }
|
|
|
| -// Observers should be notified when suspend is imminent and done. Readiness
|
| -// should be reported synchronously when GetSuspendReadinessCallback() hasn't
|
| -// been called.
|
| +// Tests that synchronous observers are notified about impending suspend
|
| +// attempts and completion.
|
| TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutCallbacks) {
|
| TestObserver observer_1(client_.get());
|
| TestObserver observer_2(client_.get());
|
|
|
| + // Observers should be notified when suspend is imminent. Readiness should be
|
| + // reported synchronously since GetSuspendReadinessCallback() hasn't been
|
| + // called.
|
| const int kSuspendId = 1;
|
| ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
|
| EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
|
| @@ -335,9 +352,8 @@ TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutCallbacks) {
|
| EXPECT_EQ(1, observer_2.num_suspend_done());
|
| }
|
|
|
| -// When observers call GetSuspendReadinessCallback() from their
|
| -// SuspendImminent() methods, the HandleSuspendReadiness method call should be
|
| -// deferred until all callbacks are run.
|
| +// Tests that readiness is deferred until asynchronous observers have run their
|
| +// callbacks.
|
| TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithCallbacks) {
|
| TestObserver observer_1(client_.get());
|
| observer_1.set_take_suspend_readiness_callback(true);
|
| @@ -345,16 +361,21 @@ TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithCallbacks) {
|
| observer_2.set_take_suspend_readiness_callback(true);
|
| TestObserver observer_3(client_.get());
|
|
|
| + // When observers call GetSuspendReadinessCallback() from their
|
| + // SuspendImminent() methods, the HandleSuspendReadiness method call should be
|
| + // deferred until all callbacks are run.
|
| const int kSuspendId = 1;
|
| EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
|
| EXPECT_TRUE(observer_1.RunSuspendReadinessCallback());
|
| ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
|
| EXPECT_TRUE(observer_2.RunSuspendReadinessCallback());
|
| EmitSuspendDoneSignal(kSuspendId);
|
| + EXPECT_EQ(1, observer_1.num_suspend_done());
|
| + EXPECT_EQ(1, observer_2.num_suspend_done());
|
| }
|
|
|
| -// The RenderProcessManagerDelegate should be notified that suspend is imminent
|
| -// only after observers have reported readiness.
|
| +// Tests that RenderProcessManagerDelegate is notified about suspend and resume
|
| +// in the common case where suspend readiness is reported.
|
| TEST_F(PowerManagerClientTest, NotifyRenderProcessManagerDelegate) {
|
| TestDelegate delegate(client_.get());
|
| TestObserver observer(client_.get());
|
| @@ -365,18 +386,138 @@ TEST_F(PowerManagerClientTest, NotifyRenderProcessManagerDelegate) {
|
| EXPECT_EQ(0, delegate.num_suspend_imminent());
|
| EXPECT_EQ(0, delegate.num_suspend_done());
|
|
|
| + // The RenderProcessManagerDelegate should be notified that suspend is
|
| + // imminent only after observers have reported readiness.
|
| ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
|
| EXPECT_TRUE(observer.RunSuspendReadinessCallback());
|
| EXPECT_EQ(1, delegate.num_suspend_imminent());
|
| EXPECT_EQ(0, delegate.num_suspend_done());
|
|
|
| + // The delegate should be notified immediately after the attempt completes.
|
| EmitSuspendDoneSignal(kSuspendId);
|
| EXPECT_EQ(1, delegate.num_suspend_imminent());
|
| EXPECT_EQ(1, delegate.num_suspend_done());
|
| }
|
|
|
| -// TODO(derat): Add more tests, e.g. for SuspendDone being received while
|
| -// readiness callbacks are still outstanding (http://crbug.com/646912) and for
|
| -// the handling of DarkSuspendImminent signals.
|
| +// Tests that DarkSuspendImminent is handled in a manner similar to
|
| +// SuspendImminent.
|
| +TEST_F(PowerManagerClientTest, ReportDarkSuspendReadiness) {
|
| + TestDelegate delegate(client_.get());
|
| + TestObserver observer(client_.get());
|
| + observer.set_take_suspend_readiness_callback(true);
|
| +
|
| + const int kSuspendId = 1;
|
| + EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
|
| + EXPECT_EQ(1, observer.num_suspend_imminent());
|
| + EXPECT_EQ(0, delegate.num_suspend_imminent());
|
| +
|
| + ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
|
| + EXPECT_TRUE(observer.RunSuspendReadinessCallback());
|
| + EXPECT_EQ(1, delegate.num_suspend_imminent());
|
| +
|
| + // The RenderProcessManagerDelegate shouldn't be notified about dark suspend
|
| + // attempts.
|
| + const int kDarkSuspendId = 5;
|
| + EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId);
|
| + EXPECT_EQ(1, observer.num_dark_suspend_imminent());
|
| + EXPECT_EQ(1, delegate.num_suspend_imminent());
|
| + EXPECT_EQ(0, delegate.num_suspend_done());
|
| +
|
| + ExpectSuspendReadiness(kHandleDarkSuspendReadiness, kDarkSuspendId,
|
| + kDarkSuspendDelayId);
|
| + EXPECT_TRUE(observer.RunSuspendReadinessCallback());
|
| + EXPECT_EQ(0, delegate.num_suspend_done());
|
| +
|
| + EmitSuspendDoneSignal(kSuspendId);
|
| + EXPECT_EQ(1, observer.num_suspend_done());
|
| + EXPECT_EQ(1, delegate.num_suspend_done());
|
| +}
|
| +
|
| +// Tests the case where a SuspendDone signal is received while a readiness
|
| +// callback is still pending.
|
| +TEST_F(PowerManagerClientTest, SuspendCancelledWhileCallbackPending) {
|
| + TestDelegate delegate(client_.get());
|
| + TestObserver observer(client_.get());
|
| + observer.set_take_suspend_readiness_callback(true);
|
| +
|
| + const int kSuspendId = 1;
|
| + EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
|
| + EXPECT_EQ(1, observer.num_suspend_imminent());
|
| +
|
| + // If the suspend attempt completes (probably due to cancellation) before the
|
| + // observer has run its readiness callback, the observer (but not the
|
| + // delegate, which hasn't been notified about suspend being imminent yet)
|
| + // should be notified about completion.
|
| + EmitSuspendDoneSignal(kSuspendId);
|
| + EXPECT_EQ(1, observer.num_suspend_done());
|
| + EXPECT_EQ(0, delegate.num_suspend_done());
|
| +
|
| + // Ensure that the delegate doesn't receive late notification of suspend being
|
| + // imminent if the readiness callback runs at this point, since that would
|
| + // leave the renderers in a frozen state (http://crbug.com/646912). There's an
|
| + // implicit expectation that powerd doesn't get notified about readiness here,
|
| + // too.
|
| + EXPECT_TRUE(observer.RunSuspendReadinessCallback());
|
| + EXPECT_EQ(0, delegate.num_suspend_imminent());
|
| + EXPECT_EQ(0, delegate.num_suspend_done());
|
| +}
|
| +
|
| +// Tests the case where a SuspendDone signal is received while a dark suspend
|
| +// readiness callback is still pending.
|
| +TEST_F(PowerManagerClientTest, SuspendDoneWhileDarkSuspendCallbackPending) {
|
| + TestDelegate delegate(client_.get());
|
| + TestObserver observer(client_.get());
|
| + observer.set_take_suspend_readiness_callback(true);
|
| +
|
| + const int kSuspendId = 1;
|
| + EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
|
| + ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
|
| + EXPECT_TRUE(observer.RunSuspendReadinessCallback());
|
| + EXPECT_EQ(1, delegate.num_suspend_imminent());
|
| +
|
| + const int kDarkSuspendId = 5;
|
| + EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId);
|
| + EXPECT_EQ(1, observer.num_dark_suspend_imminent());
|
| +
|
| + // The delegate should be notified if the attempt completes now.
|
| + EmitSuspendDoneSignal(kSuspendId);
|
| + EXPECT_EQ(1, observer.num_suspend_done());
|
| + EXPECT_EQ(1, delegate.num_suspend_done());
|
| +
|
| + // Dark suspend readiness shouldn't be reported even if the callback runs at
|
| + // this point, since the suspend attempt is already done. The delegate also
|
| + // shouldn't receive any more calls.
|
| + EXPECT_TRUE(observer.RunSuspendReadinessCallback());
|
| + EXPECT_EQ(1, delegate.num_suspend_imminent());
|
| + EXPECT_EQ(1, delegate.num_suspend_done());
|
| +}
|
| +
|
| +// Tests the case where dark suspend is announced while readiness hasn't been
|
| +// reported for the initial regular suspend attempt.
|
| +TEST_F(PowerManagerClientTest, DarkSuspendImminentWhileCallbackPending) {
|
| + TestDelegate delegate(client_.get());
|
| + TestObserver observer(client_.get());
|
| + observer.set_take_suspend_readiness_callback(true);
|
| +
|
| + // Announce that suspend is imminent and grab, but don't run, the readiness
|
| + // callback.
|
| + const int kSuspendId = 1;
|
| + EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
|
| + EXPECT_EQ(1, observer.num_suspend_imminent());
|
| + base::Closure regular_callback = observer.suspend_readiness_callback();
|
| +
|
| + // Before readiness is reported, announce that dark suspend is imminent.
|
| + const int kDarkSuspendId = 1;
|
| + EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId);
|
| + EXPECT_EQ(1, observer.num_dark_suspend_imminent());
|
| + base::Closure dark_callback = observer.suspend_readiness_callback();
|
| +
|
| + // Complete the suspend attempt and run both of the earlier callbacks. Neither
|
| + // should result in readiness being reported.
|
| + EmitSuspendDoneSignal(kSuspendId);
|
| + EXPECT_EQ(1, observer.num_suspend_done());
|
| + regular_callback.Run();
|
| + dark_callback.Run();
|
| +}
|
|
|
| } // namespace chromeos
|
|
|