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 virtual 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
);
81 ReadNode
type_root(&trans
);
82 EXPECT_EQ(BaseNode::INIT_OK
, type_root
.InitTypeRoot(type
));
84 WriteNode
node(&trans
);
85 EXPECT_EQ(WriteNode::INIT_SUCCESS
,
86 node
.InitUniqueByCreation(type
, type_root
, client_tag
));
89 void ConfigureSyncer() {
90 manager_
->ConfigureSyncer(CONFIGURE_REASON_NEW_CLIENT
,
91 ModelTypeSet(SEARCH_ENGINES
),
92 ModelTypeSet(), ModelTypeSet(), ModelTypeSet(),
93 ModelSafeRoutingInfo(),
94 base::Bind(&OnConfigDone
, true),
95 base::Bind(&OnConfigDone
, false));
98 void HandleInit(bool success
) {
100 loop_
.PostTask(FROM_HERE
,
101 base::Bind(&SyncBackupManagerTest::ConfigureSyncer
,
102 base::Unretained(this)));
104 manager_
->ShutdownOnSyncThread(STOP_SYNC
);
108 base::ScopedTempDir temp_dir_
;
109 base::MessageLoop loop_
; // Needed for WeakHandle
110 SyncManager
* manager_
;
111 InternalComponentsFactory::StorageOption storage_used_
;
114 TEST_F(SyncBackupManagerTest
, NormalizeEntry
) {
115 scoped_ptr
<SyncBackupManager
> manager(new SyncBackupManager
);
116 InitManager(manager
.get(), InternalComponentsFactory::STORAGE_IN_MEMORY
);
118 CreateEntry(manager
->GetUserShare(), SEARCH_ENGINES
, "test");
121 // New entry is local and unsynced at first.
122 ReadTransaction
trans(FROM_HERE
, manager
->GetUserShare());
123 ReadNode
pref(&trans
);
124 EXPECT_EQ(BaseNode::INIT_OK
,
125 pref
.InitByClientTagLookup(SEARCH_ENGINES
, "test"));
126 EXPECT_FALSE(pref
.GetEntry()->GetId().ServerKnows());
127 EXPECT_TRUE(pref
.GetEntry()->GetIsUnsynced());
130 manager
->SaveChanges();
133 // New entry has server ID and unsynced bit is cleared after saving.
134 ReadTransaction
trans(FROM_HERE
, manager
->GetUserShare());
135 ReadNode
pref(&trans
);
136 EXPECT_EQ(BaseNode::INIT_OK
,
137 pref
.InitByClientTagLookup(SEARCH_ENGINES
, "test"));
138 EXPECT_TRUE(pref
.GetEntry()->GetId().ServerKnows());
139 EXPECT_FALSE(pref
.GetEntry()->GetIsUnsynced());
143 TEST_F(SyncBackupManagerTest
, PersistWithSwitchToSyncShutdown
) {
144 scoped_ptr
<SyncBackupManager
> manager(new SyncBackupManager
);
145 InitManager(manager
.get(),
146 InternalComponentsFactory::STORAGE_ON_DISK_DEFERRED
);
148 CreateEntry(manager
->GetUserShare(), SEARCH_ENGINES
, "test");
149 manager
->SaveChanges();
150 manager
->ShutdownOnSyncThread(SWITCH_MODE_SYNC
);
152 // Reopen db to verify entry is persisted.
153 manager
.reset(new SyncBackupManager
);
154 InitManager(manager
.get(), InternalComponentsFactory::STORAGE_ON_DISK
);
156 ReadTransaction
trans(FROM_HERE
, manager
->GetUserShare());
157 ReadNode
pref(&trans
);
158 EXPECT_EQ(BaseNode::INIT_OK
,
159 pref
.InitByClientTagLookup(SEARCH_ENGINES
, "test"));
160 EXPECT_TRUE(pref
.GetEntry()->GetId().ServerKnows());
161 EXPECT_FALSE(pref
.GetEntry()->GetIsUnsynced());
165 TEST_F(SyncBackupManagerTest
, DontPersistWithOtherShutdown
) {
166 scoped_ptr
<SyncBackupManager
> manager(new SyncBackupManager
);
167 InitManager(manager
.get(),
168 InternalComponentsFactory::STORAGE_ON_DISK_DEFERRED
);
170 CreateEntry(manager
->GetUserShare(), SEARCH_ENGINES
, "test");
171 manager
->SaveChanges();
172 manager
->ShutdownOnSyncThread(STOP_SYNC
);
173 EXPECT_FALSE(base::PathExists(
174 temp_dir_
.path().Append(syncable::Directory::kSyncDatabaseFilename
)));
177 TEST_F(SyncBackupManagerTest
, FailToInitialize
) {
178 // Test graceful shutdown on initialization failure.
179 scoped_ptr
<SyncBackupManager
> manager(new SyncBackupManager
);
180 InitManager(manager
.get(), InternalComponentsFactory::STORAGE_INVALID
);
183 } // anonymous namespace
185 } // namespace syncer