sync_engine_initializer_unittest.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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 fake_drive_service_.reset(new drive::FakeDriveService()); 52 53 sync_context_.reset(new SyncEngineContext( 54 fake_drive_service_.get(), 55 NULL /* drive_uploader */, 56 base::MessageLoopProxy::current())); 57 58 sync_task_manager_.reset(new SyncTaskManager( 59 base::WeakPtr<SyncTaskManager::Client>(), 60 1 /* maximum_parallel_task */)); 61 sync_task_manager_->Initialize(SYNC_STATUS_OK); 62 } 63 64 virtual void TearDown() OVERRIDE { 65 sync_task_manager_.reset(); 66 metadata_database_.reset(); 67 sync_context_.reset(); 68 fake_drive_service_.reset(); 69 base::RunLoop().RunUntilIdle(); 70 } 71 72 base::FilePath database_path() { 73 return database_dir_.path(); 74 } 75 76 SyncStatusCode RunInitializer() { 77 SyncEngineInitializer* initializer = 78 new SyncEngineInitializer( 79 sync_context_.get(), 80 base::MessageLoopProxy::current(), 81 database_path(), 82 in_memory_env_.get()); 83 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 84 85 sync_task_manager_->ScheduleSyncTask( 86 FROM_HERE, 87 scoped_ptr<SyncTask>(initializer), 88 SyncTaskManager::PRIORITY_MED, 89 base::Bind(&SyncEngineInitializerTest::DidRunInitializer, 90 base::Unretained(this), initializer, &status)); 91 92 base::RunLoop().RunUntilIdle(); 93 return status; 94 } 95 96 void DidRunInitializer(SyncEngineInitializer* initializer, 97 SyncStatusCode* status_out, 98 SyncStatusCode status) { 99 *status_out = status; 100 metadata_database_ = initializer->PassMetadataDatabase(); 101 } 102 103 SyncStatusCode PopulateDatabase( 104 const google_apis::FileResource& sync_root, 105 const google_apis::FileResource** app_roots, 106 size_t app_roots_count) { 107 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 108 scoped_ptr<MetadataDatabase> database; 109 MetadataDatabase::Create( 110 base::MessageLoopProxy::current(), 111 database_path(), 112 in_memory_env_.get(), 113 CreateResultReceiver(&status, &database)); 114 base::RunLoop().RunUntilIdle(); 115 if (status != SYNC_STATUS_OK) 116 return status; 117 118 // |app_root_list| must not own the resources here. Be sure to call 119 // weak_clear later. 120 ScopedVector<google_apis::FileResource> app_root_list; 121 for (size_t i = 0; i < app_roots_count; ++i) { 122 app_root_list.push_back( 123 const_cast<google_apis::FileResource*>(app_roots[i])); 124 } 125 126 status = SYNC_STATUS_UNKNOWN; 127 database->PopulateInitialData(kInitialLargestChangeID, 128 sync_root, 129 app_root_list, 130 CreateResultReceiver(&status)); 131 base::RunLoop().RunUntilIdle(); 132 133 app_root_list.weak_clear(); 134 135 return SYNC_STATUS_OK; 136 } 137 138 scoped_ptr<google_apis::FileResource> CreateRemoteFolder( 139 const std::string& parent_folder_id, 140 const std::string& title) { 141 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 142 scoped_ptr<google_apis::ResourceEntry> entry; 143 sync_context_->GetDriveService()->AddNewDirectory( 144 parent_folder_id, title, 145 drive::DriveServiceInterface::AddNewDirectoryOptions(), 146 CreateResultReceiver(&error, &entry)); 147 base::RunLoop().RunUntilIdle(); 148 149 EXPECT_EQ(google_apis::HTTP_CREATED, error); 150 if (!entry) 151 scoped_ptr<google_apis::FileResource>(); 152 return drive::util::ConvertResourceEntryToFileResource(*entry); 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::ResourceEntry> entry; 195 sync_context_->GetDriveService()->GetResourceEntry( 196 file_id, 197 CreateResultReceiver(&error, &entry)); 198 base::RunLoop().RunUntilIdle(); 199 EXPECT_EQ(google_apis::HTTP_SUCCESS, error); 200 return !entry->GetLinkByType(google_apis::Link::LINK_PARENT); 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 scoped_ptr<drive::FakeDriveService> fake_drive_service_; 231 232 DISALLOW_COPY_AND_ASSIGN(SyncEngineInitializerTest); 233}; 234 235TEST_F(SyncEngineInitializerTest, EmptyDatabase_NoRemoteSyncRoot) { 236 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 237 238 std::string sync_root_folder_id = GetSyncRootFolderID(); 239 EXPECT_EQ(1u, CountTrackersForFile(sync_root_folder_id)); 240 241 EXPECT_TRUE(HasActiveTracker(sync_root_folder_id)); 242 243 EXPECT_EQ(1u, CountFileMetadata()); 244 EXPECT_EQ(1u, CountFileTracker()); 245} 246 247TEST_F(SyncEngineInitializerTest, EmptyDatabase_RemoteSyncRootExists) { 248 scoped_ptr<google_apis::FileResource> sync_root( 249 CreateRemoteSyncRoot()); 250 scoped_ptr<google_apis::FileResource> app_root_1( 251 CreateRemoteFolder(sync_root->file_id(), "app-root 1")); 252 scoped_ptr<google_apis::FileResource> app_root_2( 253 CreateRemoteFolder(sync_root->file_id(), "app-root 2")); 254 255 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 256 257 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id())); 258 EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id())); 259 EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id())); 260 261 EXPECT_TRUE(HasActiveTracker(sync_root->file_id())); 262 EXPECT_FALSE(HasActiveTracker(app_root_1->file_id())); 263 EXPECT_FALSE(HasActiveTracker(app_root_2->file_id())); 264 265 EXPECT_EQ(3u, CountFileMetadata()); 266 EXPECT_EQ(3u, CountFileTracker()); 267} 268 269TEST_F(SyncEngineInitializerTest, DatabaseAlreadyInitialized) { 270 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteSyncRoot()); 271 scoped_ptr<google_apis::FileResource> app_root_1( 272 CreateRemoteFolder(sync_root->file_id(), "app-root 1")); 273 scoped_ptr<google_apis::FileResource> app_root_2( 274 CreateRemoteFolder(sync_root->file_id(), "app-root 2")); 275 276 const google_apis::FileResource* app_roots[] = { 277 app_root_1.get(), app_root_2.get() 278 }; 279 EXPECT_EQ(SYNC_STATUS_OK, 280 PopulateDatabase(*sync_root, app_roots, arraysize(app_roots))); 281 282 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 283 284 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id())); 285 EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id())); 286 EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id())); 287 288 EXPECT_TRUE(HasActiveTracker(sync_root->file_id())); 289 EXPECT_FALSE(HasActiveTracker(app_root_1->file_id())); 290 EXPECT_FALSE(HasActiveTracker(app_root_2->file_id())); 291 292 EXPECT_EQ(3u, CountFileMetadata()); 293 EXPECT_EQ(3u, CountFileTracker()); 294} 295 296TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiCandidate) { 297 scoped_ptr<google_apis::FileResource> sync_root_1(CreateRemoteSyncRoot()); 298 scoped_ptr<google_apis::FileResource> sync_root_2(CreateRemoteSyncRoot()); 299 300 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 301 302 EXPECT_EQ(1u, CountTrackersForFile(sync_root_1->file_id())); 303 EXPECT_EQ(0u, CountTrackersForFile(sync_root_2->file_id())); 304 305 EXPECT_TRUE(HasActiveTracker(sync_root_1->file_id())); 306 EXPECT_FALSE(HasActiveTracker(sync_root_2->file_id())); 307 308 EXPECT_EQ(1u, CountFileMetadata()); 309 EXPECT_EQ(1u, CountFileTracker()); 310} 311 312TEST_F(SyncEngineInitializerTest, EmptyDatabase_UndetachedRemoteSyncRoot) { 313 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder( 314 std::string(), kSyncRootFolderTitle)); 315 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 316 317 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id())); 318 EXPECT_TRUE(HasActiveTracker(sync_root->file_id())); 319 320 EXPECT_TRUE(HasNoParent(sync_root->file_id())); 321 322 EXPECT_EQ(1u, CountFileMetadata()); 323 EXPECT_EQ(1u, CountFileTracker()); 324} 325 326TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiparentSyncRoot) { 327 scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder( 328 std::string(), "folder")); 329 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder( 330 std::string(), kSyncRootFolderTitle)); 331 AddParentFolder(sync_root->file_id(), folder->file_id()); 332 333 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 334 335 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id())); 336 EXPECT_TRUE(HasActiveTracker(sync_root->file_id())); 337 338 EXPECT_TRUE(HasNoParent(sync_root->file_id())); 339 340 EXPECT_EQ(1u, CountFileMetadata()); 341 EXPECT_EQ(1u, CountFileTracker()); 342} 343 344TEST_F(SyncEngineInitializerTest, EmptyDatabase_FakeRemoteSyncRoot) { 345 scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder( 346 std::string(), "folder")); 347 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder( 348 folder->file_id(), kSyncRootFolderTitle)); 349 350 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer()); 351 352 EXPECT_EQ(0u, CountTrackersForFile(sync_root->file_id())); 353 EXPECT_FALSE(HasNoParent(sync_root->file_id())); 354 355 EXPECT_EQ(1u, CountFileMetadata()); 356 EXPECT_EQ(1u, CountFileTracker()); 357} 358 359} // namespace drive_backend 360} // namespace sync_file_system 361