model_association_manager_unittest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1// Copyright 2014 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/callback.h" 6#include "base/message_loop/message_loop.h" 7#include "components/sync_driver/fake_data_type_controller.h" 8#include "components/sync_driver/model_association_manager.h" 9#include "testing/gmock/include/gmock/gmock.h" 10#include "testing/gtest/include/gtest/gtest.h" 11 12using ::testing::_; 13 14namespace sync_driver { 15 16class MockModelAssociationManagerDelegate : 17 public ModelAssociationManagerDelegate { 18 public: 19 MockModelAssociationManagerDelegate() {} 20 ~MockModelAssociationManagerDelegate() {} 21 MOCK_METHOD2(OnSingleDataTypeAssociationDone, 22 void(syncer::ModelType type, 23 const syncer::DataTypeAssociationStats& association_stats)); 24 MOCK_METHOD1(OnSingleDataTypeWillStop, void(syncer::ModelType)); 25 MOCK_METHOD1(OnModelAssociationDone, void( 26 const DataTypeManager::ConfigureResult& result)); 27}; 28 29FakeDataTypeController* GetController( 30 const DataTypeController::TypeMap& controllers, 31 syncer::ModelType model_type) { 32 DataTypeController::TypeMap::const_iterator it = 33 controllers.find(model_type); 34 if (it == controllers.end()) { 35 return NULL; 36 } 37 return (FakeDataTypeController*)(it->second.get()); 38} 39 40ACTION_P(VerifyResult, expected_result) { 41 EXPECT_EQ(arg0.status, expected_result.status); 42 EXPECT_TRUE(arg0.requested_types.Equals(expected_result.requested_types)); 43 EXPECT_EQ(arg0.failed_data_types.size(), 44 expected_result.failed_data_types.size()); 45 46 if (arg0.failed_data_types.size() == 47 expected_result.failed_data_types.size()) { 48 std::map<syncer::ModelType, syncer::SyncError>::const_iterator it1, it2; 49 for (it1 = arg0.failed_data_types.begin(), 50 it2 = expected_result.failed_data_types.begin(); 51 it1 != arg0.failed_data_types.end(); 52 ++it1, ++it2) { 53 EXPECT_EQ((*it1).first, (*it2).first); 54 } 55 } 56 57 EXPECT_TRUE(arg0.unfinished_data_types.Equals( 58 expected_result.unfinished_data_types)); 59} 60 61class SyncModelAssociationManagerTest : public testing::Test { 62 public: 63 SyncModelAssociationManagerTest() { 64 } 65 66 protected: 67 base::MessageLoopForUI ui_loop_; 68 MockModelAssociationManagerDelegate delegate_; 69 DataTypeController::TypeMap controllers_; 70}; 71 72// Start a type and make sure ModelAssociationManager callst the |Start| 73// method and calls the callback when it is done. 74TEST_F(SyncModelAssociationManagerTest, SimpleModelStart) { 75 controllers_[syncer::BOOKMARKS] = 76 new FakeDataTypeController(syncer::BOOKMARKS); 77 controllers_[syncer::APPS] = 78 new FakeDataTypeController(syncer::APPS); 79 ModelAssociationManager model_association_manager(&controllers_, 80 &delegate_); 81 syncer::ModelTypeSet types(syncer::BOOKMARKS, syncer::APPS); 82 DataTypeManager::ConfigureResult expected_result( 83 DataTypeManager::OK, 84 types, 85 std::map<syncer::ModelType, syncer::SyncError>(), 86 syncer::ModelTypeSet(), 87 syncer::ModelTypeSet()); 88 EXPECT_CALL(delegate_, OnModelAssociationDone(_)). 89 WillOnce(VerifyResult(expected_result)); 90 91 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 92 DataTypeController::NOT_RUNNING); 93 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), 94 DataTypeController::NOT_RUNNING); 95 96 // Initialize() kicks off model loading. 97 model_association_manager.Initialize(types); 98 99 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 100 DataTypeController::MODEL_LOADED); 101 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), 102 DataTypeController::MODEL_LOADED); 103 104 model_association_manager.StartAssociationAsync(types); 105 106 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 107 DataTypeController::ASSOCIATING); 108 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), 109 DataTypeController::ASSOCIATING); 110 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( 111 DataTypeController::OK); 112 GetController(controllers_, syncer::APPS)->FinishStart( 113 DataTypeController::OK); 114} 115 116// Start a type and call stop before it finishes associating. 117TEST_F(SyncModelAssociationManagerTest, StopModelBeforeFinish) { 118 controllers_[syncer::BOOKMARKS] = 119 new FakeDataTypeController(syncer::BOOKMARKS); 120 ModelAssociationManager model_association_manager( 121 &controllers_, 122 &delegate_); 123 124 syncer::ModelTypeSet types; 125 types.Put(syncer::BOOKMARKS); 126 127 std::map<syncer::ModelType, syncer::SyncError> errors; 128 syncer::SyncError error(FROM_HERE, 129 syncer::SyncError::DATATYPE_ERROR, 130 "Failed", 131 syncer::BOOKMARKS); 132 errors[syncer::BOOKMARKS] = error; 133 134 DataTypeManager::ConfigureResult expected_result( 135 DataTypeManager::ABORTED, 136 types, 137 errors, 138 syncer::ModelTypeSet(syncer::BOOKMARKS), 139 syncer::ModelTypeSet()); 140 141 EXPECT_CALL(delegate_, OnModelAssociationDone(_)). 142 WillOnce(VerifyResult(expected_result)); 143 EXPECT_CALL(delegate_, 144 OnSingleDataTypeWillStop(syncer::BOOKMARKS)); 145 146 model_association_manager.Initialize(types); 147 model_association_manager.StartAssociationAsync(types); 148 149 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 150 DataTypeController::ASSOCIATING); 151 model_association_manager.Stop(); 152 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 153 DataTypeController::NOT_RUNNING); 154} 155 156// Start a type, let it finish and then call stop. 157TEST_F(SyncModelAssociationManagerTest, StopAfterFinish) { 158 controllers_[syncer::BOOKMARKS] = 159 new FakeDataTypeController(syncer::BOOKMARKS); 160 ModelAssociationManager model_association_manager( 161 &controllers_, 162 &delegate_); 163 syncer::ModelTypeSet types; 164 types.Put(syncer::BOOKMARKS); 165 DataTypeManager::ConfigureResult expected_result( 166 DataTypeManager::OK, 167 types, 168 std::map<syncer::ModelType, syncer::SyncError>(), 169 syncer::ModelTypeSet(), 170 syncer::ModelTypeSet()); 171 EXPECT_CALL(delegate_, OnModelAssociationDone(_)). 172 WillOnce(VerifyResult(expected_result)); 173 EXPECT_CALL(delegate_, 174 OnSingleDataTypeWillStop(syncer::BOOKMARKS)); 175 176 model_association_manager.Initialize(types); 177 model_association_manager.StartAssociationAsync(types); 178 179 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 180 DataTypeController::ASSOCIATING); 181 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( 182 DataTypeController::OK); 183 184 model_association_manager.Stop(); 185 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 186 DataTypeController::NOT_RUNNING); 187} 188 189// Make a type fail model association and verify correctness. 190TEST_F(SyncModelAssociationManagerTest, TypeFailModelAssociation) { 191 controllers_[syncer::BOOKMARKS] = 192 new FakeDataTypeController(syncer::BOOKMARKS); 193 ModelAssociationManager model_association_manager( 194 &controllers_, 195 &delegate_); 196 syncer::ModelTypeSet types; 197 types.Put(syncer::BOOKMARKS); 198 std::map<syncer::ModelType, syncer::SyncError> errors; 199 syncer::SyncError error(FROM_HERE, 200 syncer::SyncError::DATATYPE_ERROR, 201 "Failed", 202 syncer::BOOKMARKS); 203 errors[syncer::BOOKMARKS] = error; 204 DataTypeManager::ConfigureResult expected_result( 205 DataTypeManager::PARTIAL_SUCCESS, 206 types, 207 errors, 208 syncer::ModelTypeSet(), 209 syncer::ModelTypeSet()); 210 EXPECT_CALL(delegate_, OnModelAssociationDone(_)). 211 WillOnce(VerifyResult(expected_result)); 212 213 model_association_manager.Initialize(types); 214 model_association_manager.StartAssociationAsync(types); 215 216 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 217 DataTypeController::ASSOCIATING); 218 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( 219 DataTypeController::ASSOCIATION_FAILED); 220 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 221 DataTypeController::NOT_RUNNING); 222} 223 224// Ensure configuring stops when a type returns a unrecoverable error. 225TEST_F(SyncModelAssociationManagerTest, TypeReturnUnrecoverableError) { 226 controllers_[syncer::BOOKMARKS] = 227 new FakeDataTypeController(syncer::BOOKMARKS); 228 ModelAssociationManager model_association_manager( 229 &controllers_, 230 &delegate_); 231 syncer::ModelTypeSet types; 232 types.Put(syncer::BOOKMARKS); 233 std::map<syncer::ModelType, syncer::SyncError> errors; 234 syncer::SyncError error(FROM_HERE, 235 syncer::SyncError::DATATYPE_ERROR, 236 "Failed", 237 syncer::BOOKMARKS); 238 errors[syncer::BOOKMARKS] = error; 239 DataTypeManager::ConfigureResult expected_result( 240 DataTypeManager::UNRECOVERABLE_ERROR, 241 types, 242 errors, 243 syncer::ModelTypeSet(), 244 syncer::ModelTypeSet()); 245 EXPECT_CALL(delegate_, OnModelAssociationDone(_)). 246 WillOnce(VerifyResult(expected_result)); 247 248 model_association_manager.Initialize(types); 249 250 model_association_manager.StartAssociationAsync(types); 251 252 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 253 DataTypeController::ASSOCIATING); 254 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( 255 DataTypeController::UNRECOVERABLE_ERROR); 256} 257 258TEST_F(SyncModelAssociationManagerTest, SlowTypeAsFailedType) { 259 controllers_[syncer::BOOKMARKS] = 260 new FakeDataTypeController(syncer::BOOKMARKS); 261 controllers_[syncer::APPS] = 262 new FakeDataTypeController(syncer::APPS); 263 GetController(controllers_, syncer::BOOKMARKS)->SetDelayModelLoad(); 264 ModelAssociationManager model_association_manager(&controllers_, 265 &delegate_); 266 syncer::ModelTypeSet types; 267 types.Put(syncer::BOOKMARKS); 268 types.Put(syncer::APPS); 269 270 std::map<syncer::ModelType, syncer::SyncError> errors; 271 syncer::SyncError error(FROM_HERE, 272 syncer::SyncError::DATATYPE_ERROR, 273 "Association timed out.", 274 syncer::BOOKMARKS); 275 errors[syncer::BOOKMARKS] = error; 276 277 syncer::ModelTypeSet expected_types_unfinished; 278 expected_types_unfinished.Put(syncer::BOOKMARKS); 279 DataTypeManager::ConfigureResult expected_result_partially_done( 280 DataTypeManager::PARTIAL_SUCCESS, 281 types, 282 errors, 283 expected_types_unfinished, 284 syncer::ModelTypeSet()); 285 286 EXPECT_CALL(delegate_, OnModelAssociationDone(_)). 287 WillOnce(VerifyResult(expected_result_partially_done)); 288 289 model_association_manager.Initialize(types); 290 model_association_manager.StartAssociationAsync(types); 291 GetController(controllers_, syncer::APPS)->FinishStart( 292 DataTypeController::OK); 293 294 model_association_manager.GetTimerForTesting()->user_task().Run(); 295 296 EXPECT_EQ(DataTypeController::NOT_RUNNING, 297 GetController(controllers_, syncer::BOOKMARKS)->state()); 298} 299 300TEST_F(SyncModelAssociationManagerTest, StartMultipleTimes) { 301 controllers_[syncer::BOOKMARKS] = 302 new FakeDataTypeController(syncer::BOOKMARKS); 303 controllers_[syncer::APPS] = 304 new FakeDataTypeController(syncer::APPS); 305 ModelAssociationManager model_association_manager(&controllers_, 306 &delegate_); 307 syncer::ModelTypeSet types; 308 types.Put(syncer::BOOKMARKS); 309 types.Put(syncer::APPS); 310 311 DataTypeManager::ConfigureResult result_1st( 312 DataTypeManager::OK, 313 syncer::ModelTypeSet(syncer::BOOKMARKS), 314 std::map<syncer::ModelType, syncer::SyncError>(), 315 syncer::ModelTypeSet(), 316 syncer::ModelTypeSet()); 317 DataTypeManager::ConfigureResult result_2nd( 318 DataTypeManager::OK, 319 syncer::ModelTypeSet(syncer::APPS), 320 std::map<syncer::ModelType, syncer::SyncError>(), 321 syncer::ModelTypeSet(), 322 syncer::ModelTypeSet()); 323 EXPECT_CALL(delegate_, OnModelAssociationDone(_)). 324 Times(2). 325 WillOnce(VerifyResult(result_1st)). 326 WillOnce(VerifyResult(result_2nd)); 327 328 model_association_manager.Initialize(types); 329 330 // Start BOOKMARKS first. 331 model_association_manager.StartAssociationAsync( 332 syncer::ModelTypeSet(syncer::BOOKMARKS)); 333 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 334 DataTypeController::ASSOCIATING); 335 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), 336 DataTypeController::MODEL_LOADED); 337 338 // Finish BOOKMARKS association. 339 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( 340 DataTypeController::OK); 341 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), 342 DataTypeController::RUNNING); 343 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), 344 DataTypeController::MODEL_LOADED); 345 346 // Start APPS next. 347 model_association_manager.StartAssociationAsync( 348 syncer::ModelTypeSet(syncer::APPS)); 349 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), 350 DataTypeController::ASSOCIATING); 351 GetController(controllers_, syncer::APPS)->FinishStart( 352 DataTypeController::OK); 353 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), 354 DataTypeController::RUNNING); 355} 356 357// Test that model that failed to load between initialization and association 358// is reported and stopped properly. 359TEST_F(SyncModelAssociationManagerTest, ModelLoadFailBeforeAssociationStart) { 360 controllers_[syncer::BOOKMARKS] = 361 new FakeDataTypeController(syncer::BOOKMARKS); 362 GetController(controllers_, syncer::BOOKMARKS)->SetModelLoadError( 363 syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, 364 "", syncer::BOOKMARKS)); 365 ModelAssociationManager model_association_manager( 366 &controllers_, 367 &delegate_); 368 syncer::ModelTypeSet types; 369 types.Put(syncer::BOOKMARKS); 370 std::map<syncer::ModelType, syncer::SyncError> errors; 371 syncer::SyncError error(FROM_HERE, 372 syncer::SyncError::DATATYPE_ERROR, 373 "Failed", 374 syncer::BOOKMARKS); 375 errors[syncer::BOOKMARKS] = error; 376 DataTypeManager::ConfigureResult expected_result( 377 DataTypeManager::PARTIAL_SUCCESS, 378 types, 379 errors, 380 syncer::ModelTypeSet(), 381 syncer::ModelTypeSet()); 382 EXPECT_CALL(delegate_, OnModelAssociationDone(_)). 383 WillOnce(VerifyResult(expected_result)); 384 385 model_association_manager.Initialize(types); 386 EXPECT_EQ(DataTypeController::DISABLED, 387 GetController(controllers_, syncer::BOOKMARKS)->state()); 388 model_association_manager.StartAssociationAsync(types); 389 EXPECT_EQ(DataTypeController::NOT_RUNNING, 390 GetController(controllers_, syncer::BOOKMARKS)->state()); 391} 392 393} // namespace sync_driver 394