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/sync_file_system/drive_backend/drive_backend_constants.h"
12 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h"
13 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
14 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
15 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
16 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
17 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
18 #include "components/drive/drive_api_util.h"
19 #include "components/drive/drive_uploader.h"
20 #include "components/drive/service/fake_drive_service.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::FakeDriveService
>
52 fake_drive_service(new drive::FakeDriveService
);
53 fake_drive_service_
= fake_drive_service
.get();
55 sync_context_
.reset(new SyncEngineContext(
56 fake_drive_service
.Pass(),
57 scoped_ptr
<drive::DriveUploaderInterface
>(),
58 nullptr /* task_logger */,
59 base::ThreadTaskRunnerHandle::Get(),
60 base::ThreadTaskRunnerHandle::Get(),
61 nullptr /* worker_pool */));
63 sync_task_manager_
.reset(new SyncTaskManager(
64 base::WeakPtr
<SyncTaskManager::Client
>(),
65 1 /* maximum_parallel_task */,
66 base::ThreadTaskRunnerHandle::Get(),
67 nullptr /* worker_pool */));
68 sync_task_manager_
->Initialize(SYNC_STATUS_OK
);
71 void TearDown() override
{
72 sync_task_manager_
.reset();
73 metadata_database_
.reset();
74 sync_context_
.reset();
75 base::RunLoop().RunUntilIdle();
78 base::FilePath
database_path() {
79 return database_dir_
.path();
82 SyncStatusCode
RunInitializer() {
83 SyncEngineInitializer
* initializer
=
84 new SyncEngineInitializer(sync_context_
.get(),
86 in_memory_env_
.get());
87 SyncStatusCode status
= SYNC_STATUS_UNKNOWN
;
89 sync_task_manager_
->ScheduleSyncTask(
91 scoped_ptr
<SyncTask
>(initializer
),
92 SyncTaskManager::PRIORITY_MED
,
93 base::Bind(&SyncEngineInitializerTest::DidRunInitializer
,
94 base::Unretained(this), initializer
, &status
));
96 base::RunLoop().RunUntilIdle();
100 void DidRunInitializer(SyncEngineInitializer
* initializer
,
101 SyncStatusCode
* status_out
,
102 SyncStatusCode status
) {
103 *status_out
= status
;
104 metadata_database_
= initializer
->PassMetadataDatabase();
107 SyncStatusCode
PopulateDatabase(
108 const google_apis::FileResource
& sync_root
,
109 const google_apis::FileResource
** app_roots
,
110 size_t app_roots_count
) {
111 SyncStatusCode status
= SYNC_STATUS_UNKNOWN
;
112 scoped_ptr
<MetadataDatabase
> database
= MetadataDatabase::Create(
113 database_path(), in_memory_env_
.get(), &status
);
114 if (status
!= SYNC_STATUS_OK
)
117 // |app_root_list| must not own the resources here. Be sure to call
119 ScopedVector
<google_apis::FileResource
> app_root_list
;
120 for (size_t i
= 0; i
< app_roots_count
; ++i
) {
121 app_root_list
.push_back(
122 const_cast<google_apis::FileResource
*>(app_roots
[i
]));
125 status
= database
->PopulateInitialData(
126 kInitialLargestChangeID
, sync_root
, app_root_list
);
128 app_root_list
.weak_clear();
132 scoped_ptr
<google_apis::FileResource
> CreateRemoteFolder(
133 const std::string
& parent_folder_id
,
134 const std::string
& title
) {
135 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
136 scoped_ptr
<google_apis::FileResource
> entry
;
137 drive::AddNewDirectoryOptions options
;
138 options
.visibility
= google_apis::drive::FILE_VISIBILITY_PRIVATE
;
139 sync_context_
->GetDriveService()->AddNewDirectory(
140 parent_folder_id
, title
, options
,
141 CreateResultReceiver(&error
, &entry
));
142 base::RunLoop().RunUntilIdle();
144 EXPECT_EQ(google_apis::HTTP_CREATED
, error
);
148 scoped_ptr
<google_apis::FileResource
> CreateRemoteSyncRoot() {
149 scoped_ptr
<google_apis::FileResource
> sync_root(
150 CreateRemoteFolder(std::string(), kSyncRootFolderTitle
));
152 for (size_t i
= 0; i
< sync_root
->parents().size(); ++i
) {
153 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
154 sync_context_
->GetDriveService()->RemoveResourceFromDirectory(
155 sync_root
->parents()[i
].file_id(),
156 sync_root
->file_id(),
157 CreateResultReceiver(&error
));
158 base::RunLoop().RunUntilIdle();
159 EXPECT_EQ(google_apis::HTTP_NO_CONTENT
, error
);
162 return sync_root
.Pass();
165 std::string
GetSyncRootFolderID() {
166 int64 sync_root_tracker_id
= metadata_database_
->GetSyncRootTrackerID();
167 FileTracker sync_root_tracker
;
168 EXPECT_TRUE(metadata_database_
->FindTrackerByTrackerID(
169 sync_root_tracker_id
, &sync_root_tracker
));
170 return sync_root_tracker
.file_id();
173 bool VerifyFolderVisibility(const std::string
& folder_id
) {
174 google_apis::drive::FileVisibility visibility
;
175 if (google_apis::HTTP_SUCCESS
!=
176 fake_drive_service_
->GetFileVisibility(
177 folder_id
, &visibility
))
179 if (visibility
!= google_apis::drive::FILE_VISIBILITY_PRIVATE
)
184 size_t CountTrackersForFile(const std::string
& file_id
) {
185 TrackerIDSet trackers
;
186 metadata_database_
->FindTrackersByFileID(file_id
, &trackers
);
187 return trackers
.size();
190 bool HasActiveTracker(const std::string
& file_id
) {
191 TrackerIDSet trackers
;
192 return metadata_database_
->FindTrackersByFileID(file_id
, &trackers
) &&
193 trackers
.has_active();
196 bool HasNoParent(const std::string
& file_id
) {
197 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
198 scoped_ptr
<google_apis::FileResource
> entry
;
199 sync_context_
->GetDriveService()->GetFileResource(
201 CreateResultReceiver(&error
, &entry
));
202 base::RunLoop().RunUntilIdle();
203 EXPECT_EQ(google_apis::HTTP_SUCCESS
, error
);
204 return entry
->parents().empty();
207 size_t CountFileMetadata() {
208 return metadata_database_
->CountFileMetadata();
211 size_t CountFileTracker() {
212 return metadata_database_
->CountFileTracker();
215 google_apis::DriveApiErrorCode
AddParentFolder(
216 const std::string
& new_parent_folder_id
,
217 const std::string
& file_id
) {
218 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
219 sync_context_
->GetDriveService()->AddResourceToDirectory(
220 new_parent_folder_id
, file_id
,
221 CreateResultReceiver(&error
));
222 base::RunLoop().RunUntilIdle();
227 content::TestBrowserThreadBundle browser_threads_
;
228 base::ScopedTempDir database_dir_
;
229 scoped_ptr
<leveldb::Env
> in_memory_env_
;
231 scoped_ptr
<MetadataDatabase
> metadata_database_
;
232 scoped_ptr
<SyncTaskManager
> sync_task_manager_
;
233 scoped_ptr
<SyncEngineContext
> sync_context_
;
234 drive::FakeDriveService
* fake_drive_service_
= nullptr;
236 DISALLOW_COPY_AND_ASSIGN(SyncEngineInitializerTest
);
239 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_NoRemoteSyncRoot
) {
240 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
242 std::string sync_root_folder_id
= GetSyncRootFolderID();
243 EXPECT_EQ(1u, CountTrackersForFile(sync_root_folder_id
));
245 EXPECT_TRUE(HasActiveTracker(sync_root_folder_id
));
247 EXPECT_EQ(1u, CountFileMetadata());
248 EXPECT_EQ(1u, CountFileTracker());
249 EXPECT_TRUE(VerifyFolderVisibility(sync_root_folder_id
));
252 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_RemoteSyncRootExists
) {
253 scoped_ptr
<google_apis::FileResource
> sync_root(
254 CreateRemoteSyncRoot());
255 scoped_ptr
<google_apis::FileResource
> app_root_1(
256 CreateRemoteFolder(sync_root
->file_id(), "app-root 1"));
257 scoped_ptr
<google_apis::FileResource
> app_root_2(
258 CreateRemoteFolder(sync_root
->file_id(), "app-root 2"));
260 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
262 EXPECT_EQ(1u, CountTrackersForFile(sync_root
->file_id()));
263 EXPECT_EQ(1u, CountTrackersForFile(app_root_1
->file_id()));
264 EXPECT_EQ(1u, CountTrackersForFile(app_root_2
->file_id()));
266 EXPECT_TRUE(HasActiveTracker(sync_root
->file_id()));
267 EXPECT_FALSE(HasActiveTracker(app_root_1
->file_id()));
268 EXPECT_FALSE(HasActiveTracker(app_root_2
->file_id()));
270 EXPECT_EQ(3u, CountFileMetadata());
271 EXPECT_EQ(3u, CountFileTracker());
274 TEST_F(SyncEngineInitializerTest
, DatabaseAlreadyInitialized
) {
275 scoped_ptr
<google_apis::FileResource
> sync_root(CreateRemoteSyncRoot());
276 scoped_ptr
<google_apis::FileResource
> app_root_1(
277 CreateRemoteFolder(sync_root
->file_id(), "app-root 1"));
278 scoped_ptr
<google_apis::FileResource
> app_root_2(
279 CreateRemoteFolder(sync_root
->file_id(), "app-root 2"));
281 const google_apis::FileResource
* app_roots
[] = {
282 app_root_1
.get(), app_root_2
.get()
284 EXPECT_EQ(SYNC_STATUS_OK
,
285 PopulateDatabase(*sync_root
, app_roots
, arraysize(app_roots
)));
287 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
289 EXPECT_EQ(1u, CountTrackersForFile(sync_root
->file_id()));
290 EXPECT_EQ(1u, CountTrackersForFile(app_root_1
->file_id()));
291 EXPECT_EQ(1u, CountTrackersForFile(app_root_2
->file_id()));
293 EXPECT_TRUE(HasActiveTracker(sync_root
->file_id()));
294 EXPECT_FALSE(HasActiveTracker(app_root_1
->file_id()));
295 EXPECT_FALSE(HasActiveTracker(app_root_2
->file_id()));
297 EXPECT_EQ(3u, CountFileMetadata());
298 EXPECT_EQ(3u, CountFileTracker());
301 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_MultiCandidate
) {
302 scoped_ptr
<google_apis::FileResource
> sync_root_1(CreateRemoteSyncRoot());
303 scoped_ptr
<google_apis::FileResource
> sync_root_2(CreateRemoteSyncRoot());
305 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
307 EXPECT_EQ(1u, CountTrackersForFile(sync_root_1
->file_id()));
308 EXPECT_EQ(0u, CountTrackersForFile(sync_root_2
->file_id()));
310 EXPECT_TRUE(HasActiveTracker(sync_root_1
->file_id()));
311 EXPECT_FALSE(HasActiveTracker(sync_root_2
->file_id()));
313 EXPECT_EQ(1u, CountFileMetadata());
314 EXPECT_EQ(1u, CountFileTracker());
317 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_UndetachedRemoteSyncRoot
) {
318 scoped_ptr
<google_apis::FileResource
> sync_root(CreateRemoteFolder(
319 std::string(), kSyncRootFolderTitle
));
320 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
322 EXPECT_EQ(1u, CountTrackersForFile(sync_root
->file_id()));
323 EXPECT_TRUE(HasActiveTracker(sync_root
->file_id()));
325 EXPECT_TRUE(HasNoParent(sync_root
->file_id()));
327 EXPECT_EQ(1u, CountFileMetadata());
328 EXPECT_EQ(1u, CountFileTracker());
331 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_MultiparentSyncRoot
) {
332 scoped_ptr
<google_apis::FileResource
> folder(CreateRemoteFolder(
333 std::string(), "folder"));
334 scoped_ptr
<google_apis::FileResource
> sync_root(CreateRemoteFolder(
335 std::string(), kSyncRootFolderTitle
));
336 AddParentFolder(sync_root
->file_id(), folder
->file_id());
338 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
340 EXPECT_EQ(1u, CountTrackersForFile(sync_root
->file_id()));
341 EXPECT_TRUE(HasActiveTracker(sync_root
->file_id()));
343 EXPECT_TRUE(HasNoParent(sync_root
->file_id()));
345 EXPECT_EQ(1u, CountFileMetadata());
346 EXPECT_EQ(1u, CountFileTracker());
349 TEST_F(SyncEngineInitializerTest
, EmptyDatabase_FakeRemoteSyncRoot
) {
350 scoped_ptr
<google_apis::FileResource
> folder(CreateRemoteFolder(
351 std::string(), "folder"));
352 scoped_ptr
<google_apis::FileResource
> sync_root(CreateRemoteFolder(
353 folder
->file_id(), kSyncRootFolderTitle
));
355 EXPECT_EQ(SYNC_STATUS_OK
, RunInitializer());
357 EXPECT_EQ(0u, CountTrackersForFile(sync_root
->file_id()));
358 EXPECT_FALSE(HasNoParent(sync_root
->file_id()));
360 EXPECT_EQ(1u, CountFileMetadata());
361 EXPECT_EQ(1u, CountFileTracker());
364 } // namespace drive_backend
365 } // namespace sync_file_system