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.
5 #include "sync/internal_api/sync_backup_manager.h"
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/syncable/entry.h"
16 #include "sync/test/test_directory_backing_store.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
22 using ::testing::Invoke
;
23 using ::testing::WithArgs
;
29 void OnConfigDone(bool success
) {
33 class SyncBackupManagerTest
: public syncer::SyncManager::Observer
,
34 public testing::Test
{
36 MOCK_METHOD1(OnSyncCycleCompleted
,
37 void(const sessions::SyncSessionSnapshot
&));
38 MOCK_METHOD1(OnConnectionStatusChange
, void(ConnectionStatus
));
39 MOCK_METHOD1(OnActionableError
, void(const SyncProtocolError
&));
40 MOCK_METHOD1(OnMigrationRequested
, void(ModelTypeSet
));;
41 MOCK_METHOD1(OnProtocolEvent
, void(const ProtocolEvent
&));
42 MOCK_METHOD4(OnInitializationComplete
,
43 void(const WeakHandle
<JsBackend
>&,
44 const WeakHandle
<DataTypeDebugInfoListener
>&,
48 void SetUp() override
{
49 CHECK(temp_dir_
.CreateUniqueTempDir());
52 void InitManager(SyncManager
* manager
,
53 InternalComponentsFactory::StorageOption storage_option
) {
55 EXPECT_CALL(*this, OnInitializationComplete(_
, _
, _
, _
))
56 .WillOnce(WithArgs
<2>(Invoke(this,
57 &SyncBackupManagerTest::HandleInit
)));
59 manager
->AddObserver(this);
61 base::RunLoop run_loop
;
63 SyncManager::InitArgs args
;
64 args
.database_location
= temp_dir_
.path();
65 args
.event_handler
= MakeWeakHandle(base::WeakPtr
<JsEventHandler
>());
66 args
.service_url
= GURL("https://example.com/");
67 args
.post_factory
= scoped_ptr
<HttpPostProviderFactory
>().Pass();
68 args
.internal_components_factory
.reset(new TestInternalComponentsFactory(
69 InternalComponentsFactory::Switches(), storage_option
,
72 EXPECT_EQ(InternalComponentsFactory::STORAGE_ON_DISK_DEFERRED
,
74 loop_
.PostTask(FROM_HERE
, run_loop
.QuitClosure());
78 void CreateEntry(UserShare
* user_share
, ModelType type
,
79 const std::string
& client_tag
) {
80 WriteTransaction
trans(FROM_HERE
, user_share
);
82 WriteNode
node(&trans
);
83 EXPECT_EQ(WriteNode::INIT_SUCCESS
,
84 node
.InitUniqueByCreation(type
, client_tag
));
87 void ConfigureSyncer() {
88 manager_
->ConfigureSyncer(CONFIGURE_REASON_NEW_CLIENT
,
89 ModelTypeSet(SEARCH_ENGINES
),
90 ModelTypeSet(), ModelTypeSet(), ModelTypeSet(),
91 ModelSafeRoutingInfo(),
92 base::Bind(&OnConfigDone
, true),
93 base::Bind(&OnConfigDone
, false));
96 void HandleInit(bool success
) {
98 loop_
.PostTask(FROM_HERE
,
99 base::Bind(&SyncBackupManagerTest::ConfigureSyncer
,
100 base::Unretained(this)));
102 manager_
->ShutdownOnSyncThread(STOP_SYNC
);
106 base::ScopedTempDir temp_dir_
;
107 base::MessageLoop loop_
; // Needed for WeakHandle
108 SyncManager
* manager_
;
109 InternalComponentsFactory::StorageOption storage_used_
;
112 TEST_F(SyncBackupManagerTest
, NormalizeEntry
) {
113 scoped_ptr
<SyncBackupManager
> manager(new SyncBackupManager
);
114 InitManager(manager
.get(), InternalComponentsFactory::STORAGE_IN_MEMORY
);
116 CreateEntry(manager
->GetUserShare(), SEARCH_ENGINES
, "test");
119 // New entry is local and unsynced at first.
120 ReadTransaction
trans(FROM_HERE
, manager
->GetUserShare());
121 ReadNode
pref(&trans
);
122 EXPECT_EQ(BaseNode::INIT_OK
,
123 pref
.InitByClientTagLookup(SEARCH_ENGINES
, "test"));
124 EXPECT_FALSE(pref
.GetEntry()->GetId().ServerKnows());
125 EXPECT_TRUE(pref
.GetEntry()->GetIsUnsynced());
128 manager
->SaveChanges();
131 // New entry has server ID and unsynced bit is cleared after saving.
132 ReadTransaction
trans(FROM_HERE
, manager
->GetUserShare());
133 ReadNode
pref(&trans
);
134 EXPECT_EQ(BaseNode::INIT_OK
,
135 pref
.InitByClientTagLookup(SEARCH_ENGINES
, "test"));
136 EXPECT_TRUE(pref
.GetEntry()->GetId().ServerKnows());
137 EXPECT_FALSE(pref
.GetEntry()->GetIsUnsynced());
141 TEST_F(SyncBackupManagerTest
, PersistWithSwitchToSyncShutdown
) {
142 scoped_ptr
<SyncBackupManager
> manager(new SyncBackupManager
);
143 InitManager(manager
.get(),
144 InternalComponentsFactory::STORAGE_ON_DISK_DEFERRED
);
146 CreateEntry(manager
->GetUserShare(), SEARCH_ENGINES
, "test");
147 manager
->SaveChanges();
148 manager
->ShutdownOnSyncThread(SWITCH_MODE_SYNC
);
150 // Reopen db to verify entry is persisted.
151 manager
.reset(new SyncBackupManager
);
152 InitManager(manager
.get(), InternalComponentsFactory::STORAGE_ON_DISK
);
154 ReadTransaction
trans(FROM_HERE
, manager
->GetUserShare());
155 ReadNode
pref(&trans
);
156 EXPECT_EQ(BaseNode::INIT_OK
,
157 pref
.InitByClientTagLookup(SEARCH_ENGINES
, "test"));
158 EXPECT_TRUE(pref
.GetEntry()->GetId().ServerKnows());
159 EXPECT_FALSE(pref
.GetEntry()->GetIsUnsynced());
163 TEST_F(SyncBackupManagerTest
, DontPersistWithOtherShutdown
) {
164 scoped_ptr
<SyncBackupManager
> manager(new SyncBackupManager
);
165 InitManager(manager
.get(),
166 InternalComponentsFactory::STORAGE_ON_DISK_DEFERRED
);
168 CreateEntry(manager
->GetUserShare(), SEARCH_ENGINES
, "test");
169 manager
->SaveChanges();
170 manager
->ShutdownOnSyncThread(STOP_SYNC
);
171 EXPECT_FALSE(base::PathExists(
172 temp_dir_
.path().Append(syncable::Directory::kSyncDatabaseFilename
)));
175 TEST_F(SyncBackupManagerTest
, FailToInitialize
) {
176 // Test graceful shutdown on initialization failure.
177 scoped_ptr
<SyncBackupManager
> manager(new SyncBackupManager
);
178 InitManager(manager
.get(), InternalComponentsFactory::STORAGE_INVALID
);
181 } // anonymous namespace
183 } // namespace syncer