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