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