| OLD | NEW |
| (Empty) |
| 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/chromeos/drive/change_list_loader.h" | |
| 6 | |
| 7 #include "base/callback_helpers.h" | |
| 8 #include "base/files/scoped_temp_dir.h" | |
| 9 #include "base/memory/scoped_ptr.h" | |
| 10 #include "base/prefs/testing_pref_service.h" | |
| 11 #include "base/run_loop.h" | |
| 12 #include "base/single_thread_task_runner.h" | |
| 13 #include "base/thread_task_runner_handle.h" | |
| 14 #include "chrome/browser/chromeos/drive/change_list_loader_observer.h" | |
| 15 #include "components/drive/drive_test_util.h" | |
| 16 #include "components/drive/event_logger.h" | |
| 17 #include "components/drive/file_cache.h" | |
| 18 #include "components/drive/file_change.h" | |
| 19 #include "components/drive/file_system_core_util.h" | |
| 20 #include "components/drive/job_scheduler.h" | |
| 21 #include "components/drive/resource_metadata.h" | |
| 22 #include "components/drive/service/fake_drive_service.h" | |
| 23 #include "components/drive/service/test_util.h" | |
| 24 #include "content/public/test/test_browser_thread_bundle.h" | |
| 25 #include "google_apis/drive/drive_api_parser.h" | |
| 26 #include "google_apis/drive/test_util.h" | |
| 27 #include "testing/gtest/include/gtest/gtest.h" | |
| 28 | |
| 29 namespace drive { | |
| 30 namespace internal { | |
| 31 | |
| 32 class TestChangeListLoaderObserver : public ChangeListLoaderObserver { | |
| 33 public: | |
| 34 explicit TestChangeListLoaderObserver(ChangeListLoader* loader) | |
| 35 : loader_(loader), | |
| 36 load_from_server_complete_count_(0), | |
| 37 initial_load_complete_count_(0) { | |
| 38 loader_->AddObserver(this); | |
| 39 } | |
| 40 | |
| 41 ~TestChangeListLoaderObserver() override { loader_->RemoveObserver(this); } | |
| 42 | |
| 43 const FileChange& changed_files() const { return changed_files_; } | |
| 44 void clear_changed_files() { changed_files_.ClearForTest(); } | |
| 45 | |
| 46 int load_from_server_complete_count() const { | |
| 47 return load_from_server_complete_count_; | |
| 48 } | |
| 49 int initial_load_complete_count() const { | |
| 50 return initial_load_complete_count_; | |
| 51 } | |
| 52 | |
| 53 // ChageListObserver overrides: | |
| 54 void OnFileChanged(const FileChange& changed_files) override { | |
| 55 changed_files_.Apply(changed_files); | |
| 56 } | |
| 57 void OnLoadFromServerComplete() override { | |
| 58 ++load_from_server_complete_count_; | |
| 59 } | |
| 60 void OnInitialLoadComplete() override { ++initial_load_complete_count_; } | |
| 61 | |
| 62 private: | |
| 63 ChangeListLoader* loader_; | |
| 64 FileChange changed_files_; | |
| 65 int load_from_server_complete_count_; | |
| 66 int initial_load_complete_count_; | |
| 67 | |
| 68 DISALLOW_COPY_AND_ASSIGN(TestChangeListLoaderObserver); | |
| 69 }; | |
| 70 | |
| 71 class ChangeListLoaderTest : public testing::Test { | |
| 72 protected: | |
| 73 void SetUp() override { | |
| 74 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
| 75 pref_service_.reset(new TestingPrefServiceSimple); | |
| 76 test_util::RegisterDrivePrefs(pref_service_->registry()); | |
| 77 | |
| 78 logger_.reset(new EventLogger); | |
| 79 | |
| 80 drive_service_.reset(new FakeDriveService); | |
| 81 ASSERT_TRUE(test_util::SetUpTestEntries(drive_service_.get())); | |
| 82 | |
| 83 scheduler_.reset(new JobScheduler( | |
| 84 pref_service_.get(), | |
| 85 logger_.get(), | |
| 86 drive_service_.get(), | |
| 87 base::ThreadTaskRunnerHandle::Get().get())); | |
| 88 metadata_storage_.reset(new ResourceMetadataStorage( | |
| 89 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get())); | |
| 90 ASSERT_TRUE(metadata_storage_->Initialize()); | |
| 91 | |
| 92 cache_.reset(new FileCache(metadata_storage_.get(), | |
| 93 temp_dir_.path(), | |
| 94 base::ThreadTaskRunnerHandle::Get().get(), | |
| 95 NULL /* free_disk_space_getter */)); | |
| 96 ASSERT_TRUE(cache_->Initialize()); | |
| 97 | |
| 98 metadata_.reset(new ResourceMetadata( | |
| 99 metadata_storage_.get(), cache_.get(), | |
| 100 base::ThreadTaskRunnerHandle::Get().get())); | |
| 101 ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize()); | |
| 102 | |
| 103 about_resource_loader_.reset(new AboutResourceLoader(scheduler_.get())); | |
| 104 loader_controller_.reset(new LoaderController); | |
| 105 change_list_loader_.reset( | |
| 106 new ChangeListLoader(logger_.get(), | |
| 107 base::ThreadTaskRunnerHandle::Get().get(), | |
| 108 metadata_.get(), | |
| 109 scheduler_.get(), | |
| 110 about_resource_loader_.get(), | |
| 111 loader_controller_.get())); | |
| 112 } | |
| 113 | |
| 114 // Adds a new file to the root directory of the service. | |
| 115 scoped_ptr<google_apis::FileResource> AddNewFile(const std::string& title) { | |
| 116 google_apis::DriveApiErrorCode error = google_apis::DRIVE_FILE_ERROR; | |
| 117 scoped_ptr<google_apis::FileResource> entry; | |
| 118 drive_service_->AddNewFile( | |
| 119 "text/plain", | |
| 120 "content text", | |
| 121 drive_service_->GetRootResourceId(), | |
| 122 title, | |
| 123 false, // shared_with_me | |
| 124 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); | |
| 125 base::RunLoop().RunUntilIdle(); | |
| 126 EXPECT_EQ(google_apis::HTTP_CREATED, error); | |
| 127 return entry.Pass(); | |
| 128 } | |
| 129 | |
| 130 content::TestBrowserThreadBundle thread_bundle_; | |
| 131 base::ScopedTempDir temp_dir_; | |
| 132 scoped_ptr<TestingPrefServiceSimple> pref_service_; | |
| 133 scoped_ptr<EventLogger> logger_; | |
| 134 scoped_ptr<FakeDriveService> drive_service_; | |
| 135 scoped_ptr<JobScheduler> scheduler_; | |
| 136 scoped_ptr<ResourceMetadataStorage, | |
| 137 test_util::DestroyHelperForTests> metadata_storage_; | |
| 138 scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_; | |
| 139 scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_; | |
| 140 scoped_ptr<AboutResourceLoader> about_resource_loader_; | |
| 141 scoped_ptr<LoaderController> loader_controller_; | |
| 142 scoped_ptr<ChangeListLoader> change_list_loader_; | |
| 143 }; | |
| 144 | |
| 145 TEST_F(ChangeListLoaderTest, AboutResourceLoader) { | |
| 146 google_apis::DriveApiErrorCode error[6] = {}; | |
| 147 scoped_ptr<google_apis::AboutResource> about[6]; | |
| 148 | |
| 149 // No resource is cached at the beginning. | |
| 150 ASSERT_FALSE(about_resource_loader_->cached_about_resource()); | |
| 151 | |
| 152 // Since no resource is cached, this "Get" should trigger the update. | |
| 153 about_resource_loader_->GetAboutResource( | |
| 154 google_apis::test_util::CreateCopyResultCallback(error + 0, about + 0)); | |
| 155 // Since there is one in-flight update, the next "Get" just wait for it. | |
| 156 about_resource_loader_->GetAboutResource( | |
| 157 google_apis::test_util::CreateCopyResultCallback(error + 1, about + 1)); | |
| 158 | |
| 159 base::RunLoop().RunUntilIdle(); | |
| 160 EXPECT_EQ(google_apis::HTTP_SUCCESS, error[0]); | |
| 161 EXPECT_EQ(google_apis::HTTP_SUCCESS, error[1]); | |
| 162 const int64 first_changestamp = about[0]->largest_change_id(); | |
| 163 EXPECT_EQ(first_changestamp, about[1]->largest_change_id()); | |
| 164 ASSERT_TRUE(about_resource_loader_->cached_about_resource()); | |
| 165 EXPECT_EQ( | |
| 166 first_changestamp, | |
| 167 about_resource_loader_->cached_about_resource()->largest_change_id()); | |
| 168 | |
| 169 // Increment changestamp by 1. | |
| 170 AddNewFile("temp"); | |
| 171 // Explicitly calling UpdateAboutResource will start another API call. | |
| 172 about_resource_loader_->UpdateAboutResource( | |
| 173 google_apis::test_util::CreateCopyResultCallback(error + 2, about + 2)); | |
| 174 // It again waits for the in-flight UpdateAboutResoure call, even though this | |
| 175 // time there is a cached result. | |
| 176 about_resource_loader_->GetAboutResource( | |
| 177 google_apis::test_util::CreateCopyResultCallback(error + 3, about + 3)); | |
| 178 | |
| 179 base::RunLoop().RunUntilIdle(); | |
| 180 EXPECT_EQ(google_apis::HTTP_SUCCESS, error[2]); | |
| 181 EXPECT_EQ(google_apis::HTTP_SUCCESS, error[3]); | |
| 182 EXPECT_EQ(first_changestamp + 1, about[2]->largest_change_id()); | |
| 183 EXPECT_EQ(first_changestamp + 1, about[3]->largest_change_id()); | |
| 184 EXPECT_EQ( | |
| 185 first_changestamp + 1, | |
| 186 about_resource_loader_->cached_about_resource()->largest_change_id()); | |
| 187 | |
| 188 // Increment changestamp by 1. | |
| 189 AddNewFile("temp2"); | |
| 190 // Now no UpdateAboutResource task is running. Returns the cached result. | |
| 191 about_resource_loader_->GetAboutResource( | |
| 192 google_apis::test_util::CreateCopyResultCallback(error + 4, about + 4)); | |
| 193 // Explicitly calling UpdateAboutResource will start another API call. | |
| 194 about_resource_loader_->UpdateAboutResource( | |
| 195 google_apis::test_util::CreateCopyResultCallback(error + 5, about + 5)); | |
| 196 | |
| 197 base::RunLoop().RunUntilIdle(); | |
| 198 EXPECT_EQ(google_apis::HTTP_NO_CONTENT, error[4]); | |
| 199 EXPECT_EQ(google_apis::HTTP_SUCCESS, error[5]); | |
| 200 EXPECT_EQ(first_changestamp + 1, about[4]->largest_change_id()); | |
| 201 EXPECT_EQ(first_changestamp + 2, about[5]->largest_change_id()); | |
| 202 EXPECT_EQ( | |
| 203 first_changestamp + 2, | |
| 204 about_resource_loader_->cached_about_resource()->largest_change_id()); | |
| 205 | |
| 206 EXPECT_EQ(3, drive_service_->about_resource_load_count()); | |
| 207 } | |
| 208 | |
| 209 TEST_F(ChangeListLoaderTest, Load) { | |
| 210 EXPECT_FALSE(change_list_loader_->IsRefreshing()); | |
| 211 | |
| 212 // Start initial load. | |
| 213 TestChangeListLoaderObserver observer(change_list_loader_.get()); | |
| 214 | |
| 215 EXPECT_EQ(0, drive_service_->about_resource_load_count()); | |
| 216 | |
| 217 FileError error = FILE_ERROR_FAILED; | |
| 218 change_list_loader_->LoadIfNeeded( | |
| 219 google_apis::test_util::CreateCopyResultCallback(&error)); | |
| 220 EXPECT_TRUE(change_list_loader_->IsRefreshing()); | |
| 221 base::RunLoop().RunUntilIdle(); | |
| 222 EXPECT_EQ(FILE_ERROR_OK, error); | |
| 223 | |
| 224 EXPECT_FALSE(change_list_loader_->IsRefreshing()); | |
| 225 int64 changestamp = 0; | |
| 226 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); | |
| 227 EXPECT_LT(0, changestamp); | |
| 228 EXPECT_EQ(1, drive_service_->file_list_load_count()); | |
| 229 EXPECT_EQ(1, drive_service_->about_resource_load_count()); | |
| 230 EXPECT_EQ(1, observer.initial_load_complete_count()); | |
| 231 EXPECT_EQ(1, observer.load_from_server_complete_count()); | |
| 232 EXPECT_TRUE(observer.changed_files().empty()); | |
| 233 | |
| 234 base::FilePath file_path = | |
| 235 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt"); | |
| 236 ResourceEntry entry; | |
| 237 EXPECT_EQ(FILE_ERROR_OK, | |
| 238 metadata_->GetResourceEntryByPath(file_path, &entry)); | |
| 239 } | |
| 240 | |
| 241 TEST_F(ChangeListLoaderTest, Load_LocalMetadataAvailable) { | |
| 242 // Prepare metadata. | |
| 243 FileError error = FILE_ERROR_FAILED; | |
| 244 change_list_loader_->LoadIfNeeded( | |
| 245 google_apis::test_util::CreateCopyResultCallback(&error)); | |
| 246 base::RunLoop().RunUntilIdle(); | |
| 247 EXPECT_EQ(FILE_ERROR_OK, error); | |
| 248 | |
| 249 // Reset loader. | |
| 250 about_resource_loader_.reset(new AboutResourceLoader(scheduler_.get())); | |
| 251 change_list_loader_.reset( | |
| 252 new ChangeListLoader(logger_.get(), | |
| 253 base::ThreadTaskRunnerHandle::Get().get(), | |
| 254 metadata_.get(), | |
| 255 scheduler_.get(), | |
| 256 about_resource_loader_.get(), | |
| 257 loader_controller_.get())); | |
| 258 | |
| 259 // Add a file to the service. | |
| 260 scoped_ptr<google_apis::FileResource> gdata_entry = AddNewFile("New File"); | |
| 261 ASSERT_TRUE(gdata_entry); | |
| 262 | |
| 263 // Start loading. Because local metadata is available, the load results in | |
| 264 // returning FILE_ERROR_OK without fetching full list of resources. | |
| 265 const int previous_file_list_load_count = | |
| 266 drive_service_->file_list_load_count(); | |
| 267 TestChangeListLoaderObserver observer(change_list_loader_.get()); | |
| 268 | |
| 269 change_list_loader_->LoadIfNeeded( | |
| 270 google_apis::test_util::CreateCopyResultCallback(&error)); | |
| 271 EXPECT_TRUE(change_list_loader_->IsRefreshing()); | |
| 272 base::RunLoop().RunUntilIdle(); | |
| 273 EXPECT_EQ(FILE_ERROR_OK, error); | |
| 274 EXPECT_EQ(previous_file_list_load_count, | |
| 275 drive_service_->file_list_load_count()); | |
| 276 EXPECT_EQ(1, observer.initial_load_complete_count()); | |
| 277 | |
| 278 // Update should be checked by Load(). | |
| 279 int64 changestamp = 0; | |
| 280 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); | |
| 281 EXPECT_EQ(drive_service_->about_resource().largest_change_id(), changestamp); | |
| 282 EXPECT_EQ(1, drive_service_->change_list_load_count()); | |
| 283 EXPECT_EQ(1, observer.load_from_server_complete_count()); | |
| 284 EXPECT_TRUE( | |
| 285 observer.changed_files().CountDirectory(util::GetDriveMyDriveRootPath())); | |
| 286 | |
| 287 base::FilePath file_path = | |
| 288 util::GetDriveMyDriveRootPath().AppendASCII(gdata_entry->title()); | |
| 289 ResourceEntry entry; | |
| 290 EXPECT_EQ(FILE_ERROR_OK, | |
| 291 metadata_->GetResourceEntryByPath(file_path, &entry)); | |
| 292 } | |
| 293 | |
| 294 TEST_F(ChangeListLoaderTest, CheckForUpdates) { | |
| 295 // CheckForUpdates() results in no-op before load. | |
| 296 FileError check_for_updates_error = FILE_ERROR_FAILED; | |
| 297 change_list_loader_->CheckForUpdates( | |
| 298 google_apis::test_util::CreateCopyResultCallback( | |
| 299 &check_for_updates_error)); | |
| 300 EXPECT_FALSE(change_list_loader_->IsRefreshing()); | |
| 301 base::RunLoop().RunUntilIdle(); | |
| 302 EXPECT_EQ(FILE_ERROR_FAILED, | |
| 303 check_for_updates_error); // Callback was not run. | |
| 304 int64 changestamp = 0; | |
| 305 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); | |
| 306 EXPECT_EQ(0, changestamp); | |
| 307 EXPECT_EQ(0, drive_service_->file_list_load_count()); | |
| 308 EXPECT_EQ(0, drive_service_->about_resource_load_count()); | |
| 309 | |
| 310 // Start initial load. | |
| 311 FileError load_error = FILE_ERROR_FAILED; | |
| 312 change_list_loader_->LoadIfNeeded( | |
| 313 google_apis::test_util::CreateCopyResultCallback(&load_error)); | |
| 314 EXPECT_TRUE(change_list_loader_->IsRefreshing()); | |
| 315 | |
| 316 // CheckForUpdates() while loading. | |
| 317 change_list_loader_->CheckForUpdates( | |
| 318 google_apis::test_util::CreateCopyResultCallback( | |
| 319 &check_for_updates_error)); | |
| 320 | |
| 321 base::RunLoop().RunUntilIdle(); | |
| 322 EXPECT_FALSE(change_list_loader_->IsRefreshing()); | |
| 323 EXPECT_EQ(FILE_ERROR_OK, load_error); | |
| 324 EXPECT_EQ(FILE_ERROR_OK, check_for_updates_error); | |
| 325 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); | |
| 326 EXPECT_LT(0, changestamp); | |
| 327 EXPECT_EQ(1, drive_service_->file_list_load_count()); | |
| 328 | |
| 329 int64 previous_changestamp = 0; | |
| 330 EXPECT_EQ(FILE_ERROR_OK, | |
| 331 metadata_->GetLargestChangestamp(&previous_changestamp)); | |
| 332 // CheckForUpdates() results in no update. | |
| 333 change_list_loader_->CheckForUpdates( | |
| 334 google_apis::test_util::CreateCopyResultCallback( | |
| 335 &check_for_updates_error)); | |
| 336 EXPECT_TRUE(change_list_loader_->IsRefreshing()); | |
| 337 base::RunLoop().RunUntilIdle(); | |
| 338 EXPECT_FALSE(change_list_loader_->IsRefreshing()); | |
| 339 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); | |
| 340 EXPECT_EQ(previous_changestamp, changestamp); | |
| 341 | |
| 342 // Add a file to the service. | |
| 343 scoped_ptr<google_apis::FileResource> gdata_entry = AddNewFile("New File"); | |
| 344 ASSERT_TRUE(gdata_entry); | |
| 345 | |
| 346 // CheckForUpdates() results in update. | |
| 347 TestChangeListLoaderObserver observer(change_list_loader_.get()); | |
| 348 change_list_loader_->CheckForUpdates( | |
| 349 google_apis::test_util::CreateCopyResultCallback( | |
| 350 &check_for_updates_error)); | |
| 351 EXPECT_TRUE(change_list_loader_->IsRefreshing()); | |
| 352 base::RunLoop().RunUntilIdle(); | |
| 353 EXPECT_FALSE(change_list_loader_->IsRefreshing()); | |
| 354 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); | |
| 355 EXPECT_LT(previous_changestamp, changestamp); | |
| 356 EXPECT_EQ(1, observer.load_from_server_complete_count()); | |
| 357 EXPECT_TRUE( | |
| 358 observer.changed_files().CountDirectory(util::GetDriveMyDriveRootPath())); | |
| 359 | |
| 360 // The new file is found in the local metadata. | |
| 361 base::FilePath new_file_path = | |
| 362 util::GetDriveMyDriveRootPath().AppendASCII(gdata_entry->title()); | |
| 363 ResourceEntry entry; | |
| 364 EXPECT_EQ(FILE_ERROR_OK, | |
| 365 metadata_->GetResourceEntryByPath(new_file_path, &entry)); | |
| 366 } | |
| 367 | |
| 368 TEST_F(ChangeListLoaderTest, Lock) { | |
| 369 FileError error = FILE_ERROR_FAILED; | |
| 370 change_list_loader_->LoadIfNeeded( | |
| 371 google_apis::test_util::CreateCopyResultCallback(&error)); | |
| 372 base::RunLoop().RunUntilIdle(); | |
| 373 EXPECT_EQ(FILE_ERROR_OK, error); | |
| 374 | |
| 375 // Add a new file. | |
| 376 scoped_ptr<google_apis::FileResource> file = AddNewFile("New File"); | |
| 377 ASSERT_TRUE(file); | |
| 378 | |
| 379 // Lock the loader. | |
| 380 scoped_ptr<base::ScopedClosureRunner> lock = loader_controller_->GetLock(); | |
| 381 | |
| 382 // Start update. | |
| 383 TestChangeListLoaderObserver observer(change_list_loader_.get()); | |
| 384 FileError check_for_updates_error = FILE_ERROR_FAILED; | |
| 385 change_list_loader_->CheckForUpdates( | |
| 386 google_apis::test_util::CreateCopyResultCallback( | |
| 387 &check_for_updates_error)); | |
| 388 base::RunLoop().RunUntilIdle(); | |
| 389 | |
| 390 // Update is pending due to the lock. | |
| 391 EXPECT_TRUE(observer.changed_files().empty()); | |
| 392 | |
| 393 // Unlock the loader, this should resume the pending update. | |
| 394 lock.reset(); | |
| 395 base::RunLoop().RunUntilIdle(); | |
| 396 EXPECT_TRUE( | |
| 397 observer.changed_files().CountDirectory(util::GetDriveMyDriveRootPath())); | |
| 398 } | |
| 399 | |
| 400 } // namespace internal | |
| 401 } // namespace drive | |
| OLD | NEW |