1 // Copyright 2013 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 "base/auto_reset.h"
6 #include "chrome/browser/undo/undo_manager.h"
7 #include "chrome/browser/undo/undo_manager_observer.h"
8 #include "chrome/browser/undo/undo_operation.h"
9 #include "testing/gtest/include/gtest/gtest.h"
13 class TestUndoOperation
;
15 // TestUndoService -------------------------------------------------------------
17 class TestUndoService
{
23 void TriggerOperation();
24 void RecordUndoCall();
26 UndoManager undo_manager_
;
28 bool performing_redo_
;
30 int undo_operation_count_
;
31 int redo_operation_count_
;
34 // TestUndoOperation -----------------------------------------------------------
36 class TestUndoOperation
: public UndoOperation
{
38 explicit TestUndoOperation(TestUndoService
* undo_service
);
39 virtual ~TestUndoOperation();
42 virtual void Undo() OVERRIDE
;
43 virtual int GetUndoLabelId() const OVERRIDE
;
44 virtual int GetRedoLabelId() const OVERRIDE
;
47 TestUndoService
* undo_service_
;
49 DISALLOW_COPY_AND_ASSIGN(TestUndoOperation
);
52 TestUndoOperation::TestUndoOperation(TestUndoService
* undo_service
)
53 : undo_service_(undo_service
) {
56 TestUndoOperation::~TestUndoOperation() {
59 void TestUndoOperation::Undo() {
60 undo_service_
->TriggerOperation();
61 undo_service_
->RecordUndoCall();
64 int TestUndoOperation::GetUndoLabelId() const {
68 int TestUndoOperation::GetRedoLabelId() const {
72 // TestUndoService -------------------------------------------------------------
74 TestUndoService::TestUndoService() : performing_redo_(false),
75 undo_operation_count_(0),
76 redo_operation_count_(0) {
79 TestUndoService::~TestUndoService() {
82 void TestUndoService::Redo() {
83 base::AutoReset
<bool> incoming_changes(&performing_redo_
, true);
87 void TestUndoService::TriggerOperation() {
88 scoped_ptr
<TestUndoOperation
> op(new TestUndoOperation(this));
89 undo_manager_
.AddUndoOperation(op
.PassAs
<UndoOperation
>());
92 void TestUndoService::RecordUndoCall() {
94 ++redo_operation_count_
;
96 ++undo_operation_count_
;
99 // TestObserver ----------------------------------------------------------------
101 class TestObserver
: public UndoManagerObserver
{
103 TestObserver() : state_change_count_(0) {}
104 // Returns the number of state change callbacks
105 int state_change_count() { return state_change_count_
; }
107 virtual void OnUndoManagerStateChange() OVERRIDE
{ ++state_change_count_
; }
110 int state_change_count_
;
112 DISALLOW_COPY_AND_ASSIGN(TestObserver
);
115 // Tests -----------------------------------------------------------------------
117 TEST(UndoServiceTest
, AddUndoActions
) {
118 TestUndoService undo_service
;
120 undo_service
.TriggerOperation();
121 undo_service
.TriggerOperation();
122 EXPECT_EQ(2U, undo_service
.undo_manager_
.undo_count());
123 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
126 TEST(UndoServiceTest
, UndoMultipleActions
) {
127 TestUndoService undo_service
;
129 undo_service
.TriggerOperation();
130 undo_service
.TriggerOperation();
132 undo_service
.undo_manager_
.Undo();
133 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
134 EXPECT_EQ(1U, undo_service
.undo_manager_
.redo_count());
136 undo_service
.undo_manager_
.Undo();
137 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
138 EXPECT_EQ(2U, undo_service
.undo_manager_
.redo_count());
140 EXPECT_EQ(2, undo_service
.undo_operation_count_
);
141 EXPECT_EQ(0, undo_service
.redo_operation_count_
);
144 TEST(UndoServiceTest
, RedoAction
) {
145 TestUndoService undo_service
;
147 undo_service
.TriggerOperation();
149 undo_service
.undo_manager_
.Undo();
150 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
151 EXPECT_EQ(1U, undo_service
.undo_manager_
.redo_count());
154 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
155 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
157 EXPECT_EQ(1, undo_service
.undo_operation_count_
);
158 EXPECT_EQ(1, undo_service
.redo_operation_count_
);
161 TEST(UndoServiceTest
, GroupActions
) {
162 TestUndoService undo_service
;
164 // Add two operations in a single action.
165 undo_service
.undo_manager_
.StartGroupingActions();
166 undo_service
.TriggerOperation();
167 undo_service
.TriggerOperation();
168 undo_service
.undo_manager_
.EndGroupingActions();
170 // Check that only one action is created.
171 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
172 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
174 undo_service
.undo_manager_
.Undo();
175 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
176 EXPECT_EQ(1U, undo_service
.undo_manager_
.redo_count());
179 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
180 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
182 // Check that both operations were called in Undo and Redo.
183 EXPECT_EQ(2, undo_service
.undo_operation_count_
);
184 EXPECT_EQ(2, undo_service
.redo_operation_count_
);
187 TEST(UndoServiceTest
, SuspendUndoTracking
) {
188 TestUndoService undo_service
;
190 undo_service
.undo_manager_
.SuspendUndoTracking();
191 EXPECT_TRUE(undo_service
.undo_manager_
.IsUndoTrakingSuspended());
193 undo_service
.TriggerOperation();
195 undo_service
.undo_manager_
.ResumeUndoTracking();
196 EXPECT_FALSE(undo_service
.undo_manager_
.IsUndoTrakingSuspended());
198 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
199 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
202 TEST(UndoServiceTest
, RedoEmptyAfterNewAction
) {
203 TestUndoService undo_service
;
205 undo_service
.TriggerOperation();
206 undo_service
.undo_manager_
.Undo();
207 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
208 EXPECT_EQ(1U, undo_service
.undo_manager_
.redo_count());
210 undo_service
.TriggerOperation();
211 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
212 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
215 TEST(UndoServiceTest
, GetAllUndoOperations
) {
216 TestUndoService undo_service
;
218 undo_service
.TriggerOperation();
220 undo_service
.undo_manager_
.StartGroupingActions();
221 undo_service
.TriggerOperation();
222 undo_service
.TriggerOperation();
223 undo_service
.undo_manager_
.EndGroupingActions();
225 undo_service
.TriggerOperation();
227 undo_service
.undo_manager_
.Undo();
228 ASSERT_EQ(2U, undo_service
.undo_manager_
.undo_count());
229 ASSERT_EQ(1U, undo_service
.undo_manager_
.redo_count());
231 std::vector
<UndoOperation
*> all_operations
=
232 undo_service
.undo_manager_
.GetAllUndoOperations();
233 EXPECT_EQ(4U, all_operations
.size());
236 TEST(UndoServiceTest
, ObserverCallbacks
) {
237 TestObserver observer
;
238 TestUndoService undo_service
;
239 undo_service
.undo_manager_
.AddObserver(&observer
);
240 EXPECT_EQ(0, observer
.state_change_count());
242 undo_service
.TriggerOperation();
243 EXPECT_EQ(1, observer
.state_change_count());
245 undo_service
.undo_manager_
.StartGroupingActions();
246 undo_service
.TriggerOperation();
247 undo_service
.TriggerOperation();
248 undo_service
.undo_manager_
.EndGroupingActions();
249 EXPECT_EQ(2, observer
.state_change_count());
251 // There should be at least 1 observer callback for undo.
252 undo_service
.undo_manager_
.Undo();
253 int callback_count_after_undo
= observer
.state_change_count();
254 EXPECT_GT(callback_count_after_undo
, 2);
256 // There should be at least 1 observer callback for redo.
257 undo_service
.undo_manager_
.Redo();
258 int callback_count_after_redo
= observer
.state_change_count();
259 EXPECT_GT(callback_count_after_redo
, callback_count_after_undo
);
261 undo_service
.undo_manager_
.RemoveObserver(&observer
);
262 undo_service
.undo_manager_
.Undo();
263 EXPECT_EQ(callback_count_after_redo
, observer
.state_change_count());