OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/dbus/power_manager_client.h" | 5 #include "chromeos/dbus/power_manager_client.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 using ::testing::Return; | 25 using ::testing::Return; |
26 using ::testing::SaveArg; | 26 using ::testing::SaveArg; |
27 | 27 |
28 namespace chromeos { | 28 namespace chromeos { |
29 | 29 |
30 namespace { | 30 namespace { |
31 | 31 |
32 // Shorthand for a few commonly-used constants. | 32 // Shorthand for a few commonly-used constants. |
33 const char* kInterface = power_manager::kPowerManagerInterface; | 33 const char* kInterface = power_manager::kPowerManagerInterface; |
34 const char* kSuspendImminent = power_manager::kSuspendImminentSignal; | 34 const char* kSuspendImminent = power_manager::kSuspendImminentSignal; |
| 35 const char* kDarkSuspendImminent = power_manager::kDarkSuspendImminentSignal; |
35 const char* kHandleSuspendReadiness = | 36 const char* kHandleSuspendReadiness = |
36 power_manager::kHandleSuspendReadinessMethod; | 37 power_manager::kHandleSuspendReadinessMethod; |
| 38 const char* kHandleDarkSuspendReadiness = |
| 39 power_manager::kHandleDarkSuspendReadinessMethod; |
37 | 40 |
38 // Matcher that verifies that a dbus::Message has member |name|. | 41 // Matcher that verifies that a dbus::Message has member |name|. |
39 MATCHER_P(HasMember, name, "") { | 42 MATCHER_P(HasMember, name, "") { |
40 if (arg->GetMember() != name) { | 43 if (arg->GetMember() != name) { |
41 *result_listener << "has member " << arg->GetMember(); | 44 *result_listener << "has member " << arg->GetMember(); |
42 return false; | 45 return false; |
43 } | 46 } |
44 return true; | 47 return true; |
45 } | 48 } |
46 | 49 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 // Stub implementation of PowerManagerClient::Observer. | 81 // Stub implementation of PowerManagerClient::Observer. |
79 class TestObserver : public PowerManagerClient::Observer { | 82 class TestObserver : public PowerManagerClient::Observer { |
80 public: | 83 public: |
81 explicit TestObserver(PowerManagerClient* client) : client_(client) { | 84 explicit TestObserver(PowerManagerClient* client) : client_(client) { |
82 client_->AddObserver(this); | 85 client_->AddObserver(this); |
83 } | 86 } |
84 ~TestObserver() override { client_->RemoveObserver(this); } | 87 ~TestObserver() override { client_->RemoveObserver(this); } |
85 | 88 |
86 int num_suspend_imminent() const { return num_suspend_imminent_; } | 89 int num_suspend_imminent() const { return num_suspend_imminent_; } |
87 int num_suspend_done() const { return num_suspend_done_; } | 90 int num_suspend_done() const { return num_suspend_done_; } |
| 91 int num_dark_suspend_imminent() const { return num_dark_suspend_imminent_; } |
| 92 base::Closure suspend_readiness_callback() const { |
| 93 return suspend_readiness_callback_; |
| 94 } |
88 | 95 |
89 void set_take_suspend_readiness_callback(bool take_callback) { | 96 void set_take_suspend_readiness_callback(bool take_callback) { |
90 take_suspend_readiness_callback_ = take_callback; | 97 take_suspend_readiness_callback_ = take_callback; |
91 } | 98 } |
92 | 99 |
93 // Runs |suspend_readiness_callback_|. | 100 // Runs |suspend_readiness_callback_|. |
94 bool RunSuspendReadinessCallback() WARN_UNUSED_RESULT { | 101 bool RunSuspendReadinessCallback() WARN_UNUSED_RESULT { |
95 if (suspend_readiness_callback_.is_null()) | 102 if (suspend_readiness_callback_.is_null()) |
96 return false; | 103 return false; |
97 | 104 |
98 auto cb = suspend_readiness_callback_; | 105 auto cb = suspend_readiness_callback_; |
99 suspend_readiness_callback_.Reset(); | 106 suspend_readiness_callback_.Reset(); |
100 cb.Run(); | 107 cb.Run(); |
101 return true; | 108 return true; |
102 } | 109 } |
103 | 110 |
104 // PowerManagerClient::Observer: | 111 // PowerManagerClient::Observer: |
105 void SuspendImminent() override { | 112 void SuspendImminent() override { |
106 num_suspend_imminent_++; | 113 num_suspend_imminent_++; |
107 if (take_suspend_readiness_callback_) | 114 if (take_suspend_readiness_callback_) |
108 suspend_readiness_callback_ = client_->GetSuspendReadinessCallback(); | 115 suspend_readiness_callback_ = client_->GetSuspendReadinessCallback(); |
109 } | 116 } |
110 void SuspendDone(const base::TimeDelta& sleep_duration) override { | 117 void SuspendDone(const base::TimeDelta& sleep_duration) override { |
111 num_suspend_done_++; | 118 num_suspend_done_++; |
112 } | 119 } |
| 120 void DarkSuspendImminent() override { |
| 121 num_dark_suspend_imminent_++; |
| 122 if (take_suspend_readiness_callback_) |
| 123 suspend_readiness_callback_ = client_->GetSuspendReadinessCallback(); |
| 124 } |
113 | 125 |
114 private: | 126 private: |
115 PowerManagerClient* client_; // Not owned. | 127 PowerManagerClient* client_; // Not owned. |
116 | 128 |
117 // Number of times SuspendImminent() and SuspendDone() have been called. | 129 // Number of times SuspendImminent(), SuspendDone(), and DarkSuspendImminent() |
| 130 // have been called. |
118 int num_suspend_imminent_ = 0; | 131 int num_suspend_imminent_ = 0; |
119 int num_suspend_done_ = 0; | 132 int num_suspend_done_ = 0; |
| 133 int num_dark_suspend_imminent_ = 0; |
120 | 134 |
121 // Should SuspendImminent() call |client_|'s GetSuspendReadinessCallback() | 135 // Should SuspendImminent() and DarkSuspendImminent() call |client_|'s |
122 // method? | 136 // GetSuspendReadinessCallback() method? |
123 bool take_suspend_readiness_callback_ = false; | 137 bool take_suspend_readiness_callback_ = false; |
124 | 138 |
125 // Callback returned by |client_|'s GetSuspendReadinessCallback() method. | 139 // Callback returned by |client_|'s GetSuspendReadinessCallback() method. |
126 base::Closure suspend_readiness_callback_; | 140 base::Closure suspend_readiness_callback_; |
127 | 141 |
128 DISALLOW_COPY_AND_ASSIGN(TestObserver); | 142 DISALLOW_COPY_AND_ASSIGN(TestObserver); |
129 }; | 143 }; |
130 | 144 |
131 // Stub implementation of PowerManagerClient::RenderProcessManagerDelegate. | 145 // Stub implementation of PowerManagerClient::RenderProcessManagerDelegate. |
132 class TestDelegate : public PowerManagerClient::RenderProcessManagerDelegate { | 146 class TestDelegate : public PowerManagerClient::RenderProcessManagerDelegate { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 CHECK(dbus::MessageWriter(response.get()).AppendProtoAsArrayOfBytes(proto)); | 312 CHECK(dbus::MessageWriter(response.get()).AppendProtoAsArrayOfBytes(proto)); |
299 | 313 |
300 message_loop_.task_runner()->PostTask( | 314 message_loop_.task_runner()->PostTask( |
301 FROM_HERE, | 315 FROM_HERE, |
302 base::Bind(&RunResponseCallback, callback, base::Passed(&response))); | 316 base::Bind(&RunResponseCallback, callback, base::Passed(&response))); |
303 } | 317 } |
304 | 318 |
305 DISALLOW_COPY_AND_ASSIGN(PowerManagerClientTest); | 319 DISALLOW_COPY_AND_ASSIGN(PowerManagerClientTest); |
306 }; | 320 }; |
307 | 321 |
308 // Suspend readiness should be reported immediately when there are no observers. | 322 // Tests that suspend readiness is reported immediately when there are no |
| 323 // observers. |
309 TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutObservers) { | 324 TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutObservers) { |
310 const int kSuspendId = 1; | 325 const int kSuspendId = 1; |
311 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); | 326 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); |
312 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); | 327 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); |
313 EmitSuspendDoneSignal(kSuspendId); | 328 EmitSuspendDoneSignal(kSuspendId); |
314 } | 329 } |
315 | 330 |
316 // Observers should be notified when suspend is imminent and done. Readiness | 331 // Tests that synchronous observers are notified about impending suspend |
317 // should be reported synchronously when GetSuspendReadinessCallback() hasn't | 332 // attempts and completion. |
318 // been called. | |
319 TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutCallbacks) { | 333 TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutCallbacks) { |
320 TestObserver observer_1(client_.get()); | 334 TestObserver observer_1(client_.get()); |
321 TestObserver observer_2(client_.get()); | 335 TestObserver observer_2(client_.get()); |
322 | 336 |
| 337 // Observers should be notified when suspend is imminent. Readiness should be |
| 338 // reported synchronously since GetSuspendReadinessCallback() hasn't been |
| 339 // called. |
323 const int kSuspendId = 1; | 340 const int kSuspendId = 1; |
324 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); | 341 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); |
325 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); | 342 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); |
326 EXPECT_EQ(1, observer_1.num_suspend_imminent()); | 343 EXPECT_EQ(1, observer_1.num_suspend_imminent()); |
327 EXPECT_EQ(0, observer_1.num_suspend_done()); | 344 EXPECT_EQ(0, observer_1.num_suspend_done()); |
328 EXPECT_EQ(1, observer_2.num_suspend_imminent()); | 345 EXPECT_EQ(1, observer_2.num_suspend_imminent()); |
329 EXPECT_EQ(0, observer_2.num_suspend_done()); | 346 EXPECT_EQ(0, observer_2.num_suspend_done()); |
330 | 347 |
331 EmitSuspendDoneSignal(kSuspendId); | 348 EmitSuspendDoneSignal(kSuspendId); |
332 EXPECT_EQ(1, observer_1.num_suspend_imminent()); | 349 EXPECT_EQ(1, observer_1.num_suspend_imminent()); |
333 EXPECT_EQ(1, observer_1.num_suspend_done()); | 350 EXPECT_EQ(1, observer_1.num_suspend_done()); |
334 EXPECT_EQ(1, observer_2.num_suspend_imminent()); | 351 EXPECT_EQ(1, observer_2.num_suspend_imminent()); |
335 EXPECT_EQ(1, observer_2.num_suspend_done()); | 352 EXPECT_EQ(1, observer_2.num_suspend_done()); |
336 } | 353 } |
337 | 354 |
338 // When observers call GetSuspendReadinessCallback() from their | 355 // Tests that readiness is deferred until asynchronous observers have run their |
339 // SuspendImminent() methods, the HandleSuspendReadiness method call should be | 356 // callbacks. |
340 // deferred until all callbacks are run. | |
341 TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithCallbacks) { | 357 TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithCallbacks) { |
342 TestObserver observer_1(client_.get()); | 358 TestObserver observer_1(client_.get()); |
343 observer_1.set_take_suspend_readiness_callback(true); | 359 observer_1.set_take_suspend_readiness_callback(true); |
344 TestObserver observer_2(client_.get()); | 360 TestObserver observer_2(client_.get()); |
345 observer_2.set_take_suspend_readiness_callback(true); | 361 observer_2.set_take_suspend_readiness_callback(true); |
346 TestObserver observer_3(client_.get()); | 362 TestObserver observer_3(client_.get()); |
347 | 363 |
| 364 // When observers call GetSuspendReadinessCallback() from their |
| 365 // SuspendImminent() methods, the HandleSuspendReadiness method call should be |
| 366 // deferred until all callbacks are run. |
348 const int kSuspendId = 1; | 367 const int kSuspendId = 1; |
349 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); | 368 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); |
350 EXPECT_TRUE(observer_1.RunSuspendReadinessCallback()); | 369 EXPECT_TRUE(observer_1.RunSuspendReadinessCallback()); |
351 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); | 370 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); |
352 EXPECT_TRUE(observer_2.RunSuspendReadinessCallback()); | 371 EXPECT_TRUE(observer_2.RunSuspendReadinessCallback()); |
353 EmitSuspendDoneSignal(kSuspendId); | 372 EmitSuspendDoneSignal(kSuspendId); |
| 373 EXPECT_EQ(1, observer_1.num_suspend_done()); |
| 374 EXPECT_EQ(1, observer_2.num_suspend_done()); |
354 } | 375 } |
355 | 376 |
356 // The RenderProcessManagerDelegate should be notified that suspend is imminent | 377 // Tests that RenderProcessManagerDelegate is notified about suspend and resume |
357 // only after observers have reported readiness. | 378 // in the common case where suspend readiness is reported. |
358 TEST_F(PowerManagerClientTest, NotifyRenderProcessManagerDelegate) { | 379 TEST_F(PowerManagerClientTest, NotifyRenderProcessManagerDelegate) { |
359 TestDelegate delegate(client_.get()); | 380 TestDelegate delegate(client_.get()); |
360 TestObserver observer(client_.get()); | 381 TestObserver observer(client_.get()); |
361 observer.set_take_suspend_readiness_callback(true); | 382 observer.set_take_suspend_readiness_callback(true); |
362 | 383 |
363 const int kSuspendId = 1; | 384 const int kSuspendId = 1; |
364 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); | 385 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); |
365 EXPECT_EQ(0, delegate.num_suspend_imminent()); | 386 EXPECT_EQ(0, delegate.num_suspend_imminent()); |
366 EXPECT_EQ(0, delegate.num_suspend_done()); | 387 EXPECT_EQ(0, delegate.num_suspend_done()); |
367 | 388 |
| 389 // The RenderProcessManagerDelegate should be notified that suspend is |
| 390 // imminent only after observers have reported readiness. |
368 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); | 391 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); |
369 EXPECT_TRUE(observer.RunSuspendReadinessCallback()); | 392 EXPECT_TRUE(observer.RunSuspendReadinessCallback()); |
370 EXPECT_EQ(1, delegate.num_suspend_imminent()); | 393 EXPECT_EQ(1, delegate.num_suspend_imminent()); |
371 EXPECT_EQ(0, delegate.num_suspend_done()); | 394 EXPECT_EQ(0, delegate.num_suspend_done()); |
372 | 395 |
| 396 // The delegate should be notified immediately after the attempt completes. |
373 EmitSuspendDoneSignal(kSuspendId); | 397 EmitSuspendDoneSignal(kSuspendId); |
374 EXPECT_EQ(1, delegate.num_suspend_imminent()); | 398 EXPECT_EQ(1, delegate.num_suspend_imminent()); |
375 EXPECT_EQ(1, delegate.num_suspend_done()); | 399 EXPECT_EQ(1, delegate.num_suspend_done()); |
376 } | 400 } |
377 | 401 |
378 // TODO(derat): Add more tests, e.g. for SuspendDone being received while | 402 // Tests that DarkSuspendImminent is handled in a manner similar to |
379 // readiness callbacks are still outstanding (http://crbug.com/646912) and for | 403 // SuspendImminent. |
380 // the handling of DarkSuspendImminent signals. | 404 TEST_F(PowerManagerClientTest, ReportDarkSuspendReadiness) { |
| 405 TestDelegate delegate(client_.get()); |
| 406 TestObserver observer(client_.get()); |
| 407 observer.set_take_suspend_readiness_callback(true); |
| 408 |
| 409 const int kSuspendId = 1; |
| 410 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); |
| 411 EXPECT_EQ(1, observer.num_suspend_imminent()); |
| 412 EXPECT_EQ(0, delegate.num_suspend_imminent()); |
| 413 |
| 414 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); |
| 415 EXPECT_TRUE(observer.RunSuspendReadinessCallback()); |
| 416 EXPECT_EQ(1, delegate.num_suspend_imminent()); |
| 417 |
| 418 // The RenderProcessManagerDelegate shouldn't be notified about dark suspend |
| 419 // attempts. |
| 420 const int kDarkSuspendId = 5; |
| 421 EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId); |
| 422 EXPECT_EQ(1, observer.num_dark_suspend_imminent()); |
| 423 EXPECT_EQ(1, delegate.num_suspend_imminent()); |
| 424 EXPECT_EQ(0, delegate.num_suspend_done()); |
| 425 |
| 426 ExpectSuspendReadiness(kHandleDarkSuspendReadiness, kDarkSuspendId, |
| 427 kDarkSuspendDelayId); |
| 428 EXPECT_TRUE(observer.RunSuspendReadinessCallback()); |
| 429 EXPECT_EQ(0, delegate.num_suspend_done()); |
| 430 |
| 431 EmitSuspendDoneSignal(kSuspendId); |
| 432 EXPECT_EQ(1, observer.num_suspend_done()); |
| 433 EXPECT_EQ(1, delegate.num_suspend_done()); |
| 434 } |
| 435 |
| 436 // Tests the case where a SuspendDone signal is received while a readiness |
| 437 // callback is still pending. |
| 438 TEST_F(PowerManagerClientTest, SuspendCancelledWhileCallbackPending) { |
| 439 TestDelegate delegate(client_.get()); |
| 440 TestObserver observer(client_.get()); |
| 441 observer.set_take_suspend_readiness_callback(true); |
| 442 |
| 443 const int kSuspendId = 1; |
| 444 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); |
| 445 EXPECT_EQ(1, observer.num_suspend_imminent()); |
| 446 |
| 447 // If the suspend attempt completes (probably due to cancellation) before the |
| 448 // observer has run its readiness callback, the observer (but not the |
| 449 // delegate, which hasn't been notified about suspend being imminent yet) |
| 450 // should be notified about completion. |
| 451 EmitSuspendDoneSignal(kSuspendId); |
| 452 EXPECT_EQ(1, observer.num_suspend_done()); |
| 453 EXPECT_EQ(0, delegate.num_suspend_done()); |
| 454 |
| 455 // Ensure that the delegate doesn't receive late notification of suspend being |
| 456 // imminent if the readiness callback runs at this point, since that would |
| 457 // leave the renderers in a frozen state (http://crbug.com/646912). There's an |
| 458 // implicit expectation that powerd doesn't get notified about readiness here, |
| 459 // too. |
| 460 EXPECT_TRUE(observer.RunSuspendReadinessCallback()); |
| 461 EXPECT_EQ(0, delegate.num_suspend_imminent()); |
| 462 EXPECT_EQ(0, delegate.num_suspend_done()); |
| 463 } |
| 464 |
| 465 // Tests the case where a SuspendDone signal is received while a dark suspend |
| 466 // readiness callback is still pending. |
| 467 TEST_F(PowerManagerClientTest, SuspendDoneWhileDarkSuspendCallbackPending) { |
| 468 TestDelegate delegate(client_.get()); |
| 469 TestObserver observer(client_.get()); |
| 470 observer.set_take_suspend_readiness_callback(true); |
| 471 |
| 472 const int kSuspendId = 1; |
| 473 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); |
| 474 ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId); |
| 475 EXPECT_TRUE(observer.RunSuspendReadinessCallback()); |
| 476 EXPECT_EQ(1, delegate.num_suspend_imminent()); |
| 477 |
| 478 const int kDarkSuspendId = 5; |
| 479 EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId); |
| 480 EXPECT_EQ(1, observer.num_dark_suspend_imminent()); |
| 481 |
| 482 // The delegate should be notified if the attempt completes now. |
| 483 EmitSuspendDoneSignal(kSuspendId); |
| 484 EXPECT_EQ(1, observer.num_suspend_done()); |
| 485 EXPECT_EQ(1, delegate.num_suspend_done()); |
| 486 |
| 487 // Dark suspend readiness shouldn't be reported even if the callback runs at |
| 488 // this point, since the suspend attempt is already done. The delegate also |
| 489 // shouldn't receive any more calls. |
| 490 EXPECT_TRUE(observer.RunSuspendReadinessCallback()); |
| 491 EXPECT_EQ(1, delegate.num_suspend_imminent()); |
| 492 EXPECT_EQ(1, delegate.num_suspend_done()); |
| 493 } |
| 494 |
| 495 // Tests the case where dark suspend is announced while readiness hasn't been |
| 496 // reported for the initial regular suspend attempt. |
| 497 TEST_F(PowerManagerClientTest, DarkSuspendImminentWhileCallbackPending) { |
| 498 TestDelegate delegate(client_.get()); |
| 499 TestObserver observer(client_.get()); |
| 500 observer.set_take_suspend_readiness_callback(true); |
| 501 |
| 502 // Announce that suspend is imminent and grab, but don't run, the readiness |
| 503 // callback. |
| 504 const int kSuspendId = 1; |
| 505 EmitSuspendImminentSignal(kSuspendImminent, kSuspendId); |
| 506 EXPECT_EQ(1, observer.num_suspend_imminent()); |
| 507 base::Closure regular_callback = observer.suspend_readiness_callback(); |
| 508 |
| 509 // Before readiness is reported, announce that dark suspend is imminent. |
| 510 const int kDarkSuspendId = 1; |
| 511 EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId); |
| 512 EXPECT_EQ(1, observer.num_dark_suspend_imminent()); |
| 513 base::Closure dark_callback = observer.suspend_readiness_callback(); |
| 514 |
| 515 // Complete the suspend attempt and run both of the earlier callbacks. Neither |
| 516 // should result in readiness being reported. |
| 517 EmitSuspendDoneSignal(kSuspendId); |
| 518 EXPECT_EQ(1, observer.num_suspend_done()); |
| 519 regular_callback.Run(); |
| 520 dark_callback.Run(); |
| 521 } |
381 | 522 |
382 } // namespace chromeos | 523 } // namespace chromeos |
OLD | NEW |