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