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.
4
5 #include "base/auto_reset.h"
6 #include "chrome/browser/undo/undo_manager.h"
7 #include "chrome/browser/undo/undo_operation.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 namespace {
11
12 class TestUndoOperation;
13
14 // TestUndoService -------------------------------------------------------------
15
16 class TestUndoService {
17 public:
18 TestUndoService();
19 ~TestUndoService();
20
21 void Redo();
22 void TriggerOperation();
23 void RecordUndoCall();
24
25 UndoManager undo_manager_;
26
27 bool performing_redo_;
28
29 int undo_operation_count_;
30 int redo_operation_count_;
31 };
32
33 // TestUndoOperation -----------------------------------------------------------
34
35 class TestUndoOperation : public UndoOperation {
36 public:
37 explicit TestUndoOperation(TestUndoService* undo_service);
38 virtual ~TestUndoOperation();
39
40 // UndoOperation:
41 virtual void Undo() OVERRIDE;
42
43 private:
44 TestUndoService* undo_service_;
45
46 DISALLOW_COPY_AND_ASSIGN(TestUndoOperation);
47 };
48
TestUndoOperation(TestUndoService * undo_service)49 TestUndoOperation::TestUndoOperation(TestUndoService* undo_service)
50 : undo_service_(undo_service) {
51 }
52
~TestUndoOperation()53 TestUndoOperation::~TestUndoOperation() {
54 }
55
Undo()56 void TestUndoOperation::Undo() {
57 undo_service_->TriggerOperation();
58 undo_service_->RecordUndoCall();
59 }
60
61 // TestUndoService -------------------------------------------------------------
62
TestUndoService()63 TestUndoService::TestUndoService() : performing_redo_(false),
64 undo_operation_count_(0),
65 redo_operation_count_(0) {
66 }
67
~TestUndoService()68 TestUndoService::~TestUndoService() {
69 }
70
Redo()71 void TestUndoService::Redo() {
72 base::AutoReset<bool> incoming_changes(&performing_redo_, true);
73 undo_manager_.Redo();
74 }
75
TriggerOperation()76 void TestUndoService::TriggerOperation() {
77 scoped_ptr<TestUndoOperation> op(new TestUndoOperation(this));
78 undo_manager_.AddUndoOperation(op.PassAs<UndoOperation>());
79 }
80
RecordUndoCall()81 void TestUndoService::RecordUndoCall() {
82 if (performing_redo_)
83 ++redo_operation_count_;
84 else
85 ++undo_operation_count_;
86 }
87
88 // Tests -----------------------------------------------------------------------
89
TEST(UndoServiceTest,AddUndoActions)90 TEST(UndoServiceTest, AddUndoActions) {
91 TestUndoService undo_service;
92
93 undo_service.TriggerOperation();
94 undo_service.TriggerOperation();
95 EXPECT_EQ(2U, undo_service.undo_manager_.undo_count());
96 EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
97 }
98
TEST(UndoServiceTest,UndoMultipleActions)99 TEST(UndoServiceTest, UndoMultipleActions) {
100 TestUndoService undo_service;
101
102 undo_service.TriggerOperation();
103 undo_service.TriggerOperation();
104
105 undo_service.undo_manager_.Undo();
106 EXPECT_EQ(1U, undo_service.undo_manager_.undo_count());
107 EXPECT_EQ(1U, undo_service.undo_manager_.redo_count());
108
109 undo_service.undo_manager_.Undo();
110 EXPECT_EQ(0U, undo_service.undo_manager_.undo_count());
111 EXPECT_EQ(2U, undo_service.undo_manager_.redo_count());
112
113 EXPECT_EQ(2, undo_service.undo_operation_count_);
114 EXPECT_EQ(0, undo_service.redo_operation_count_);
115 }
116
TEST(UndoServiceTest,RedoAction)117 TEST(UndoServiceTest, RedoAction) {
118 TestUndoService undo_service;
119
120 undo_service.TriggerOperation();
121
122 undo_service.undo_manager_.Undo();
123 EXPECT_EQ(0U, undo_service.undo_manager_.undo_count());
124 EXPECT_EQ(1U, undo_service.undo_manager_.redo_count());
125
126 undo_service.Redo();
127 EXPECT_EQ(1U, undo_service.undo_manager_.undo_count());
128 EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
129
130 EXPECT_EQ(1, undo_service.undo_operation_count_);
131 EXPECT_EQ(1, undo_service.redo_operation_count_);
132 }
133
TEST(UndoServiceTest,GroupActions)134 TEST(UndoServiceTest, GroupActions) {
135 TestUndoService undo_service;
136
137 // Add two operations in a single action.
138 undo_service.undo_manager_.StartGroupingActions();
139 undo_service.TriggerOperation();
140 undo_service.TriggerOperation();
141 undo_service.undo_manager_.EndGroupingActions();
142
143 // Check that only one action is created.
144 EXPECT_EQ(1U, undo_service.undo_manager_.undo_count());
145 EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
146
147 undo_service.undo_manager_.Undo();
148 EXPECT_EQ(0U, undo_service.undo_manager_.undo_count());
149 EXPECT_EQ(1U, undo_service.undo_manager_.redo_count());
150
151 undo_service.Redo();
152 EXPECT_EQ(1U, undo_service.undo_manager_.undo_count());
153 EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
154
155 // Check that both operations were called in Undo and Redo.
156 EXPECT_EQ(2, undo_service.undo_operation_count_);
157 EXPECT_EQ(2, undo_service.redo_operation_count_);
158 }
159
TEST(UndoServiceTest,SuspendUndoTracking)160 TEST(UndoServiceTest, SuspendUndoTracking) {
161 TestUndoService undo_service;
162
163 undo_service.undo_manager_.SuspendUndoTracking();
164 EXPECT_TRUE(undo_service.undo_manager_.IsUndoTrakingSuspended());
165
166 undo_service.TriggerOperation();
167
168 undo_service.undo_manager_.ResumeUndoTracking();
169 EXPECT_FALSE(undo_service.undo_manager_.IsUndoTrakingSuspended());
170
171 EXPECT_EQ(0U, undo_service.undo_manager_.undo_count());
172 EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
173 }
174
TEST(UndoServiceTest,RedoEmptyAfterNewAction)175 TEST(UndoServiceTest, RedoEmptyAfterNewAction) {
176 TestUndoService undo_service;
177
178 undo_service.TriggerOperation();
179 undo_service.undo_manager_.Undo();
180 EXPECT_EQ(0U, undo_service.undo_manager_.undo_count());
181 EXPECT_EQ(1U, undo_service.undo_manager_.redo_count());
182
183 undo_service.TriggerOperation();
184 EXPECT_EQ(1U, undo_service.undo_manager_.undo_count());
185 EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
186 }
187
TEST(UndoServiceTest,GetAllUndoOperations)188 TEST(UndoServiceTest, GetAllUndoOperations) {
189 TestUndoService undo_service;
190
191 undo_service.TriggerOperation();
192
193 undo_service.undo_manager_.StartGroupingActions();
194 undo_service.TriggerOperation();
195 undo_service.TriggerOperation();
196 undo_service.undo_manager_.EndGroupingActions();
197
198 undo_service.TriggerOperation();
199
200 undo_service.undo_manager_.Undo();
201 ASSERT_EQ(2U, undo_service.undo_manager_.undo_count());
202 ASSERT_EQ(1U, undo_service.undo_manager_.redo_count());
203
204 std::vector<UndoOperation*> all_operations =
205 undo_service.undo_manager_.GetAllUndoOperations();
206 EXPECT_EQ(4U, all_operations.size());
207 }
208
209 } // namespace
210