Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: chromeos/dbus/power_manager_client_unittest.cc

Issue 2340153002: chromeos: Fix renderer-freezing race during aborted suspend. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chromeos/dbus/power_manager_client.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « chromeos/dbus/power_manager_client.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698