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 "chrome/browser/drive/drive_uploader.h"
15 #include "chrome/browser/drive/fake_drive_service.h"
16 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
17 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
18 #include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.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 "content/public/test/test_browser_thread_bundle.h"
24 #include "google_apis/drive/gdata_wapi_parser.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
27 #include "third_party/leveldatabase/src/include/leveldb/db.h"
28 #include "third_party/leveldatabase/src/include/leveldb/env.h"
29 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
31 namespace sync_file_system {
32 namespace drive_backend {
35 const int64 kSyncRootTrackerID = 100;
38 class RegisterAppTaskTest : public testing::Test {
41 : next_file_id_(1000),
42 next_tracker_id_(10000) {}
43 virtual ~RegisterAppTaskTest() {}
45 virtual void SetUp() OVERRIDE {
46 ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
47 in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
49 scoped_ptr<drive::FakeDriveService>
50 fake_drive_service(new drive::FakeDriveService);
51 scoped_ptr<drive::DriveUploaderInterface>
52 drive_uploader(new drive::DriveUploader(
53 fake_drive_service.get(),
54 base::MessageLoopProxy::current()));
56 fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
57 fake_drive_service.get(), drive_uploader.get(),
58 kSyncRootFolderTitle));
61 new SyncEngineContext(
62 fake_drive_service.PassAs<drive::DriveServiceInterface>(),
63 drive_uploader.Pass(),
64 base::MessageLoopProxy::current(),
65 base::MessageLoopProxy::current(),
66 base::MessageLoopProxy::current()));
68 ASSERT_EQ(google_apis::HTTP_CREATED,
69 fake_drive_service_helper_->AddOrphanedFolder(
70 kSyncRootFolderTitle, &sync_root_folder_id_));
73 virtual void TearDown() OVERRIDE {
75 base::RunLoop().RunUntilIdle();
79 scoped_ptr<leveldb::DB> OpenLevelDB() {
80 leveldb::DB* db = NULL;
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<leveldb::DB>(db);
90 void SetUpInitialData(leveldb::DB* 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 leveldb::WriteBatch batch;
114 batch.Put(kDatabaseVersionKey,
115 base::Int64ToString(kCurrentDatabaseVersion));
116 PutServiceMetadataToBatch(service_metadata, &batch);
117 PutFileMetadataToBatch(sync_root_metadata, &batch);
118 PutFileTrackerToBatch(sync_root_tracker, &batch);
119 EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
122 void CreateMetadataDatabase(scoped_ptr<leveldb::DB> db) {
124 ASSERT_FALSE(context_->GetMetadataDatabase());
125 scoped_ptr<MetadataDatabase> metadata_db;
126 ASSERT_EQ(SYNC_STATUS_OK,
127 MetadataDatabase::CreateForTesting(
128 db.Pass(), &metadata_db));
129 context_->SetMetadataDatabase(metadata_db.Pass());
132 SyncStatusCode RunRegisterAppTask(const std::string& app_id) {
133 RegisterAppTask task(context_.get(), app_id);
134 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
135 task.RunExclusive(CreateResultReceiver(&status));
136 base::RunLoop().RunUntilIdle();
140 void SetUpRegisteredAppRoot(
141 const std::string& app_id,
144 details.set_title(app_id);
145 details.set_file_kind(FILE_KIND_FOLDER);
146 details.add_parent_folder_ids(sync_root_folder_id_);
148 FileMetadata metadata;
149 metadata.set_file_id(GenerateFileID());
150 *metadata.mutable_details() = details;
153 tracker.set_parent_tracker_id(kSyncRootTrackerID);
154 tracker.set_tracker_id(next_tracker_id_++);
155 tracker.set_file_id(metadata.file_id());
156 tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
157 tracker.set_app_id(app_id);
158 *tracker.mutable_synced_details() = details;
159 tracker.set_active(true);
161 leveldb::WriteBatch batch;
162 PutFileMetadataToBatch(metadata, &batch);
163 PutFileTrackerToBatch(tracker, &batch);
164 EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
167 void SetUpUnregisteredAppRoot(const std::string& app_id,
170 details.set_title(app_id);
171 details.set_file_kind(FILE_KIND_FOLDER);
172 details.add_parent_folder_ids(sync_root_folder_id_);
174 FileMetadata metadata;
175 metadata.set_file_id(GenerateFileID());
176 *metadata.mutable_details() = details;
179 tracker.set_parent_tracker_id(kSyncRootTrackerID);
180 tracker.set_tracker_id(next_tracker_id_++);
181 tracker.set_file_id(metadata.file_id());
182 tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
183 *tracker.mutable_synced_details() = details;
184 tracker.set_active(false);
186 leveldb::WriteBatch batch;
187 PutFileMetadataToBatch(metadata, &batch);
188 PutFileTrackerToBatch(tracker, &batch);
189 EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
192 size_t CountRegisteredAppRoot() {
193 std::vector<std::string> app_ids;
194 context_->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
195 return app_ids.size();
198 bool IsAppRegistered(const std::string& app_id) {
199 TrackerIDSet trackers;
200 if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
201 kSyncRootTrackerID, app_id, &trackers))
203 return trackers.has_active();
206 size_t CountRemoteFileInSyncRoot() {
207 ScopedVector<google_apis::ResourceEntry> files;
208 EXPECT_EQ(google_apis::HTTP_SUCCESS,
209 fake_drive_service_helper_->ListFilesInFolder(
210 sync_root_folder_id_, &files));
214 bool HasRemoteAppRoot(const std::string& app_id) {
216 if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
217 kSyncRootTrackerID, app_id, &files) ||
221 FileTracker app_root_tracker;
222 EXPECT_TRUE(context_->GetMetadataDatabase()->FindTrackerByTrackerID(
223 files.active_tracker(), &app_root_tracker));
224 std::string app_root_folder_id = app_root_tracker.file_id();
225 scoped_ptr<google_apis::ResourceEntry> entry;
226 if (google_apis::HTTP_SUCCESS !=
227 fake_drive_service_helper_->GetResourceEntry(
228 app_root_folder_id, &entry))
231 return !entry->deleted();
235 std::string GenerateFileID() {
236 return base::StringPrintf("file_id_%" PRId64, next_file_id_++);
239 scoped_ptr<leveldb::Env> in_memory_env_;
241 std::string sync_root_folder_id_;
244 int64 next_tracker_id_;
246 content::TestBrowserThreadBundle browser_threads_;
247 base::ScopedTempDir database_dir_;
249 scoped_ptr<SyncEngineContext> context_;
250 scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
252 DISALLOW_COPY_AND_ASSIGN(RegisterAppTaskTest);
255 TEST_F(RegisterAppTaskTest, AlreadyRegistered) {
256 scoped_ptr<leveldb::DB> db(OpenLevelDB());
258 SetUpInitialData(db.get());
260 const std::string kAppID = "app_id";
261 SetUpRegisteredAppRoot(kAppID, db.get());
263 CreateMetadataDatabase(db.Pass());
264 EXPECT_EQ(SYNC_STATUS_OK, RunRegisterAppTask(kAppID));
266 EXPECT_EQ(1u, CountRegisteredAppRoot());
267 EXPECT_TRUE(IsAppRegistered(kAppID));
270 TEST_F(RegisterAppTaskTest, CreateAppFolder) {
271 scoped_ptr<leveldb::DB> db(OpenLevelDB());
273 SetUpInitialData(db.get());
275 const std::string kAppID = "app_id";
276 CreateMetadataDatabase(db.Pass());
277 RunRegisterAppTask(kAppID);
279 EXPECT_EQ(1u, CountRegisteredAppRoot());
280 EXPECT_TRUE(IsAppRegistered(kAppID));
282 EXPECT_EQ(1u, CountRemoteFileInSyncRoot());
283 EXPECT_TRUE(HasRemoteAppRoot(kAppID));
286 TEST_F(RegisterAppTaskTest, RegisterExistingFolder) {
287 scoped_ptr<leveldb::DB> db(OpenLevelDB());
289 SetUpInitialData(db.get());
291 const std::string kAppID = "app_id";
292 SetUpUnregisteredAppRoot(kAppID, db.get());
294 CreateMetadataDatabase(db.Pass());
295 RunRegisterAppTask(kAppID);
297 EXPECT_EQ(1u, CountRegisteredAppRoot());
298 EXPECT_TRUE(IsAppRegistered(kAppID));
301 TEST_F(RegisterAppTaskTest, RegisterExistingFolder_MultipleCandidate) {
302 scoped_ptr<leveldb::DB> db(OpenLevelDB());
304 SetUpInitialData(db.get());
306 const std::string kAppID = "app_id";
307 SetUpUnregisteredAppRoot(kAppID, db.get());
308 SetUpUnregisteredAppRoot(kAppID, db.get());
310 CreateMetadataDatabase(db.Pass());
311 RunRegisterAppTask(kAppID);
313 EXPECT_EQ(1u, CountRegisteredAppRoot());
314 EXPECT_TRUE(IsAppRegistered(kAppID));
317 } // namespace drive_backend
318 } // namespace sync_file_system