Home | History | Annotate | Download | only in undo
      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