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 49 TestUndoOperation::TestUndoOperation(TestUndoService* undo_service) 50 : undo_service_(undo_service) { 51 } 52 53 TestUndoOperation::~TestUndoOperation() { 54 } 55 56 void TestUndoOperation::Undo() { 57 undo_service_->TriggerOperation(); 58 undo_service_->RecordUndoCall(); 59 } 60 61 // TestUndoService ------------------------------------------------------------- 62 63 TestUndoService::TestUndoService() : performing_redo_(false), 64 undo_operation_count_(0), 65 redo_operation_count_(0) { 66 } 67 68 TestUndoService::~TestUndoService() { 69 } 70 71 void TestUndoService::Redo() { 72 base::AutoReset<bool> incoming_changes(&performing_redo_, true); 73 undo_manager_.Redo(); 74 } 75 76 void TestUndoService::TriggerOperation() { 77 scoped_ptr<TestUndoOperation> op(new TestUndoOperation(this)); 78 undo_manager_.AddUndoOperation(op.PassAs<UndoOperation>()); 79 } 80 81 void TestUndoService::RecordUndoCall() { 82 if (performing_redo_) 83 ++redo_operation_count_; 84 else 85 ++undo_operation_count_; 86 } 87 88 // Tests ----------------------------------------------------------------------- 89 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 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 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 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 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 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 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