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"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/format_macros.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "chrome/browser/drive/fake_drive_service.h"
13 #include "chrome/browser/google_apis/gdata_wapi_parser.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_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_v1/fake_drive_service_helper.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 "testing/gtest/include/gtest/gtest.h"
23 #include "third_party/leveldatabase/src/include/leveldb/db.h"
24 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
26 namespace sync_file_system {
27 namespace drive_backend {
30 const int64 kSyncRootTrackerID = 100;
33 class RegisterAppTaskTest : public testing::Test,
34 public SyncEngineContext {
37 : next_file_id_(1000),
38 next_tracker_id_(10000) {}
39 virtual ~RegisterAppTaskTest() {}
41 virtual void SetUp() OVERRIDE {
42 ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
44 fake_drive_service_.reset(new drive::FakeDriveService);
45 ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
46 "sync_file_system/account_metadata.json"));
47 ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
48 "gdata/empty_feed.json"));
50 drive_uploader_.reset(new drive::DriveUploader(
51 fake_drive_service_.get(), base::MessageLoopProxy::current()));
53 fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
54 fake_drive_service_.get(), drive_uploader_.get()));
56 ASSERT_EQ(google_apis::HTTP_CREATED,
57 fake_drive_service_helper_->AddOrphanedFolder(
58 kSyncRootFolderTitle, &sync_root_folder_id_));
61 virtual void TearDown() OVERRIDE {
62 metadata_database_.reset();
63 base::RunLoop().RunUntilIdle();
66 virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE {
67 return fake_drive_service_.get();
70 virtual MetadataDatabase* GetMetadataDatabase() OVERRIDE {
71 return metadata_database_.get();
75 scoped_ptr<leveldb::DB> OpenLevelDB() {
76 leveldb::DB* db = NULL;
77 leveldb::Options options;
78 options.create_if_missing = true;
79 leveldb::Status status =
80 leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
81 EXPECT_TRUE(status.ok());
82 return make_scoped_ptr<leveldb::DB>(db);
85 void SetUpInitialData(leveldb::DB* db) {
86 ServiceMetadata service_metadata;
87 service_metadata.set_largest_change_id(100);
88 service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
89 service_metadata.set_next_tracker_id(next_tracker_id_);
91 FileDetails sync_root_details;
92 sync_root_details.set_title(kSyncRootFolderTitle);
93 sync_root_details.set_file_kind(FILE_KIND_FOLDER);
94 sync_root_details.set_change_id(1);
96 FileMetadata sync_root_metadata;
97 sync_root_metadata.set_file_id(sync_root_folder_id_);
98 *sync_root_metadata.mutable_details() = sync_root_details;
100 FileTracker sync_root_tracker;
101 sync_root_tracker.set_tracker_id(service_metadata.sync_root_tracker_id());
102 sync_root_tracker.set_parent_tracker_id(0);
103 sync_root_tracker.set_file_id(sync_root_metadata.file_id());
104 sync_root_tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
105 *sync_root_tracker.mutable_synced_details() = sync_root_details;
106 sync_root_tracker.set_active(true);
108 leveldb::WriteBatch batch;
109 batch.Put(kDatabaseVersionKey,
110 base::Int64ToString(kCurrentDatabaseVersion));
111 PutServiceMetadataToBatch(service_metadata, &batch);
112 PutFileToBatch(sync_root_metadata, &batch);
113 PutTrackerToBatch(sync_root_tracker, &batch);
114 EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
117 void CreateMetadataDatabase(scoped_ptr<leveldb::DB> db) {
119 ASSERT_FALSE(metadata_database_);
120 ASSERT_EQ(SYNC_STATUS_OK,
121 MetadataDatabase::CreateForTesting(
122 db.Pass(), &metadata_database_));
125 SyncStatusCode RunRegisterAppTask(const std::string& app_id) {
126 RegisterAppTask task(this, app_id);
127 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
128 task.Run(CreateResultReceiver(&status));
129 base::RunLoop().RunUntilIdle();
133 void SetUpRegisteredAppRoot(
134 const std::string& app_id,
137 details.set_title(app_id);
138 details.set_file_kind(FILE_KIND_FOLDER);
139 details.add_parent_folder_ids(sync_root_folder_id_);
141 FileMetadata metadata;
142 metadata.set_file_id(GenerateFileID());
143 *metadata.mutable_details() = details;
146 tracker.set_parent_tracker_id(kSyncRootTrackerID);
147 tracker.set_tracker_id(next_tracker_id_++);
148 tracker.set_file_id(metadata.file_id());
149 tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
150 tracker.set_app_id(app_id);
151 *tracker.mutable_synced_details() = details;
152 tracker.set_active(true);
154 leveldb::WriteBatch batch;
155 PutFileToBatch(metadata, &batch);
156 PutTrackerToBatch(tracker, &batch);
157 EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
160 void SetUpUnregisteredAppRoot(const std::string& app_id,
163 details.set_title(app_id);
164 details.set_file_kind(FILE_KIND_FOLDER);
165 details.add_parent_folder_ids(sync_root_folder_id_);
167 FileMetadata metadata;
168 metadata.set_file_id(GenerateFileID());
169 *metadata.mutable_details() = details;
172 tracker.set_parent_tracker_id(kSyncRootTrackerID);
173 tracker.set_tracker_id(next_tracker_id_++);
174 tracker.set_file_id(metadata.file_id());
175 tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
176 *tracker.mutable_synced_details() = details;
177 tracker.set_active(false);
179 leveldb::WriteBatch batch;
180 PutFileToBatch(metadata, &batch);
181 PutTrackerToBatch(tracker, &batch);
182 EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
185 size_t CountRegisteredAppRoot() {
186 // TODO(tzik): Add function to MetadataDatabase to list trackers by parent.
187 typedef MetadataDatabase::TrackersByTitle TrackersByTitle;
188 const TrackersByTitle& trackers_by_title =
189 metadata_database_->trackers_by_parent_and_title_[kSyncRootTrackerID];
192 for (TrackersByTitle::const_iterator itr = trackers_by_title.begin();
193 itr != trackers_by_title.end(); ++itr) {
194 if (itr->second.has_active())
201 bool IsAppRegistered(const std::string& app_id) {
203 if (!metadata_database_->FindTrackersByParentAndTitle(
204 kSyncRootTrackerID, app_id, &trackers))
206 return trackers.has_active();
209 size_t CountRemoteFileInSyncRoot() {
210 ScopedVector<google_apis::ResourceEntry> files;
211 EXPECT_EQ(google_apis::HTTP_SUCCESS,
212 fake_drive_service_helper_->ListFilesInFolder(
213 sync_root_folder_id_, &files));
217 bool HasRemoteAppRoot(const std::string& app_id) {
219 if (!metadata_database_->FindTrackersByParentAndTitle(
220 kSyncRootTrackerID, app_id, &files) ||
224 std::string app_root_folder_id = files.active_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 std::string sync_root_folder_id_;
242 int64 next_tracker_id_;
244 content::TestBrowserThreadBundle browser_threads_;
245 base::ScopedTempDir database_dir_;
247 scoped_ptr<drive::FakeDriveService> fake_drive_service_;
248 scoped_ptr<drive::DriveUploader> drive_uploader_;
249 scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
251 scoped_ptr<MetadataDatabase> metadata_database_;
253 DISALLOW_COPY_AND_ASSIGN(RegisterAppTaskTest);
256 TEST_F(RegisterAppTaskTest, AlreadyRegistered) {
257 scoped_ptr<leveldb::DB> db(OpenLevelDB());
259 SetUpInitialData(db.get());
261 const std::string kAppID = "app_id";
262 SetUpRegisteredAppRoot(kAppID, db.get());
264 CreateMetadataDatabase(db.Pass());
265 EXPECT_EQ(SYNC_STATUS_OK, RunRegisterAppTask(kAppID));
267 EXPECT_EQ(1u, CountRegisteredAppRoot());
268 EXPECT_TRUE(IsAppRegistered(kAppID));
271 TEST_F(RegisterAppTaskTest, CreateAppFolder) {
272 scoped_ptr<leveldb::DB> db(OpenLevelDB());
274 SetUpInitialData(db.get());
276 const std::string kAppID = "app_id";
277 CreateMetadataDatabase(db.Pass());
278 RunRegisterAppTask(kAppID);
280 EXPECT_EQ(1u, CountRegisteredAppRoot());
281 EXPECT_TRUE(IsAppRegistered(kAppID));
283 EXPECT_EQ(1u, CountRemoteFileInSyncRoot());
284 EXPECT_TRUE(HasRemoteAppRoot(kAppID));
287 TEST_F(RegisterAppTaskTest, RegisterExistingFolder) {
288 scoped_ptr<leveldb::DB> db(OpenLevelDB());
290 SetUpInitialData(db.get());
292 const std::string kAppID = "app_id";
293 SetUpUnregisteredAppRoot(kAppID, db.get());
295 CreateMetadataDatabase(db.Pass());
296 RunRegisterAppTask(kAppID);
298 EXPECT_EQ(1u, CountRegisteredAppRoot());
299 EXPECT_TRUE(IsAppRegistered(kAppID));
302 TEST_F(RegisterAppTaskTest, RegisterExistingFolder_MultipleCandidate) {
303 scoped_ptr<leveldb::DB> db(OpenLevelDB());
305 SetUpInitialData(db.get());
307 const std::string kAppID = "app_id";
308 SetUpUnregisteredAppRoot(kAppID, db.get());
309 SetUpUnregisteredAppRoot(kAppID, db.get());
311 CreateMetadataDatabase(db.Pass());
312 RunRegisterAppTask(kAppID);
314 EXPECT_EQ(1u, CountRegisteredAppRoot());
315 EXPECT_TRUE(IsAppRegistered(kAppID));
318 } // namespace drive_backend
319 } // namespace sync_file_system