1 // Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h" 6 7 #include "base/callback.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/message_loop.h" 10 #include "base/task.h" 11 #include "chrome/browser/bookmarks/bookmark_model.h" 12 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/sync/glue/bookmark_data_type_controller.h" 14 #include "chrome/browser/sync/glue/change_processor_mock.h" 15 #include "chrome/browser/sync/glue/model_associator_mock.h" 16 #include "chrome/browser/sync/profile_sync_factory_mock.h" 17 #include "chrome/browser/sync/profile_sync_service_mock.h" 18 #include "chrome/test/profile_mock.h" 19 #include "content/browser/browser_thread.h" 20 #include "content/common/notification_service.h" 21 #include "content/common/notification_source.h" 22 #include "content/common/notification_type.h" 23 #include "testing/gmock/include/gmock/gmock.h" 24 25 using browser_sync::BookmarkDataTypeController; 26 using browser_sync::ChangeProcessorMock; 27 using browser_sync::DataTypeController; 28 using browser_sync::ModelAssociatorMock; 29 using testing::_; 30 using testing::DoAll; 31 using testing::InvokeWithoutArgs; 32 using testing::Return; 33 using testing::SetArgumentPointee; 34 35 class StartCallback { 36 public: 37 MOCK_METHOD2(Run, void(DataTypeController::StartResult result, 38 const tracked_objects::Location& location)); 39 }; 40 41 class BookmarkModelMock : public BookmarkModel { 42 public: 43 BookmarkModelMock() : BookmarkModel(NULL) {} 44 MOCK_METHOD0(IsLoaded, bool()); 45 }; 46 47 class BookmarkDataTypeControllerTest : public testing::Test { 48 public: 49 BookmarkDataTypeControllerTest() 50 : ui_thread_(BrowserThread::UI, &message_loop_) {} 51 52 virtual void SetUp() { 53 model_associator_ = new ModelAssociatorMock(); 54 change_processor_ = new ChangeProcessorMock(); 55 profile_sync_factory_.reset( 56 new ProfileSyncFactoryMock(model_associator_, 57 change_processor_)); 58 bookmark_dtc_ = 59 new BookmarkDataTypeController(profile_sync_factory_.get(), 60 &profile_, 61 &service_); 62 } 63 64 protected: 65 void SetStartExpectations() { 66 EXPECT_CALL(profile_, GetBookmarkModel()). 67 WillOnce(Return(&bookmark_model_)); 68 EXPECT_CALL(bookmark_model_, IsLoaded()).WillRepeatedly(Return(true)); 69 } 70 71 void SetAssociateExpectations() { 72 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()). 73 WillRepeatedly(Return(true)); 74 EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)); 75 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 76 WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true))); 77 EXPECT_CALL(*model_associator_, AssociateModels()). 78 WillRepeatedly(Return(true)); 79 EXPECT_CALL(service_, ActivateDataType(_, _)); 80 } 81 82 void SetStopExpectations() { 83 EXPECT_CALL(service_, DeactivateDataType(_, _)); 84 EXPECT_CALL(*model_associator_, DisassociateModels()); 85 } 86 87 MessageLoopForUI message_loop_; 88 BrowserThread ui_thread_; 89 scoped_refptr<BookmarkDataTypeController> bookmark_dtc_; 90 scoped_ptr<ProfileSyncFactoryMock> profile_sync_factory_; 91 ProfileMock profile_; 92 BookmarkModelMock bookmark_model_; 93 ProfileSyncServiceMock service_; 94 ModelAssociatorMock* model_associator_; 95 ChangeProcessorMock* change_processor_; 96 StartCallback start_callback_; 97 }; 98 99 TEST_F(BookmarkDataTypeControllerTest, StartBookmarkModelReady) { 100 SetStartExpectations(); 101 SetAssociateExpectations(); 102 103 EXPECT_EQ(DataTypeController::NOT_RUNNING, bookmark_dtc_->state()); 104 105 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _)); 106 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 107 EXPECT_EQ(DataTypeController::RUNNING, bookmark_dtc_->state()); 108 } 109 110 TEST_F(BookmarkDataTypeControllerTest, StartBookmarkModelNotReady) { 111 SetStartExpectations(); 112 EXPECT_CALL(bookmark_model_, IsLoaded()).WillRepeatedly(Return(false)); 113 SetAssociateExpectations(); 114 115 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _)); 116 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 117 EXPECT_EQ(DataTypeController::MODEL_STARTING, bookmark_dtc_->state()); 118 119 // Send the notification that the bookmark model has started. 120 NotificationService::current()->Notify( 121 NotificationType::BOOKMARK_MODEL_LOADED, 122 Source<Profile>(&profile_), 123 NotificationService::NoDetails()); 124 EXPECT_EQ(DataTypeController::RUNNING, bookmark_dtc_->state()); 125 } 126 127 TEST_F(BookmarkDataTypeControllerTest, StartFirstRun) { 128 SetStartExpectations(); 129 SetAssociateExpectations(); 130 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 131 WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(true))); 132 EXPECT_CALL(start_callback_, Run(DataTypeController::OK_FIRST_RUN, _)); 133 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 134 } 135 136 TEST_F(BookmarkDataTypeControllerTest, StartBusy) { 137 SetStartExpectations(); 138 EXPECT_CALL(bookmark_model_, IsLoaded()).WillRepeatedly(Return(false)); 139 140 EXPECT_CALL(start_callback_, Run(DataTypeController::BUSY, _)); 141 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 142 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 143 } 144 145 TEST_F(BookmarkDataTypeControllerTest, StartOk) { 146 SetStartExpectations(); 147 SetAssociateExpectations(); 148 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 149 WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true))); 150 151 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _)); 152 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 153 } 154 155 TEST_F(BookmarkDataTypeControllerTest, StartAssociationFailed) { 156 SetStartExpectations(); 157 // Set up association to fail. 158 EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)); 159 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()). 160 WillRepeatedly(Return(true)); 161 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 162 WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true))); 163 EXPECT_CALL(*model_associator_, AssociateModels()). 164 WillRepeatedly(Return(false)); 165 166 EXPECT_CALL(start_callback_, Run(DataTypeController::ASSOCIATION_FAILED, _)); 167 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 168 EXPECT_EQ(DataTypeController::NOT_RUNNING, bookmark_dtc_->state()); 169 } 170 171 TEST_F(BookmarkDataTypeControllerTest, 172 StartAssociationTriggersUnrecoverableError) { 173 SetStartExpectations(); 174 // Set up association to fail with an unrecoverable error. 175 EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)); 176 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()). 177 WillRepeatedly(Return(true)); 178 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 179 WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false))); 180 EXPECT_CALL(start_callback_, Run(DataTypeController::UNRECOVERABLE_ERROR, _)); 181 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 182 EXPECT_EQ(DataTypeController::NOT_RUNNING, bookmark_dtc_->state()); 183 } 184 185 TEST_F(BookmarkDataTypeControllerTest, StartAborted) { 186 SetStartExpectations(); 187 EXPECT_CALL(bookmark_model_, IsLoaded()).WillRepeatedly(Return(false)); 188 189 EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED, _)); 190 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 191 bookmark_dtc_->Stop(); 192 EXPECT_EQ(DataTypeController::NOT_RUNNING, bookmark_dtc_->state()); 193 } 194 195 TEST_F(BookmarkDataTypeControllerTest, Stop) { 196 SetStartExpectations(); 197 SetAssociateExpectations(); 198 SetStopExpectations(); 199 200 EXPECT_EQ(DataTypeController::NOT_RUNNING, bookmark_dtc_->state()); 201 202 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _)); 203 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 204 EXPECT_EQ(DataTypeController::RUNNING, bookmark_dtc_->state()); 205 bookmark_dtc_->Stop(); 206 EXPECT_EQ(DataTypeController::NOT_RUNNING, bookmark_dtc_->state()); 207 } 208 209 TEST_F(BookmarkDataTypeControllerTest, OnUnrecoverableError) { 210 SetStartExpectations(); 211 SetAssociateExpectations(); 212 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 213 WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true))); 214 EXPECT_CALL(service_, OnUnrecoverableError(_,_)). 215 WillOnce(InvokeWithoutArgs(bookmark_dtc_.get(), 216 &BookmarkDataTypeController::Stop)); 217 SetStopExpectations(); 218 219 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _)); 220 bookmark_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 221 // This should cause bookmark_dtc_->Stop() to be called. 222 bookmark_dtc_->OnUnrecoverableError(FROM_HERE, "Test"); 223 } 224