Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / sync / internal_api / sync_rollback_manager_unittest.cc
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 "sync/internal_api/sync_rollback_manager.h"
6
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/run_loop.h"
9 #include "sync/internal_api/public/read_node.h"
10 #include "sync/internal_api/public/read_transaction.h"
11 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
12 #include "sync/internal_api/public/test/test_internal_components_factory.h"
13 #include "sync/internal_api/public/write_node.h"
14 #include "sync/internal_api/public/write_transaction.h"
15 #include "sync/internal_api/sync_backup_manager.h"
16 #include "sync/syncable/entry.h"
17 #include "sync/test/engine/fake_model_worker.h"
18 #include "sync/test/test_directory_backing_store.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "url/gurl.h"
22
23 using ::testing::_;
24 using ::testing::DoDefault;
25 using ::testing::Invoke;
26 using ::testing::Truly;
27 using ::testing::WithArgs;
28
29 namespace syncer {
30
31 namespace {
32
33 class TestChangeDelegate : public SyncManager::ChangeDelegate {
34  public:
35   TestChangeDelegate() {
36     ON_CALL(*this, OnChangesApplied(_, _, _, _))
37         .WillByDefault(
38             WithArgs<3>(Invoke(this,
39                                &TestChangeDelegate::VerifyDeletes)));
40   }
41
42   void add_expected_delete(int64 v) {
43     expected_deletes_.insert(v);
44   }
45
46   MOCK_METHOD4(OnChangesApplied,
47                void(ModelType model_type,
48                     int64 model_version,
49                     const BaseTransaction* trans,
50                     const ImmutableChangeRecordList& changes));
51   MOCK_METHOD1(OnChangesComplete, void(ModelType model_type));
52
53  private:
54   void VerifyDeletes(const ImmutableChangeRecordList& changes) {
55     std::set<int64> deleted;
56     for (size_t i = 0; i < changes.Get().size(); ++i) {
57       const ChangeRecord& change = (changes.Get())[i];
58       EXPECT_EQ(ChangeRecord::ACTION_DELETE, change.action);
59       EXPECT_TRUE(deleted.find(change.id) == deleted.end());
60       deleted.insert(change.id);
61     }
62     EXPECT_TRUE(expected_deletes_ == deleted);
63   }
64
65   std::set<int64> expected_deletes_;
66 };
67
68 class SyncRollbackManagerTest : public testing::Test,
69                                 public SyncManager::Observer {
70  protected:
71   virtual void SetUp() OVERRIDE {
72     CHECK(temp_dir_.CreateUniqueTempDir());
73
74     worker_ = new FakeModelWorker(GROUP_UI);
75   }
76
77   MOCK_METHOD1(OnSyncCycleCompleted,
78                void(const sessions::SyncSessionSnapshot&));
79   MOCK_METHOD1(OnConnectionStatusChange, void(ConnectionStatus));
80   MOCK_METHOD4(OnInitializationComplete,
81                void(const WeakHandle<JsBackend>&,
82                     const WeakHandle<DataTypeDebugInfoListener>&,
83                     bool, ModelTypeSet));
84   MOCK_METHOD1(OnActionableError, void(const SyncProtocolError&));
85   MOCK_METHOD1(OnMigrationRequested, void(ModelTypeSet));;
86   MOCK_METHOD1(OnProtocolEvent, void(const ProtocolEvent&));
87
88   void OnConfigDone(bool success) {
89     EXPECT_TRUE(success);
90   }
91
92   int64 CreateEntry(UserShare* user_share, ModelType type,
93                     const std::string& client_tag) {
94     WriteTransaction trans(FROM_HERE, user_share);
95     ReadNode type_root(&trans);
96     EXPECT_EQ(BaseNode::INIT_OK, type_root.InitTypeRoot(type));
97
98     WriteNode node(&trans);
99     EXPECT_EQ(WriteNode::INIT_SUCCESS,
100               node.InitUniqueByCreation(type, type_root, client_tag));
101     return node.GetEntry()->GetMetahandle();
102   }
103
104   void InitManager(SyncManager* manager, ModelTypeSet types,
105                    TestChangeDelegate* delegate,
106                    InternalComponentsFactory::StorageOption storage_option) {
107     manager_ = manager;
108     types_ = types;
109
110     EXPECT_CALL(*this, OnInitializationComplete(_, _, _, _))
111         .WillOnce(WithArgs<2>(Invoke(this,
112                                      &SyncRollbackManagerTest::HandleInit)));
113
114     manager->AddObserver(this);
115
116     base::RunLoop run_loop;
117     SyncManager::InitArgs args;
118     args.database_location = temp_dir_.path();
119     args.service_url = GURL("https://example.com/");
120     args.workers.push_back(worker_);
121     args.change_delegate = delegate;
122
123     InternalComponentsFactory::StorageOption storage_used;
124     args.internal_components_factory.reset(new TestInternalComponentsFactory(
125         InternalComponentsFactory::Switches(), storage_option, &storage_used));
126     manager->Init(&args);
127     EXPECT_EQ(storage_option, storage_used);
128     loop_.PostTask(FROM_HERE, run_loop.QuitClosure());
129     run_loop.Run();
130   }
131
132   // Create and persist an entry by unique tag in DB.
133   void PrepopulateDb(ModelType type, const std::string& client_tag) {
134     SyncBackupManager backup_manager;
135     TestChangeDelegate delegate;
136     InitManager(&backup_manager, ModelTypeSet(type), &delegate,
137                 InternalComponentsFactory::STORAGE_ON_DISK_DEFERRED);
138     CreateEntry(backup_manager.GetUserShare(), type, client_tag);
139     backup_manager.ShutdownOnSyncThread(SWITCH_MODE_SYNC);
140   }
141
142   // Verify entry with |client_tag| exists in sync directory.
143   bool VerifyEntry(UserShare* user_share, ModelType type,
144                    const std::string& client_tag) {
145     ReadTransaction trans(FROM_HERE, user_share);
146     ReadNode node(&trans);
147     return BaseNode::INIT_OK == node.InitByClientTagLookup(type, client_tag);
148   }
149
150  private:
151   void ConfigureSyncer() {
152     manager_->ConfigureSyncer(
153           CONFIGURE_REASON_NEW_CLIENT,
154           types_,
155           ModelTypeSet(), ModelTypeSet(), ModelTypeSet(),
156           ModelSafeRoutingInfo(),
157           base::Bind(&SyncRollbackManagerTest::OnConfigDone,
158                      base::Unretained(this), true),
159           base::Bind(&SyncRollbackManagerTest::OnConfigDone,
160                      base::Unretained(this), false));
161   }
162
163   void HandleInit(bool success) {
164     if (success) {
165       loop_.PostTask(FROM_HERE,
166                      base::Bind(&SyncRollbackManagerTest::ConfigureSyncer,
167                                 base::Unretained(this)));
168     } else {
169       manager_->ShutdownOnSyncThread(STOP_SYNC);
170     }
171   }
172
173   base::ScopedTempDir temp_dir_;
174   scoped_refptr<ModelSafeWorker> worker_;
175   base::MessageLoop loop_;    // Needed for WeakHandle
176   SyncManager* manager_;
177   ModelTypeSet types_;
178 };
179
180 bool IsRollbackDoneAction(SyncProtocolError e) {
181   return e.action == syncer::ROLLBACK_DONE;
182 }
183
184 TEST_F(SyncRollbackManagerTest, RollbackBasic) {
185   PrepopulateDb(PREFERENCES, "pref1");
186
187   TestChangeDelegate delegate;
188   SyncRollbackManager rollback_manager;
189   InitManager(&rollback_manager, ModelTypeSet(PREFERENCES), &delegate,
190               InternalComponentsFactory::STORAGE_ON_DISK);
191
192   // Simulate a new entry added during type initialization.
193   int64 new_pref_id =
194       CreateEntry(rollback_manager.GetUserShare(), PREFERENCES, "pref2");
195
196   delegate.add_expected_delete(new_pref_id);
197   EXPECT_CALL(delegate, OnChangesApplied(_, _, _, _))
198       .Times(1)
199       .WillOnce(DoDefault());
200   EXPECT_CALL(delegate, OnChangesComplete(_)).Times(1);
201   EXPECT_CALL(*this, OnActionableError(Truly(IsRollbackDoneAction))).Times(1);
202
203   ModelSafeRoutingInfo routing_info;
204   routing_info[PREFERENCES] = GROUP_UI;
205   rollback_manager.StartSyncingNormally(routing_info);
206 }
207
208 TEST_F(SyncRollbackManagerTest, NoRollbackOfTypesNotBackedUp) {
209   PrepopulateDb(PREFERENCES, "pref1");
210
211   TestChangeDelegate delegate;
212   SyncRollbackManager rollback_manager;
213   InitManager(&rollback_manager, ModelTypeSet(PREFERENCES, APPS), &delegate,
214               InternalComponentsFactory::STORAGE_ON_DISK);
215
216   // Simulate new entry added during type initialization.
217   int64 new_pref_id =
218       CreateEntry(rollback_manager.GetUserShare(), PREFERENCES, "pref2");
219   CreateEntry(rollback_manager.GetUserShare(), APPS, "app1");
220
221   delegate.add_expected_delete(new_pref_id);
222   EXPECT_CALL(delegate, OnChangesApplied(_, _, _, _))
223       .Times(1)
224       .WillOnce(DoDefault());
225   EXPECT_CALL(delegate, OnChangesComplete(_)).Times(1);
226
227   ModelSafeRoutingInfo routing_info;
228   routing_info[PREFERENCES] = GROUP_UI;
229   rollback_manager.StartSyncingNormally(routing_info);
230
231   // APP entry is still valid.
232   EXPECT_TRUE(VerifyEntry(rollback_manager.GetUserShare(), APPS, "app1"));
233 }
234
235 TEST_F(SyncRollbackManagerTest, BackupDbNotChangedOnAbort) {
236   PrepopulateDb(PREFERENCES, "pref1");
237
238   TestChangeDelegate delegate;
239   scoped_ptr<SyncRollbackManager> rollback_manager(
240       new SyncRollbackManager);
241   InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate,
242               InternalComponentsFactory::STORAGE_ON_DISK);
243
244   // Simulate a new entry added during type initialization.
245   CreateEntry(rollback_manager->GetUserShare(), PREFERENCES, "pref2");
246
247   // Manager was shut down before sync starts.
248   rollback_manager->ShutdownOnSyncThread(STOP_SYNC);
249
250   // Verify new entry was not persisted.
251   rollback_manager.reset(new SyncRollbackManager);
252   InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate,
253               InternalComponentsFactory::STORAGE_ON_DISK);
254   EXPECT_FALSE(VerifyEntry(rollback_manager->GetUserShare(), PREFERENCES,
255                            "pref2"));
256 }
257
258 TEST_F(SyncRollbackManagerTest, OnInitializationFailure) {
259   // Test graceful shutdown on initialization failure.
260   scoped_ptr<SyncRollbackManager> rollback_manager(
261       new SyncRollbackManager);
262   InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), NULL,
263               InternalComponentsFactory::STORAGE_ON_DISK);
264 }
265
266 }  // anonymous namespace
267
268 }  // namespace syncer