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/register_app_task.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/format_macros.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
16 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
17 #include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
18 #include "chrome/browser/sync_file_system/drive_backend/leveldb_wrapper.h"
19 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
20 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
21 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
22 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
23 #include "components/drive/drive_uploader.h"
24 #include "components/drive/service/fake_drive_service.h"
25 #include "content/public/test/test_browser_thread_bundle.h"
26 #include "google_apis/drive/drive_api_parser.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
29 #include "third_party/leveldatabase/src/include/leveldb/db.h"
30 #include "third_party/leveldatabase/src/include/leveldb/env.h"
32 namespace sync_file_system
{
33 namespace drive_backend
{
36 const int64 kSyncRootTrackerID
= 100;
39 class RegisterAppTaskTest
: public testing::Test
{
42 : next_file_id_(1000),
43 next_tracker_id_(10000) {}
44 ~RegisterAppTaskTest() override
{}
46 void SetUp() override
{
47 ASSERT_TRUE(database_dir_
.CreateUniqueTempDir());
48 in_memory_env_
.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
50 scoped_ptr
<drive::FakeDriveService
>
51 fake_drive_service(new drive::FakeDriveService
);
52 scoped_ptr
<drive::DriveUploaderInterface
>
53 drive_uploader(new drive::DriveUploader(
54 fake_drive_service
.get(),
55 base::ThreadTaskRunnerHandle::Get()));
57 fake_drive_service_helper_
.reset(new FakeDriveServiceHelper(
58 fake_drive_service
.get(), drive_uploader
.get(),
59 kSyncRootFolderTitle
));
61 context_
.reset(new SyncEngineContext(fake_drive_service
.Pass(),
62 drive_uploader
.Pass(),
63 nullptr /* task_logger */,
64 base::ThreadTaskRunnerHandle::Get(),
65 base::ThreadTaskRunnerHandle::Get(),
66 nullptr /* worker_pool */));
68 ASSERT_EQ(google_apis::HTTP_CREATED
,
69 fake_drive_service_helper_
->AddOrphanedFolder(
70 kSyncRootFolderTitle
, &sync_root_folder_id_
));
73 void TearDown() override
{
75 base::RunLoop().RunUntilIdle();
79 scoped_ptr
<LevelDBWrapper
> OpenLevelDB() {
80 leveldb::DB
* db
= nullptr;
81 leveldb::Options options
;
82 options
.create_if_missing
= true;
83 options
.env
= in_memory_env_
.get();
84 leveldb::Status status
=
85 leveldb::DB::Open(options
, database_dir_
.path().AsUTF8Unsafe(), &db
);
86 EXPECT_TRUE(status
.ok());
87 return make_scoped_ptr(new LevelDBWrapper(make_scoped_ptr(db
)));
90 void SetUpInitialData(LevelDBWrapper
* db
) {
91 ServiceMetadata service_metadata
;
92 service_metadata
.set_largest_change_id(100);
93 service_metadata
.set_sync_root_tracker_id(kSyncRootTrackerID
);
94 service_metadata
.set_next_tracker_id(next_tracker_id_
);
96 FileDetails sync_root_details
;
97 sync_root_details
.set_title(kSyncRootFolderTitle
);
98 sync_root_details
.set_file_kind(FILE_KIND_FOLDER
);
99 sync_root_details
.set_change_id(1);
101 FileMetadata sync_root_metadata
;
102 sync_root_metadata
.set_file_id(sync_root_folder_id_
);
103 *sync_root_metadata
.mutable_details() = sync_root_details
;
105 FileTracker sync_root_tracker
;
106 sync_root_tracker
.set_tracker_id(service_metadata
.sync_root_tracker_id());
107 sync_root_tracker
.set_parent_tracker_id(0);
108 sync_root_tracker
.set_file_id(sync_root_metadata
.file_id());
109 sync_root_tracker
.set_tracker_kind(TRACKER_KIND_REGULAR
);
110 *sync_root_tracker
.mutable_synced_details() = sync_root_details
;
111 sync_root_tracker
.set_active(true);
113 db
->Put(kDatabaseVersionKey
,
114 base::Int64ToString(kCurrentDatabaseVersion
));
115 PutServiceMetadataToDB(service_metadata
, db
);
116 PutFileMetadataToDB(sync_root_metadata
, db
);
117 PutFileTrackerToDB(sync_root_tracker
, db
);
118 EXPECT_TRUE(db
->Commit().ok());
121 void CreateMetadataDatabase(scoped_ptr
<LevelDBWrapper
> db
) {
123 ASSERT_FALSE(context_
->GetMetadataDatabase());
124 scoped_ptr
<MetadataDatabase
> metadata_db
;
125 ASSERT_EQ(SYNC_STATUS_OK
,
126 MetadataDatabase::CreateForTesting(
127 db
.Pass(), true /* enable_on_disk_index */, &metadata_db
));
128 context_
->SetMetadataDatabase(metadata_db
.Pass());
131 SyncStatusCode
RunRegisterAppTask(const std::string
& app_id
) {
132 RegisterAppTask
task(context_
.get(), app_id
);
133 SyncStatusCode status
= SYNC_STATUS_UNKNOWN
;
134 task
.RunExclusive(CreateResultReceiver(&status
));
135 base::RunLoop().RunUntilIdle();
139 void SetUpRegisteredAppRoot(
140 const std::string
& app_id
,
141 LevelDBWrapper
* db
) {
143 details
.set_title(app_id
);
144 details
.set_file_kind(FILE_KIND_FOLDER
);
145 details
.add_parent_folder_ids(sync_root_folder_id_
);
147 FileMetadata metadata
;
148 metadata
.set_file_id(GenerateFileID());
149 *metadata
.mutable_details() = details
;
152 tracker
.set_parent_tracker_id(kSyncRootTrackerID
);
153 tracker
.set_tracker_id(next_tracker_id_
++);
154 tracker
.set_file_id(metadata
.file_id());
155 tracker
.set_tracker_kind(TRACKER_KIND_APP_ROOT
);
156 tracker
.set_app_id(app_id
);
157 *tracker
.mutable_synced_details() = details
;
158 tracker
.set_active(true);
160 PutFileMetadataToDB(metadata
, db
);
161 PutFileTrackerToDB(tracker
, db
);
162 EXPECT_TRUE(db
->Commit().ok());
165 void SetUpUnregisteredAppRoot(const std::string
& app_id
,
166 LevelDBWrapper
* db
) {
168 details
.set_title(app_id
);
169 details
.set_file_kind(FILE_KIND_FOLDER
);
170 details
.add_parent_folder_ids(sync_root_folder_id_
);
172 FileMetadata metadata
;
173 metadata
.set_file_id(GenerateFileID());
174 *metadata
.mutable_details() = details
;
177 tracker
.set_parent_tracker_id(kSyncRootTrackerID
);
178 tracker
.set_tracker_id(next_tracker_id_
++);
179 tracker
.set_file_id(metadata
.file_id());
180 tracker
.set_tracker_kind(TRACKER_KIND_REGULAR
);
181 *tracker
.mutable_synced_details() = details
;
182 tracker
.set_active(false);
184 PutFileMetadataToDB(metadata
, db
);
185 PutFileTrackerToDB(tracker
, db
);
186 EXPECT_TRUE(db
->Commit().ok());
189 size_t CountRegisteredAppRoot() {
190 std::vector
<std::string
> app_ids
;
191 context_
->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids
);
192 return app_ids
.size();
195 bool IsAppRegistered(const std::string
& app_id
) {
196 TrackerIDSet trackers
;
197 if (!context_
->GetMetadataDatabase()->FindTrackersByParentAndTitle(
198 kSyncRootTrackerID
, app_id
, &trackers
))
200 return trackers
.has_active();
203 size_t CountRemoteFileInSyncRoot() {
204 ScopedVector
<google_apis::FileResource
> files
;
205 EXPECT_EQ(google_apis::HTTP_SUCCESS
,
206 fake_drive_service_helper_
->ListFilesInFolder(
207 sync_root_folder_id_
, &files
));
211 bool GetAppRootFolderID(const std::string
& app_id
,
212 std::string
* app_root_folder_id
) {
214 if (!context_
->GetMetadataDatabase()->FindTrackersByParentAndTitle(
215 kSyncRootTrackerID
, app_id
, &files
) ||
219 FileTracker app_root_tracker
;
220 EXPECT_TRUE(context_
->GetMetadataDatabase()->FindTrackerByTrackerID(
221 files
.active_tracker(), &app_root_tracker
));
222 *app_root_folder_id
= app_root_tracker
.file_id();
226 bool HasRemoteAppRoot(const std::string
& app_id
) {
227 std::string app_root_folder_id
;
228 if (!GetAppRootFolderID(app_id
, &app_root_folder_id
))
231 scoped_ptr
<google_apis::FileResource
> entry
;
232 if (google_apis::HTTP_SUCCESS
!=
233 fake_drive_service_helper_
->GetFileResource(app_root_folder_id
, &entry
))
236 return !entry
->labels().is_trashed();
239 bool VerifyRemoteAppRootVisibility(const std::string
& app_id
) {
240 std::string app_root_folder_id
;
241 if (!GetAppRootFolderID(app_id
, &app_root_folder_id
))
244 google_apis::drive::FileVisibility visibility
;
245 if (google_apis::HTTP_SUCCESS
!=
246 fake_drive_service_helper_
->GetFileVisibility(
247 app_root_folder_id
, &visibility
))
249 if (visibility
!= google_apis::drive::FILE_VISIBILITY_PRIVATE
)
256 std::string
GenerateFileID() {
257 return base::StringPrintf("file_id_%" PRId64
, next_file_id_
++);
260 scoped_ptr
<leveldb::Env
> in_memory_env_
;
262 std::string sync_root_folder_id_
;
265 int64 next_tracker_id_
;
267 content::TestBrowserThreadBundle browser_threads_
;
268 base::ScopedTempDir database_dir_
;
270 scoped_ptr
<SyncEngineContext
> context_
;
271 scoped_ptr
<FakeDriveServiceHelper
> fake_drive_service_helper_
;
273 DISALLOW_COPY_AND_ASSIGN(RegisterAppTaskTest
);
276 TEST_F(RegisterAppTaskTest
, AlreadyRegistered
) {
277 scoped_ptr
<LevelDBWrapper
> db
= OpenLevelDB();
279 SetUpInitialData(db
.get());
281 const std::string kAppID
= "app_id";
282 SetUpRegisteredAppRoot(kAppID
, db
.get());
284 CreateMetadataDatabase(db
.Pass());
285 EXPECT_EQ(SYNC_STATUS_OK
, RunRegisterAppTask(kAppID
));
287 EXPECT_EQ(1u, CountRegisteredAppRoot());
288 EXPECT_TRUE(IsAppRegistered(kAppID
));
291 TEST_F(RegisterAppTaskTest
, CreateAppFolder
) {
292 scoped_ptr
<LevelDBWrapper
> db
= OpenLevelDB();
294 SetUpInitialData(db
.get());
296 const std::string kAppID
= "app_id";
297 CreateMetadataDatabase(db
.Pass());
298 RunRegisterAppTask(kAppID
);
300 EXPECT_EQ(1u, CountRegisteredAppRoot());
301 EXPECT_TRUE(IsAppRegistered(kAppID
));
303 EXPECT_EQ(1u, CountRemoteFileInSyncRoot());
304 EXPECT_TRUE(HasRemoteAppRoot(kAppID
));
305 EXPECT_TRUE(VerifyRemoteAppRootVisibility(kAppID
));
308 TEST_F(RegisterAppTaskTest
, RegisterExistingFolder
) {
309 scoped_ptr
<LevelDBWrapper
> db
= OpenLevelDB();
311 SetUpInitialData(db
.get());
313 const std::string kAppID
= "app_id";
314 SetUpUnregisteredAppRoot(kAppID
, db
.get());
316 CreateMetadataDatabase(db
.Pass());
317 RunRegisterAppTask(kAppID
);
319 EXPECT_EQ(1u, CountRegisteredAppRoot());
320 EXPECT_TRUE(IsAppRegistered(kAppID
));
323 TEST_F(RegisterAppTaskTest
, RegisterExistingFolder_MultipleCandidate
) {
324 scoped_ptr
<LevelDBWrapper
> db
= OpenLevelDB();
326 SetUpInitialData(db
.get());
328 const std::string kAppID
= "app_id";
329 SetUpUnregisteredAppRoot(kAppID
, db
.get());
330 SetUpUnregisteredAppRoot(kAppID
, db
.get());
332 CreateMetadataDatabase(db
.Pass());
333 RunRegisterAppTask(kAppID
);
335 EXPECT_EQ(1u, CountRegisteredAppRoot());
336 EXPECT_TRUE(IsAppRegistered(kAppID
));
339 } // namespace drive_backend
340 } // namespace sync_file_system