Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / undo / undo_manager_test.cc
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_manager_observer.h"
8 #include "chrome/browser/undo/undo_operation.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace {
12
13 class TestUndoOperation;
14
15 // TestUndoService -------------------------------------------------------------
16
17 class TestUndoService {
18  public:
19   TestUndoService();
20   ~TestUndoService();
21
22   void Redo();
23   void TriggerOperation();
24   void RecordUndoCall();
25
26   UndoManager undo_manager_;
27
28   bool performing_redo_;
29
30   int undo_operation_count_;
31   int redo_operation_count_;
32 };
33
34 // TestUndoOperation -----------------------------------------------------------
35
36 class TestUndoOperation : public UndoOperation {
37  public:
38   explicit TestUndoOperation(TestUndoService* undo_service);
39   virtual ~TestUndoOperation();
40
41   // UndoOperation:
42   virtual void Undo() OVERRIDE;
43   virtual int GetUndoLabelId() const OVERRIDE;
44   virtual int GetRedoLabelId() const OVERRIDE;
45
46  private:
47   TestUndoService* undo_service_;
48
49   DISALLOW_COPY_AND_ASSIGN(TestUndoOperation);
50 };
51
52 TestUndoOperation::TestUndoOperation(TestUndoService* undo_service)
53       : undo_service_(undo_service) {
54 }
55
56 TestUndoOperation::~TestUndoOperation() {
57 }
58
59 void TestUndoOperation::Undo() {
60   undo_service_->TriggerOperation();
61   undo_service_->RecordUndoCall();
62 }
63
64 int TestUndoOperation::GetUndoLabelId() const {
65   return 0;
66 }
67
68 int TestUndoOperation::GetRedoLabelId() const {
69   return 0;
70 }
71
72 // TestUndoService -------------------------------------------------------------
73
74 TestUndoService::TestUndoService() : performing_redo_(false),
75                                      undo_operation_count_(0),
76                                      redo_operation_count_(0) {
77 }
78
79 TestUndoService::~TestUndoService() {
80 }
81
82 void TestUndoService::Redo() {
83   base::AutoReset<bool> incoming_changes(&performing_redo_, true);
84   undo_manager_.Redo();
85 }
86
87 void TestUndoService::TriggerOperation() {
88   scoped_ptr<TestUndoOperation> op(new TestUndoOperation(this));
89   undo_manager_.AddUndoOperation(op.PassAs<UndoOperation>());
90 }
91
92 void TestUndoService::RecordUndoCall() {
93   if (performing_redo_)
94     ++redo_operation_count_;
95   else
96     ++undo_operation_count_;
97 }
98
99 // TestObserver ----------------------------------------------------------------
100
101 class TestObserver : public UndoManagerObserver {
102  public:
103   TestObserver() : state_change_count_(0) {}
104   // Returns the number of state change callbacks
105   int state_change_count() { return state_change_count_; }
106
107   virtual void OnUndoManagerStateChange() OVERRIDE { ++state_change_count_; }
108
109  private:
110   int state_change_count_;
111
112   DISALLOW_COPY_AND_ASSIGN(TestObserver);
113 };
114
115 // Tests -----------------------------------------------------------------------
116
117 TEST(UndoServiceTest, AddUndoActions) {
118   TestUndoService undo_service;
119
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());
124 }
125
126 TEST(UndoServiceTest, UndoMultipleActions) {
127   TestUndoService undo_service;
128
129   undo_service.TriggerOperation();
130   undo_service.TriggerOperation();
131
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());
135
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());
139
140   EXPECT_EQ(2, undo_service.undo_operation_count_);
141   EXPECT_EQ(0, undo_service.redo_operation_count_);
142 }
143
144 TEST(UndoServiceTest, RedoAction) {
145   TestUndoService undo_service;
146
147   undo_service.TriggerOperation();
148
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());
152
153   undo_service.Redo();
154   EXPECT_EQ(1U, undo_service.undo_manager_.undo_count());
155   EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
156
157   EXPECT_EQ(1, undo_service.undo_operation_count_);
158   EXPECT_EQ(1, undo_service.redo_operation_count_);
159 }
160
161 TEST(UndoServiceTest, GroupActions) {
162   TestUndoService undo_service;
163
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();
169
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());
173
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());
177
178   undo_service.Redo();
179   EXPECT_EQ(1U, undo_service.undo_manager_.undo_count());
180   EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
181
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_);
185 }
186
187 TEST(UndoServiceTest, SuspendUndoTracking) {
188   TestUndoService undo_service;
189
190   undo_service.undo_manager_.SuspendUndoTracking();
191   EXPECT_TRUE(undo_service.undo_manager_.IsUndoTrakingSuspended());
192
193   undo_service.TriggerOperation();
194
195   undo_service.undo_manager_.ResumeUndoTracking();
196   EXPECT_FALSE(undo_service.undo_manager_.IsUndoTrakingSuspended());
197
198   EXPECT_EQ(0U, undo_service.undo_manager_.undo_count());
199   EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
200 }
201
202 TEST(UndoServiceTest, RedoEmptyAfterNewAction) {
203   TestUndoService undo_service;
204
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());
209
210   undo_service.TriggerOperation();
211   EXPECT_EQ(1U, undo_service.undo_manager_.undo_count());
212   EXPECT_EQ(0U, undo_service.undo_manager_.redo_count());
213 }
214
215 TEST(UndoServiceTest, GetAllUndoOperations) {
216   TestUndoService undo_service;
217
218   undo_service.TriggerOperation();
219
220   undo_service.undo_manager_.StartGroupingActions();
221   undo_service.TriggerOperation();
222   undo_service.TriggerOperation();
223   undo_service.undo_manager_.EndGroupingActions();
224
225   undo_service.TriggerOperation();
226
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());
230
231   std::vector<UndoOperation*> all_operations =
232       undo_service.undo_manager_.GetAllUndoOperations();
233   EXPECT_EQ(4U, all_operations.size());
234 }
235
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());
241
242   undo_service.TriggerOperation();
243   EXPECT_EQ(1, observer.state_change_count());
244
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());
250
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);
255
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);
260
261   undo_service.undo_manager_.RemoveObserver(&observer);
262   undo_service.undo_manager_.Undo();
263   EXPECT_EQ(callback_count_after_redo, observer.state_change_count());
264 }
265
266 } // namespace