sync_engine_initializer_unittest.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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/sync_engine_initializer.h" 6 7#include "base/bind.h" 8#include "base/files/scoped_temp_dir.h" 9#include "base/run_loop.h" 10#include "chrome/browser/drive/drive_api_util.h" 11#include "chrome/browser/drive/drive_uploader.h" 12#include "chrome/browser/drive/fake_drive_service.h" 13#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h" 14#include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h" 15#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 16#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" 17#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 18#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h" 19#include "chrome/browser/sync_file_system/sync_file_system_test_util.h" 20#include "content/public/test/test_browser_thread_bundle.h" 21#include "google_apis/drive/drive_api_parser.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/env.h" 26 27namespace sync_file_system { 28namespace drive_backend { 29 30namespace { 31 32const int64 kInitialLargestChangeID = 1234; 33 34} // namespace 35 36class SyncEngineInitializerTest : public testing::Test { 37 public: 38 struct TrackedFile { 39 scoped_ptr<google_apis::FileResource> resource; 40 FileMetadata metadata; 41 FileTracker tracker; 42 }; 43 44 SyncEngineInitializerTest() {} 45 virtual ~SyncEngineInitializerTest() {} 46 47 virtual void SetUp() OVERRIDE { 48 ASSERT_TRUE(database_dir_.CreateUniqueTempDir()); 49 in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); 50 51 scoped_ptr<drive::FakeDriveService> fake_drive_service( 52 new drive::FakeDriveService()); 53 ASSERT_TRUE(fake_drive_service->LoadAccountMetadataForWapi( 54 "sync_file_system/account_metadata.json")); 55 ASSERT_TRUE(fake_drive_service->LoadResourceListForWapi( 56 "gdata/empty_feed.json")); 57 58 sync_context_.reset(new SyncEngineContext( 59 fake_drive_service.PassAs<drive::DriveServiceInterface>(), 60 scoped_ptr<drive::DriveUploaderInterface>(), 61 base::MessageLoopProxy::current())); 62 63 sync_task_manager_.reset(new SyncTaskManager( 64 base::WeakPtr<SyncTaskManager::Client>(), 65 1 /* maximum_parallel_task */)); 66 sync_task_manager_->Initialize(SYNC_STATUS_OK); 67 } 68 69 virtual void TearDown() OVERRIDE { 70 sync_task_manager_.reset(); 71 metadata_database_.reset(); 72 sync_context_.reset(); 73 base::RunLoop().RunUntilIdle(); 74 } 75 76 base::FilePath database_path() { 77 return database_dir_.path(); 78 } 79 80 SyncStatusCode RunInitializer() { 81 SyncEngineInitializer* initializer = 82 new SyncEngineInitializer( 83 sync_context_.get(), 84 base::MessageLoopProxy::current(), 85 database_path(), 86 in_memory_env_.get()); 87 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 88 89 sync_task_manager_->ScheduleSyncTask( 90 FROM_HERE, 91 scoped_ptr<SyncTask>(initializer), 92 SyncTaskManager::PRIORITY_MED, 93 base::Bind(&SyncEngineInitializerTest::DidRunInitializer, 94 base::Unretained(this), initializer, &status)); 95 96 base::RunLoop().RunUntilIdle(); 97 return status; 98 } 99 100 void DidRunInitializer(SyncEngineInitializer* initializer, 101 SyncStatusCode* status_out, 102 SyncStatusCode status) { 103 *status_out = status; 104 metadata_database_ = initializer->PassMetadataDatabase(); 105 } 106 107 SyncStatusCode PopulateDatabase( 108 const google_apis::FileResource& sync_root, 109 const google_apis::FileResource** app_roots, 110 size_t app_roots_count) { 111 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 112 scoped_ptr<MetadataDatabase> database; 113 MetadataDatabase::Create( 114 base::MessageLoopProxy::current(), 115 database_path(), 116 in_memory_env_.get(), 117 CreateResultReceiver(&status, &database)); 118 base::RunLoop().RunUntilIdle(); 119 if (status != SYNC_STATUS_OK) 120 return status; 121 122 // |app_root_list| must not own the resources here. Be sure to call 123 // weak_clear later. 124 ScopedVector<google_apis::FileResource> app_root_list; 125 for (size_t i = 0; i < app_roots_count; ++i) { 126 app_root_list.push_back( 127 const_cast<google_apis::FileResource*>(app_roots[i])); 128 } 129 130 status = SYNC_STATUS_UNKNOWN; 131 database->PopulateInitialData(kInitialLargestChangeID, 132 sync_root, 133 app_root_list, 134 CreateResultReceiver(&status)); 135 base::RunLoop().RunUntilIdle(); 136 137 app_root_list.weak_clear(); 138 139 return SYNC_STATUS_OK; 140 } 141 142 scoped_ptr<google_apis::FileResource> CreateRemoteFolder( 143 const std::string& parent_folder_id, 144 const std::string& title) { 145 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 146 scoped_ptr<google_apis::ResourceEntry> entry; 147 sync_context_->GetDriveService()->AddNewDirectory( 148 parent_folder_id, title, 149 drive::DriveServiceInterface::AddNewDirectoryOptions(), 150 CreateResultReceiver(&error, &entry)); 151 base::RunLoop().RunUntilIdle(); 152 153 EXPECT_EQ(google_apis::HTTP_CREATED, error); 154 if (!entry) 155 scoped_ptr<google_apis::FileResource>(); 156 return drive::util::ConvertResourceEntryToFileResource(*entry); 157 } 158 159 scoped_ptr<google_apis::FileResource> CreateRemoteSyncRoot() { 160 scoped_ptr<google_apis::FileResource> sync_root( 161 CreateRemoteFolder(std::string(), kSyncRootFolderTitle)); 162 163 for (size_t i = 0; i < sync_root->parents().size(); ++i) { 164 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 165 sync_context_->GetDriveService()->RemoveResourceFromDirectory( 166 sync_root->parents()[i].file_id(), 167 sync_root->file_id(), 168 CreateResultReceiver(&error)); 169 base::RunLoop().RunUntilIdle(); 170 EXPECT_EQ(google_apis::HTTP_NO_CONTENT, error); 171 } 172 173 return sync_root.Pass(); 174 } 175 176 std::string GetSyncRootFolderID() { 177 int64 sync_root_tracker_id = metadata_database_->GetSyncRootTrackerID(); 178 FileTracker sync_root_tracker; 179 EXPECT_TRUE(metadata_database_->FindTrackerByTrackerID( 180 sync_root_tracker_id, &sync_root_tracker)); 181 return sync_root_tracker.file_id(); 182 } 183 184 size_t CountTrackersForFile(const std::string& file_id) { 185 TrackerIDSet trackers; 186 metadata_database_->FindTrackersByFileID(file_id, &trackers); 187 return trackers.size(); 188 } 189 190 bool HasActiveTracker(const std::string& file_id) { 191 TrackerIDSet trackers; 192 return metadata_database_->FindTrackersByFileID(file_id, &trackers) && 193 trackers.has_active(); 194 } 195 196 bool HasNoParent(const std::string& file_id) { 197 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 198 scoped_ptr<google_apis::ResourceEntry> entry; 199 sync_context_->GetDriveService()->GetResourceEntry( 200 file_id, 201 CreateResultReceiver(&error, &entry)); 202 base::RunLoop().RunUntilIdle(); 203 EXPECT_EQ(google_apis::HTTP_SUCCESS, error); 204 return !entry->GetLinkByType(google_apis::Link::LINK_PARENT); 205 } 206 207 size_t CountFileMetadata() { 208 return metadata_database_->CountFileMetadata(); 209 } 210 211 size_t CountFileTracker() { 212 return metadata_database_->CountFileTracker(); 213 } 214 215 google_apis::GDataErrorCode AddParentFolder( 216 const std::string& new_parent_folder_id, 217 const std::string& file_id) { 218 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 219 sync_context_->GetDriveService()->AddResourceToDirectory( 220 new_parent_folder_id, file_id, 221 CreateResultReceiver(&error)); 222 base::RunLoop().RunUntilIdle(); 223 return error; 224 } 225 226 private: 227 content::TestBrowserThreadBundle browser_threads_; 228 base::ScopedTempDir database_dir_; 229 scoped_ptr<leveldb::Env> in_memory_env_; 230 231 scoped_ptr<MetadataDatabase> metadata_database_; 232 scoped_ptr<SyncTaskManager> sync_task_manager_; 233 scoped_ptr<SyncEngineContext> sync_context_; 234 235 DISALLOW_COPY_AND_ASSIGN(SyncEngineInitializerTest); 236}; 237 238TEST_F(SyncEngineInitializerTest, EmptyDatabase_NoRemoteSyncRoot) { 239 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 240 241 std::string sync_root_folder_id = GetSyncRootFolderID(); 242 EXPECT_EQ(1u, CountTrackersForFile(sync_root_folder_id)); 243 244 EXPECT_TRUE(HasActiveTracker(sync_root_folder_id)); 245 246 EXPECT_EQ(1u, CountFileMetadata()); 247 EXPECT_EQ(1u, CountFileTracker()); 248} 249 250TEST_F(SyncEngineInitializerTest, EmptyDatabase_RemoteSyncRootExists) { 251 scoped_ptr<google_apis::FileResource> sync_root( 252 CreateRemoteSyncRoot()); 253 scoped_ptr<google_apis::FileResource> app_root_1( 254 CreateRemoteFolder(sync_root->file_id(), "app-root 1")); 255 scoped_ptr<google_apis::FileResource> app_root_2( 256 CreateRemoteFolder(sync_root->file_id(), "app-root 2")); 257 258 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 259 260 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id())); 261 EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id())); 262 EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id())); 263 264 EXPECT_TRUE(HasActiveTracker(sync_root->file_id())); 265 EXPECT_FALSE(HasActiveTracker(app_root_1->file_id())); 266 EXPECT_FALSE(HasActiveTracker(app_root_2->file_id())); 267 268 EXPECT_EQ(3u, CountFileMetadata()); 269 EXPECT_EQ(3u, CountFileTracker()); 270} 271 272TEST_F(SyncEngineInitializerTest, DatabaseAlreadyInitialized) { 273 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteSyncRoot()); 274 scoped_ptr<google_apis::FileResource> app_root_1( 275 CreateRemoteFolder(sync_root->file_id(), "app-root 1")); 276 scoped_ptr<google_apis::FileResource> app_root_2( 277 CreateRemoteFolder(sync_root->file_id(), "app-root 2")); 278 279 const google_apis::FileResource* app_roots[] = { 280 app_root_1.get(), app_root_2.get() 281 }; 282 EXPECT_EQ(SYNC_STATUS_OK, 283 PopulateDatabase(*sync_root, app_roots, arraysize(app_roots))); 284 285 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 286 287 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id())); 288 EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id())); 289 EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id())); 290 291 EXPECT_TRUE(HasActiveTracker(sync_root->file_id())); 292 EXPECT_FALSE(HasActiveTracker(app_root_1->file_id())); 293 EXPECT_FALSE(HasActiveTracker(app_root_2->file_id())); 294 295 EXPECT_EQ(3u, CountFileMetadata()); 296 EXPECT_EQ(3u, CountFileTracker()); 297} 298 299TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiCandidate) { 300 scoped_ptr<google_apis::FileResource> sync_root_1(CreateRemoteSyncRoot()); 301 scoped_ptr<google_apis::FileResource> sync_root_2(CreateRemoteSyncRoot()); 302 303 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 304 305 EXPECT_EQ(1u, CountTrackersForFile(sync_root_1->file_id())); 306 EXPECT_EQ(0u, CountTrackersForFile(sync_root_2->file_id())); 307 308 EXPECT_TRUE(HasActiveTracker(sync_root_1->file_id())); 309 EXPECT_FALSE(HasActiveTracker(sync_root_2->file_id())); 310 311 EXPECT_EQ(1u, CountFileMetadata()); 312 EXPECT_EQ(1u, CountFileTracker()); 313} 314 315TEST_F(SyncEngineInitializerTest, EmptyDatabase_UndetachedRemoteSyncRoot) { 316 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder( 317 std::string(), kSyncRootFolderTitle)); 318 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 319 320 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id())); 321 EXPECT_TRUE(HasActiveTracker(sync_root->file_id())); 322 323 EXPECT_TRUE(HasNoParent(sync_root->file_id())); 324 325 EXPECT_EQ(1u, CountFileMetadata()); 326 EXPECT_EQ(1u, CountFileTracker()); 327} 328 329TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiparentSyncRoot) { 330 scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder( 331 std::string(), "folder")); 332 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder( 333 std::string(), kSyncRootFolderTitle)); 334 AddParentFolder(sync_root->file_id(), folder->file_id()); 335 336 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 337 338 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id())); 339 EXPECT_TRUE(HasActiveTracker(sync_root->file_id())); 340 341 EXPECT_TRUE(HasNoParent(sync_root->file_id())); 342 343 EXPECT_EQ(1u, CountFileMetadata()); 344 EXPECT_EQ(1u, CountFileTracker()); 345} 346 347TEST_F(SyncEngineInitializerTest, EmptyDatabase_FakeRemoteSyncRoot) { 348 scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder( 349 std::string(), "folder")); 350 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder( 351 folder->file_id(), kSyncRootFolderTitle)); 352 353 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 354 355 EXPECT_EQ(0u, CountTrackersForFile(sync_root->file_id())); 356 EXPECT_FALSE(HasNoParent(sync_root->file_id())); 357 358 EXPECT_EQ(1u, CountFileMetadata()); 359 EXPECT_EQ(1u, CountFileTracker()); 360} 361 362} // namespace drive_backend 363} // namespace sync_file_system 364