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 "base/tracked_objects.h" 12 #include "chrome/browser/sync/glue/change_processor_mock.h" 13 #include "chrome/browser/sync/glue/frontend_data_type_controller.h" 14 #include "chrome/browser/sync/glue/frontend_data_type_controller_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 21 using browser_sync::ChangeProcessorMock; 22 using browser_sync::DataTypeController; 23 using browser_sync::FrontendDataTypeController; 24 using browser_sync::FrontendDataTypeControllerMock; 25 using browser_sync::ModelAssociatorMock; 26 using testing::_; 27 using testing::DoAll; 28 using testing::InvokeWithoutArgs; 29 using testing::Return; 30 using testing::SetArgumentPointee; 31 using testing::StrictMock; 32 33 class StartCallback { 34 public: 35 MOCK_METHOD2(Run, void(DataTypeController::StartResult result, 36 const tracked_objects::Location& from_here)); 37 }; 38 39 class FrontendDataTypeControllerFake : public FrontendDataTypeController { 40 public: 41 FrontendDataTypeControllerFake( 42 ProfileSyncFactory* profile_sync_factory, 43 Profile* profile, 44 ProfileSyncService* sync_service, 45 FrontendDataTypeControllerMock* mock) 46 : FrontendDataTypeController(profile_sync_factory, 47 profile, 48 sync_service), 49 mock_(mock) {} 50 virtual syncable::ModelType type() const { return syncable::BOOKMARKS; } 51 52 private: 53 virtual void CreateSyncComponents() { 54 ProfileSyncFactory::SyncComponents sync_components = 55 profile_sync_factory_-> 56 CreateBookmarkSyncComponents(sync_service_, this); 57 model_associator_.reset(sync_components.model_associator); 58 change_processor_.reset(sync_components.change_processor); 59 } 60 61 // We mock the following methods because their default implementations do 62 // nothing, but we still want to make sure they're called appropriately. 63 virtual bool StartModels() { 64 return mock_->StartModels(); 65 } 66 virtual void CleanupState() { 67 mock_->CleanupState(); 68 } 69 virtual void RecordUnrecoverableError( 70 const tracked_objects::Location& from_here, 71 const std::string& message) { 72 mock_->RecordUnrecoverableError(from_here, message); 73 } 74 virtual void RecordAssociationTime(base::TimeDelta time) { 75 mock_->RecordAssociationTime(time); 76 } 77 virtual void RecordStartFailure(DataTypeController::StartResult result) { 78 mock_->RecordStartFailure(result); 79 } 80 private: 81 FrontendDataTypeControllerMock* mock_; 82 }; 83 84 class FrontendDataTypeControllerTest : public testing::Test { 85 public: 86 FrontendDataTypeControllerTest() 87 : ui_thread_(BrowserThread::UI, &message_loop_) {} 88 89 virtual void SetUp() { 90 profile_sync_factory_.reset(new ProfileSyncFactoryMock()); 91 dtc_mock_ = new StrictMock<FrontendDataTypeControllerMock>(); 92 frontend_dtc_ = 93 new FrontendDataTypeControllerFake(profile_sync_factory_.get(), 94 &profile_, 95 &service_, 96 dtc_mock_.get()); 97 } 98 99 protected: 100 void SetStartExpectations() { 101 EXPECT_CALL(*dtc_mock_, StartModels()).WillOnce(Return(true)); 102 model_associator_ = new ModelAssociatorMock(); 103 change_processor_ = new ChangeProcessorMock(); 104 EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)). 105 WillOnce(Return(ProfileSyncFactory::SyncComponents(model_associator_, 106 change_processor_))); 107 } 108 109 void SetAssociateExpectations() { 110 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()). 111 WillOnce(Return(true)); 112 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 113 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true))); 114 EXPECT_CALL(*model_associator_, AssociateModels()). 115 WillOnce(Return(true)); 116 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_)); 117 } 118 119 void SetActivateExpectations(DataTypeController::StartResult result) { 120 EXPECT_CALL(service_, ActivateDataType(_, _)); 121 EXPECT_CALL(start_callback_, Run(result,_)); 122 } 123 124 void SetStopExpectations() { 125 EXPECT_CALL(*dtc_mock_, CleanupState()); 126 EXPECT_CALL(service_, DeactivateDataType(_, _)); 127 EXPECT_CALL(*model_associator_, DisassociateModels()); 128 } 129 130 void SetStartFailExpectations(DataTypeController::StartResult result) { 131 EXPECT_CALL(*dtc_mock_, CleanupState()); 132 EXPECT_CALL(*dtc_mock_, RecordStartFailure(result)); 133 EXPECT_CALL(start_callback_, Run(result,_)); 134 } 135 136 MessageLoopForUI message_loop_; 137 BrowserThread ui_thread_; 138 scoped_refptr<FrontendDataTypeControllerFake> frontend_dtc_; 139 scoped_ptr<ProfileSyncFactoryMock> profile_sync_factory_; 140 scoped_refptr<FrontendDataTypeControllerMock> dtc_mock_; 141 ProfileMock profile_; 142 ProfileSyncServiceMock service_; 143 ModelAssociatorMock* model_associator_; 144 ChangeProcessorMock* change_processor_; 145 StartCallback start_callback_; 146 }; 147 148 TEST_F(FrontendDataTypeControllerTest, StartOk) { 149 SetStartExpectations(); 150 SetAssociateExpectations(); 151 SetActivateExpectations(DataTypeController::OK); 152 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 153 frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 154 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state()); 155 } 156 157 TEST_F(FrontendDataTypeControllerTest, StartFirstRun) { 158 SetStartExpectations(); 159 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()). 160 WillOnce(Return(true)); 161 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 162 WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true))); 163 EXPECT_CALL(*model_associator_, AssociateModels()). 164 WillOnce(Return(true)); 165 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_)); 166 SetActivateExpectations(DataTypeController::OK_FIRST_RUN); 167 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 168 frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 169 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state()); 170 } 171 172 TEST_F(FrontendDataTypeControllerTest, StartAssociationFailed) { 173 SetStartExpectations(); 174 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()). 175 WillOnce(Return(true)); 176 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 177 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true))); 178 EXPECT_CALL(*model_associator_, AssociateModels()). 179 WillOnce(Return(false)); 180 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_)); 181 SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED); 182 // Set up association to fail with an association failed error. 183 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 184 frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 185 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 186 } 187 188 TEST_F(FrontendDataTypeControllerTest, 189 StartAssociationTriggersUnrecoverableError) { 190 SetStartExpectations(); 191 SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR); 192 // Set up association to fail with an unrecoverable error. 193 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()). 194 WillRepeatedly(Return(true)); 195 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)). 196 WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false))); 197 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 198 frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 199 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 200 } 201 202 TEST_F(FrontendDataTypeControllerTest, StartAssociationCryptoNotReady) { 203 SetStartExpectations(); 204 SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO); 205 // Set up association to fail with a NEEDS_CRYPTO error. 206 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()). 207 WillRepeatedly(Return(false)); 208 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 209 frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 210 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 211 } 212 213 TEST_F(FrontendDataTypeControllerTest, Stop) { 214 SetStartExpectations(); 215 SetAssociateExpectations(); 216 SetActivateExpectations(DataTypeController::OK); 217 SetStopExpectations(); 218 219 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 220 frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 221 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state()); 222 frontend_dtc_->Stop(); 223 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 224 } 225 226 TEST_F(FrontendDataTypeControllerTest, OnUnrecoverableError) { 227 SetStartExpectations(); 228 SetAssociateExpectations(); 229 SetActivateExpectations(DataTypeController::OK); 230 EXPECT_CALL(*dtc_mock_, RecordUnrecoverableError(_, "Test")); 231 EXPECT_CALL(service_, OnUnrecoverableError(_,_)). 232 WillOnce(InvokeWithoutArgs(frontend_dtc_.get(), 233 &FrontendDataTypeController::Stop)); 234 SetStopExpectations(); 235 236 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 237 frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run)); 238 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state()); 239 // This should cause frontend_dtc_->Stop() to be called. 240 frontend_dtc_->OnUnrecoverableError(FROM_HERE, "Test"); 241 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state()); 242 } 243