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