register_app_task_unittest.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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. 4 5#include "chrome/browser/sync_file_system/drive_backend/register_app_task.h" 6 7#include <vector> 8 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/drive/drive_uploader.h" 16#include "chrome/browser/drive/fake_drive_service.h" 17#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h" 18#include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h" 19#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h" 20#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 21#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" 22#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 23#include "chrome/browser/sync_file_system/sync_file_system_test_util.h" 24#include "content/public/test/test_browser_thread_bundle.h" 25#include "google_apis/drive/drive_api_parser.h" 26#include "testing/gtest/include/gtest/gtest.h" 27#include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 28#include "third_party/leveldatabase/src/include/leveldb/db.h" 29#include "third_party/leveldatabase/src/include/leveldb/env.h" 30#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 31 32namespace sync_file_system { 33namespace drive_backend { 34 35namespace { 36const int64 kSyncRootTrackerID = 100; 37} // namespace 38 39class RegisterAppTaskTest : public testing::Test { 40 public: 41 RegisterAppTaskTest() 42 : next_file_id_(1000), 43 next_tracker_id_(10000) {} 44 virtual ~RegisterAppTaskTest() {} 45 46 virtual void SetUp() OVERRIDE { 47 ASSERT_TRUE(database_dir_.CreateUniqueTempDir()); 48 in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); 49 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())); 56 57 fake_drive_service_helper_.reset(new FakeDriveServiceHelper( 58 fake_drive_service.get(), drive_uploader.get(), 59 kSyncRootFolderTitle)); 60 61 context_.reset( 62 new SyncEngineContext( 63 fake_drive_service.PassAs<drive::DriveServiceInterface>(), 64 drive_uploader.Pass(), 65 NULL, 66 base::ThreadTaskRunnerHandle::Get(), 67 base::ThreadTaskRunnerHandle::Get(), 68 base::ThreadTaskRunnerHandle::Get())); 69 70 ASSERT_EQ(google_apis::HTTP_CREATED, 71 fake_drive_service_helper_->AddOrphanedFolder( 72 kSyncRootFolderTitle, &sync_root_folder_id_)); 73 } 74 75 virtual void TearDown() OVERRIDE { 76 context_.reset(); 77 base::RunLoop().RunUntilIdle(); 78 } 79 80 protected: 81 scoped_ptr<leveldb::DB> OpenLevelDB() { 82 leveldb::DB* db = NULL; 83 leveldb::Options options; 84 options.create_if_missing = true; 85 options.env = in_memory_env_.get(); 86 leveldb::Status status = 87 leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db); 88 EXPECT_TRUE(status.ok()); 89 return make_scoped_ptr<leveldb::DB>(db); 90 } 91 92 void SetUpInitialData(leveldb::DB* db) { 93 ServiceMetadata service_metadata; 94 service_metadata.set_largest_change_id(100); 95 service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID); 96 service_metadata.set_next_tracker_id(next_tracker_id_); 97 98 FileDetails sync_root_details; 99 sync_root_details.set_title(kSyncRootFolderTitle); 100 sync_root_details.set_file_kind(FILE_KIND_FOLDER); 101 sync_root_details.set_change_id(1); 102 103 FileMetadata sync_root_metadata; 104 sync_root_metadata.set_file_id(sync_root_folder_id_); 105 *sync_root_metadata.mutable_details() = sync_root_details; 106 107 FileTracker sync_root_tracker; 108 sync_root_tracker.set_tracker_id(service_metadata.sync_root_tracker_id()); 109 sync_root_tracker.set_parent_tracker_id(0); 110 sync_root_tracker.set_file_id(sync_root_metadata.file_id()); 111 sync_root_tracker.set_tracker_kind(TRACKER_KIND_REGULAR); 112 *sync_root_tracker.mutable_synced_details() = sync_root_details; 113 sync_root_tracker.set_active(true); 114 115 leveldb::WriteBatch batch; 116 batch.Put(kDatabaseVersionKey, 117 base::Int64ToString(kCurrentDatabaseVersion)); 118 PutServiceMetadataToBatch(service_metadata, &batch); 119 PutFileMetadataToBatch(sync_root_metadata, &batch); 120 PutFileTrackerToBatch(sync_root_tracker, &batch); 121 EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok()); 122 } 123 124 void CreateMetadataDatabase(scoped_ptr<leveldb::DB> db) { 125 ASSERT_TRUE(db); 126 ASSERT_FALSE(context_->GetMetadataDatabase()); 127 scoped_ptr<MetadataDatabase> metadata_db; 128 ASSERT_EQ(SYNC_STATUS_OK, 129 MetadataDatabase::CreateForTesting( 130 db.Pass(), &metadata_db)); 131 context_->SetMetadataDatabase(metadata_db.Pass()); 132 } 133 134 SyncStatusCode RunRegisterAppTask(const std::string& app_id) { 135 RegisterAppTask task(context_.get(), app_id); 136 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 137 task.RunExclusive(CreateResultReceiver(&status)); 138 base::RunLoop().RunUntilIdle(); 139 return status; 140 } 141 142 void SetUpRegisteredAppRoot( 143 const std::string& app_id, 144 leveldb::DB* db) { 145 FileDetails details; 146 details.set_title(app_id); 147 details.set_file_kind(FILE_KIND_FOLDER); 148 details.add_parent_folder_ids(sync_root_folder_id_); 149 150 FileMetadata metadata; 151 metadata.set_file_id(GenerateFileID()); 152 *metadata.mutable_details() = details; 153 154 FileTracker tracker; 155 tracker.set_parent_tracker_id(kSyncRootTrackerID); 156 tracker.set_tracker_id(next_tracker_id_++); 157 tracker.set_file_id(metadata.file_id()); 158 tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT); 159 tracker.set_app_id(app_id); 160 *tracker.mutable_synced_details() = details; 161 tracker.set_active(true); 162 163 leveldb::WriteBatch batch; 164 PutFileMetadataToBatch(metadata, &batch); 165 PutFileTrackerToBatch(tracker, &batch); 166 EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok()); 167 } 168 169 void SetUpUnregisteredAppRoot(const std::string& app_id, 170 leveldb::DB* db) { 171 FileDetails details; 172 details.set_title(app_id); 173 details.set_file_kind(FILE_KIND_FOLDER); 174 details.add_parent_folder_ids(sync_root_folder_id_); 175 176 FileMetadata metadata; 177 metadata.set_file_id(GenerateFileID()); 178 *metadata.mutable_details() = details; 179 180 FileTracker tracker; 181 tracker.set_parent_tracker_id(kSyncRootTrackerID); 182 tracker.set_tracker_id(next_tracker_id_++); 183 tracker.set_file_id(metadata.file_id()); 184 tracker.set_tracker_kind(TRACKER_KIND_REGULAR); 185 *tracker.mutable_synced_details() = details; 186 tracker.set_active(false); 187 188 leveldb::WriteBatch batch; 189 PutFileMetadataToBatch(metadata, &batch); 190 PutFileTrackerToBatch(tracker, &batch); 191 EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok()); 192 } 193 194 size_t CountRegisteredAppRoot() { 195 std::vector<std::string> app_ids; 196 context_->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids); 197 return app_ids.size(); 198 } 199 200 bool IsAppRegistered(const std::string& app_id) { 201 TrackerIDSet trackers; 202 if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle( 203 kSyncRootTrackerID, app_id, &trackers)) 204 return false; 205 return trackers.has_active(); 206 } 207 208 size_t CountRemoteFileInSyncRoot() { 209 ScopedVector<google_apis::ResourceEntry> files; 210 EXPECT_EQ(google_apis::HTTP_SUCCESS, 211 fake_drive_service_helper_->ListFilesInFolder( 212 sync_root_folder_id_, &files)); 213 return files.size(); 214 } 215 216 bool HasRemoteAppRoot(const std::string& app_id) { 217 TrackerIDSet files; 218 if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle( 219 kSyncRootTrackerID, app_id, &files) || 220 !files.has_active()) 221 return false; 222 223 FileTracker app_root_tracker; 224 EXPECT_TRUE(context_->GetMetadataDatabase()->FindTrackerByTrackerID( 225 files.active_tracker(), &app_root_tracker)); 226 std::string app_root_folder_id = app_root_tracker.file_id(); 227 scoped_ptr<google_apis::FileResource> entry; 228 if (google_apis::HTTP_SUCCESS != 229 fake_drive_service_helper_->GetFileResource(app_root_folder_id, &entry)) 230 return false; 231 232 return !entry->labels().is_trashed(); 233 } 234 235 private: 236 std::string GenerateFileID() { 237 return base::StringPrintf("file_id_%" PRId64, next_file_id_++); 238 } 239 240 scoped_ptr<leveldb::Env> in_memory_env_; 241 242 std::string sync_root_folder_id_; 243 244 int64 next_file_id_; 245 int64 next_tracker_id_; 246 247 content::TestBrowserThreadBundle browser_threads_; 248 base::ScopedTempDir database_dir_; 249 250 scoped_ptr<SyncEngineContext> context_; 251 scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_; 252 253 DISALLOW_COPY_AND_ASSIGN(RegisterAppTaskTest); 254}; 255 256TEST_F(RegisterAppTaskTest, AlreadyRegistered) { 257 scoped_ptr<leveldb::DB> db(OpenLevelDB()); 258 ASSERT_TRUE(db); 259 SetUpInitialData(db.get()); 260 261 const std::string kAppID = "app_id"; 262 SetUpRegisteredAppRoot(kAppID, db.get()); 263 264 CreateMetadataDatabase(db.Pass()); 265 EXPECT_EQ(SYNC_STATUS_OK, RunRegisterAppTask(kAppID)); 266 267 EXPECT_EQ(1u, CountRegisteredAppRoot()); 268 EXPECT_TRUE(IsAppRegistered(kAppID)); 269} 270 271TEST_F(RegisterAppTaskTest, CreateAppFolder) { 272 scoped_ptr<leveldb::DB> db(OpenLevelDB()); 273 ASSERT_TRUE(db); 274 SetUpInitialData(db.get()); 275 276 const std::string kAppID = "app_id"; 277 CreateMetadataDatabase(db.Pass()); 278 RunRegisterAppTask(kAppID); 279 280 EXPECT_EQ(1u, CountRegisteredAppRoot()); 281 EXPECT_TRUE(IsAppRegistered(kAppID)); 282 283 EXPECT_EQ(1u, CountRemoteFileInSyncRoot()); 284 EXPECT_TRUE(HasRemoteAppRoot(kAppID)); 285} 286 287TEST_F(RegisterAppTaskTest, RegisterExistingFolder) { 288 scoped_ptr<leveldb::DB> db(OpenLevelDB()); 289 ASSERT_TRUE(db); 290 SetUpInitialData(db.get()); 291 292 const std::string kAppID = "app_id"; 293 SetUpUnregisteredAppRoot(kAppID, db.get()); 294 295 CreateMetadataDatabase(db.Pass()); 296 RunRegisterAppTask(kAppID); 297 298 EXPECT_EQ(1u, CountRegisteredAppRoot()); 299 EXPECT_TRUE(IsAppRegistered(kAppID)); 300} 301 302TEST_F(RegisterAppTaskTest, RegisterExistingFolder_MultipleCandidate) { 303 scoped_ptr<leveldb::DB> db(OpenLevelDB()); 304 ASSERT_TRUE(db); 305 SetUpInitialData(db.get()); 306 307 const std::string kAppID = "app_id"; 308 SetUpUnregisteredAppRoot(kAppID, db.get()); 309 SetUpUnregisteredAppRoot(kAppID, db.get()); 310 311 CreateMetadataDatabase(db.Pass()); 312 RunRegisterAppTask(kAppID); 313 314 EXPECT_EQ(1u, CountRegisteredAppRoot()); 315 EXPECT_TRUE(IsAppRegistered(kAppID)); 316} 317 318} // namespace drive_backend 319} // namespace sync_file_system 320