file_cache_unittest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright (c) 2012 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/file_cache.h" 6 7#include <string> 8#include <vector> 9 10#include "base/file_util.h" 11#include "base/files/scoped_temp_dir.h" 12#include "base/message_loop.h" 13#include "base/threading/sequenced_worker_pool.h" 14#include "chrome/browser/chromeos/drive/drive.pb.h" 15#include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h" 16#include "chrome/browser/chromeos/drive/file_system_util.h" 17#include "chrome/browser/chromeos/drive/mock_file_cache_observer.h" 18#include "chrome/browser/chromeos/drive/test_util.h" 19#include "chrome/browser/google_apis/test_util.h" 20#include "content/public/test/test_browser_thread.h" 21#include "testing/gmock/include/gmock/gmock.h" 22#include "testing/gtest/include/gtest/gtest.h" 23 24using ::testing::StrictMock; 25 26namespace drive { 27namespace internal { 28namespace { 29 30struct PathToVerify { 31 PathToVerify(const base::FilePath& in_path_to_scan, 32 const base::FilePath& in_expected_existing_path) : 33 path_to_scan(in_path_to_scan), 34 expected_existing_path(in_expected_existing_path) { 35 } 36 37 base::FilePath path_to_scan; 38 base::FilePath expected_existing_path; 39}; 40 41// Copies results from Iterate(). 42void OnIterate(std::vector<std::string>* out_resource_ids, 43 std::vector<FileCacheEntry>* out_cache_entries, 44 const std::string& resource_id, 45 const FileCacheEntry& cache_entry) { 46 out_resource_ids->push_back(resource_id); 47 out_cache_entries->push_back(cache_entry); 48} 49 50// Called upon completion of Iterate(). 51void OnIterateCompleted(bool* out_is_called) { 52 *out_is_called = true; 53} 54 55} // namespace 56 57class FileCacheTest : public testing::Test { 58 protected: 59 FileCacheTest() 60 : ui_thread_(content::BrowserThread::UI, &message_loop_), 61 expected_error_(FILE_ERROR_OK), 62 expected_cache_state_(0), 63 expected_sub_dir_type_(FileCache::CACHE_TYPE_META), 64 expected_success_(true) { 65 } 66 67 virtual void SetUp() OVERRIDE { 68 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 69 fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter); 70 71 scoped_refptr<base::SequencedWorkerPool> pool = 72 content::BrowserThread::GetBlockingPool(); 73 blocking_task_runner_ = 74 pool->GetSequencedTaskRunner(pool->GetSequenceToken()); 75 cache_.reset(new FileCache(temp_dir_.path(), 76 blocking_task_runner_, 77 fake_free_disk_space_getter_.get())); 78 79 mock_cache_observer_.reset(new StrictMock<MockCacheObserver>); 80 cache_->AddObserver(mock_cache_observer_.get()); 81 82 bool success = false; 83 cache_->RequestInitialize( 84 google_apis::test_util::CreateCopyResultCallback(&success)); 85 google_apis::test_util::RunBlockingPoolTask(); 86 ASSERT_TRUE(success); 87 } 88 89 virtual void TearDown() OVERRIDE { 90 cache_.reset(); 91 } 92 93 void TestGetFileFromCacheByResourceIdAndMd5( 94 const std::string& resource_id, 95 const std::string& md5, 96 FileError expected_error, 97 const std::string& expected_file_extension) { 98 FileError error = FILE_ERROR_OK; 99 base::FilePath cache_file_path; 100 cache_->GetFileOnUIThread(resource_id, md5, 101 google_apis::test_util::CreateCopyResultCallback( 102 &error, &cache_file_path)); 103 google_apis::test_util::RunBlockingPoolTask(); 104 105 EXPECT_EQ(expected_error, error); 106 if (error == FILE_ERROR_OK) { 107 // Verify filename of |cache_file_path|. 108 base::FilePath base_name = cache_file_path.BaseName(); 109 EXPECT_EQ(util::EscapeCacheFileName(resource_id) + 110 base::FilePath::kExtensionSeparator + 111 util::EscapeCacheFileName( 112 expected_file_extension.empty() ? 113 md5 : expected_file_extension), 114 base_name.value()); 115 } else { 116 EXPECT_TRUE(cache_file_path.empty()); 117 } 118 } 119 120 void TestStoreToCache( 121 const std::string& resource_id, 122 const std::string& md5, 123 const base::FilePath& source_path, 124 FileError expected_error, 125 int expected_cache_state, 126 FileCache::CacheSubDirectoryType expected_sub_dir_type) { 127 expected_error_ = expected_error; 128 expected_cache_state_ = expected_cache_state; 129 expected_sub_dir_type_ = expected_sub_dir_type; 130 131 FileError error = FILE_ERROR_OK; 132 cache_->StoreOnUIThread( 133 resource_id, md5, source_path, 134 FileCache::FILE_OPERATION_COPY, 135 google_apis::test_util::CreateCopyResultCallback(&error)); 136 google_apis::test_util::RunBlockingPoolTask(); 137 VerifyCacheFileState(error, resource_id, md5); 138 } 139 140 void TestStoreLocallyModifiedToCache( 141 const std::string& resource_id, 142 const std::string& md5, 143 const base::FilePath& source_path, 144 FileError expected_error, 145 int expected_cache_state, 146 FileCache::CacheSubDirectoryType expected_sub_dir_type) { 147 expected_error_ = expected_error; 148 expected_cache_state_ = expected_cache_state; 149 expected_sub_dir_type_ = expected_sub_dir_type; 150 151 FileError error = FILE_ERROR_OK; 152 cache_->StoreLocallyModifiedOnUIThread( 153 resource_id, md5, source_path, 154 FileCache::FILE_OPERATION_COPY, 155 google_apis::test_util::CreateCopyResultCallback(&error)); 156 google_apis::test_util::RunBlockingPoolTask(); 157 VerifyCacheFileState(error, resource_id, md5); 158 } 159 160 void TestRemoveFromCache(const std::string& resource_id, 161 FileError expected_error) { 162 expected_error_ = expected_error; 163 164 FileError error = FILE_ERROR_OK; 165 cache_->RemoveOnUIThread( 166 resource_id, 167 google_apis::test_util::CreateCopyResultCallback(&error)); 168 google_apis::test_util::RunBlockingPoolTask(); 169 VerifyRemoveFromCache(error, resource_id, ""); 170 } 171 172 void VerifyRemoveFromCache(FileError error, 173 const std::string& resource_id, 174 const std::string& md5) { 175 EXPECT_EQ(expected_error_, error); 176 177 // Verify cache map. 178 FileCacheEntry cache_entry; 179 const bool cache_entry_found = 180 GetCacheEntryFromOriginThread(resource_id, md5, &cache_entry); 181 if (cache_entry_found) 182 EXPECT_TRUE(cache_entry.is_dirty()); 183 184 // If entry doesn't exist, verify that no files with "<resource_id>.*" 185 // exist in persistent and tmp dirs. 186 std::vector<PathToVerify> paths_to_verify; 187 paths_to_verify.push_back( // Index 0: CACHE_TYPE_TMP. 188 PathToVerify(cache_->GetCacheFilePath(resource_id, "*", 189 FileCache::CACHE_TYPE_TMP, 190 FileCache::CACHED_FILE_FROM_SERVER), base::FilePath())); 191 paths_to_verify.push_back( // Index 1: CACHE_TYPE_PERSISTENT. 192 PathToVerify(cache_->GetCacheFilePath(resource_id, "*", 193 FileCache::CACHE_TYPE_PERSISTENT, 194 FileCache::CACHED_FILE_FROM_SERVER), base::FilePath())); 195 if (!cache_entry_found) { 196 for (size_t i = 0; i < paths_to_verify.size(); ++i) { 197 file_util::FileEnumerator enumerator( 198 paths_to_verify[i].path_to_scan.DirName(), false /* not recursive*/, 199 file_util::FileEnumerator::FILES, 200 paths_to_verify[i].path_to_scan.BaseName().value()); 201 EXPECT_TRUE(enumerator.Next().empty()); 202 } 203 } else { 204 // Entry is dirty, verify that: 205 // - no files with "<resource_id>.*" exist in tmp dir 206 // - only 1 "<resource_id>.local" exists in persistent dir 207 // - if entry is pinned, only 1 <resource_id> exists in pinned dir. 208 209 // Change expected_existing_path of CACHE_TYPE_PERSISTENT (index 1). 210 paths_to_verify[1].expected_existing_path = 211 GetCacheFilePath(resource_id, 212 std::string(), 213 FileCache::CACHE_TYPE_PERSISTENT, 214 FileCache::CACHED_FILE_LOCALLY_MODIFIED); 215 216 for (size_t i = 0; i < paths_to_verify.size(); ++i) { 217 const struct PathToVerify& verify = paths_to_verify[i]; 218 file_util::FileEnumerator enumerator( 219 verify.path_to_scan.DirName(), false /* not recursive */, 220 file_util::FileEnumerator::FILES, 221 verify.path_to_scan.BaseName().value()); 222 size_t num_files_found = 0; 223 for (base::FilePath current = enumerator.Next(); !current.empty(); 224 current = enumerator.Next()) { 225 ++num_files_found; 226 EXPECT_EQ(verify.expected_existing_path, current); 227 } 228 if (verify.expected_existing_path.empty()) 229 EXPECT_EQ(0U, num_files_found); 230 else 231 EXPECT_EQ(1U, num_files_found); 232 } 233 } 234 } 235 236 void TestPin( 237 const std::string& resource_id, 238 const std::string& md5, 239 FileError expected_error, 240 int expected_cache_state, 241 FileCache::CacheSubDirectoryType expected_sub_dir_type) { 242 expected_error_ = expected_error; 243 expected_cache_state_ = expected_cache_state; 244 expected_sub_dir_type_ = expected_sub_dir_type; 245 246 FileError error = FILE_ERROR_OK; 247 cache_->PinOnUIThread( 248 resource_id, md5, 249 google_apis::test_util::CreateCopyResultCallback(&error)); 250 google_apis::test_util::RunBlockingPoolTask(); 251 VerifyCacheFileState(error, resource_id, md5); 252 } 253 254 void TestUnpin( 255 const std::string& resource_id, 256 const std::string& md5, 257 FileError expected_error, 258 int expected_cache_state, 259 FileCache::CacheSubDirectoryType expected_sub_dir_type) { 260 expected_error_ = expected_error; 261 expected_cache_state_ = expected_cache_state; 262 expected_sub_dir_type_ = expected_sub_dir_type; 263 264 FileError error = FILE_ERROR_OK; 265 cache_->UnpinOnUIThread( 266 resource_id, md5, 267 google_apis::test_util::CreateCopyResultCallback(&error)); 268 google_apis::test_util::RunBlockingPoolTask(); 269 VerifyCacheFileState(error, resource_id, md5); 270 } 271 272 void TestMarkDirty(const std::string& resource_id, 273 const std::string& md5, 274 FileError expected_error, 275 int expected_cache_state, 276 FileCache::CacheSubDirectoryType expected_sub_dir_type) { 277 expected_error_ = expected_error; 278 expected_cache_state_ = expected_cache_state; 279 expected_sub_dir_type_ = expected_sub_dir_type; 280 281 FileError error = FILE_ERROR_OK; 282 cache_->MarkDirtyOnUIThread( 283 resource_id, md5, 284 google_apis::test_util::CreateCopyResultCallback(&error)); 285 google_apis::test_util::RunBlockingPoolTask(); 286 287 VerifyCacheFileState(error, resource_id, md5); 288 289 // Verify filename. 290 if (error == FILE_ERROR_OK) { 291 base::FilePath cache_file_path; 292 cache_->GetFileOnUIThread( 293 resource_id, md5, 294 google_apis::test_util::CreateCopyResultCallback( 295 &error, &cache_file_path)); 296 google_apis::test_util::RunBlockingPoolTask(); 297 298 EXPECT_EQ(FILE_ERROR_OK, error); 299 base::FilePath base_name = cache_file_path.BaseName(); 300 EXPECT_EQ(util::EscapeCacheFileName(resource_id) + 301 base::FilePath::kExtensionSeparator + 302 "local", 303 base_name.value()); 304 } 305 } 306 307 void TestCommitDirty( 308 const std::string& resource_id, 309 const std::string& md5, 310 FileError expected_error, 311 int expected_cache_state, 312 FileCache::CacheSubDirectoryType expected_sub_dir_type) { 313 expected_error_ = expected_error; 314 expected_cache_state_ = expected_cache_state; 315 expected_sub_dir_type_ = expected_sub_dir_type; 316 317 FileError error = FILE_ERROR_OK; 318 cache_->CommitDirtyOnUIThread( 319 resource_id, md5, 320 google_apis::test_util::CreateCopyResultCallback(&error)); 321 google_apis::test_util::RunBlockingPoolTask(); 322 VerifyCacheFileState(error, resource_id, md5); 323 } 324 325 void TestClearDirty( 326 const std::string& resource_id, 327 const std::string& md5, 328 FileError expected_error, 329 int expected_cache_state, 330 FileCache::CacheSubDirectoryType expected_sub_dir_type) { 331 expected_error_ = expected_error; 332 expected_cache_state_ = expected_cache_state; 333 expected_sub_dir_type_ = expected_sub_dir_type; 334 335 FileError error = FILE_ERROR_OK; 336 PostTaskAndReplyWithResult( 337 blocking_task_runner_, 338 FROM_HERE, 339 base::Bind(&FileCache::ClearDirty, 340 base::Unretained(cache_.get()), 341 resource_id, md5), 342 google_apis::test_util::CreateCopyResultCallback(&error)); 343 google_apis::test_util::RunBlockingPoolTask(); 344 VerifyCacheFileState(error, resource_id, md5); 345 } 346 347 void TestMarkAsMounted( 348 const std::string& resource_id, 349 const std::string& md5, 350 FileError expected_error, 351 int expected_cache_state, 352 FileCache::CacheSubDirectoryType expected_sub_dir_type) { 353 expected_error_ = expected_error; 354 expected_cache_state_ = expected_cache_state; 355 expected_sub_dir_type_ = expected_sub_dir_type; 356 357 FileError error = FILE_ERROR_OK; 358 base::FilePath cache_file_path; 359 cache_->MarkAsMountedOnUIThread( 360 resource_id, md5, 361 google_apis::test_util::CreateCopyResultCallback( 362 &error, &cache_file_path)); 363 google_apis::test_util::RunBlockingPoolTask(); 364 365 EXPECT_TRUE(file_util::PathExists(cache_file_path)); 366 EXPECT_EQ(cache_file_path, 367 cache_->GetCacheFilePath(resource_id, 368 md5, 369 expected_sub_dir_type_, 370 FileCache::CACHED_FILE_MOUNTED)); 371 } 372 373 void TestMarkAsUnmounted( 374 const std::string& resource_id, 375 const std::string& md5, 376 const base::FilePath& file_path, 377 FileError expected_error, 378 int expected_cache_state, 379 FileCache::CacheSubDirectoryType expected_sub_dir_type) { 380 expected_error_ = expected_error; 381 expected_cache_state_ = expected_cache_state; 382 expected_sub_dir_type_ = expected_sub_dir_type; 383 384 FileError error = FILE_ERROR_OK; 385 cache_->MarkAsUnmountedOnUIThread( 386 file_path, 387 google_apis::test_util::CreateCopyResultCallback(&error)); 388 google_apis::test_util::RunBlockingPoolTask(); 389 390 base::FilePath cache_file_path; 391 cache_->GetFileOnUIThread( 392 resource_id, md5, 393 google_apis::test_util::CreateCopyResultCallback( 394 &error, &cache_file_path)); 395 google_apis::test_util::RunBlockingPoolTask(); 396 EXPECT_EQ(FILE_ERROR_OK, error); 397 398 EXPECT_TRUE(file_util::PathExists(cache_file_path)); 399 EXPECT_EQ(cache_file_path, 400 cache_->GetCacheFilePath(resource_id, 401 md5, 402 expected_sub_dir_type_, 403 FileCache::CACHED_FILE_FROM_SERVER)); 404 } 405 406 void VerifyCacheFileState(FileError error, 407 const std::string& resource_id, 408 const std::string& md5) { 409 EXPECT_EQ(expected_error_, error); 410 411 // Verify cache map. 412 FileCacheEntry cache_entry; 413 const bool cache_entry_found = 414 GetCacheEntryFromOriginThread(resource_id, md5, &cache_entry); 415 if (test_util::ToCacheEntry(expected_cache_state_).is_present() || 416 test_util::ToCacheEntry(expected_cache_state_).is_pinned()) { 417 ASSERT_TRUE(cache_entry_found); 418 EXPECT_TRUE(test_util::CacheStatesEqual( 419 test_util::ToCacheEntry(expected_cache_state_), 420 cache_entry)); 421 EXPECT_EQ(expected_sub_dir_type_, 422 FileCache::GetSubDirectoryType(cache_entry)); 423 } else { 424 EXPECT_FALSE(cache_entry_found); 425 } 426 427 // Verify actual cache file. 428 base::FilePath dest_path = cache_->GetCacheFilePath( 429 resource_id, 430 md5, 431 test_util::ToCacheEntry(expected_cache_state_).is_pinned() || 432 test_util::ToCacheEntry(expected_cache_state_).is_dirty() ? 433 FileCache::CACHE_TYPE_PERSISTENT : 434 FileCache::CACHE_TYPE_TMP, 435 test_util::ToCacheEntry(expected_cache_state_).is_dirty() ? 436 FileCache::CACHED_FILE_LOCALLY_MODIFIED : 437 FileCache::CACHED_FILE_FROM_SERVER); 438 bool exists = file_util::PathExists(dest_path); 439 if (test_util::ToCacheEntry(expected_cache_state_).is_present()) 440 EXPECT_TRUE(exists); 441 else 442 EXPECT_FALSE(exists); 443 } 444 445 base::FilePath GetCacheFilePath(const std::string& resource_id, 446 const std::string& md5, 447 FileCache::CacheSubDirectoryType sub_dir_type, 448 FileCache::CachedFileOrigin file_origin) { 449 return cache_->GetCacheFilePath(resource_id, md5, sub_dir_type, 450 file_origin); 451 } 452 453 // Helper function to call GetCacheEntry from origin thread. 454 bool GetCacheEntryFromOriginThread(const std::string& resource_id, 455 const std::string& md5, 456 FileCacheEntry* cache_entry) { 457 bool result = false; 458 cache_->GetCacheEntryOnUIThread( 459 resource_id, md5, 460 google_apis::test_util::CreateCopyResultCallback(&result, cache_entry)); 461 google_apis::test_util::RunBlockingPoolTask(); 462 return result; 463 } 464 465 // Returns true if the cache entry exists for the given resource ID and MD5. 466 bool CacheEntryExists(const std::string& resource_id, 467 const std::string& md5) { 468 FileCacheEntry cache_entry; 469 return GetCacheEntryFromOriginThread(resource_id, md5, &cache_entry); 470 } 471 472 void TestGetCacheFilePath(const std::string& resource_id, 473 const std::string& md5, 474 const std::string& expected_filename) { 475 base::FilePath actual_path = cache_->GetCacheFilePath( 476 resource_id, 477 md5, 478 FileCache::CACHE_TYPE_TMP, 479 FileCache::CACHED_FILE_FROM_SERVER); 480 base::FilePath expected_path = 481 cache_->GetCacheDirectoryPath(FileCache::CACHE_TYPE_TMP); 482 expected_path = expected_path.Append( 483 base::FilePath::FromUTF8Unsafe(expected_filename)); 484 EXPECT_EQ(expected_path, actual_path); 485 486 base::FilePath base_name = actual_path.BaseName(); 487 488 // base::FilePath::Extension returns ".", so strip it. 489 std::string unescaped_md5 = util::UnescapeCacheFileName( 490 base_name.Extension().substr(1)); 491 EXPECT_EQ(md5, unescaped_md5); 492 std::string unescaped_resource_id = util::UnescapeCacheFileName( 493 base_name.RemoveExtension().value()); 494 EXPECT_EQ(resource_id, unescaped_resource_id); 495 } 496 497 // Returns the number of the cache files with name <resource_id>, and Confirm 498 // that they have the <md5>. This should return 1 or 0. 499 size_t CountCacheFiles(const std::string& resource_id, 500 const std::string& md5) { 501 base::FilePath path = GetCacheFilePath( 502 resource_id, "*", 503 (test_util::ToCacheEntry(expected_cache_state_).is_pinned() ? 504 FileCache::CACHE_TYPE_PERSISTENT : 505 FileCache::CACHE_TYPE_TMP), 506 FileCache::CACHED_FILE_FROM_SERVER); 507 file_util::FileEnumerator enumerator(path.DirName(), false, 508 file_util::FileEnumerator::FILES, 509 path.BaseName().value()); 510 size_t num_files_found = 0; 511 for (base::FilePath current = enumerator.Next(); !current.empty(); 512 current = enumerator.Next()) { 513 ++num_files_found; 514 EXPECT_EQ(util::EscapeCacheFileName(resource_id) + 515 base::FilePath::kExtensionSeparator + 516 util::EscapeCacheFileName(md5), 517 current.BaseName().value()); 518 } 519 return num_files_found; 520 } 521 522 base::MessageLoopForUI message_loop_; 523 content::TestBrowserThread ui_thread_; 524 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; 525 base::ScopedTempDir temp_dir_; 526 527 scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_; 528 scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_; 529 scoped_ptr<StrictMock<MockCacheObserver> > mock_cache_observer_; 530 531 FileError expected_error_; 532 int expected_cache_state_; 533 FileCache::CacheSubDirectoryType expected_sub_dir_type_; 534 bool expected_success_; 535 std::string expected_file_extension_; 536}; 537 538TEST_F(FileCacheTest, GetCacheFilePath) { 539 // Use alphanumeric characters for resource id. 540 std::string resource_id("pdf:1a2b"); 541 std::string md5("abcdef0123456789"); 542 TestGetCacheFilePath(resource_id, md5, 543 resource_id + base::FilePath::kExtensionSeparator + md5); 544 545 // Use non-alphanumeric characters for resource id, including '.' which is an 546 // extension separator, to test that the characters are escaped and unescaped 547 // correctly, and '.' doesn't mess up the filename format and operations. 548 resource_id = "pdf:`~!@#$%^&*()-_=+[{|]}\\;',<.>/?"; 549 std::string escaped_resource_id = util::EscapeCacheFileName(resource_id); 550 std::string escaped_md5 = util::EscapeCacheFileName(md5); 551 TestGetCacheFilePath( 552 resource_id, md5, escaped_resource_id + 553 base::FilePath::kExtensionSeparator + escaped_md5); 554} 555 556TEST_F(FileCacheTest, StoreToCacheSimple) { 557 fake_free_disk_space_getter_->set_fake_free_disk_space( 558 test_util::kLotsOfSpace); 559 560 std::string resource_id("pdf:1a2b"); 561 std::string md5("abcdef0123456789"); 562 563 // Store an existing file. 564 TestStoreToCache( 565 resource_id, md5, 566 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 567 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 568 FileCache::CACHE_TYPE_TMP); 569 570 // Store a non-existent file to the same |resource_id| and |md5|. 571 TestStoreToCache(resource_id, md5, base::FilePath("./non_existent.json"), 572 FILE_ERROR_FAILED, 573 test_util::TEST_CACHE_STATE_PRESENT, 574 FileCache::CACHE_TYPE_TMP); 575 576 // Store a different existing file to the same |resource_id| but different 577 // |md5|. 578 md5 = "new_md5"; 579 TestStoreToCache( 580 resource_id, md5, 581 google_apis::test_util::GetTestFilePath("chromeos/gdata/empty_feed.json"), 582 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 583 FileCache::CACHE_TYPE_TMP); 584 585 // Verify that there's only one file with name <resource_id>, i.e. previously 586 // cached file with the different md5 should be deleted. 587 EXPECT_EQ(1U, CountCacheFiles(resource_id, md5)); 588} 589 590TEST_F(FileCacheTest, LocallyModifiedSimple) { 591 fake_free_disk_space_getter_->set_fake_free_disk_space( 592 test_util::kLotsOfSpace); 593 594 std::string resource_id("pdf:1a2b"); 595 std::string md5("abcdef0123456789"); 596 597 const int kDirtyCacheState = 598 test_util::TEST_CACHE_STATE_PRESENT | 599 test_util::TEST_CACHE_STATE_DIRTY | 600 test_util::TEST_CACHE_STATE_PERSISTENT; 601 602 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(resource_id)).Times(1); 603 TestStoreLocallyModifiedToCache( 604 resource_id, md5, 605 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 606 FILE_ERROR_OK, kDirtyCacheState, FileCache::CACHE_TYPE_PERSISTENT); 607} 608 609TEST_F(FileCacheTest, GetFromCacheSimple) { 610 fake_free_disk_space_getter_->set_fake_free_disk_space( 611 test_util::kLotsOfSpace); 612 613 std::string resource_id("pdf:1a2b"); 614 std::string md5("abcdef0123456789"); 615 // First store a file to cache. 616 TestStoreToCache( 617 resource_id, md5, 618 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 619 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 620 FileCache::CACHE_TYPE_TMP); 621 622 // Then try to get the existing file from cache. 623 TestGetFileFromCacheByResourceIdAndMd5( 624 resource_id, md5, FILE_ERROR_OK, md5); 625 626 // Get file from cache with same resource id as existing file but different 627 // md5. 628 TestGetFileFromCacheByResourceIdAndMd5( 629 resource_id, "9999", FILE_ERROR_NOT_FOUND, md5); 630 631 // Get file from cache with different resource id from existing file but same 632 // md5. 633 resource_id = "document:1a2b"; 634 TestGetFileFromCacheByResourceIdAndMd5( 635 resource_id, md5, FILE_ERROR_NOT_FOUND, md5); 636} 637 638TEST_F(FileCacheTest, RemoveFromCacheSimple) { 639 fake_free_disk_space_getter_->set_fake_free_disk_space( 640 test_util::kLotsOfSpace); 641 642 // Use alphanumeric characters for resource id. 643 std::string resource_id("pdf:1a2b"); 644 std::string md5("abcdef0123456789"); 645 // First store a file to cache. 646 TestStoreToCache( 647 resource_id, md5, 648 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 649 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 650 FileCache::CACHE_TYPE_TMP); 651 652 // Then try to remove existing file from cache. 653 TestRemoveFromCache(resource_id, FILE_ERROR_OK); 654 655 // Repeat using non-alphanumeric characters for resource id, including '.' 656 // which is an extension separator. 657 resource_id = "pdf:`~!@#$%^&*()-_=+[{|]}\\;',<.>/?"; 658 TestStoreToCache( 659 resource_id, md5, 660 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 661 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 662 FileCache::CACHE_TYPE_TMP); 663 664 TestRemoveFromCache(resource_id, FILE_ERROR_OK); 665} 666 667TEST_F(FileCacheTest, PinAndUnpin) { 668 fake_free_disk_space_getter_->set_fake_free_disk_space( 669 test_util::kLotsOfSpace); 670 671 std::string resource_id("pdf:1a2b"); 672 std::string md5("abcdef0123456789"); 673 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(2); 674 EXPECT_CALL(*mock_cache_observer_, OnCacheUnpinned(resource_id, md5)) 675 .Times(1); 676 677 // First store a file to cache. 678 TestStoreToCache( 679 resource_id, md5, 680 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 681 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 682 FileCache::CACHE_TYPE_TMP); 683 684 // Pin the existing file in cache. 685 TestPin(resource_id, md5, FILE_ERROR_OK, 686 test_util::TEST_CACHE_STATE_PRESENT | 687 test_util::TEST_CACHE_STATE_PINNED | 688 test_util::TEST_CACHE_STATE_PERSISTENT, 689 FileCache::CACHE_TYPE_PERSISTENT); 690 691 // Unpin the existing file in cache. 692 TestUnpin(resource_id, md5, FILE_ERROR_OK, 693 test_util::TEST_CACHE_STATE_PRESENT, 694 FileCache::CACHE_TYPE_TMP); 695 696 // Pin back the same existing file in cache. 697 TestPin(resource_id, md5, FILE_ERROR_OK, 698 test_util::TEST_CACHE_STATE_PRESENT | 699 test_util::TEST_CACHE_STATE_PINNED | 700 test_util::TEST_CACHE_STATE_PERSISTENT, 701 FileCache::CACHE_TYPE_PERSISTENT); 702 703 // Pin a non-existent file in cache. 704 resource_id = "document:1a2b"; 705 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(1); 706 EXPECT_CALL(*mock_cache_observer_, OnCacheUnpinned(resource_id, md5)) 707 .Times(1); 708 709 TestPin(resource_id, md5, FILE_ERROR_OK, 710 test_util::TEST_CACHE_STATE_PINNED, 711 FileCache::CACHE_TYPE_TMP); 712 713 // Unpin the previously pinned non-existent file in cache. 714 TestUnpin(resource_id, md5, FILE_ERROR_OK, 715 test_util::TEST_CACHE_STATE_NONE, 716 FileCache::CACHE_TYPE_TMP); 717 718 // Unpin a file that doesn't exist in cache and is not pinned, i.e. cache 719 // has zero knowledge of the file. 720 resource_id = "not-in-cache:1a2b"; 721 // Because unpinning will fail, OnCacheUnpinned() won't be run. 722 EXPECT_CALL(*mock_cache_observer_, OnCacheUnpinned(resource_id, md5)) 723 .Times(0); 724 725 TestUnpin(resource_id, md5, FILE_ERROR_NOT_FOUND, 726 test_util::TEST_CACHE_STATE_NONE, 727 FileCache::CACHE_TYPE_TMP /* non-applicable */); 728} 729 730TEST_F(FileCacheTest, StoreToCachePinned) { 731 fake_free_disk_space_getter_->set_fake_free_disk_space( 732 test_util::kLotsOfSpace); 733 734 std::string resource_id("pdf:1a2b"); 735 std::string md5("abcdef0123456789"); 736 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(1); 737 738 // Pin a non-existent file. 739 TestPin(resource_id, md5, FILE_ERROR_OK, 740 test_util::TEST_CACHE_STATE_PINNED, 741 FileCache::CACHE_TYPE_TMP); 742 743 // Store an existing file to a previously pinned file. 744 TestStoreToCache( 745 resource_id, md5, 746 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 747 FILE_ERROR_OK, 748 test_util::TEST_CACHE_STATE_PRESENT | 749 test_util::TEST_CACHE_STATE_PINNED | 750 test_util::TEST_CACHE_STATE_PERSISTENT, 751 FileCache::CACHE_TYPE_PERSISTENT); 752 753 // Store a non-existent file to a previously pinned and stored file. 754 TestStoreToCache(resource_id, md5, base::FilePath("./non_existent.json"), 755 FILE_ERROR_FAILED, 756 test_util::TEST_CACHE_STATE_PRESENT | 757 test_util::TEST_CACHE_STATE_PINNED | 758 test_util::TEST_CACHE_STATE_PERSISTENT, 759 FileCache::CACHE_TYPE_PERSISTENT); 760} 761 762TEST_F(FileCacheTest, GetFromCachePinned) { 763 fake_free_disk_space_getter_->set_fake_free_disk_space( 764 test_util::kLotsOfSpace); 765 766 std::string resource_id("pdf:1a2b"); 767 std::string md5("abcdef0123456789"); 768 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(1); 769 770 // Pin a non-existent file. 771 TestPin(resource_id, md5, FILE_ERROR_OK, 772 test_util::TEST_CACHE_STATE_PINNED, 773 FileCache::CACHE_TYPE_TMP); 774 775 // Get the non-existent pinned file from cache. 776 TestGetFileFromCacheByResourceIdAndMd5( 777 resource_id, md5, FILE_ERROR_NOT_FOUND, md5); 778 779 // Store an existing file to the previously pinned non-existent file. 780 TestStoreToCache( 781 resource_id, md5, 782 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 783 FILE_ERROR_OK, 784 test_util::TEST_CACHE_STATE_PRESENT | 785 test_util::TEST_CACHE_STATE_PINNED | 786 test_util::TEST_CACHE_STATE_PERSISTENT, 787 FileCache::CACHE_TYPE_PERSISTENT); 788 789 // Get the previously pinned and stored file from cache. 790 TestGetFileFromCacheByResourceIdAndMd5( 791 resource_id, md5, FILE_ERROR_OK, md5); 792} 793 794TEST_F(FileCacheTest, RemoveFromCachePinned) { 795 fake_free_disk_space_getter_->set_fake_free_disk_space( 796 test_util::kLotsOfSpace); 797 798 // Use alphanumeric characters for resource_id. 799 std::string resource_id("pdf:1a2b"); 800 std::string md5("abcdef0123456789"); 801 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(1); 802 803 // Store a file to cache, and pin it. 804 TestStoreToCache( 805 resource_id, md5, 806 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 807 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 808 FileCache::CACHE_TYPE_TMP); 809 TestPin(resource_id, md5, FILE_ERROR_OK, 810 test_util::TEST_CACHE_STATE_PRESENT | 811 test_util::TEST_CACHE_STATE_PINNED | 812 test_util::TEST_CACHE_STATE_PERSISTENT, 813 FileCache::CACHE_TYPE_PERSISTENT); 814 815 // Remove |resource_id| from cache. 816 TestRemoveFromCache(resource_id, FILE_ERROR_OK); 817 818 // Repeat using non-alphanumeric characters for resource id, including '.' 819 // which is an extension separator. 820 resource_id = "pdf:`~!@#$%^&*()-_=+[{|]}\\;',<.>/?"; 821 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(1); 822 823 TestStoreToCache( 824 resource_id, md5, 825 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 826 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 827 FileCache::CACHE_TYPE_TMP); 828 TestPin(resource_id, md5, FILE_ERROR_OK, 829 test_util::TEST_CACHE_STATE_PRESENT | 830 test_util::TEST_CACHE_STATE_PINNED | 831 test_util::TEST_CACHE_STATE_PERSISTENT, 832 FileCache::CACHE_TYPE_PERSISTENT); 833 834 TestRemoveFromCache(resource_id, FILE_ERROR_OK); 835} 836 837TEST_F(FileCacheTest, DirtyCacheSimple) { 838 fake_free_disk_space_getter_->set_fake_free_disk_space( 839 test_util::kLotsOfSpace); 840 841 std::string resource_id("pdf:1a2b"); 842 std::string md5("abcdef0123456789"); 843 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(resource_id)).Times(1); 844 845 // First store a file to cache. 846 TestStoreToCache( 847 resource_id, md5, 848 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 849 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 850 FileCache::CACHE_TYPE_TMP); 851 852 // Mark the file dirty. 853 TestMarkDirty(resource_id, md5, FILE_ERROR_OK, 854 test_util::TEST_CACHE_STATE_PRESENT | 855 test_util::TEST_CACHE_STATE_DIRTY | 856 test_util::TEST_CACHE_STATE_PERSISTENT, 857 FileCache::CACHE_TYPE_PERSISTENT); 858 859 // Commit the file dirty. 860 TestCommitDirty(resource_id, md5, FILE_ERROR_OK, 861 test_util::TEST_CACHE_STATE_PRESENT | 862 test_util::TEST_CACHE_STATE_DIRTY | 863 test_util::TEST_CACHE_STATE_PERSISTENT, 864 FileCache::CACHE_TYPE_PERSISTENT); 865 866 // Clear dirty state of the file. 867 TestClearDirty(resource_id, md5, FILE_ERROR_OK, 868 test_util::TEST_CACHE_STATE_PRESENT, 869 FileCache::CACHE_TYPE_TMP); 870} 871 872TEST_F(FileCacheTest, DirtyCachePinned) { 873 fake_free_disk_space_getter_->set_fake_free_disk_space( 874 test_util::kLotsOfSpace); 875 876 std::string resource_id("pdf:1a2b"); 877 std::string md5("abcdef0123456789"); 878 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(1); 879 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(resource_id)).Times(1); 880 881 // First store a file to cache and pin it. 882 TestStoreToCache( 883 resource_id, md5, 884 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 885 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 886 FileCache::CACHE_TYPE_TMP); 887 TestPin(resource_id, md5, FILE_ERROR_OK, 888 test_util::TEST_CACHE_STATE_PRESENT | 889 test_util::TEST_CACHE_STATE_PINNED | 890 test_util::TEST_CACHE_STATE_PERSISTENT, 891 FileCache::CACHE_TYPE_PERSISTENT); 892 893 // Mark the file dirty. 894 TestMarkDirty(resource_id, md5, FILE_ERROR_OK, 895 test_util::TEST_CACHE_STATE_PRESENT | 896 test_util::TEST_CACHE_STATE_DIRTY | 897 test_util::TEST_CACHE_STATE_PINNED | 898 test_util::TEST_CACHE_STATE_PERSISTENT, 899 FileCache::CACHE_TYPE_PERSISTENT); 900 901 // Commit the file dirty. 902 TestCommitDirty(resource_id, md5, FILE_ERROR_OK, 903 test_util::TEST_CACHE_STATE_PRESENT | 904 test_util::TEST_CACHE_STATE_DIRTY | 905 test_util::TEST_CACHE_STATE_PINNED | 906 test_util::TEST_CACHE_STATE_PERSISTENT, 907 FileCache::CACHE_TYPE_PERSISTENT); 908 909 // Clear dirty state of the file. 910 TestClearDirty(resource_id, md5, FILE_ERROR_OK, 911 test_util::TEST_CACHE_STATE_PRESENT | 912 test_util::TEST_CACHE_STATE_PINNED | 913 test_util::TEST_CACHE_STATE_PERSISTENT, 914 FileCache::CACHE_TYPE_PERSISTENT); 915} 916 917// Test is disabled because it is flaky (http://crbug.com/134146) 918TEST_F(FileCacheTest, PinAndUnpinDirtyCache) { 919 fake_free_disk_space_getter_->set_fake_free_disk_space( 920 test_util::kLotsOfSpace); 921 922 std::string resource_id("pdf:1a2b"); 923 std::string md5("abcdef0123456789"); 924 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(1); 925 EXPECT_CALL(*mock_cache_observer_, OnCacheUnpinned(resource_id, md5)) 926 .Times(1); 927 928 // First store a file to cache and mark it as dirty. 929 TestStoreToCache( 930 resource_id, md5, 931 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 932 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 933 FileCache::CACHE_TYPE_TMP); 934 TestMarkDirty(resource_id, md5, FILE_ERROR_OK, 935 test_util::TEST_CACHE_STATE_PRESENT | 936 test_util::TEST_CACHE_STATE_DIRTY | 937 test_util::TEST_CACHE_STATE_PERSISTENT, 938 FileCache::CACHE_TYPE_PERSISTENT); 939 940 // Verifies dirty file exists. 941 base::FilePath dirty_path; 942 FileError error = FILE_ERROR_FAILED; 943 cache_->GetFileOnUIThread( 944 resource_id, md5, 945 google_apis::test_util::CreateCopyResultCallback(&error, &dirty_path)); 946 google_apis::test_util::RunBlockingPoolTask(); 947 EXPECT_EQ(FILE_ERROR_OK, error); 948 EXPECT_TRUE(file_util::PathExists(dirty_path)); 949 950 // Pin the dirty file. 951 TestPin(resource_id, md5, FILE_ERROR_OK, 952 test_util::TEST_CACHE_STATE_PRESENT | 953 test_util::TEST_CACHE_STATE_DIRTY | 954 test_util::TEST_CACHE_STATE_PINNED | 955 test_util::TEST_CACHE_STATE_PERSISTENT, 956 FileCache::CACHE_TYPE_PERSISTENT); 957 958 // Verify dirty file still exist at the same pathname. 959 EXPECT_TRUE(file_util::PathExists(dirty_path)); 960 961 // Unpin the dirty file. 962 TestUnpin(resource_id, md5, FILE_ERROR_OK, 963 test_util::TEST_CACHE_STATE_PRESENT | 964 test_util::TEST_CACHE_STATE_DIRTY | 965 test_util::TEST_CACHE_STATE_PERSISTENT, 966 FileCache::CACHE_TYPE_PERSISTENT); 967 968 // Verify dirty file still exist at the same pathname. 969 EXPECT_TRUE(file_util::PathExists(dirty_path)); 970} 971 972TEST_F(FileCacheTest, DirtyCacheRepetitive) { 973 fake_free_disk_space_getter_->set_fake_free_disk_space( 974 test_util::kLotsOfSpace); 975 976 std::string resource_id("pdf:1a2b"); 977 std::string md5("abcdef0123456789"); 978 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(resource_id)).Times(3); 979 980 // First store a file to cache. 981 TestStoreToCache( 982 resource_id, md5, 983 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 984 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 985 FileCache::CACHE_TYPE_TMP); 986 987 // Mark the file dirty. 988 TestMarkDirty(resource_id, md5, FILE_ERROR_OK, 989 test_util::TEST_CACHE_STATE_PRESENT | 990 test_util::TEST_CACHE_STATE_DIRTY | 991 test_util::TEST_CACHE_STATE_PERSISTENT, 992 FileCache::CACHE_TYPE_PERSISTENT); 993 994 // Again, mark the file dirty. Nothing should change. 995 TestMarkDirty(resource_id, md5, FILE_ERROR_OK, 996 test_util::TEST_CACHE_STATE_PRESENT | 997 test_util::TEST_CACHE_STATE_DIRTY | 998 test_util::TEST_CACHE_STATE_PERSISTENT, 999 FileCache::CACHE_TYPE_PERSISTENT); 1000 1001 // Commit the file dirty. 1002 TestCommitDirty(resource_id, md5, FILE_ERROR_OK, 1003 test_util::TEST_CACHE_STATE_PRESENT | 1004 test_util::TEST_CACHE_STATE_DIRTY | 1005 test_util::TEST_CACHE_STATE_PERSISTENT, 1006 FileCache::CACHE_TYPE_PERSISTENT); 1007 1008 // Again, commit the file dirty. Nothing should change. 1009 TestCommitDirty(resource_id, md5, FILE_ERROR_OK, 1010 test_util::TEST_CACHE_STATE_PRESENT | 1011 test_util::TEST_CACHE_STATE_DIRTY | 1012 test_util::TEST_CACHE_STATE_PERSISTENT, 1013 FileCache::CACHE_TYPE_PERSISTENT); 1014 1015 // Mark the file dirty again after it's being committed. 1016 TestMarkDirty(resource_id, md5, FILE_ERROR_OK, 1017 test_util::TEST_CACHE_STATE_PRESENT | 1018 test_util::TEST_CACHE_STATE_DIRTY | 1019 test_util::TEST_CACHE_STATE_PERSISTENT, 1020 FileCache::CACHE_TYPE_PERSISTENT); 1021 1022 // Commit the file dirty. 1023 TestCommitDirty(resource_id, md5, FILE_ERROR_OK, 1024 test_util::TEST_CACHE_STATE_PRESENT | 1025 test_util::TEST_CACHE_STATE_DIRTY | 1026 test_util::TEST_CACHE_STATE_PERSISTENT, 1027 FileCache::CACHE_TYPE_PERSISTENT); 1028 1029 // Clear dirty state of the file. 1030 TestClearDirty(resource_id, md5, FILE_ERROR_OK, 1031 test_util::TEST_CACHE_STATE_PRESENT, 1032 FileCache::CACHE_TYPE_TMP); 1033 1034 // Again, clear dirty state of the file, which is no longer dirty. 1035 TestClearDirty(resource_id, md5, FILE_ERROR_INVALID_OPERATION, 1036 test_util::TEST_CACHE_STATE_PRESENT, 1037 FileCache::CACHE_TYPE_TMP); 1038} 1039 1040TEST_F(FileCacheTest, DirtyCacheInvalid) { 1041 fake_free_disk_space_getter_->set_fake_free_disk_space( 1042 test_util::kLotsOfSpace); 1043 1044 std::string resource_id("pdf:1a2b"); 1045 std::string md5("abcdef0123456789"); 1046 1047 // Mark a non-existent file dirty. 1048 TestMarkDirty(resource_id, md5, FILE_ERROR_NOT_FOUND, 1049 test_util::TEST_CACHE_STATE_NONE, 1050 FileCache::CACHE_TYPE_TMP); 1051 1052 // Clear dirty state of a non-existent file. 1053 TestClearDirty(resource_id, md5, FILE_ERROR_NOT_FOUND, 1054 test_util::TEST_CACHE_STATE_NONE, 1055 FileCache::CACHE_TYPE_TMP); 1056 1057 // Store a file to cache. 1058 TestStoreToCache( 1059 resource_id, md5, 1060 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 1061 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 1062 FileCache::CACHE_TYPE_TMP); 1063 1064 // Clear dirty state of a non-dirty existing file. 1065 TestClearDirty(resource_id, md5, FILE_ERROR_INVALID_OPERATION, 1066 test_util::TEST_CACHE_STATE_PRESENT, 1067 FileCache::CACHE_TYPE_TMP); 1068 1069 // Mark an existing file dirty, then store a new file to the same resource id 1070 // but different md5, which should fail. 1071 TestMarkDirty(resource_id, md5, FILE_ERROR_OK, 1072 test_util::TEST_CACHE_STATE_PRESENT | 1073 test_util::TEST_CACHE_STATE_DIRTY | 1074 test_util::TEST_CACHE_STATE_PERSISTENT, 1075 FileCache::CACHE_TYPE_PERSISTENT); 1076 md5 = "new_md5"; 1077 TestStoreToCache( 1078 resource_id, md5, 1079 google_apis::test_util::GetTestFilePath( 1080 "chromeos/gdata/empty_feed.json"), 1081 FILE_ERROR_IN_USE, 1082 test_util::TEST_CACHE_STATE_PRESENT | 1083 test_util::TEST_CACHE_STATE_DIRTY | 1084 test_util::TEST_CACHE_STATE_PERSISTENT, 1085 FileCache::CACHE_TYPE_PERSISTENT); 1086} 1087 1088TEST_F(FileCacheTest, RemoveFromDirtyCache) { 1089 fake_free_disk_space_getter_->set_fake_free_disk_space( 1090 test_util::kLotsOfSpace); 1091 1092 std::string resource_id("pdf:1a2b"); 1093 std::string md5("abcdef0123456789"); 1094 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(1); 1095 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(resource_id)).Times(1); 1096 1097 // Store a file to cache, pin it, mark it dirty and commit it. 1098 TestStoreToCache( 1099 resource_id, md5, 1100 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 1101 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 1102 FileCache::CACHE_TYPE_TMP); 1103 TestPin(resource_id, md5, FILE_ERROR_OK, 1104 test_util::TEST_CACHE_STATE_PRESENT | 1105 test_util::TEST_CACHE_STATE_PINNED | 1106 test_util::TEST_CACHE_STATE_PERSISTENT, 1107 FileCache::CACHE_TYPE_PERSISTENT); 1108 TestMarkDirty(resource_id, md5, FILE_ERROR_OK, 1109 test_util::TEST_CACHE_STATE_PRESENT | 1110 test_util::TEST_CACHE_STATE_PINNED | 1111 test_util::TEST_CACHE_STATE_DIRTY | 1112 test_util::TEST_CACHE_STATE_PERSISTENT, 1113 FileCache::CACHE_TYPE_PERSISTENT); 1114 TestCommitDirty(resource_id, md5, FILE_ERROR_OK, 1115 test_util::TEST_CACHE_STATE_PRESENT | 1116 test_util::TEST_CACHE_STATE_PINNED | 1117 test_util::TEST_CACHE_STATE_DIRTY | 1118 test_util::TEST_CACHE_STATE_PERSISTENT, 1119 FileCache::CACHE_TYPE_PERSISTENT); 1120 1121 // Try to remove the file. Since file is dirty, it should not be removed. 1122 TestRemoveFromCache(resource_id, FILE_ERROR_OK); 1123} 1124 1125TEST_F(FileCacheTest, MountUnmount) { 1126 fake_free_disk_space_getter_->set_fake_free_disk_space( 1127 test_util::kLotsOfSpace); 1128 1129 std::string resource_id("pdf:1a2b"); 1130 std::string md5("abcdef0123456789"); 1131 1132 // First store a file to cache in the tmp subdir. 1133 TestStoreToCache( 1134 resource_id, md5, 1135 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 1136 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 1137 FileCache::CACHE_TYPE_TMP); 1138 1139 // Mark the file mounted. 1140 TestMarkAsMounted(resource_id, 1141 md5, 1142 FILE_ERROR_OK, 1143 test_util::TEST_CACHE_STATE_PRESENT | 1144 test_util::TEST_CACHE_STATE_MOUNTED | 1145 test_util::TEST_CACHE_STATE_PERSISTENT, 1146 FileCache::CACHE_TYPE_PERSISTENT); 1147 EXPECT_TRUE(CacheEntryExists(resource_id, md5)); 1148 1149 // Clear mounted state of the file. 1150 base::FilePath file_path; 1151 FileError error = FILE_ERROR_FAILED; 1152 cache_->GetFileOnUIThread( 1153 resource_id, md5, 1154 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 1155 google_apis::test_util::RunBlockingPoolTask(); 1156 EXPECT_EQ(FILE_ERROR_OK, error); 1157 1158 TestMarkAsUnmounted(resource_id, md5, file_path, 1159 FILE_ERROR_OK, 1160 test_util::TEST_CACHE_STATE_PRESENT, 1161 FileCache::CACHE_TYPE_TMP); 1162 EXPECT_TRUE(CacheEntryExists(resource_id, md5)); 1163 1164 // Try to remove the file. 1165 TestRemoveFromCache(resource_id, FILE_ERROR_OK); 1166} 1167 1168TEST_F(FileCacheTest, Iterate) { 1169 fake_free_disk_space_getter_->set_fake_free_disk_space( 1170 test_util::kLotsOfSpace); 1171 const std::vector<test_util::TestCacheResource> cache_resources( 1172 test_util::GetDefaultTestCacheResources()); 1173 // Set mock expectations. 1174 for (size_t i = 0; i < cache_resources.size(); ++i) { 1175 if (cache_resources[i].is_pinned) { 1176 EXPECT_CALL(*mock_cache_observer_, 1177 OnCachePinned(cache_resources[i].resource_id, 1178 cache_resources[i].md5)).Times(1); 1179 } 1180 if (cache_resources[i].is_dirty) { 1181 EXPECT_CALL(*mock_cache_observer_, 1182 OnCacheCommitted(cache_resources[i].resource_id)).Times(1); 1183 } 1184 } 1185 ASSERT_TRUE(test_util::PrepareTestCacheResources( 1186 cache_.get(), 1187 cache_resources)); 1188 1189 std::vector<std::string> resource_ids; 1190 std::vector<FileCacheEntry> cache_entries; 1191 bool completed = false; 1192 cache_->IterateOnUIThread( 1193 base::Bind(&OnIterate, &resource_ids, &cache_entries), 1194 base::Bind(&OnIterateCompleted, &completed)); 1195 google_apis::test_util::RunBlockingPoolTask(); 1196 1197 ASSERT_TRUE(completed); 1198 1199 sort(resource_ids.begin(), resource_ids.end()); 1200 ASSERT_EQ(6U, resource_ids.size()); 1201 EXPECT_EQ("dirty:existing", resource_ids[0]); 1202 EXPECT_EQ("dirty_and_pinned:existing", resource_ids[1]); 1203 EXPECT_EQ("pinned:existing", resource_ids[2]); 1204 EXPECT_EQ("pinned:non-existent", resource_ids[3]); 1205 EXPECT_EQ("tmp:`~!@#$%^&*()-_=+[{|]}\\;',<.>/?", resource_ids[4]); 1206 EXPECT_EQ("tmp:resource_id", resource_ids[5]); 1207 1208 ASSERT_EQ(6U, cache_entries.size()); 1209} 1210 1211 1212TEST_F(FileCacheTest, ClearAll) { 1213 fake_free_disk_space_getter_->set_fake_free_disk_space( 1214 test_util::kLotsOfSpace); 1215 1216 std::string resource_id("pdf:1a2b"); 1217 std::string md5("abcdef0123456789"); 1218 1219 // Store an existing file. 1220 TestStoreToCache( 1221 resource_id, md5, 1222 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 1223 FILE_ERROR_OK, test_util::TEST_CACHE_STATE_PRESENT, 1224 FileCache::CACHE_TYPE_TMP); 1225 1226 // Verify that there's only one cached file. 1227 EXPECT_EQ(1U, CountCacheFiles(resource_id, md5)); 1228 1229 // Clear cache. 1230 bool success = false; 1231 cache_->ClearAllOnUIThread( 1232 google_apis::test_util::CreateCopyResultCallback(&success)); 1233 google_apis::test_util::RunBlockingPoolTask(); 1234 EXPECT_TRUE(success); 1235 1236 // Verify that all the cache is removed. 1237 expected_error_ = FILE_ERROR_OK; 1238 VerifyRemoveFromCache(FILE_ERROR_OK, resource_id, md5); 1239 EXPECT_EQ(0U, CountCacheFiles(resource_id, md5)); 1240} 1241 1242TEST_F(FileCacheTest, StoreToCacheNoSpace) { 1243 fake_free_disk_space_getter_->set_fake_free_disk_space(0); 1244 1245 std::string resource_id("pdf:1a2b"); 1246 std::string md5("abcdef0123456789"); 1247 1248 // Try to store an existing file. 1249 TestStoreToCache( 1250 resource_id, md5, 1251 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 1252 FILE_ERROR_NO_SPACE, 1253 test_util::TEST_CACHE_STATE_NONE, 1254 FileCache::CACHE_TYPE_TMP); 1255 1256 // Verify that there's no files added. 1257 EXPECT_EQ(0U, CountCacheFiles(resource_id, md5)); 1258} 1259 1260// Don't use TEST_F, as we don't want SetUp() and TearDown() for this test. 1261TEST(FileCacheExtraTest, InitializationFailure) { 1262 base::MessageLoopForUI message_loop; 1263 content::TestBrowserThread ui_thread(content::BrowserThread::UI, 1264 &message_loop); 1265 1266 scoped_refptr<base::SequencedWorkerPool> pool = 1267 content::BrowserThread::GetBlockingPool(); 1268 1269 // Set the cache root to a non existent path, so the initialization fails. 1270 scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache(new FileCache( 1271 base::FilePath::FromUTF8Unsafe("/somewhere/nonexistent/blah/blah"), 1272 pool->GetSequencedTaskRunner(pool->GetSequenceToken()), 1273 NULL /* free_disk_space_getter */)); 1274 1275 bool success = true; 1276 cache->RequestInitialize( 1277 google_apis::test_util::CreateCopyResultCallback(&success)); 1278 google_apis::test_util::RunBlockingPoolTask(); 1279 EXPECT_FALSE(success); 1280} 1281 1282TEST_F(FileCacheTest, UpdatePinnedCache) { 1283 fake_free_disk_space_getter_->set_fake_free_disk_space( 1284 test_util::kLotsOfSpace); 1285 1286 std::string resource_id("pdf:1a2b"); 1287 std::string md5("abcdef0123456789"); 1288 std::string md5_modified("aaaaaa0000000000"); 1289 1290 // Store an existing file. 1291 TestStoreToCache( 1292 resource_id, md5, 1293 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 1294 FILE_ERROR_OK, 1295 test_util::TEST_CACHE_STATE_PRESENT, 1296 FileCache::CACHE_TYPE_TMP); 1297 1298 // Pin the file. 1299 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(resource_id, md5)).Times(1); 1300 TestPin( 1301 resource_id, md5, 1302 FILE_ERROR_OK, 1303 test_util::TEST_CACHE_STATE_PRESENT | 1304 test_util::TEST_CACHE_STATE_PINNED | 1305 test_util::TEST_CACHE_STATE_PERSISTENT, 1306 FileCache::CACHE_TYPE_PERSISTENT); 1307 1308 // Store the file with a modified content and md5. It should stay pinned. 1309 TestStoreToCache( 1310 resource_id, md5_modified, 1311 google_apis::test_util::GetTestFilePath("chromeos/gdata/empty_feed.json"), 1312 FILE_ERROR_OK, 1313 test_util::TEST_CACHE_STATE_PRESENT | 1314 test_util::TEST_CACHE_STATE_PINNED | 1315 test_util::TEST_CACHE_STATE_PERSISTENT, 1316 FileCache::CACHE_TYPE_PERSISTENT); 1317} 1318 1319} // namespace internal 1320} // namespace drive 1321