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