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