1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/power/renderer_freezer.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "chromeos/dbus/dbus_thread_manager.h"
12 #include "chromeos/dbus/fake_power_manager_client.h"
13 #include "testing/gtest/include/gtest/gtest-death-test.h"
14 #include "testing/gtest/include/gtest/gtest.h"
19 // Class that delegates used in testing can inherit from to record calls that
20 // are made by the code being tested.
21 class ActionRecorder {
24 virtual ~ActionRecorder() {}
26 // Returns a comma-separated string describing the actions that were
27 // requested since the previous call to GetActions() (i.e. results are
29 std::string GetActions() {
30 std::string actions = actions_;
36 // Appends |new_action| to |actions_|, using a comma as a separator if
37 // other actions are already listed.
38 void AppendAction(const std::string& new_action) {
39 if (!actions_.empty())
41 actions_ += new_action;
45 // Comma-separated list of actions that have been performed.
48 DISALLOW_COPY_AND_ASSIGN(ActionRecorder);
51 // Actions that can be returned by TestDelegate::GetActions().
52 const char kFreezeRenderers[] = "freeze_renderers";
53 const char kThawRenderers[] = "thaw_renderers";
54 const char kNoActions[] = "";
56 // Test implementation of RendererFreezer::Delegate that records the actions it
57 // was asked to perform.
58 class TestDelegate : public RendererFreezer::Delegate, public ActionRecorder {
61 : can_freeze_renderers_(true),
62 freeze_renderers_result_(true),
63 thaw_renderers_result_(true) {}
65 virtual ~TestDelegate() {}
67 // RendererFreezer::Delegate overrides.
68 virtual bool FreezeRenderers() override {
69 AppendAction(kFreezeRenderers);
71 return freeze_renderers_result_;
73 virtual bool ThawRenderers() override {
74 AppendAction(kThawRenderers);
76 return thaw_renderers_result_;
78 virtual bool CanFreezeRenderers() override { return can_freeze_renderers_; }
80 void set_freeze_renderers_result(bool result) {
81 freeze_renderers_result_ = result;
84 void set_thaw_renderers_result(bool result) {
85 thaw_renderers_result_ = result;
88 // Sets whether the delegate is capable of freezing renderers. This also
89 // changes |freeze_renderers_result_| and |thaw_renderers_result_|.
90 void set_can_freeze_renderers(bool can_freeze) {
91 can_freeze_renderers_ = can_freeze;
93 // If the delegate cannot freeze renderers, then the result of trying to do
95 freeze_renderers_result_ = can_freeze;
96 thaw_renderers_result_ = can_freeze;
100 bool can_freeze_renderers_;
101 bool freeze_renderers_result_;
102 bool thaw_renderers_result_;
104 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
109 class RendererFreezerTest : public testing::Test {
111 RendererFreezerTest()
112 : power_manager_client_(new FakePowerManagerClient()),
113 test_delegate_(new TestDelegate()) {
114 DBusThreadManager::GetSetterForTesting()->SetPowerManagerClient(
115 scoped_ptr<PowerManagerClient>(power_manager_client_));
118 virtual ~RendererFreezerTest() {
119 renderer_freezer_.reset();
121 DBusThreadManager::Shutdown();
125 renderer_freezer_.reset(new RendererFreezer(
126 scoped_ptr<RendererFreezer::Delegate>(test_delegate_)));
130 FakePowerManagerClient* power_manager_client_;
131 TestDelegate* test_delegate_;
133 scoped_ptr<RendererFreezer> renderer_freezer_;
136 base::MessageLoop message_loop_;
137 DISALLOW_COPY_AND_ASSIGN(RendererFreezerTest);
140 // Tests that the RendererFreezer freezes renderers on suspend and thaws them on
142 TEST_F(RendererFreezerTest, SuspendResume) {
145 power_manager_client_->SendSuspendImminent();
147 // The RendererFreezer should have grabbed an asynchronous callback and done
149 EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
150 EXPECT_EQ(kNoActions, test_delegate_->GetActions());
152 // The RendererFreezer should eventually freeze the renderers and run the
154 base::RunLoop().RunUntilIdle();
155 EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
156 EXPECT_EQ(kFreezeRenderers, test_delegate_->GetActions());
158 // The renderers should be thawed when we resume.
159 power_manager_client_->SendSuspendDone();
160 EXPECT_EQ(kThawRenderers, test_delegate_->GetActions());
163 // Tests that the RendereFreezer doesn't freeze renderers if the suspend attempt
164 // was canceled before it had a chance to complete.
165 TEST_F(RendererFreezerTest, SuspendCanceled) {
168 // We shouldn't do anything yet.
169 power_manager_client_->SendSuspendImminent();
170 EXPECT_EQ(kNoActions, test_delegate_->GetActions());
172 // If a suspend gets canceled for any reason, we should see a SuspendDone().
173 power_manager_client_->SendSuspendDone();
175 // We shouldn't try to freeze the renderers now.
176 base::RunLoop().RunUntilIdle();
177 EXPECT_EQ(kNoActions, test_delegate_->GetActions());
180 // Tests that the renderer freezer does nothing if the delegate cannot freeze
182 TEST_F(RendererFreezerTest, DelegateCannotFreezeRenderers) {
183 test_delegate_->set_can_freeze_renderers(false);
186 power_manager_client_->SendSuspendImminent();
188 // The RendererFreezer should not have grabbed a callback or done anything
190 EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
191 EXPECT_EQ(kNoActions, test_delegate_->GetActions());
193 // There should be nothing in the message loop.
194 base::RunLoop().RunUntilIdle();
195 EXPECT_EQ(kNoActions, test_delegate_->GetActions());
197 // Nothing happens on resume.
198 power_manager_client_->SendSuspendDone();
199 EXPECT_EQ(kNoActions, test_delegate_->GetActions());
202 // Tests that the RendererFreezer does nothing on resume if the freezing
203 // operation was unsuccessful.
204 TEST_F(RendererFreezerTest, ErrorFreezingRenderers) {
206 test_delegate_->set_freeze_renderers_result(false);
208 power_manager_client_->SendSuspendImminent();
209 EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
211 // The freezing operation should fail, but we should still report readiness.
212 base::RunLoop().RunUntilIdle();
213 EXPECT_EQ(kFreezeRenderers, test_delegate_->GetActions());
214 EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
216 // Since the delegate reported that the freezing was unsuccessful, don't do
217 // anything on resume.
218 power_manager_client_->SendSuspendDone();
219 EXPECT_EQ(kNoActions, test_delegate_->GetActions());
222 #if defined(GTEST_HAS_DEATH_TEST)
223 // Tests that the RendererFreezer crashes the browser if the freezing operation
224 // was successful but the thawing operation failed.
225 TEST_F(RendererFreezerTest, ErrorThawingRenderers) {
227 test_delegate_->set_thaw_renderers_result(false);
229 power_manager_client_->SendSuspendImminent();
230 base::RunLoop().RunUntilIdle();
231 EXPECT_EQ(kFreezeRenderers, test_delegate_->GetActions());
233 EXPECT_DEATH(power_manager_client_->SendSuspendDone(), "Unable to thaw");
235 #endif // GTEST_HAS_DEATH_TEST
237 } // namespace chromeos