1 // Copyright 2013 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 "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/run_loop.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "chrome/browser/drive/drive_api_util.h"
12 #include "chrome/browser/drive/drive_uploader.h"
13 #include "chrome/browser/drive/fake_drive_service.h"
14 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
15 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h"
16 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
17 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
18 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
19 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
20 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "google_apis/drive/drive_api_parser.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
25 #include "third_party/leveldatabase/src/include/leveldb/env.h"
27 namespace sync_file_system
{
28 namespace drive_backend
{
32 const int64 kInitialLargestChangeID
= 1234;
36 class SyncEngineInitializerTest
: public testing::Test
{
39 scoped_ptr
<google_apis::FileResource
> resource
;
40 FileMetadata metadata
;
44 SyncEngineInitializerTest() {}
45 ~SyncEngineInitializerTest() override
{}
47 void SetUp() override
{
48 ASSERT_TRUE(database_dir_
.CreateUniqueTempDir());
49 in_memory_env_
.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
51 scoped_ptr
<drive::DriveServiceInterface
>
52 fake_drive_service(new drive::FakeDriveService
);
54 sync_context_
.reset(new SyncEngineContext(
55 fake_drive_service
.Pass(),
56 scoped_ptr
<drive::DriveUploaderInterface
>(),
57 nullptr /* task_logger */,
58 base::ThreadTaskRunnerHandle::Get(),
59 base::ThreadTaskRunnerHandle::Get(),
60 nullptr /* worker_pool */));
62 sync_task_manager_
.reset(new SyncTaskManager(
63 base::WeakPtr
<SyncTaskManager::Client
>(),
64 1 /* maximum_parallel_task */,
65 base::ThreadTaskRunnerHandle::Get(),
66 nullptr /* worker_pool */));
67 sync_task_manager_
->Initialize(SYNC_STATUS_OK
);
70 void TearDown() override
{
71 sync_task_manager_
.reset();
72 metadata_database_
.reset();
73 sync_context_
.reset();
74 base::RunLoop().RunUntilIdle();
77 base::FilePath
database_path() {
78 return database_dir_
.path();
81 SyncStatusCode
RunInitializer() {
82 SyncEngineInitializer
* initializer
=
83 new SyncEngineInitializer(sync_context_
.get(),
85 in_memory_env_
.get());
86 SyncStatusCode status
= SYNC_STATUS_UNKNOWN
;
88 sync_task_manager_
->ScheduleSyncTask(
90 scoped_ptr
<SyncTask
>(initializer
),
91 SyncTaskManager::PRIORITY_MED
,
92 base::Bind(&SyncEngineInitializerTest::DidRunInitializer
,
93 base::Unretained(this), initializer
, &status
));
95 base::RunLoop().RunUntilIdle();
99 void DidRunInitializer(SyncEngineInitializer
* initializer
,
100 SyncStatusCode
* status_out
,
101 SyncStatusCode status
) {
102 *status_out
= status
;
103 metadata_database_
= initializer
->PassMetadataDatabase();
106 SyncStatusCode
PopulateDatabase(
107 const google_apis::FileResource
& sync_root
,
108 const google_apis::FileResource
** app_roots
,
109 size_t app_roots_count
) {
110 SyncStatusCode status
= SYNC_STATUS_UNKNOWN
;
111 scoped_ptr
<MetadataDatabase
> database
= MetadataDatabase::Create(
112 database_path(), in_memory_env_
.get(), &status
);
113 if (status
!= SYNC_STATUS_OK
)
116 // |app_root_list| must not own the resources here. Be sure to call
118 ScopedVector
<google_apis::FileResource
> app_root_list
;
119 for (size_t i
= 0; i
< app_roots_count
; ++i
) {
120 app_root_list
.push_back(
121 const_cast<google_apis::FileResource
*>(app_roots
[i
]));
124 status
= database
->PopulateInitialData(
125 kInitialLargestChangeID
, sync_root
, app_root_list
);
127 app_root_list
.weak_clear();
131 scoped_ptr
<google_apis::FileResource
> CreateRemoteFolder(
132 const std::string
& parent_folder_id
,
133 const std::string
& title
) {
134 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
135 scoped_ptr
<google_apis::FileResource
> entry
;
136 sync_context_
->GetDriveService()->AddNewDirectory(
137 parent_folder_id
, title
, drive::AddNewDirectoryOptions(),
138 CreateResultReceiver(&error
, &entry
));
139 base::RunLoop().RunUntilIdle();
141 EXPECT_EQ(google_apis::HTTP_CREATED
, error
);
145 scoped_ptr
<google_apis::FileResource
> CreateRemoteSyncRoot() {
146 scoped_ptr
<google_apis::FileResource
> sync_root(
147 CreateRemoteFolder(std::string(), kSyncRootFolderTitle
));
149 for (size_t i
= 0; i
< sync_root
->parents().size(); ++i
) {
150 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
151 sync_context_
->GetDriveService()->RemoveResourceFromDirectory(
152 sync_root
->parents()[i
].file_id(),
153 sync_root
->file_id(),
154 CreateResultReceiver(&error
));
155 base::RunLoop().RunUntilIdle();
156 EXPECT_EQ(google_apis::HTTP_NO_CONTENT
, error
);
159 return sync_root
.Pass();
162 std::string
GetSyncRootFolderID() {
163 int64 sync_root_tracker_id
= metadata_database_
->GetSyncRootTrackerID();
164 FileTracker sync_root_tracker
;
165 EXPECT_TRUE(metadata_database_
->FindTrackerByTrackerID(
166 sync_root_tracker_id
, &sync_root_tracker
));
167 return sync_root_tracker
.file_id();
170 size_t CountTrackersForFile(const std::string
& file_id
) {
171 TrackerIDSet trackers
;
172 metadata_database_
->FindTrackersByFileID(file_id
, &trackers
);
173 return trackers
.size();
176 bool HasActiveTracker(const std::string
& file_id
) {
177 TrackerIDSet trackers
;
178 return metadata_database_
->FindTrackersByFileID(file_id
, &trackers
) &&
179 trackers
.has_active();
182 bool HasNoParent(const std::string
& file_id
) {
183 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
184 scoped_ptr
<google_apis::FileResource
> entry
;
185 sync_context_
->GetDriveService()->GetFileResource(
187 CreateResultReceiver(&error
, &entry
));
188 base::RunLoop().RunUntilIdle();
189 EXPECT_EQ(google_apis::HTTP_SUCCESS
, error
);
190 return entry
->parents().empty();
193 size_t CountFileMetadata() {
194 return metadata_database_
->CountFileMetadata();
197 size_t CountFileTracker() {
198 return metadata_database_
->CountFileTracker();
201 google_apis::DriveApiErrorCode
AddParentFolder(
202 const std::string
& new_parent_folder_id
,
203 const std::string
& file_id
) {
204 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
205 sync_context_
->GetDriveService()->AddResourceToDirectory(
206 new_parent_folder_id
, file_id
,
207 CreateResultReceiver(&error
));
208 base::RunLoop().RunUntilIdle();
213 content::TestBrowserThreadBundle browser_threads_
;
214 base::ScopedTempDir database_dir_
;
215 scoped_ptr
<leveldb::Env
> in_memory_env_
;
217 scoped_ptr
<MetadataDatabase
> metadata_database_
;
218 scoped_ptr
<SyncTaskManager
> sync_task_manager_
;
219 scoped_ptr
<SyncEngineContext
> sync_context_
;
221 DISALLOW_COPY_AND_ASSIGN(SyncEngineInitializerTest
);
224 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_NoRemoteSyncRoot
) {
225 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
227 std::string sync_root_folder_id
= GetSyncRootFolderID();
228 EXPECT_EQ(1u, CountTrackersForFile(sync_root_folder_id
));
230 EXPECT_TRUE(HasActiveTracker(sync_root_folder_id
));
232 EXPECT_EQ(1u, CountFileMetadata());
233 EXPECT_EQ(1u, CountFileTracker());
236 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_RemoteSyncRootExists
) {
237 scoped_ptr
<google_apis::FileResource
> sync_root(
238 CreateRemoteSyncRoot());
239 scoped_ptr
<google_apis::FileResource
> app_root_1(
240 CreateRemoteFolder(sync_root
->file_id(), "app-root 1"));
241 scoped_ptr
<google_apis::FileResource
> app_root_2(
242 CreateRemoteFolder(sync_root
->file_id(), "app-root 2"));
244 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
246 EXPECT_EQ(1u, CountTrackersForFile(sync_root
->file_id()));
247 EXPECT_EQ(1u, CountTrackersForFile(app_root_1
->file_id()));
248 EXPECT_EQ(1u, CountTrackersForFile(app_root_2
->file_id()));
250 EXPECT_TRUE(HasActiveTracker(sync_root
->file_id()));
251 EXPECT_FALSE(HasActiveTracker(app_root_1
->file_id()));
252 EXPECT_FALSE(HasActiveTracker(app_root_2
->file_id()));
254 EXPECT_EQ(3u, CountFileMetadata());
255 EXPECT_EQ(3u, CountFileTracker());
258 TEST_F(SyncEngineInitializerTest
, DatabaseAlreadyInitialized
) {
259 scoped_ptr
<google_apis::FileResource
> sync_root(CreateRemoteSyncRoot());
260 scoped_ptr
<google_apis::FileResource
> app_root_1(
261 CreateRemoteFolder(sync_root
->file_id(), "app-root 1"));
262 scoped_ptr
<google_apis::FileResource
> app_root_2(
263 CreateRemoteFolder(sync_root
->file_id(), "app-root 2"));
265 const google_apis::FileResource
* app_roots
[] = {
266 app_root_1
.get(), app_root_2
.get()
268 EXPECT_EQ(SYNC_STATUS_OK
,
269 PopulateDatabase(*sync_root
, app_roots
, arraysize(app_roots
)));
271 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
273 EXPECT_EQ(1u, CountTrackersForFile(sync_root
->file_id()));
274 EXPECT_EQ(1u, CountTrackersForFile(app_root_1
->file_id()));
275 EXPECT_EQ(1u, CountTrackersForFile(app_root_2
->file_id()));
277 EXPECT_TRUE(HasActiveTracker(sync_root
->file_id()));
278 EXPECT_FALSE(HasActiveTracker(app_root_1
->file_id()));
279 EXPECT_FALSE(HasActiveTracker(app_root_2
->file_id()));
281 EXPECT_EQ(3u, CountFileMetadata());
282 EXPECT_EQ(3u, CountFileTracker());
285 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_MultiCandidate
) {
286 scoped_ptr
<google_apis::FileResource
> sync_root_1(CreateRemoteSyncRoot());
287 scoped_ptr
<google_apis::FileResource
> sync_root_2(CreateRemoteSyncRoot());
289 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
291 EXPECT_EQ(1u, CountTrackersForFile(sync_root_1
->file_id()));
292 EXPECT_EQ(0u, CountTrackersForFile(sync_root_2
->file_id()));
294 EXPECT_TRUE(HasActiveTracker(sync_root_1
->file_id()));
295 EXPECT_FALSE(HasActiveTracker(sync_root_2
->file_id()));
297 EXPECT_EQ(1u, CountFileMetadata());
298 EXPECT_EQ(1u, CountFileTracker());
301 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_UndetachedRemoteSyncRoot
) {
302 scoped_ptr
<google_apis::FileResource
> sync_root(CreateRemoteFolder(
303 std::string(), kSyncRootFolderTitle
));
304 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
306 EXPECT_EQ(1u, CountTrackersForFile(sync_root
->file_id()));
307 EXPECT_TRUE(HasActiveTracker(sync_root
->file_id()));
309 EXPECT_TRUE(HasNoParent(sync_root
->file_id()));
311 EXPECT_EQ(1u, CountFileMetadata());
312 EXPECT_EQ(1u, CountFileTracker());
315 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_MultiparentSyncRoot
) {
316 scoped_ptr
<google_apis::FileResource
> folder(CreateRemoteFolder(
317 std::string(), "folder"));
318 scoped_ptr
<google_apis::FileResource
> sync_root(CreateRemoteFolder(
319 std::string(), kSyncRootFolderTitle
));
320 AddParentFolder(sync_root
->file_id(), folder
->file_id());
322 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
324 EXPECT_EQ(1u, CountTrackersForFile(sync_root
->file_id()));
325 EXPECT_TRUE(HasActiveTracker(sync_root
->file_id()));
327 EXPECT_TRUE(HasNoParent(sync_root
->file_id()));
329 EXPECT_EQ(1u, CountFileMetadata());
330 EXPECT_EQ(1u, CountFileTracker());
333 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_FakeRemoteSyncRoot
) {
334 scoped_ptr
<google_apis::FileResource
> folder(CreateRemoteFolder(
335 std::string(), "folder"));
336 scoped_ptr
<google_apis::FileResource
> sync_root(CreateRemoteFolder(
337 folder
->file_id(), kSyncRootFolderTitle
));
339 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
341 EXPECT_EQ(0u, CountTrackersForFile(sync_root
->file_id()));
342 EXPECT_FALSE(HasNoParent(sync_root
->file_id()));
344 EXPECT_EQ(1u, CountFileMetadata());
345 EXPECT_EQ(1u, CountFileTracker());
348 } // namespace drive_backend
349 } // namespace sync_file_system