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 "components/undo/undo_manager.h"
7 #include "components/undo/undo_manager_observer.h"
8 #include "components/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 ~TestUndoOperation() override
;
43 int GetUndoLabelId() const override
;
44 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 undo_manager_
.AddUndoOperation(make_scoped_ptr(new TestUndoOperation(this)));
91 void TestUndoService::RecordUndoCall() {
93 ++redo_operation_count_
;
95 ++undo_operation_count_
;
98 // TestObserver ----------------------------------------------------------------
100 class TestObserver
: public UndoManagerObserver
{
102 TestObserver() : state_change_count_(0) {}
103 // Returns the number of state change callbacks
104 int state_change_count() { return state_change_count_
; }
106 void OnUndoManagerStateChange() override
{ ++state_change_count_
; }
109 int state_change_count_
;
111 DISALLOW_COPY_AND_ASSIGN(TestObserver
);
114 // Tests -----------------------------------------------------------------------
116 TEST(UndoServiceTest
, AddUndoActions
) {
117 TestUndoService undo_service
;
119 undo_service
.TriggerOperation();
120 undo_service
.TriggerOperation();
121 EXPECT_EQ(2U, undo_service
.undo_manager_
.undo_count());
122 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
125 TEST(UndoServiceTest
, UndoMultipleActions
) {
126 TestUndoService undo_service
;
128 undo_service
.TriggerOperation();
129 undo_service
.TriggerOperation();
131 undo_service
.undo_manager_
.Undo();
132 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
133 EXPECT_EQ(1U, undo_service
.undo_manager_
.redo_count());
135 undo_service
.undo_manager_
.Undo();
136 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
137 EXPECT_EQ(2U, undo_service
.undo_manager_
.redo_count());
139 EXPECT_EQ(2, undo_service
.undo_operation_count_
);
140 EXPECT_EQ(0, undo_service
.redo_operation_count_
);
143 TEST(UndoServiceTest
, RedoAction
) {
144 TestUndoService undo_service
;
146 undo_service
.TriggerOperation();
148 undo_service
.undo_manager_
.Undo();
149 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
150 EXPECT_EQ(1U, undo_service
.undo_manager_
.redo_count());
153 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
154 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
156 EXPECT_EQ(1, undo_service
.undo_operation_count_
);
157 EXPECT_EQ(1, undo_service
.redo_operation_count_
);
160 TEST(UndoServiceTest
, GroupActions
) {
161 TestUndoService undo_service
;
163 // Add two operations in a single action.
164 undo_service
.undo_manager_
.StartGroupingActions();
165 undo_service
.TriggerOperation();
166 undo_service
.TriggerOperation();
167 undo_service
.undo_manager_
.EndGroupingActions();
169 // Check that only one action is created.
170 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
171 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
173 undo_service
.undo_manager_
.Undo();
174 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
175 EXPECT_EQ(1U, undo_service
.undo_manager_
.redo_count());
178 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
179 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
181 // Check that both operations were called in Undo and Redo.
182 EXPECT_EQ(2, undo_service
.undo_operation_count_
);
183 EXPECT_EQ(2, undo_service
.redo_operation_count_
);
186 TEST(UndoServiceTest
, SuspendUndoTracking
) {
187 TestUndoService undo_service
;
189 undo_service
.undo_manager_
.SuspendUndoTracking();
190 EXPECT_TRUE(undo_service
.undo_manager_
.IsUndoTrakingSuspended());
192 undo_service
.TriggerOperation();
194 undo_service
.undo_manager_
.ResumeUndoTracking();
195 EXPECT_FALSE(undo_service
.undo_manager_
.IsUndoTrakingSuspended());
197 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
198 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
201 TEST(UndoServiceTest
, RedoEmptyAfterNewAction
) {
202 TestUndoService undo_service
;
204 undo_service
.TriggerOperation();
205 undo_service
.undo_manager_
.Undo();
206 EXPECT_EQ(0U, undo_service
.undo_manager_
.undo_count());
207 EXPECT_EQ(1U, undo_service
.undo_manager_
.redo_count());
209 undo_service
.TriggerOperation();
210 EXPECT_EQ(1U, undo_service
.undo_manager_
.undo_count());
211 EXPECT_EQ(0U, undo_service
.undo_manager_
.redo_count());
214 TEST(UndoServiceTest
, GetAllUndoOperations
) {
215 TestUndoService undo_service
;
217 undo_service
.TriggerOperation();
219 undo_service
.undo_manager_
.StartGroupingActions();
220 undo_service
.TriggerOperation();
221 undo_service
.TriggerOperation();
222 undo_service
.undo_manager_
.EndGroupingActions();
224 undo_service
.TriggerOperation();
226 undo_service
.undo_manager_
.Undo();
227 ASSERT_EQ(2U, undo_service
.undo_manager_
.undo_count());
228 ASSERT_EQ(1U, undo_service
.undo_manager_
.redo_count());
230 std::vector
<UndoOperation
*> all_operations
=
231 undo_service
.undo_manager_
.GetAllUndoOperations();
232 EXPECT_EQ(4U, all_operations
.size());
235 TEST(UndoServiceTest
, ObserverCallbacks
) {
236 TestObserver observer
;
237 TestUndoService undo_service
;
238 undo_service
.undo_manager_
.AddObserver(&observer
);
239 EXPECT_EQ(0, observer
.state_change_count());
241 undo_service
.TriggerOperation();
242 EXPECT_EQ(1, observer
.state_change_count());
244 undo_service
.undo_manager_
.StartGroupingActions();
245 undo_service
.TriggerOperation();
246 undo_service
.TriggerOperation();
247 undo_service
.undo_manager_
.EndGroupingActions();
248 EXPECT_EQ(2, observer
.state_change_count());
250 // There should be at least 1 observer callback for undo.
251 undo_service
.undo_manager_
.Undo();
252 int callback_count_after_undo
= observer
.state_change_count();
253 EXPECT_GT(callback_count_after_undo
, 2);
255 // There should be at least 1 observer callback for redo.
256 undo_service
.undo_manager_
.Redo();
257 int callback_count_after_redo
= observer
.state_change_count();
258 EXPECT_GT(callback_count_after_redo
, callback_count_after_undo
);
260 undo_service
.undo_manager_
.RemoveObserver(&observer
);
261 undo_service
.undo_manager_
.Undo();
262 EXPECT_EQ(callback_count_after_redo
, observer
.state_change_count());