data_type_manager_impl2_unittest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
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 "chrome/browser/sync/glue/data_type_manager_impl2.h" 6 7#include <set> 8 9#include "base/message_loop.h" 10#include "base/scoped_ptr.h" 11#include "base/stl_util-inl.h" 12#include "base/task.h" 13#include "chrome/browser/sync/glue/data_type_controller.h" 14#include "chrome/browser/sync/glue/data_type_controller_mock.h" 15#include "chrome/browser/sync/glue/sync_backend_host_mock.h" 16#include "chrome/browser/sync/profile_sync_test_util.h" 17#include "chrome/browser/sync/syncable/model_type.h" 18#include "content/browser/browser_thread.h" 19#include "content/common/notification_details.h" 20#include "content/common/notification_observer_mock.h" 21#include "content/common/notification_registrar.h" 22#include "content/common/notification_service.h" 23#include "content/common/notification_type.h" 24#include "testing/gmock/include/gmock/gmock.h" 25#include "testing/gtest/include/gtest/gtest.h" 26 27using browser_sync::DataTypeManager; 28using browser_sync::DataTypeManagerImpl2; 29using browser_sync::DataTypeController; 30using browser_sync::DataTypeControllerMock; 31using browser_sync::SyncBackendHostMock; 32using testing::_; 33using testing::DoAll; 34using testing::DoDefault; 35using testing::InSequence; 36using testing::Property; 37using testing::Pointee; 38using testing::Return; 39using testing::SaveArg; 40 41ACTION_P(InvokeCallback, callback_result) { 42 arg0->Run(callback_result); 43 delete arg0; 44} 45 46class DataTypeManagerImpl2Test : public testing::Test { 47 public: 48 DataTypeManagerImpl2Test() 49 : ui_thread_(BrowserThread::UI, &message_loop_) {} 50 51 virtual ~DataTypeManagerImpl2Test() { 52 } 53 54 protected: 55 virtual void SetUp() { 56 registrar_.Add(&observer_, 57 NotificationType::SYNC_CONFIGURE_START, 58 NotificationService::AllSources()); 59 registrar_.Add(&observer_, 60 NotificationType::SYNC_CONFIGURE_DONE, 61 NotificationService::AllSources()); 62 } 63 64 DataTypeControllerMock* MakeBookmarkDTC() { 65 DataTypeControllerMock* dtc = new DataTypeControllerMock(); 66 EXPECT_CALL(*dtc, enabled()).WillRepeatedly(Return(true)); 67 EXPECT_CALL(*dtc, type()).WillRepeatedly(Return(syncable::BOOKMARKS)); 68 EXPECT_CALL(*dtc, name()).WillRepeatedly(Return("bookmark")); 69 return dtc; 70 } 71 72 DataTypeControllerMock* MakePreferenceDTC() { 73 DataTypeControllerMock* dtc = new DataTypeControllerMock(); 74 EXPECT_CALL(*dtc, enabled()).WillRepeatedly(Return(true)); 75 EXPECT_CALL(*dtc, type()).WillRepeatedly(Return(syncable::PREFERENCES)); 76 EXPECT_CALL(*dtc, name()).WillRepeatedly(Return("preference")); 77 return dtc; 78 } 79 80 DataTypeControllerMock* MakePasswordDTC() { 81 DataTypeControllerMock* dtc = new DataTypeControllerMock(); 82 EXPECT_CALL(*dtc, enabled()).WillRepeatedly(Return(true)); 83 EXPECT_CALL(*dtc, type()).WillRepeatedly(Return(syncable::PASSWORDS)); 84 EXPECT_CALL(*dtc, name()).WillRepeatedly(Return("passwords")); 85 return dtc; 86 } 87 88 void SetStartStopExpectations(DataTypeControllerMock* mock_dtc) { 89 InSequence seq; 90 EXPECT_CALL(*mock_dtc, state()). 91 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 92 EXPECT_CALL(*mock_dtc, Start(_)). 93 WillOnce(InvokeCallback((DataTypeController::OK))); 94 EXPECT_CALL(*mock_dtc, state()). 95 WillRepeatedly(Return(DataTypeController::RUNNING)); 96 EXPECT_CALL(*mock_dtc, Stop()).Times(1); 97 EXPECT_CALL(*mock_dtc, state()). 98 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 99 } 100 101 void SetBusyStartStopExpectations(DataTypeControllerMock* mock_dtc, 102 DataTypeController::State busy_state) { 103 InSequence seq; 104 EXPECT_CALL(*mock_dtc, state()). 105 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 106 EXPECT_CALL(*mock_dtc, Start(_)). 107 WillOnce(InvokeCallback((DataTypeController::OK))); 108 EXPECT_CALL(*mock_dtc, state()). 109 WillRepeatedly(Return(busy_state)); 110 EXPECT_CALL(*mock_dtc, Stop()).Times(1); 111 EXPECT_CALL(*mock_dtc, state()). 112 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 113 } 114 115 void SetNotUsedExpectations(DataTypeControllerMock* mock_dtc) { 116 EXPECT_CALL(*mock_dtc, Start(_)).Times(0); 117 EXPECT_CALL(*mock_dtc, Stop()).Times(0); 118 EXPECT_CALL(*mock_dtc, state()). 119 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 120 } 121 122 void SetConfigureStartExpectation() { 123 EXPECT_CALL( 124 observer_, 125 Observe(NotificationType(NotificationType::SYNC_CONFIGURE_START), 126 _, _)); 127 } 128 129 void SetConfigureDoneExpectation(DataTypeManager::ConfigureResult result) { 130 EXPECT_CALL( 131 observer_, 132 Observe(NotificationType(NotificationType::SYNC_CONFIGURE_DONE), _, 133 Property(&Details<DataTypeManager::ConfigureResult>::ptr, 134 Pointee(result)))); 135 } 136 137 MessageLoopForUI message_loop_; 138 BrowserThread ui_thread_; 139 DataTypeController::TypeMap controllers_; 140 SyncBackendHostMock backend_; 141 NotificationObserverMock observer_; 142 NotificationRegistrar registrar_; 143 std::set<syncable::ModelType> types_; 144}; 145 146TEST_F(DataTypeManagerImpl2Test, NoControllers) { 147 DataTypeManagerImpl2 dtm(&backend_, controllers_); 148 SetConfigureStartExpectation(); 149 SetConfigureDoneExpectation(DataTypeManager::OK); 150 dtm.Configure(types_); 151 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 152 dtm.Stop(); 153 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 154} 155 156TEST_F(DataTypeManagerImpl2Test, ConfigureOne) { 157 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 158 SetStartStopExpectations(bookmark_dtc); 159 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 160 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1); 161 DataTypeManagerImpl2 dtm(&backend_, controllers_); 162 types_.insert(syncable::BOOKMARKS); 163 SetConfigureStartExpectation(); 164 SetConfigureDoneExpectation(DataTypeManager::OK); 165 dtm.Configure(types_); 166 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 167 dtm.Stop(); 168 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 169} 170 171TEST_F(DataTypeManagerImpl2Test, ConfigureOneStopWhileStarting) { 172 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 173 SetBusyStartStopExpectations(bookmark_dtc, 174 DataTypeController::MODEL_STARTING); 175 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 176 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1); 177 DataTypeManagerImpl2 dtm(&backend_, controllers_); 178 types_.insert(syncable::BOOKMARKS); 179 SetConfigureStartExpectation(); 180 SetConfigureDoneExpectation(DataTypeManager::OK); 181 dtm.Configure(types_); 182 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 183 dtm.Stop(); 184 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 185} 186 187TEST_F(DataTypeManagerImpl2Test, ConfigureOneStopWhileAssociating) { 188 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 189 SetBusyStartStopExpectations(bookmark_dtc, DataTypeController::ASSOCIATING); 190 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 191 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1); 192 DataTypeManagerImpl2 dtm(&backend_, controllers_); 193 types_.insert(syncable::BOOKMARKS); 194 SetConfigureStartExpectation(); 195 SetConfigureDoneExpectation(DataTypeManager::OK); 196 dtm.Configure(types_); 197 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 198 dtm.Stop(); 199 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 200} 201 202TEST_F(DataTypeManagerImpl2Test, OneWaitingForCrypto) { 203 DataTypeControllerMock* password_dtc = MakePasswordDTC(); 204 EXPECT_CALL(*password_dtc, state()). 205 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 206 EXPECT_CALL(*password_dtc, Start(_)). 207 WillOnce(InvokeCallback((DataTypeController::NEEDS_CRYPTO))); 208 EXPECT_CALL(*password_dtc, state()). 209 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 210 211 controllers_[syncable::PASSWORDS] = password_dtc; 212 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1); 213 214 DataTypeManagerImpl2 dtm(&backend_, controllers_); 215 types_.insert(syncable::PASSWORDS); 216 SetConfigureStartExpectation(); 217 SetConfigureDoneExpectation(DataTypeManager::OK); 218 dtm.Configure(types_); 219 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 220 dtm.Stop(); 221 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 222} 223 224TEST_F(DataTypeManagerImpl2Test, ConfigureOneThenAnother) { 225 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 226 SetStartStopExpectations(bookmark_dtc); 227 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 228 DataTypeControllerMock* preference_dtc = MakePreferenceDTC(); 229 SetStartStopExpectations(preference_dtc); 230 controllers_[syncable::PREFERENCES] = preference_dtc; 231 232 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2); 233 DataTypeManagerImpl2 dtm(&backend_, controllers_); 234 types_.insert(syncable::BOOKMARKS); 235 236 SetConfigureStartExpectation(); 237 SetConfigureDoneExpectation(DataTypeManager::OK); 238 dtm.Configure(types_); 239 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 240 241 types_.insert(syncable::PREFERENCES); 242 SetConfigureStartExpectation(); 243 SetConfigureDoneExpectation(DataTypeManager::OK); 244 dtm.Configure(types_); 245 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 246 247 dtm.Stop(); 248 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 249} 250 251TEST_F(DataTypeManagerImpl2Test, ConfigureOneThenSwitch) { 252 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 253 SetStartStopExpectations(bookmark_dtc); 254 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 255 DataTypeControllerMock* preference_dtc = MakePreferenceDTC(); 256 SetStartStopExpectations(preference_dtc); 257 controllers_[syncable::PREFERENCES] = preference_dtc; 258 259 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2); 260 DataTypeManagerImpl2 dtm(&backend_, controllers_); 261 types_.insert(syncable::BOOKMARKS); 262 263 SetConfigureStartExpectation(); 264 SetConfigureDoneExpectation(DataTypeManager::OK); 265 dtm.Configure(types_); 266 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 267 268 types_.clear(); 269 types_.insert(syncable::PREFERENCES); 270 SetConfigureStartExpectation(); 271 SetConfigureDoneExpectation(DataTypeManager::OK); 272 dtm.Configure(types_); 273 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 274 275 dtm.Stop(); 276 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 277} 278 279TEST_F(DataTypeManagerImpl2Test, ConfigureWhileOneInFlight) { 280 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 281 // Save the callback here so we can interrupt startup. 282 DataTypeController::StartCallback* callback; 283 { 284 InSequence seq; 285 EXPECT_CALL(*bookmark_dtc, state()). 286 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 287 EXPECT_CALL(*bookmark_dtc, Start(_)). 288 WillOnce(SaveArg<0>(&callback)); 289 EXPECT_CALL(*bookmark_dtc, state()). 290 WillRepeatedly(Return(DataTypeController::RUNNING)); 291 EXPECT_CALL(*bookmark_dtc, Stop()).Times(1); 292 EXPECT_CALL(*bookmark_dtc, state()). 293 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 294 } 295 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 296 297 DataTypeControllerMock* preference_dtc = MakePreferenceDTC(); 298 SetStartStopExpectations(preference_dtc); 299 controllers_[syncable::PREFERENCES] = preference_dtc; 300 301 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2); 302 DataTypeManagerImpl2 dtm(&backend_, controllers_); 303 types_.insert(syncable::BOOKMARKS); 304 305 SetConfigureStartExpectation(); 306 SetConfigureDoneExpectation(DataTypeManager::OK); 307 dtm.Configure(types_); 308 309 // At this point, the bookmarks dtc should be in flight. Add 310 // preferences and continue starting bookmarks. 311 types_.insert(syncable::PREFERENCES); 312 dtm.Configure(types_); 313 callback->Run(DataTypeController::OK); 314 delete callback; 315 316 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 317 318 dtm.Stop(); 319 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 320} 321 322TEST_F(DataTypeManagerImpl2Test, OneFailingController) { 323 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 324 EXPECT_CALL(*bookmark_dtc, Start(_)). 325 WillOnce(InvokeCallback((DataTypeController::ASSOCIATION_FAILED))); 326 EXPECT_CALL(*bookmark_dtc, Stop()).Times(0); 327 EXPECT_CALL(*bookmark_dtc, state()). 328 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 329 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 330 331 DataTypeManagerImpl2 dtm(&backend_, controllers_); 332 SetConfigureStartExpectation(); 333 SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED); 334 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1); 335 336 types_.insert(syncable::BOOKMARKS); 337 dtm.Configure(types_); 338 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 339} 340 341TEST_F(DataTypeManagerImpl2Test, StopWhileInFlight) { 342 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 343 SetStartStopExpectations(bookmark_dtc); 344 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 345 346 DataTypeControllerMock* preference_dtc = MakePreferenceDTC(); 347 // Save the callback here so we can interrupt startup. 348 DataTypeController::StartCallback* callback; 349 EXPECT_CALL(*preference_dtc, Start(_)). 350 WillOnce(SaveArg<0>(&callback)); 351 EXPECT_CALL(*preference_dtc, Stop()).Times(1); 352 EXPECT_CALL(*preference_dtc, state()). 353 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 354 controllers_[syncable::PREFERENCES] = preference_dtc; 355 356 DataTypeManagerImpl2 dtm(&backend_, controllers_); 357 SetConfigureStartExpectation(); 358 SetConfigureDoneExpectation(DataTypeManager::ABORTED); 359 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1); 360 361 types_.insert(syncable::BOOKMARKS); 362 types_.insert(syncable::PREFERENCES); 363 dtm.Configure(types_); 364 // Configure should stop in the CONFIGURING state because we are 365 // waiting for the preferences callback to be invoked. 366 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm.state()); 367 368 // Call stop before the preference callback is invoked. 369 dtm.Stop(); 370 callback->Run(DataTypeController::ABORTED); 371 delete callback; 372 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 373} 374 375TEST_F(DataTypeManagerImpl2Test, SecondControllerFails) { 376 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 377 SetStartStopExpectations(bookmark_dtc); 378 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 379 380 DataTypeControllerMock* preference_dtc = MakePreferenceDTC(); 381 EXPECT_CALL(*preference_dtc, Start(_)). 382 WillOnce(InvokeCallback((DataTypeController::ASSOCIATION_FAILED))); 383 EXPECT_CALL(*preference_dtc, Stop()).Times(0); 384 EXPECT_CALL(*preference_dtc, state()). 385 WillRepeatedly(Return(DataTypeController::NOT_RUNNING)); 386 controllers_[syncable::PREFERENCES] = preference_dtc; 387 388 DataTypeManagerImpl2 dtm(&backend_, controllers_); 389 SetConfigureStartExpectation(); 390 SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED); 391 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1); 392 393 types_.insert(syncable::BOOKMARKS); 394 types_.insert(syncable::PREFERENCES); 395 dtm.Configure(types_); 396 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 397} 398 399TEST_F(DataTypeManagerImpl2Test, ConfigureWhileDownloadPending) { 400 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 401 SetStartStopExpectations(bookmark_dtc); 402 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 403 404 DataTypeControllerMock* preference_dtc = MakePreferenceDTC(); 405 SetStartStopExpectations(preference_dtc); 406 controllers_[syncable::PREFERENCES] = preference_dtc; 407 408 DataTypeManagerImpl2 dtm(&backend_, controllers_); 409 SetConfigureStartExpectation(); 410 SetConfigureDoneExpectation(DataTypeManager::OK); 411 CancelableTask* task; 412 // Grab the task the first time this is called so we can configure 413 // before it is finished. 414 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)). 415 WillOnce(SaveArg<2>(&task)). 416 WillOnce(DoDefault()); 417 418 types_.insert(syncable::BOOKMARKS); 419 dtm.Configure(types_); 420 // Configure should stop in the DOWNLOAD_PENDING state because we 421 // are waiting for the download ready task to be run. 422 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm.state()); 423 424 types_.insert(syncable::PREFERENCES); 425 dtm.Configure(types_); 426 427 // Should now be RESTARTING. 428 EXPECT_EQ(DataTypeManager::RESTARTING, dtm.state()); 429 430 // Running the task will queue a restart task to the message loop, and 431 // eventually get us configured. 432 task->Run(); 433 delete task; 434 EXPECT_EQ(DataTypeManager::RESTARTING, dtm.state()); 435 MessageLoop::current()->RunAllPending(); 436 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); 437 438 dtm.Stop(); 439 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 440} 441 442TEST_F(DataTypeManagerImpl2Test, StopWhileDownloadPending) { 443 DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); 444 SetNotUsedExpectations(bookmark_dtc); 445 controllers_[syncable::BOOKMARKS] = bookmark_dtc; 446 447 DataTypeManagerImpl2 dtm(&backend_, controllers_); 448 SetConfigureStartExpectation(); 449 SetConfigureDoneExpectation(DataTypeManager::ABORTED); 450 CancelableTask* task; 451 // Grab the task the first time this is called so we can stop 452 // before it is finished. 453 EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)). 454 WillOnce(SaveArg<2>(&task)); 455 456 types_.insert(syncable::BOOKMARKS); 457 dtm.Configure(types_); 458 // Configure should stop in the DOWNLOAD_PENDING state because we 459 // are waiting for the download ready task to be run. 460 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm.state()); 461 462 dtm.Stop(); 463 EXPECT_EQ(DataTypeManager::STOPPED, dtm.state()); 464 465 // It should be perfectly safe to run this task even though the DTM 466 // has been stopped. 467 task->Run(); 468 delete task; 469} 470