Chromium Code Reviews| Index: ui/display/chromeos/display_configurator_unittest.cc |
| diff --git a/ui/display/chromeos/display_configurator_unittest.cc b/ui/display/chromeos/display_configurator_unittest.cc |
| index d04850e6806e125db8540233cff9b72c1c2658c0..79a849d74a48ecd49548194fe857c1bb697f8693 100644 |
| --- a/ui/display/chromeos/display_configurator_unittest.cc |
| +++ b/ui/display/chromeos/display_configurator_unittest.cc |
| @@ -7,6 +7,7 @@ |
| #include <stddef.h> |
| #include <stdint.h> |
| +#include "base/callback_helpers.h" |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/memory/scoped_vector.h" |
| @@ -23,6 +24,12 @@ namespace test { |
| namespace { |
| +enum CallbackResult { |
| + CALLBACK_FAILURE, |
| + CALLBACK_SUCCESS, |
| + CALLBACK_NOT_CALLED, |
| +}; |
| + |
| class TestObserver : public DisplayConfigurator::Observer { |
| public: |
| explicit TestObserver(DisplayConfigurator* configurator) |
| @@ -119,14 +126,75 @@ class TestMirroringController |
| DISALLOW_COPY_AND_ASSIGN(TestMirroringController); |
| }; |
| -class DisplayConfiguratorTest : public testing::Test { |
| +// Abstracts waiting for the display configuration to be completed and getting |
| +// the time it took to complete. |
| +class ConfigurationWaiter { |
| public: |
| - enum CallbackResult { |
| - CALLBACK_FAILURE, |
| - CALLBACK_SUCCESS, |
| - CALLBACK_NOT_CALLED, |
| - }; |
| + using OnConfigurationCallback = base::Callback<void(bool)>; |
| + |
| + ConfigurationWaiter() |
| + : on_configured_callback_(base::Bind(&ConfigurationWaiter::OnConfigured, |
| + base::Unretained(this))), |
| + start_(base::TimeTicks::Now()), |
| + end_(base::TimeTicks::Max()), |
| + callback_result_(CALLBACK_NOT_CALLED), |
| + pending_configuration_(true) { |
| + } |
| + |
| + ~ConfigurationWaiter() = default; |
| + |
| + void Reset() { |
| + start_ = base::TimeTicks::Now(); |
| + end_ = base::TimeTicks::Max(); |
| + callback_result_ = CALLBACK_NOT_CALLED; |
| + pending_configuration_ = true; |
| + } |
| + |
| + base::TimeDelta Wait() { |
|
Daniel Erat
2016/10/21 21:09:45
add WARN_UNUSED_RESULT to make sure callers check
afakhry
2016/10/22 00:28:48
Done.
|
| + if (pending_configuration_) { |
| + base::RunLoop run_loop; |
| + quit_closure_ = run_loop.QuitClosure(); |
| + run_loop.Run(); |
| + } |
| + |
| + return end_ - start_; |
| + } |
| + |
| + const DisplayConfigurator::ConfigurationCallback& |
| + on_configuration_callback() const { |
| + return on_configured_callback_; |
| + } |
| + |
| + CallbackResult callback_result() const { return callback_result_; } |
| + |
| + private: |
| + void OnConfigured(bool status) { |
| + callback_result_ = status ? CALLBACK_SUCCESS : CALLBACK_FAILURE; |
| + |
| + pending_configuration_ = false; |
| + end_ = base::TimeTicks::Now(); |
| + |
| + if (!quit_closure_.is_null()) |
| + base::ResetAndReturn(&quit_closure_).Run(); |
| + } |
| + |
| + const DisplayConfigurator::ConfigurationCallback on_configured_callback_; |
| + |
| + base::TimeTicks start_; |
|
Daniel Erat
2016/10/21 21:09:45
please add comments describing what all of these m
afakhry
2016/10/22 00:28:48
Done.
|
| + base::TimeTicks end_; |
| + base::Closure quit_closure_; |
| + |
| + CallbackResult callback_result_; |
| + bool pending_configuration_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ConfigurationWaiter); |
| +}; |
| + |
| +} // namespace |
| + |
| +class DisplayConfiguratorTest : public testing::Test { |
| + public: |
| DisplayConfiguratorTest() |
| : small_mode_(gfx::Size(1366, 768), false, 60.0f), |
| big_mode_(gfx::Size(2560, 1600), false, 60.0f), |
| @@ -135,7 +203,6 @@ class DisplayConfiguratorTest : public testing::Test { |
| enable_content_protection_status_(0), |
| enable_content_protection_call_count_(0), |
| query_content_protection_call_count_(0), |
| - callback_result_(CALLBACK_NOT_CALLED), |
| display_control_result_(CALLBACK_NOT_CALLED) {} |
| ~DisplayConfiguratorTest() override {} |
| @@ -184,10 +251,6 @@ class DisplayConfiguratorTest : public testing::Test { |
| UpdateOutputs(2, false); |
| } |
| - void OnConfiguredCallback(bool status) { |
| - callback_result_ = (status ? CALLBACK_SUCCESS : CALLBACK_FAILURE); |
| - } |
| - |
| void OnDisplayControlUpdated(bool status) { |
| display_control_result_ = (status ? CALLBACK_SUCCESS : CALLBACK_FAILURE); |
| } |
| @@ -208,6 +271,15 @@ class DisplayConfiguratorTest : public testing::Test { |
| const DisplayMode big_mode_; |
| protected: |
| + // The delay less than which we expect the configuration to be finished. |
| + static const int kMaxShortDelayMs = |
|
Daniel Erat
2016/10/21 21:09:45
make both of these be base::TimeDeltas (possibly n
afakhry
2016/10/22 00:28:48
Great suggestion. Actually, they can even be const
|
| + DisplayConfigurator::kConfigureDelayMs / 3; |
| + |
| + // The minimum configuration delay we expect when resuming while in 2+ display |
| + // mode. |
| + static const int kMinLongDelayMs = |
| + DisplayConfigurator::kResumeConfigureMultiDisplayDelayMs; |
| + |
| // Configures |native_display_delegate_| to return the first |num_outputs| |
| // entries from |
| // |outputs_|. If |send_events| is true, also sends screen-change and |
| @@ -247,10 +319,9 @@ class DisplayConfiguratorTest : public testing::Test { |
| log_->GetActionsAndClear()); |
| } |
| - CallbackResult PopCallbackResult() { |
| - CallbackResult result = callback_result_; |
| - callback_result_ = CALLBACK_NOT_CALLED; |
| - return result; |
| + void ResumeDisplays( |
| + const DisplayConfigurator::ConfigurationCallback& callback) { |
| + configurator_.ResumeDisplaysInternal(callback); |
| } |
| CallbackResult PopDisplayControlResult() { |
| @@ -276,15 +347,12 @@ class DisplayConfiguratorTest : public testing::Test { |
| TestDisplaySnapshot outputs_[3]; |
| - CallbackResult callback_result_; |
| CallbackResult display_control_result_; |
| private: |
| DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorTest); |
| }; |
| -} // namespace |
| - |
| TEST_F(DisplayConfiguratorTest, FindDisplayModeMatchingSize) { |
| std::vector<const DisplayMode*> modes; |
| @@ -669,12 +737,14 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) { |
| // Turning off the internal display should switch the external display to |
| // its native mode. |
| observer_.Reset(); |
| + ConfigurationWaiter config_waiter; |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
|
Daniel Erat
2016/10/21 21:09:45
how about inlining all of these?
EXPECT_LT(config
afakhry
2016/10/22 00:28:48
Done.
|
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -692,12 +762,14 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) { |
| // When all displays are turned off, the framebuffer should switch back |
| // to the mirrored size. |
| observer_.Reset(); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions(kGrab, |
| GetFramebufferAction( |
| @@ -713,12 +785,14 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) { |
| // Turn all displays on and check that mirroring is still used. |
| observer_.Reset(); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -770,12 +844,14 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) { |
| // Turning off the internal display should switch the external display to |
| // its native mode. |
| observer_.Reset(); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -794,12 +870,14 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) { |
| // When all displays are turned off, the framebuffer should switch back |
| // to the extended + software mirroring. |
| observer_.Reset(); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -823,12 +901,14 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) { |
| // Turn all displays on and check that mirroring is still used. |
| observer_.Reset(); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -860,9 +940,11 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) { |
| // was connected while suspended. |
| const gfx::Size framebuffer_size = configurator_.framebuffer_size(); |
| DCHECK(!framebuffer_size.IsEmpty()); |
| - configurator_.SuspendDisplays(base::Bind( |
| - &DisplayConfiguratorTest::OnConfiguredCallback, base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + ConfigurationWaiter config_waiter; |
| + configurator_.SuspendDisplays(config_waiter.on_configuration_callback()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(framebuffer_size.ToString(), |
| configurator_.framebuffer_size().ToString()); |
| EXPECT_EQ( |
| @@ -874,7 +956,13 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) { |
| kSync, |
| NULL), |
| log_->GetActionsAndClear()); |
| - configurator_.ResumeDisplays(); |
| + |
| + // No resume delay in single display mode. |
| + config_waiter.Reset(); |
| + ResumeDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -887,12 +975,14 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) { |
| // Now turn the display off before suspending and check that the |
| // configurator turns it back on and syncs with the server. |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -902,19 +992,28 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) { |
| NULL), |
| log_->GetActionsAndClear()); |
| - configurator_.SuspendDisplays(base::Bind( |
| - &DisplayConfiguratorTest::OnConfiguredCallback, base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.Reset(); |
| + configurator_.SuspendDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(kSync, log_->GetActionsAndClear()); |
| - configurator_.ResumeDisplays(); |
| + config_waiter.Reset(); |
| + ResumeDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -938,12 +1037,16 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) { |
| NULL), |
| log_->GetActionsAndClear()); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, |
| + configurator_.display_state()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -955,22 +1058,37 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) { |
| NULL), |
| log_->GetActionsAndClear()); |
| - configurator_.SuspendDisplays(base::Bind( |
| - &DisplayConfiguratorTest::OnConfiguredCallback, base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + // No delay in suspend. |
| + config_waiter.Reset(); |
| + configurator_.SuspendDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| + EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, |
| + configurator_.current_power_state()); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, |
| + configurator_.display_state()); |
| EXPECT_EQ(kSync, log_->GetActionsAndClear()); |
| // If a display is disconnected while suspended, the configurator should |
| - // pick up the change and only turn on the internal display. |
| + // pick up the change and only turn on the internal display. The should be |
| + // a longer configuration delay when we set the displays back to on. |
| UpdateOutputs(1, false); |
| - configurator_.ResumeDisplays(); |
| + config_waiter.Reset(); |
| + ResumeDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_GE(delay, base::TimeDelta::FromMilliseconds(kMinLongDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -993,19 +1111,23 @@ TEST_F(DisplayConfiguratorTest, Headless) { |
| // Not much should happen when the display power state is changed while |
| // no displays are connected. |
| + ConfigurationWaiter config_waiter; |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear()); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, NULL), |
| log_->GetActionsAndClear()); |
| @@ -1249,9 +1371,11 @@ TEST_F(DisplayConfiguratorTest, DoNotConfigureWithSuspendedDisplays) { |
| // after the displays have been suspended. This event should be ignored since |
| // the DisplayConfigurator will force a probe and reconfiguration of displays |
| // at resume time. |
| - configurator_.SuspendDisplays(base::Bind( |
| - &DisplayConfiguratorTest::OnConfiguredCallback, base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + ConfigurationWaiter config_waiter; |
| + configurator_.SuspendDisplays(config_waiter.on_configuration_callback()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -1270,19 +1394,23 @@ TEST_F(DisplayConfiguratorTest, DoNotConfigureWithSuspendedDisplays) { |
| // Calls to SetDisplayPower should do nothing if the power state doesn't |
| // change. |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -1316,9 +1444,11 @@ TEST_F(DisplayConfiguratorTest, DoNotConfigureWithSuspendedDisplays) { |
| // task should not run either and the timer should be stopped. The displays |
| // should be turned off by suspend. |
| configurator_.OnConfigurationChanged(); |
| - configurator_.SuspendDisplays(base::Bind( |
| - &DisplayConfiguratorTest::OnConfiguredCallback, base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.Reset(); |
| + configurator_.SuspendDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, |
| @@ -1547,12 +1677,14 @@ TEST_F(DisplayConfiguratorTest, SaveDisplayPowerStateOnConfigFailure) { |
| observer_.Reset(); |
| // Turn off the internal display, simulating docked mode. |
| + ConfigurationWaiter config_waiter; |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(1, observer_.num_changes()); |
| EXPECT_EQ(0, observer_.num_failures()); |
| log_->GetActionsAndClear(); |
| @@ -1563,9 +1695,10 @@ TEST_F(DisplayConfiguratorTest, SaveDisplayPowerStateOnConfigFailure) { |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_FAILURE, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_FAILURE, config_waiter.callback_result()); |
| EXPECT_EQ(1, observer_.num_changes()); |
| EXPECT_EQ(1, observer_.num_failures()); |
| log_->GetActionsAndClear(); |
| @@ -1595,12 +1728,14 @@ TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) { |
| observer_.Reset(); |
| // Turn off the internal display, simulating docked mode. |
| + ConfigurationWaiter config_waiter; |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(1, observer_.num_changes()); |
| EXPECT_EQ(0, observer_.num_failures()); |
| EXPECT_EQ( |
| @@ -1618,9 +1753,11 @@ TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) { |
| // Suspend and resume the system. Resuming should restore the previous power |
| // state and force a probe. Suspend should turn off the displays since an |
| // external monitor is connected. |
| - configurator_.SuspendDisplays(base::Bind( |
| - &DisplayConfiguratorTest::OnConfiguredCallback, base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.Reset(); |
| + configurator_.SuspendDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(2, observer_.num_changes()); |
| EXPECT_EQ( |
| JoinActions( |
| @@ -1635,12 +1772,14 @@ TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) { |
| log_->GetActionsAndClear()); |
| // Before the task runs, exit docked mode. |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(3, observer_.num_changes()); |
| EXPECT_EQ(0, observer_.num_failures()); |
| EXPECT_EQ( |
| @@ -1656,7 +1795,13 @@ TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) { |
| log_->GetActionsAndClear()); |
| // Check that the display states are not changed after resuming. |
| - configurator_.ResumeDisplays(); |
| + config_waiter.Reset(); |
| + ResumeDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| + EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |
| + configurator_.current_power_state()); |
| EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |
| } |
| @@ -1696,21 +1841,21 @@ TEST_F(DisplayConfiguratorTest, |
| native_display_delegate_->set_run_async(true); |
| + ConfigurationWaiter config_waiter; |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| + config_waiter.on_configuration_callback()); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| + config_waiter.on_configuration_callback()); |
| - EXPECT_EQ(CALLBACK_NOT_CALLED, PopCallbackResult()); |
| - base::RunLoop().RunUntilIdle(); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + EXPECT_EQ(CALLBACK_NOT_CALLED, config_waiter.callback_result()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(1, observer_.num_changes()); |
| EXPECT_EQ(0, observer_.num_failures()); |
| @@ -1731,9 +1876,11 @@ TEST_F(DisplayConfiguratorTest, |
| kUngrab, NULL), |
| log_->GetActionsAndClear()); |
| + config_waiter.Reset(); |
| EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |
| - base::RunLoop().RunUntilIdle(); |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ(2, observer_.num_changes()); |
| EXPECT_EQ(0, observer_.num_failures()); |
| @@ -1764,13 +1911,14 @@ TEST_F(DisplayConfiguratorTest, |
| // Fail display configuration. |
| native_display_delegate_->set_max_configurable_pixels(-1); |
| + ConfigurationWaiter config_waiter; |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - |
| - EXPECT_EQ(CALLBACK_FAILURE, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_FAILURE, config_waiter.callback_result()); |
| EXPECT_EQ(0, observer_.num_changes()); |
| EXPECT_EQ(1, observer_.num_failures()); |
| @@ -1794,11 +1942,13 @@ TEST_F(DisplayConfiguratorTest, |
| // This configuration should trigger a display configuration since the |
| // previous configuration failed. |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| EXPECT_EQ(0, observer_.num_changes()); |
| EXPECT_EQ(2, observer_.num_failures()); |
| @@ -1884,13 +2034,14 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) { |
| log_->GetActionsAndClear()); |
| // Verify that turning the power off works. |
| + ConfigurationWaiter config_waiter; |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, GetFramebufferAction( |
| @@ -1911,13 +2062,14 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) { |
| kUngrab, NULL), |
| log_->GetActionsAndClear()); |
| + config_waiter.Reset(); |
| configurator_.SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, |
| DisplayConfigurator::kSetDisplayPowerNoFlags, |
| - base::Bind(&DisplayConfiguratorTest::OnConfiguredCallback, |
| - base::Unretained(this))); |
| - |
| - EXPECT_EQ(CALLBACK_SUCCESS, PopCallbackResult()); |
| + config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| EXPECT_EQ( |
| JoinActions( |
| kGrab, GetFramebufferAction( |
| @@ -1957,5 +2109,94 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) { |
| log_->GetActionsAndClear()); |
| } |
| +// Tests the suspend and resume behavior when in dual or multi display modes. |
| +TEST_F(DisplayConfiguratorTest, SuspendResumeWithMultipleDisplays) { |
| + InitWithSingleOutput(); |
| + state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |
| + observer_.Reset(); |
| + UpdateOutputs(2, true); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |
| + configurator_.display_state()); |
| + EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |
| + EXPECT_EQ(1, observer_.num_changes()); |
| + EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |
| + configurator_.current_power_state()); |
| + |
| + // Suspending displays should result in an immediate configuration without |
| + // delays, even in dual display mode. |
| + ConfigurationWaiter config_waiter; |
| + configurator_.SuspendDisplays(config_waiter.on_configuration_callback()); |
| + base::TimeDelta delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| + EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, |
| + configurator_.current_power_state()); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |
| + configurator_.display_state()); |
| + |
| + // Resuming from suspend with dual displays, should be done after a delay, and |
| + // after the configuration we should still expect to be in a dual display |
| + // mode. |
| + config_waiter.Reset(); |
| + ResumeDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_GE(delay, base::TimeDelta::FromMilliseconds(kMinLongDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| + EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |
| + configurator_.current_power_state()); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |
| + configurator_.display_state()); |
| + |
| + // Suspend displays and disconnect one of them while in suspend. |
| + config_waiter.Reset(); |
| + configurator_.SuspendDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |
| + configurator_.display_state()); |
| + EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, |
| + configurator_.current_power_state()); |
| + UpdateOutputs(1, false); |
| + |
| + // Now resume, and expect that we'll still have a long delay since we were in |
| + // dual mode before suspend. The configurator should pick up the change and |
| + // detect that we are in single display mode now. |
| + config_waiter.Reset(); |
| + ResumeDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_GE(delay, base::TimeDelta::FromMilliseconds(kMinLongDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| + EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |
| + configurator_.current_power_state()); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state()); |
| + |
| + // Verify that the above is the exact same behavior for 3+ displays. |
| + UpdateOutputs(3, true); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, |
| + configurator_.display_state()); |
| + // Suspend. |
| + config_waiter.Reset(); |
| + configurator_.SuspendDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_LT(delay, base::TimeDelta::FromMilliseconds(kMaxShortDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, |
| + configurator_.display_state()); |
| + EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, |
| + configurator_.current_power_state()); |
| + |
| + // Resume and expect the correct delay. |
| + config_waiter.Reset(); |
| + ResumeDisplays(config_waiter.on_configuration_callback()); |
| + delay = config_waiter.Wait(); |
| + EXPECT_GE(delay, base::TimeDelta::FromMilliseconds(kMinLongDelayMs)); |
| + EXPECT_EQ(CALLBACK_SUCCESS, config_waiter.callback_result()); |
| + EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |
| + configurator_.current_power_state()); |
| + EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, |
| + configurator_.display_state()); |
| +} |
| + |
| } // namespace test |
| } // namespace ui |