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 "base/basictypes.h" 6 #include "base/files/file_util.h" 7 #include "base/metrics/field_trial.h" 8 #include "base/port.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 12 #include "base/thread_task_runner_handle.h" 13 #include "base/threading/platform_thread.h" 14 #include "base/threading/thread_restrictions.h" 15 #include "net/base/cache_type.h" 16 #include "net/base/io_buffer.h" 17 #include "net/base/net_errors.h" 18 #include "net/base/test_completion_callback.h" 19 #include "net/disk_cache/blockfile/backend_impl.h" 20 #include "net/disk_cache/blockfile/entry_impl.h" 21 #include "net/disk_cache/blockfile/experiments.h" 22 #include "net/disk_cache/blockfile/histogram_macros.h" 23 #include "net/disk_cache/blockfile/mapped_file.h" 24 #include "net/disk_cache/cache_util.h" 25 #include "net/disk_cache/disk_cache_test_base.h" 26 #include "net/disk_cache/disk_cache_test_util.h" 27 #include "net/disk_cache/memory/mem_backend_impl.h" 28 #include "net/disk_cache/simple/simple_backend_impl.h" 29 #include "net/disk_cache/simple/simple_entry_format.h" 30 #include "net/disk_cache/simple/simple_test_util.h" 31 #include "net/disk_cache/simple/simple_util.h" 32 #include "testing/gtest/include/gtest/gtest.h" 33 34 #if defined(OS_WIN) 35 #include "base/win/scoped_handle.h" 36 #endif 37 38 // Provide a BackendImpl object to macros from histogram_macros.h. 39 #define CACHE_UMA_BACKEND_IMPL_OBJ backend_ 40 41 using base::Time; 42 43 namespace { 44 45 const char kExistingEntryKey[] = "existing entry key"; 46 47 scoped_ptr<disk_cache::BackendImpl> CreateExistingEntryCache( 48 const base::Thread& cache_thread, 49 base::FilePath& cache_path) { 50 net::TestCompletionCallback cb; 51 52 scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl( 53 cache_path, cache_thread.message_loop_proxy(), NULL)); 54 int rv = cache->Init(cb.callback()); 55 if (cb.GetResult(rv) != net::OK) 56 return scoped_ptr<disk_cache::BackendImpl>(); 57 58 disk_cache::Entry* entry = NULL; 59 rv = cache->CreateEntry(kExistingEntryKey, &entry, cb.callback()); 60 if (cb.GetResult(rv) != net::OK) 61 return scoped_ptr<disk_cache::BackendImpl>(); 62 entry->Close(); 63 64 return cache.Pass(); 65 } 66 67 } // namespace 68 69 // Tests that can run with different types of caches. 70 class DiskCacheBackendTest : public DiskCacheTestWithCache { 71 protected: 72 // Some utility methods: 73 74 // Perform IO operations on the cache until there is pending IO. 75 int GeneratePendingIO(net::TestCompletionCallback* cb); 76 77 // Adds 5 sparse entries. |doomed_start| and |doomed_end| if not NULL, 78 // will be filled with times, used by DoomEntriesSince and DoomEntriesBetween. 79 // There are 4 entries after doomed_start and 2 after doomed_end. 80 void InitSparseCache(base::Time* doomed_start, base::Time* doomed_end); 81 82 bool CreateSetOfRandomEntries(std::set<std::string>* key_pool); 83 bool EnumerateAndMatchKeys(int max_to_open, 84 TestIterator* iter, 85 std::set<std::string>* keys_to_match, 86 size_t* count); 87 88 // Actual tests: 89 void BackendBasics(); 90 void BackendKeying(); 91 void BackendShutdownWithPendingFileIO(bool fast); 92 void BackendShutdownWithPendingIO(bool fast); 93 void BackendShutdownWithPendingCreate(bool fast); 94 void BackendSetSize(); 95 void BackendLoad(); 96 void BackendChain(); 97 void BackendValidEntry(); 98 void BackendInvalidEntry(); 99 void BackendInvalidEntryRead(); 100 void BackendInvalidEntryWithLoad(); 101 void BackendTrimInvalidEntry(); 102 void BackendTrimInvalidEntry2(); 103 void BackendEnumerations(); 104 void BackendEnumerations2(); 105 void BackendInvalidEntryEnumeration(); 106 void BackendFixEnumerators(); 107 void BackendDoomRecent(); 108 void BackendDoomBetween(); 109 void BackendTransaction(const std::string& name, int num_entries, bool load); 110 void BackendRecoverInsert(); 111 void BackendRecoverRemove(); 112 void BackendRecoverWithEviction(); 113 void BackendInvalidEntry2(); 114 void BackendInvalidEntry3(); 115 void BackendInvalidEntry7(); 116 void BackendInvalidEntry8(); 117 void BackendInvalidEntry9(bool eviction); 118 void BackendInvalidEntry10(bool eviction); 119 void BackendInvalidEntry11(bool eviction); 120 void BackendTrimInvalidEntry12(); 121 void BackendDoomAll(); 122 void BackendDoomAll2(); 123 void BackendInvalidRankings(); 124 void BackendInvalidRankings2(); 125 void BackendDisable(); 126 void BackendDisable2(); 127 void BackendDisable3(); 128 void BackendDisable4(); 129 }; 130 131 int DiskCacheBackendTest::GeneratePendingIO(net::TestCompletionCallback* cb) { 132 if (!use_current_thread_) { 133 ADD_FAILURE(); 134 return net::ERR_FAILED; 135 } 136 137 disk_cache::Entry* entry; 138 int rv = cache_->CreateEntry("some key", &entry, cb->callback()); 139 if (cb->GetResult(rv) != net::OK) 140 return net::ERR_CACHE_CREATE_FAILURE; 141 142 const int kSize = 25000; 143 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 144 CacheTestFillBuffer(buffer->data(), kSize, false); 145 146 for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) { 147 // We are using the current thread as the cache thread because we want to 148 // be able to call directly this method to make sure that the OS (instead 149 // of us switching thread) is returning IO pending. 150 if (!simple_cache_mode_) { 151 rv = static_cast<disk_cache::EntryImpl*>(entry)->WriteDataImpl( 152 0, i, buffer.get(), kSize, cb->callback(), false); 153 } else { 154 rv = entry->WriteData(0, i, buffer.get(), kSize, cb->callback(), false); 155 } 156 157 if (rv == net::ERR_IO_PENDING) 158 break; 159 if (rv != kSize) 160 rv = net::ERR_FAILED; 161 } 162 163 // Don't call Close() to avoid going through the queue or we'll deadlock 164 // waiting for the operation to finish. 165 if (!simple_cache_mode_) 166 static_cast<disk_cache::EntryImpl*>(entry)->Release(); 167 else 168 entry->Close(); 169 170 return rv; 171 } 172 173 void DiskCacheBackendTest::InitSparseCache(base::Time* doomed_start, 174 base::Time* doomed_end) { 175 InitCache(); 176 177 const int kSize = 50; 178 // This must be greater then MemEntryImpl::kMaxSparseEntrySize. 179 const int kOffset = 10 + 1024 * 1024; 180 181 disk_cache::Entry* entry0 = NULL; 182 disk_cache::Entry* entry1 = NULL; 183 disk_cache::Entry* entry2 = NULL; 184 185 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 186 CacheTestFillBuffer(buffer->data(), kSize, false); 187 188 ASSERT_EQ(net::OK, CreateEntry("zeroth", &entry0)); 189 ASSERT_EQ(kSize, WriteSparseData(entry0, 0, buffer.get(), kSize)); 190 ASSERT_EQ(kSize, 191 WriteSparseData(entry0, kOffset + kSize, buffer.get(), kSize)); 192 entry0->Close(); 193 194 FlushQueueForTest(); 195 AddDelay(); 196 if (doomed_start) 197 *doomed_start = base::Time::Now(); 198 199 // Order in rankings list: 200 // first_part1, first_part2, second_part1, second_part2 201 ASSERT_EQ(net::OK, CreateEntry("first", &entry1)); 202 ASSERT_EQ(kSize, WriteSparseData(entry1, 0, buffer.get(), kSize)); 203 ASSERT_EQ(kSize, 204 WriteSparseData(entry1, kOffset + kSize, buffer.get(), kSize)); 205 entry1->Close(); 206 207 ASSERT_EQ(net::OK, CreateEntry("second", &entry2)); 208 ASSERT_EQ(kSize, WriteSparseData(entry2, 0, buffer.get(), kSize)); 209 ASSERT_EQ(kSize, 210 WriteSparseData(entry2, kOffset + kSize, buffer.get(), kSize)); 211 entry2->Close(); 212 213 FlushQueueForTest(); 214 AddDelay(); 215 if (doomed_end) 216 *doomed_end = base::Time::Now(); 217 218 // Order in rankings list: 219 // third_part1, fourth_part1, third_part2, fourth_part2 220 disk_cache::Entry* entry3 = NULL; 221 disk_cache::Entry* entry4 = NULL; 222 ASSERT_EQ(net::OK, CreateEntry("third", &entry3)); 223 ASSERT_EQ(kSize, WriteSparseData(entry3, 0, buffer.get(), kSize)); 224 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry4)); 225 ASSERT_EQ(kSize, WriteSparseData(entry4, 0, buffer.get(), kSize)); 226 ASSERT_EQ(kSize, 227 WriteSparseData(entry3, kOffset + kSize, buffer.get(), kSize)); 228 ASSERT_EQ(kSize, 229 WriteSparseData(entry4, kOffset + kSize, buffer.get(), kSize)); 230 entry3->Close(); 231 entry4->Close(); 232 233 FlushQueueForTest(); 234 AddDelay(); 235 } 236 237 // Creates entries based on random keys. Stores these keys in |key_pool|. 238 bool DiskCacheBackendTest::CreateSetOfRandomEntries( 239 std::set<std::string>* key_pool) { 240 const int kNumEntries = 10; 241 242 for (int i = 0; i < kNumEntries; ++i) { 243 std::string key = GenerateKey(true); 244 disk_cache::Entry* entry; 245 if (CreateEntry(key, &entry) != net::OK) 246 return false; 247 key_pool->insert(key); 248 entry->Close(); 249 } 250 return key_pool->size() == implicit_cast<size_t>(cache_->GetEntryCount()); 251 } 252 253 // Performs iteration over the backend and checks that the keys of entries 254 // opened are in |keys_to_match|, then erases them. Up to |max_to_open| entries 255 // will be opened, if it is positive. Otherwise, iteration will continue until 256 // OpenNextEntry stops returning net::OK. 257 bool DiskCacheBackendTest::EnumerateAndMatchKeys( 258 int max_to_open, 259 TestIterator* iter, 260 std::set<std::string>* keys_to_match, 261 size_t* count) { 262 disk_cache::Entry* entry; 263 264 if (!iter) 265 return false; 266 while (iter->OpenNextEntry(&entry) == net::OK) { 267 if (!entry) 268 return false; 269 EXPECT_EQ(1U, keys_to_match->erase(entry->GetKey())); 270 entry->Close(); 271 ++(*count); 272 if (max_to_open >= 0 && implicit_cast<int>(*count) >= max_to_open) 273 break; 274 }; 275 276 return true; 277 } 278 279 void DiskCacheBackendTest::BackendBasics() { 280 InitCache(); 281 disk_cache::Entry *entry1 = NULL, *entry2 = NULL; 282 EXPECT_NE(net::OK, OpenEntry("the first key", &entry1)); 283 ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1)); 284 ASSERT_TRUE(NULL != entry1); 285 entry1->Close(); 286 entry1 = NULL; 287 288 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1)); 289 ASSERT_TRUE(NULL != entry1); 290 entry1->Close(); 291 entry1 = NULL; 292 293 EXPECT_NE(net::OK, CreateEntry("the first key", &entry1)); 294 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1)); 295 EXPECT_NE(net::OK, OpenEntry("some other key", &entry2)); 296 ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2)); 297 ASSERT_TRUE(NULL != entry1); 298 ASSERT_TRUE(NULL != entry2); 299 EXPECT_EQ(2, cache_->GetEntryCount()); 300 301 disk_cache::Entry* entry3 = NULL; 302 ASSERT_EQ(net::OK, OpenEntry("some other key", &entry3)); 303 ASSERT_TRUE(NULL != entry3); 304 EXPECT_TRUE(entry2 == entry3); 305 EXPECT_EQ(2, cache_->GetEntryCount()); 306 307 EXPECT_EQ(net::OK, DoomEntry("some other key")); 308 EXPECT_EQ(1, cache_->GetEntryCount()); 309 entry1->Close(); 310 entry2->Close(); 311 entry3->Close(); 312 313 EXPECT_EQ(net::OK, DoomEntry("the first key")); 314 EXPECT_EQ(0, cache_->GetEntryCount()); 315 316 ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1)); 317 ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2)); 318 entry1->Doom(); 319 entry1->Close(); 320 EXPECT_EQ(net::OK, DoomEntry("some other key")); 321 EXPECT_EQ(0, cache_->GetEntryCount()); 322 entry2->Close(); 323 } 324 325 TEST_F(DiskCacheBackendTest, Basics) { 326 BackendBasics(); 327 } 328 329 TEST_F(DiskCacheBackendTest, NewEvictionBasics) { 330 SetNewEviction(); 331 BackendBasics(); 332 } 333 334 TEST_F(DiskCacheBackendTest, MemoryOnlyBasics) { 335 SetMemoryOnlyMode(); 336 BackendBasics(); 337 } 338 339 TEST_F(DiskCacheBackendTest, AppCacheBasics) { 340 SetCacheType(net::APP_CACHE); 341 BackendBasics(); 342 } 343 344 TEST_F(DiskCacheBackendTest, ShaderCacheBasics) { 345 SetCacheType(net::SHADER_CACHE); 346 BackendBasics(); 347 } 348 349 void DiskCacheBackendTest::BackendKeying() { 350 InitCache(); 351 const char* kName1 = "the first key"; 352 const char* kName2 = "the first Key"; 353 disk_cache::Entry *entry1, *entry2; 354 ASSERT_EQ(net::OK, CreateEntry(kName1, &entry1)); 355 356 ASSERT_EQ(net::OK, CreateEntry(kName2, &entry2)); 357 EXPECT_TRUE(entry1 != entry2) << "Case sensitive"; 358 entry2->Close(); 359 360 char buffer[30]; 361 base::strlcpy(buffer, kName1, arraysize(buffer)); 362 ASSERT_EQ(net::OK, OpenEntry(buffer, &entry2)); 363 EXPECT_TRUE(entry1 == entry2); 364 entry2->Close(); 365 366 base::strlcpy(buffer + 1, kName1, arraysize(buffer) - 1); 367 ASSERT_EQ(net::OK, OpenEntry(buffer + 1, &entry2)); 368 EXPECT_TRUE(entry1 == entry2); 369 entry2->Close(); 370 371 base::strlcpy(buffer + 3, kName1, arraysize(buffer) - 3); 372 ASSERT_EQ(net::OK, OpenEntry(buffer + 3, &entry2)); 373 EXPECT_TRUE(entry1 == entry2); 374 entry2->Close(); 375 376 // Now verify long keys. 377 char buffer2[20000]; 378 memset(buffer2, 's', sizeof(buffer2)); 379 buffer2[1023] = '\0'; 380 ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on block file"; 381 entry2->Close(); 382 383 buffer2[1023] = 'g'; 384 buffer2[19999] = '\0'; 385 ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on external file"; 386 entry2->Close(); 387 entry1->Close(); 388 } 389 390 TEST_F(DiskCacheBackendTest, Keying) { 391 BackendKeying(); 392 } 393 394 TEST_F(DiskCacheBackendTest, NewEvictionKeying) { 395 SetNewEviction(); 396 BackendKeying(); 397 } 398 399 TEST_F(DiskCacheBackendTest, MemoryOnlyKeying) { 400 SetMemoryOnlyMode(); 401 BackendKeying(); 402 } 403 404 TEST_F(DiskCacheBackendTest, AppCacheKeying) { 405 SetCacheType(net::APP_CACHE); 406 BackendKeying(); 407 } 408 409 TEST_F(DiskCacheBackendTest, ShaderCacheKeying) { 410 SetCacheType(net::SHADER_CACHE); 411 BackendKeying(); 412 } 413 414 TEST_F(DiskCacheTest, CreateBackend) { 415 net::TestCompletionCallback cb; 416 417 { 418 ASSERT_TRUE(CleanupCacheDir()); 419 base::Thread cache_thread("CacheThread"); 420 ASSERT_TRUE(cache_thread.StartWithOptions( 421 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 422 423 // Test the private factory method(s). 424 scoped_ptr<disk_cache::Backend> cache; 425 cache = disk_cache::MemBackendImpl::CreateBackend(0, NULL); 426 ASSERT_TRUE(cache.get()); 427 cache.reset(); 428 429 // Now test the public API. 430 int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, 431 net::CACHE_BACKEND_DEFAULT, 432 cache_path_, 433 0, 434 false, 435 cache_thread.task_runner(), 436 NULL, 437 &cache, 438 cb.callback()); 439 ASSERT_EQ(net::OK, cb.GetResult(rv)); 440 ASSERT_TRUE(cache.get()); 441 cache.reset(); 442 443 rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE, 444 net::CACHE_BACKEND_DEFAULT, 445 base::FilePath(), 0, 446 false, NULL, NULL, &cache, 447 cb.callback()); 448 ASSERT_EQ(net::OK, cb.GetResult(rv)); 449 ASSERT_TRUE(cache.get()); 450 cache.reset(); 451 } 452 453 base::MessageLoop::current()->RunUntilIdle(); 454 } 455 456 // Tests that |BackendImpl| fails to initialize with a missing file. 457 TEST_F(DiskCacheBackendTest, CreateBackend_MissingFile) { 458 ASSERT_TRUE(CopyTestCache("bad_entry")); 459 base::FilePath filename = cache_path_.AppendASCII("data_1"); 460 base::DeleteFile(filename, false); 461 base::Thread cache_thread("CacheThread"); 462 ASSERT_TRUE(cache_thread.StartWithOptions( 463 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 464 net::TestCompletionCallback cb; 465 466 bool prev = base::ThreadRestrictions::SetIOAllowed(false); 467 scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl( 468 cache_path_, cache_thread.task_runner(), NULL)); 469 int rv = cache->Init(cb.callback()); 470 EXPECT_EQ(net::ERR_FAILED, cb.GetResult(rv)); 471 base::ThreadRestrictions::SetIOAllowed(prev); 472 473 cache.reset(); 474 DisableIntegrityCheck(); 475 } 476 477 TEST_F(DiskCacheBackendTest, ExternalFiles) { 478 InitCache(); 479 // First, let's create a file on the folder. 480 base::FilePath filename = cache_path_.AppendASCII("f_000001"); 481 482 const int kSize = 50; 483 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize)); 484 CacheTestFillBuffer(buffer1->data(), kSize, false); 485 ASSERT_EQ(kSize, base::WriteFile(filename, buffer1->data(), kSize)); 486 487 // Now let's create a file with the cache. 488 disk_cache::Entry* entry; 489 ASSERT_EQ(net::OK, CreateEntry("key", &entry)); 490 ASSERT_EQ(0, WriteData(entry, 0, 20000, buffer1.get(), 0, false)); 491 entry->Close(); 492 493 // And verify that the first file is still there. 494 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize)); 495 ASSERT_EQ(kSize, base::ReadFile(filename, buffer2->data(), kSize)); 496 EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize)); 497 } 498 499 // Tests that we deal with file-level pending operations at destruction time. 500 void DiskCacheBackendTest::BackendShutdownWithPendingFileIO(bool fast) { 501 ASSERT_TRUE(CleanupCacheDir()); 502 uint32 flags = disk_cache::kNoBuffering; 503 if (!fast) 504 flags |= disk_cache::kNoRandom; 505 506 UseCurrentThread(); 507 CreateBackend(flags, NULL); 508 509 net::TestCompletionCallback cb; 510 int rv = GeneratePendingIO(&cb); 511 512 // The cache destructor will see one pending operation here. 513 cache_.reset(); 514 515 if (rv == net::ERR_IO_PENDING) { 516 if (fast || simple_cache_mode_) 517 EXPECT_FALSE(cb.have_result()); 518 else 519 EXPECT_TRUE(cb.have_result()); 520 } 521 522 base::MessageLoop::current()->RunUntilIdle(); 523 524 #if !defined(OS_IOS) 525 // Wait for the actual operation to complete, or we'll keep a file handle that 526 // may cause issues later. Note that on iOS systems even though this test 527 // uses a single thread, the actual IO is posted to a worker thread and the 528 // cache destructor breaks the link to reach cb when the operation completes. 529 rv = cb.GetResult(rv); 530 #endif 531 } 532 533 TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO) { 534 BackendShutdownWithPendingFileIO(false); 535 } 536 537 // Here and below, tests that simulate crashes are not compiled in LeakSanitizer 538 // builds because they contain a lot of intentional memory leaks. 539 // The wrapper scripts used to run tests under Valgrind Memcheck will also 540 // disable these tests. See: 541 // tools/valgrind/gtest_exclude/net_unittests.gtest-memcheck.txt 542 #if !defined(LEAK_SANITIZER) 543 // We'll be leaking from this test. 544 TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO_Fast) { 545 // The integrity test sets kNoRandom so there's a version mismatch if we don't 546 // force new eviction. 547 SetNewEviction(); 548 BackendShutdownWithPendingFileIO(true); 549 } 550 #endif 551 552 // See crbug.com/330074 553 #if !defined(OS_IOS) 554 // Tests that one cache instance is not affected by another one going away. 555 TEST_F(DiskCacheBackendTest, MultipleInstancesWithPendingFileIO) { 556 base::ScopedTempDir store; 557 ASSERT_TRUE(store.CreateUniqueTempDir()); 558 559 net::TestCompletionCallback cb; 560 scoped_ptr<disk_cache::Backend> extra_cache; 561 int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, 562 net::CACHE_BACKEND_DEFAULT, 563 store.path(), 564 0, 565 false, 566 base::ThreadTaskRunnerHandle::Get(), 567 NULL, 568 &extra_cache, 569 cb.callback()); 570 ASSERT_EQ(net::OK, cb.GetResult(rv)); 571 ASSERT_TRUE(extra_cache.get() != NULL); 572 573 ASSERT_TRUE(CleanupCacheDir()); 574 SetNewEviction(); // Match the expected behavior for integrity verification. 575 UseCurrentThread(); 576 577 CreateBackend(disk_cache::kNoBuffering, NULL); 578 rv = GeneratePendingIO(&cb); 579 580 // cache_ has a pending operation, and extra_cache will go away. 581 extra_cache.reset(); 582 583 if (rv == net::ERR_IO_PENDING) 584 EXPECT_FALSE(cb.have_result()); 585 586 base::MessageLoop::current()->RunUntilIdle(); 587 588 // Wait for the actual operation to complete, or we'll keep a file handle that 589 // may cause issues later. 590 rv = cb.GetResult(rv); 591 } 592 #endif 593 594 // Tests that we deal with background-thread pending operations. 595 void DiskCacheBackendTest::BackendShutdownWithPendingIO(bool fast) { 596 net::TestCompletionCallback cb; 597 598 { 599 ASSERT_TRUE(CleanupCacheDir()); 600 base::Thread cache_thread("CacheThread"); 601 ASSERT_TRUE(cache_thread.StartWithOptions( 602 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 603 604 uint32 flags = disk_cache::kNoBuffering; 605 if (!fast) 606 flags |= disk_cache::kNoRandom; 607 608 CreateBackend(flags, &cache_thread); 609 610 disk_cache::Entry* entry; 611 int rv = cache_->CreateEntry("some key", &entry, cb.callback()); 612 ASSERT_EQ(net::OK, cb.GetResult(rv)); 613 614 entry->Close(); 615 616 // The cache destructor will see one pending operation here. 617 cache_.reset(); 618 } 619 620 base::MessageLoop::current()->RunUntilIdle(); 621 } 622 623 TEST_F(DiskCacheBackendTest, ShutdownWithPendingIO) { 624 BackendShutdownWithPendingIO(false); 625 } 626 627 #if !defined(LEAK_SANITIZER) 628 // We'll be leaking from this test. 629 TEST_F(DiskCacheBackendTest, ShutdownWithPendingIO_Fast) { 630 // The integrity test sets kNoRandom so there's a version mismatch if we don't 631 // force new eviction. 632 SetNewEviction(); 633 BackendShutdownWithPendingIO(true); 634 } 635 #endif 636 637 // Tests that we deal with create-type pending operations. 638 void DiskCacheBackendTest::BackendShutdownWithPendingCreate(bool fast) { 639 net::TestCompletionCallback cb; 640 641 { 642 ASSERT_TRUE(CleanupCacheDir()); 643 base::Thread cache_thread("CacheThread"); 644 ASSERT_TRUE(cache_thread.StartWithOptions( 645 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 646 647 disk_cache::BackendFlags flags = 648 fast ? disk_cache::kNone : disk_cache::kNoRandom; 649 CreateBackend(flags, &cache_thread); 650 651 disk_cache::Entry* entry; 652 int rv = cache_->CreateEntry("some key", &entry, cb.callback()); 653 ASSERT_EQ(net::ERR_IO_PENDING, rv); 654 655 cache_.reset(); 656 EXPECT_FALSE(cb.have_result()); 657 } 658 659 base::MessageLoop::current()->RunUntilIdle(); 660 } 661 662 TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate) { 663 BackendShutdownWithPendingCreate(false); 664 } 665 666 #if !defined(LEAK_SANITIZER) 667 // We'll be leaking an entry from this test. 668 TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate_Fast) { 669 // The integrity test sets kNoRandom so there's a version mismatch if we don't 670 // force new eviction. 671 SetNewEviction(); 672 BackendShutdownWithPendingCreate(true); 673 } 674 #endif 675 676 // Disabled on android since this test requires cache creator to create 677 // blockfile caches. 678 #if !defined(OS_ANDROID) 679 TEST_F(DiskCacheTest, TruncatedIndex) { 680 ASSERT_TRUE(CleanupCacheDir()); 681 base::FilePath index = cache_path_.AppendASCII("index"); 682 ASSERT_EQ(5, base::WriteFile(index, "hello", 5)); 683 684 base::Thread cache_thread("CacheThread"); 685 ASSERT_TRUE(cache_thread.StartWithOptions( 686 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 687 net::TestCompletionCallback cb; 688 689 scoped_ptr<disk_cache::Backend> backend; 690 int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, 691 net::CACHE_BACKEND_BLOCKFILE, 692 cache_path_, 693 0, 694 false, 695 cache_thread.task_runner(), 696 NULL, 697 &backend, 698 cb.callback()); 699 ASSERT_NE(net::OK, cb.GetResult(rv)); 700 701 ASSERT_FALSE(backend); 702 } 703 #endif 704 705 void DiskCacheBackendTest::BackendSetSize() { 706 const int cache_size = 0x10000; // 64 kB 707 SetMaxSize(cache_size); 708 InitCache(); 709 710 std::string first("some key"); 711 std::string second("something else"); 712 disk_cache::Entry* entry; 713 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 714 715 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(cache_size)); 716 memset(buffer->data(), 0, cache_size); 717 EXPECT_EQ(cache_size / 10, 718 WriteData(entry, 0, 0, buffer.get(), cache_size / 10, false)) 719 << "normal file"; 720 721 EXPECT_EQ(net::ERR_FAILED, 722 WriteData(entry, 1, 0, buffer.get(), cache_size / 5, false)) 723 << "file size above the limit"; 724 725 // By doubling the total size, we make this file cacheable. 726 SetMaxSize(cache_size * 2); 727 EXPECT_EQ(cache_size / 5, 728 WriteData(entry, 1, 0, buffer.get(), cache_size / 5, false)); 729 730 // Let's fill up the cache!. 731 SetMaxSize(cache_size * 10); 732 EXPECT_EQ(cache_size * 3 / 4, 733 WriteData(entry, 0, 0, buffer.get(), cache_size * 3 / 4, false)); 734 entry->Close(); 735 FlushQueueForTest(); 736 737 SetMaxSize(cache_size); 738 739 // The cache is 95% full. 740 741 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 742 EXPECT_EQ(cache_size / 10, 743 WriteData(entry, 0, 0, buffer.get(), cache_size / 10, false)); 744 745 disk_cache::Entry* entry2; 746 ASSERT_EQ(net::OK, CreateEntry("an extra key", &entry2)); 747 EXPECT_EQ(cache_size / 10, 748 WriteData(entry2, 0, 0, buffer.get(), cache_size / 10, false)); 749 entry2->Close(); // This will trigger the cache trim. 750 751 EXPECT_NE(net::OK, OpenEntry(first, &entry2)); 752 753 FlushQueueForTest(); // Make sure that we are done trimming the cache. 754 FlushQueueForTest(); // We may have posted two tasks to evict stuff. 755 756 entry->Close(); 757 ASSERT_EQ(net::OK, OpenEntry(second, &entry)); 758 EXPECT_EQ(cache_size / 10, entry->GetDataSize(0)); 759 entry->Close(); 760 } 761 762 TEST_F(DiskCacheBackendTest, SetSize) { 763 BackendSetSize(); 764 } 765 766 TEST_F(DiskCacheBackendTest, NewEvictionSetSize) { 767 SetNewEviction(); 768 BackendSetSize(); 769 } 770 771 TEST_F(DiskCacheBackendTest, MemoryOnlySetSize) { 772 SetMemoryOnlyMode(); 773 BackendSetSize(); 774 } 775 776 void DiskCacheBackendTest::BackendLoad() { 777 InitCache(); 778 int seed = static_cast<int>(Time::Now().ToInternalValue()); 779 srand(seed); 780 781 disk_cache::Entry* entries[100]; 782 for (int i = 0; i < 100; i++) { 783 std::string key = GenerateKey(true); 784 ASSERT_EQ(net::OK, CreateEntry(key, &entries[i])); 785 } 786 EXPECT_EQ(100, cache_->GetEntryCount()); 787 788 for (int i = 0; i < 100; i++) { 789 int source1 = rand() % 100; 790 int source2 = rand() % 100; 791 disk_cache::Entry* temp = entries[source1]; 792 entries[source1] = entries[source2]; 793 entries[source2] = temp; 794 } 795 796 for (int i = 0; i < 100; i++) { 797 disk_cache::Entry* entry; 798 ASSERT_EQ(net::OK, OpenEntry(entries[i]->GetKey(), &entry)); 799 EXPECT_TRUE(entry == entries[i]); 800 entry->Close(); 801 entries[i]->Doom(); 802 entries[i]->Close(); 803 } 804 FlushQueueForTest(); 805 EXPECT_EQ(0, cache_->GetEntryCount()); 806 } 807 808 TEST_F(DiskCacheBackendTest, Load) { 809 // Work with a tiny index table (16 entries) 810 SetMask(0xf); 811 SetMaxSize(0x100000); 812 BackendLoad(); 813 } 814 815 TEST_F(DiskCacheBackendTest, NewEvictionLoad) { 816 SetNewEviction(); 817 // Work with a tiny index table (16 entries) 818 SetMask(0xf); 819 SetMaxSize(0x100000); 820 BackendLoad(); 821 } 822 823 TEST_F(DiskCacheBackendTest, MemoryOnlyLoad) { 824 SetMaxSize(0x100000); 825 SetMemoryOnlyMode(); 826 BackendLoad(); 827 } 828 829 TEST_F(DiskCacheBackendTest, AppCacheLoad) { 830 SetCacheType(net::APP_CACHE); 831 // Work with a tiny index table (16 entries) 832 SetMask(0xf); 833 SetMaxSize(0x100000); 834 BackendLoad(); 835 } 836 837 TEST_F(DiskCacheBackendTest, ShaderCacheLoad) { 838 SetCacheType(net::SHADER_CACHE); 839 // Work with a tiny index table (16 entries) 840 SetMask(0xf); 841 SetMaxSize(0x100000); 842 BackendLoad(); 843 } 844 845 // Tests the chaining of an entry to the current head. 846 void DiskCacheBackendTest::BackendChain() { 847 SetMask(0x1); // 2-entry table. 848 SetMaxSize(0x3000); // 12 kB. 849 InitCache(); 850 851 disk_cache::Entry* entry; 852 ASSERT_EQ(net::OK, CreateEntry("The first key", &entry)); 853 entry->Close(); 854 ASSERT_EQ(net::OK, CreateEntry("The Second key", &entry)); 855 entry->Close(); 856 } 857 858 TEST_F(DiskCacheBackendTest, Chain) { 859 BackendChain(); 860 } 861 862 TEST_F(DiskCacheBackendTest, NewEvictionChain) { 863 SetNewEviction(); 864 BackendChain(); 865 } 866 867 TEST_F(DiskCacheBackendTest, AppCacheChain) { 868 SetCacheType(net::APP_CACHE); 869 BackendChain(); 870 } 871 872 TEST_F(DiskCacheBackendTest, ShaderCacheChain) { 873 SetCacheType(net::SHADER_CACHE); 874 BackendChain(); 875 } 876 877 TEST_F(DiskCacheBackendTest, NewEvictionTrim) { 878 SetNewEviction(); 879 InitCache(); 880 881 disk_cache::Entry* entry; 882 for (int i = 0; i < 100; i++) { 883 std::string name(base::StringPrintf("Key %d", i)); 884 ASSERT_EQ(net::OK, CreateEntry(name, &entry)); 885 entry->Close(); 886 if (i < 90) { 887 // Entries 0 to 89 are in list 1; 90 to 99 are in list 0. 888 ASSERT_EQ(net::OK, OpenEntry(name, &entry)); 889 entry->Close(); 890 } 891 } 892 893 // The first eviction must come from list 1 (10% limit), the second must come 894 // from list 0. 895 TrimForTest(false); 896 EXPECT_NE(net::OK, OpenEntry("Key 0", &entry)); 897 TrimForTest(false); 898 EXPECT_NE(net::OK, OpenEntry("Key 90", &entry)); 899 900 // Double check that we still have the list tails. 901 ASSERT_EQ(net::OK, OpenEntry("Key 1", &entry)); 902 entry->Close(); 903 ASSERT_EQ(net::OK, OpenEntry("Key 91", &entry)); 904 entry->Close(); 905 } 906 907 // Before looking for invalid entries, let's check a valid entry. 908 void DiskCacheBackendTest::BackendValidEntry() { 909 InitCache(); 910 911 std::string key("Some key"); 912 disk_cache::Entry* entry; 913 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 914 915 const int kSize = 50; 916 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize)); 917 memset(buffer1->data(), 0, kSize); 918 base::strlcpy(buffer1->data(), "And the data to save", kSize); 919 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer1.get(), kSize, false)); 920 entry->Close(); 921 SimulateCrash(); 922 923 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 924 925 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize)); 926 memset(buffer2->data(), 0, kSize); 927 EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer2.get(), kSize)); 928 entry->Close(); 929 EXPECT_STREQ(buffer1->data(), buffer2->data()); 930 } 931 932 TEST_F(DiskCacheBackendTest, ValidEntry) { 933 BackendValidEntry(); 934 } 935 936 TEST_F(DiskCacheBackendTest, NewEvictionValidEntry) { 937 SetNewEviction(); 938 BackendValidEntry(); 939 } 940 941 // The same logic of the previous test (ValidEntry), but this time force the 942 // entry to be invalid, simulating a crash in the middle. 943 // We'll be leaking memory from this test. 944 void DiskCacheBackendTest::BackendInvalidEntry() { 945 InitCache(); 946 947 std::string key("Some key"); 948 disk_cache::Entry* entry; 949 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 950 951 const int kSize = 50; 952 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 953 memset(buffer->data(), 0, kSize); 954 base::strlcpy(buffer->data(), "And the data to save", kSize); 955 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false)); 956 SimulateCrash(); 957 958 EXPECT_NE(net::OK, OpenEntry(key, &entry)); 959 EXPECT_EQ(0, cache_->GetEntryCount()); 960 } 961 962 #if !defined(LEAK_SANITIZER) 963 // We'll be leaking memory from this test. 964 TEST_F(DiskCacheBackendTest, InvalidEntry) { 965 BackendInvalidEntry(); 966 } 967 968 // We'll be leaking memory from this test. 969 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry) { 970 SetNewEviction(); 971 BackendInvalidEntry(); 972 } 973 974 // We'll be leaking memory from this test. 975 TEST_F(DiskCacheBackendTest, AppCacheInvalidEntry) { 976 SetCacheType(net::APP_CACHE); 977 BackendInvalidEntry(); 978 } 979 980 // We'll be leaking memory from this test. 981 TEST_F(DiskCacheBackendTest, ShaderCacheInvalidEntry) { 982 SetCacheType(net::SHADER_CACHE); 983 BackendInvalidEntry(); 984 } 985 986 // Almost the same test, but this time crash the cache after reading an entry. 987 // We'll be leaking memory from this test. 988 void DiskCacheBackendTest::BackendInvalidEntryRead() { 989 InitCache(); 990 991 std::string key("Some key"); 992 disk_cache::Entry* entry; 993 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 994 995 const int kSize = 50; 996 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 997 memset(buffer->data(), 0, kSize); 998 base::strlcpy(buffer->data(), "And the data to save", kSize); 999 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false)); 1000 entry->Close(); 1001 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 1002 EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer.get(), kSize)); 1003 1004 SimulateCrash(); 1005 1006 if (type_ == net::APP_CACHE) { 1007 // Reading an entry and crashing should not make it dirty. 1008 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 1009 EXPECT_EQ(1, cache_->GetEntryCount()); 1010 entry->Close(); 1011 } else { 1012 EXPECT_NE(net::OK, OpenEntry(key, &entry)); 1013 EXPECT_EQ(0, cache_->GetEntryCount()); 1014 } 1015 } 1016 1017 // We'll be leaking memory from this test. 1018 TEST_F(DiskCacheBackendTest, InvalidEntryRead) { 1019 BackendInvalidEntryRead(); 1020 } 1021 1022 // We'll be leaking memory from this test. 1023 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryRead) { 1024 SetNewEviction(); 1025 BackendInvalidEntryRead(); 1026 } 1027 1028 // We'll be leaking memory from this test. 1029 TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryRead) { 1030 SetCacheType(net::APP_CACHE); 1031 BackendInvalidEntryRead(); 1032 } 1033 1034 // We'll be leaking memory from this test. 1035 TEST_F(DiskCacheBackendTest, ShaderCacheInvalidEntryRead) { 1036 SetCacheType(net::SHADER_CACHE); 1037 BackendInvalidEntryRead(); 1038 } 1039 1040 // We'll be leaking memory from this test. 1041 void DiskCacheBackendTest::BackendInvalidEntryWithLoad() { 1042 // Work with a tiny index table (16 entries) 1043 SetMask(0xf); 1044 SetMaxSize(0x100000); 1045 InitCache(); 1046 1047 int seed = static_cast<int>(Time::Now().ToInternalValue()); 1048 srand(seed); 1049 1050 const int kNumEntries = 100; 1051 disk_cache::Entry* entries[kNumEntries]; 1052 for (int i = 0; i < kNumEntries; i++) { 1053 std::string key = GenerateKey(true); 1054 ASSERT_EQ(net::OK, CreateEntry(key, &entries[i])); 1055 } 1056 EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); 1057 1058 for (int i = 0; i < kNumEntries; i++) { 1059 int source1 = rand() % kNumEntries; 1060 int source2 = rand() % kNumEntries; 1061 disk_cache::Entry* temp = entries[source1]; 1062 entries[source1] = entries[source2]; 1063 entries[source2] = temp; 1064 } 1065 1066 std::string keys[kNumEntries]; 1067 for (int i = 0; i < kNumEntries; i++) { 1068 keys[i] = entries[i]->GetKey(); 1069 if (i < kNumEntries / 2) 1070 entries[i]->Close(); 1071 } 1072 1073 SimulateCrash(); 1074 1075 for (int i = kNumEntries / 2; i < kNumEntries; i++) { 1076 disk_cache::Entry* entry; 1077 EXPECT_NE(net::OK, OpenEntry(keys[i], &entry)); 1078 } 1079 1080 for (int i = 0; i < kNumEntries / 2; i++) { 1081 disk_cache::Entry* entry; 1082 ASSERT_EQ(net::OK, OpenEntry(keys[i], &entry)); 1083 entry->Close(); 1084 } 1085 1086 EXPECT_EQ(kNumEntries / 2, cache_->GetEntryCount()); 1087 } 1088 1089 // We'll be leaking memory from this test. 1090 TEST_F(DiskCacheBackendTest, InvalidEntryWithLoad) { 1091 BackendInvalidEntryWithLoad(); 1092 } 1093 1094 // We'll be leaking memory from this test. 1095 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryWithLoad) { 1096 SetNewEviction(); 1097 BackendInvalidEntryWithLoad(); 1098 } 1099 1100 // We'll be leaking memory from this test. 1101 TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryWithLoad) { 1102 SetCacheType(net::APP_CACHE); 1103 BackendInvalidEntryWithLoad(); 1104 } 1105 1106 // We'll be leaking memory from this test. 1107 TEST_F(DiskCacheBackendTest, ShaderCacheInvalidEntryWithLoad) { 1108 SetCacheType(net::SHADER_CACHE); 1109 BackendInvalidEntryWithLoad(); 1110 } 1111 1112 // We'll be leaking memory from this test. 1113 void DiskCacheBackendTest::BackendTrimInvalidEntry() { 1114 const int kSize = 0x3000; // 12 kB 1115 SetMaxSize(kSize * 10); 1116 InitCache(); 1117 1118 std::string first("some key"); 1119 std::string second("something else"); 1120 disk_cache::Entry* entry; 1121 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 1122 1123 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 1124 memset(buffer->data(), 0, kSize); 1125 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false)); 1126 1127 // Simulate a crash. 1128 SimulateCrash(); 1129 1130 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 1131 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false)); 1132 1133 EXPECT_EQ(2, cache_->GetEntryCount()); 1134 SetMaxSize(kSize); 1135 entry->Close(); // Trim the cache. 1136 FlushQueueForTest(); 1137 1138 // If we evicted the entry in less than 20mS, we have one entry in the cache; 1139 // if it took more than that, we posted a task and we'll delete the second 1140 // entry too. 1141 base::MessageLoop::current()->RunUntilIdle(); 1142 1143 // This may be not thread-safe in general, but for now it's OK so add some 1144 // ThreadSanitizer annotations to ignore data races on cache_. 1145 // See http://crbug.com/55970 1146 ANNOTATE_IGNORE_READS_BEGIN(); 1147 EXPECT_GE(1, cache_->GetEntryCount()); 1148 ANNOTATE_IGNORE_READS_END(); 1149 1150 EXPECT_NE(net::OK, OpenEntry(first, &entry)); 1151 } 1152 1153 // We'll be leaking memory from this test. 1154 TEST_F(DiskCacheBackendTest, TrimInvalidEntry) { 1155 BackendTrimInvalidEntry(); 1156 } 1157 1158 // We'll be leaking memory from this test. 1159 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry) { 1160 SetNewEviction(); 1161 BackendTrimInvalidEntry(); 1162 } 1163 1164 // We'll be leaking memory from this test. 1165 void DiskCacheBackendTest::BackendTrimInvalidEntry2() { 1166 SetMask(0xf); // 16-entry table. 1167 1168 const int kSize = 0x3000; // 12 kB 1169 SetMaxSize(kSize * 40); 1170 InitCache(); 1171 1172 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 1173 memset(buffer->data(), 0, kSize); 1174 disk_cache::Entry* entry; 1175 1176 // Writing 32 entries to this cache chains most of them. 1177 for (int i = 0; i < 32; i++) { 1178 std::string key(base::StringPrintf("some key %d", i)); 1179 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 1180 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false)); 1181 entry->Close(); 1182 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 1183 // Note that we are not closing the entries. 1184 } 1185 1186 // Simulate a crash. 1187 SimulateCrash(); 1188 1189 ASSERT_EQ(net::OK, CreateEntry("Something else", &entry)); 1190 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false)); 1191 1192 FlushQueueForTest(); 1193 EXPECT_EQ(33, cache_->GetEntryCount()); 1194 SetMaxSize(kSize); 1195 1196 // For the new eviction code, all corrupt entries are on the second list so 1197 // they are not going away that easy. 1198 if (new_eviction_) { 1199 EXPECT_EQ(net::OK, DoomAllEntries()); 1200 } 1201 1202 entry->Close(); // Trim the cache. 1203 FlushQueueForTest(); 1204 1205 // We may abort the eviction before cleaning up everything. 1206 base::MessageLoop::current()->RunUntilIdle(); 1207 FlushQueueForTest(); 1208 // If it's not clear enough: we may still have eviction tasks running at this 1209 // time, so the number of entries is changing while we read it. 1210 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); 1211 EXPECT_GE(30, cache_->GetEntryCount()); 1212 ANNOTATE_IGNORE_READS_AND_WRITES_END(); 1213 } 1214 1215 // We'll be leaking memory from this test. 1216 TEST_F(DiskCacheBackendTest, TrimInvalidEntry2) { 1217 BackendTrimInvalidEntry2(); 1218 } 1219 1220 // We'll be leaking memory from this test. 1221 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry2) { 1222 SetNewEviction(); 1223 BackendTrimInvalidEntry2(); 1224 } 1225 #endif // !defined(LEAK_SANITIZER) 1226 1227 void DiskCacheBackendTest::BackendEnumerations() { 1228 InitCache(); 1229 Time initial = Time::Now(); 1230 1231 const int kNumEntries = 100; 1232 for (int i = 0; i < kNumEntries; i++) { 1233 std::string key = GenerateKey(true); 1234 disk_cache::Entry* entry; 1235 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 1236 entry->Close(); 1237 } 1238 EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); 1239 Time final = Time::Now(); 1240 1241 disk_cache::Entry* entry; 1242 scoped_ptr<TestIterator> iter = CreateIterator(); 1243 int count = 0; 1244 Time last_modified[kNumEntries]; 1245 Time last_used[kNumEntries]; 1246 while (iter->OpenNextEntry(&entry) == net::OK) { 1247 ASSERT_TRUE(NULL != entry); 1248 if (count < kNumEntries) { 1249 last_modified[count] = entry->GetLastModified(); 1250 last_used[count] = entry->GetLastUsed(); 1251 EXPECT_TRUE(initial <= last_modified[count]); 1252 EXPECT_TRUE(final >= last_modified[count]); 1253 } 1254 1255 entry->Close(); 1256 count++; 1257 }; 1258 EXPECT_EQ(kNumEntries, count); 1259 1260 iter = CreateIterator(); 1261 count = 0; 1262 // The previous enumeration should not have changed the timestamps. 1263 while (iter->OpenNextEntry(&entry) == net::OK) { 1264 ASSERT_TRUE(NULL != entry); 1265 if (count < kNumEntries) { 1266 EXPECT_TRUE(last_modified[count] == entry->GetLastModified()); 1267 EXPECT_TRUE(last_used[count] == entry->GetLastUsed()); 1268 } 1269 entry->Close(); 1270 count++; 1271 }; 1272 EXPECT_EQ(kNumEntries, count); 1273 } 1274 1275 TEST_F(DiskCacheBackendTest, Enumerations) { 1276 BackendEnumerations(); 1277 } 1278 1279 TEST_F(DiskCacheBackendTest, NewEvictionEnumerations) { 1280 SetNewEviction(); 1281 BackendEnumerations(); 1282 } 1283 1284 TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations) { 1285 SetMemoryOnlyMode(); 1286 BackendEnumerations(); 1287 } 1288 1289 TEST_F(DiskCacheBackendTest, ShaderCacheEnumerations) { 1290 SetCacheType(net::SHADER_CACHE); 1291 BackendEnumerations(); 1292 } 1293 1294 TEST_F(DiskCacheBackendTest, AppCacheEnumerations) { 1295 SetCacheType(net::APP_CACHE); 1296 BackendEnumerations(); 1297 } 1298 1299 // Verifies enumerations while entries are open. 1300 void DiskCacheBackendTest::BackendEnumerations2() { 1301 InitCache(); 1302 const std::string first("first"); 1303 const std::string second("second"); 1304 disk_cache::Entry *entry1, *entry2; 1305 ASSERT_EQ(net::OK, CreateEntry(first, &entry1)); 1306 entry1->Close(); 1307 ASSERT_EQ(net::OK, CreateEntry(second, &entry2)); 1308 entry2->Close(); 1309 FlushQueueForTest(); 1310 1311 // Make sure that the timestamp is not the same. 1312 AddDelay(); 1313 ASSERT_EQ(net::OK, OpenEntry(second, &entry1)); 1314 scoped_ptr<TestIterator> iter = CreateIterator(); 1315 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry2)); 1316 EXPECT_EQ(entry2->GetKey(), second); 1317 1318 // Two entries and the iterator pointing at "first". 1319 entry1->Close(); 1320 entry2->Close(); 1321 1322 // The iterator should still be valid, so we should not crash. 1323 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry2)); 1324 EXPECT_EQ(entry2->GetKey(), first); 1325 entry2->Close(); 1326 iter = CreateIterator(); 1327 1328 // Modify the oldest entry and get the newest element. 1329 ASSERT_EQ(net::OK, OpenEntry(first, &entry1)); 1330 EXPECT_EQ(0, WriteData(entry1, 0, 200, NULL, 0, false)); 1331 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry2)); 1332 if (type_ == net::APP_CACHE) { 1333 // The list is not updated. 1334 EXPECT_EQ(entry2->GetKey(), second); 1335 } else { 1336 EXPECT_EQ(entry2->GetKey(), first); 1337 } 1338 1339 entry1->Close(); 1340 entry2->Close(); 1341 } 1342 1343 TEST_F(DiskCacheBackendTest, Enumerations2) { 1344 BackendEnumerations2(); 1345 } 1346 1347 TEST_F(DiskCacheBackendTest, NewEvictionEnumerations2) { 1348 SetNewEviction(); 1349 BackendEnumerations2(); 1350 } 1351 1352 TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations2) { 1353 SetMemoryOnlyMode(); 1354 BackendEnumerations2(); 1355 } 1356 1357 TEST_F(DiskCacheBackendTest, AppCacheEnumerations2) { 1358 SetCacheType(net::APP_CACHE); 1359 BackendEnumerations2(); 1360 } 1361 1362 TEST_F(DiskCacheBackendTest, ShaderCacheEnumerations2) { 1363 SetCacheType(net::SHADER_CACHE); 1364 BackendEnumerations2(); 1365 } 1366 1367 // Verify that ReadData calls do not update the LRU cache 1368 // when using the SHADER_CACHE type. 1369 TEST_F(DiskCacheBackendTest, ShaderCacheEnumerationReadData) { 1370 SetCacheType(net::SHADER_CACHE); 1371 InitCache(); 1372 const std::string first("first"); 1373 const std::string second("second"); 1374 disk_cache::Entry *entry1, *entry2; 1375 const int kSize = 50; 1376 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize)); 1377 1378 ASSERT_EQ(net::OK, CreateEntry(first, &entry1)); 1379 memset(buffer1->data(), 0, kSize); 1380 base::strlcpy(buffer1->data(), "And the data to save", kSize); 1381 EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1.get(), kSize, false)); 1382 1383 ASSERT_EQ(net::OK, CreateEntry(second, &entry2)); 1384 entry2->Close(); 1385 1386 FlushQueueForTest(); 1387 1388 // Make sure that the timestamp is not the same. 1389 AddDelay(); 1390 1391 // Read from the last item in the LRU. 1392 EXPECT_EQ(kSize, ReadData(entry1, 0, 0, buffer1.get(), kSize)); 1393 entry1->Close(); 1394 1395 scoped_ptr<TestIterator> iter = CreateIterator(); 1396 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry2)); 1397 EXPECT_EQ(entry2->GetKey(), second); 1398 entry2->Close(); 1399 } 1400 1401 #if !defined(LEAK_SANITIZER) 1402 // Verify handling of invalid entries while doing enumerations. 1403 // We'll be leaking memory from this test. 1404 void DiskCacheBackendTest::BackendInvalidEntryEnumeration() { 1405 InitCache(); 1406 1407 std::string key("Some key"); 1408 disk_cache::Entry *entry, *entry1, *entry2; 1409 ASSERT_EQ(net::OK, CreateEntry(key, &entry1)); 1410 1411 const int kSize = 50; 1412 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize)); 1413 memset(buffer1->data(), 0, kSize); 1414 base::strlcpy(buffer1->data(), "And the data to save", kSize); 1415 EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1.get(), kSize, false)); 1416 entry1->Close(); 1417 ASSERT_EQ(net::OK, OpenEntry(key, &entry1)); 1418 EXPECT_EQ(kSize, ReadData(entry1, 0, 0, buffer1.get(), kSize)); 1419 1420 std::string key2("Another key"); 1421 ASSERT_EQ(net::OK, CreateEntry(key2, &entry2)); 1422 entry2->Close(); 1423 ASSERT_EQ(2, cache_->GetEntryCount()); 1424 1425 SimulateCrash(); 1426 1427 scoped_ptr<TestIterator> iter = CreateIterator(); 1428 int count = 0; 1429 while (iter->OpenNextEntry(&entry) == net::OK) { 1430 ASSERT_TRUE(NULL != entry); 1431 EXPECT_EQ(key2, entry->GetKey()); 1432 entry->Close(); 1433 count++; 1434 }; 1435 EXPECT_EQ(1, count); 1436 EXPECT_EQ(1, cache_->GetEntryCount()); 1437 } 1438 1439 // We'll be leaking memory from this test. 1440 TEST_F(DiskCacheBackendTest, InvalidEntryEnumeration) { 1441 BackendInvalidEntryEnumeration(); 1442 } 1443 1444 // We'll be leaking memory from this test. 1445 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryEnumeration) { 1446 SetNewEviction(); 1447 BackendInvalidEntryEnumeration(); 1448 } 1449 #endif // !defined(LEAK_SANITIZER) 1450 1451 // Tests that if for some reason entries are modified close to existing cache 1452 // iterators, we don't generate fatal errors or reset the cache. 1453 void DiskCacheBackendTest::BackendFixEnumerators() { 1454 InitCache(); 1455 1456 int seed = static_cast<int>(Time::Now().ToInternalValue()); 1457 srand(seed); 1458 1459 const int kNumEntries = 10; 1460 for (int i = 0; i < kNumEntries; i++) { 1461 std::string key = GenerateKey(true); 1462 disk_cache::Entry* entry; 1463 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 1464 entry->Close(); 1465 } 1466 EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); 1467 1468 disk_cache::Entry *entry1, *entry2; 1469 scoped_ptr<TestIterator> iter1 = CreateIterator(), iter2 = CreateIterator(); 1470 ASSERT_EQ(net::OK, iter1->OpenNextEntry(&entry1)); 1471 ASSERT_TRUE(NULL != entry1); 1472 entry1->Close(); 1473 entry1 = NULL; 1474 1475 // Let's go to the middle of the list. 1476 for (int i = 0; i < kNumEntries / 2; i++) { 1477 if (entry1) 1478 entry1->Close(); 1479 ASSERT_EQ(net::OK, iter1->OpenNextEntry(&entry1)); 1480 ASSERT_TRUE(NULL != entry1); 1481 1482 ASSERT_EQ(net::OK, iter2->OpenNextEntry(&entry2)); 1483 ASSERT_TRUE(NULL != entry2); 1484 entry2->Close(); 1485 } 1486 1487 // Messing up with entry1 will modify entry2->next. 1488 entry1->Doom(); 1489 ASSERT_EQ(net::OK, iter2->OpenNextEntry(&entry2)); 1490 ASSERT_TRUE(NULL != entry2); 1491 1492 // The link entry2->entry1 should be broken. 1493 EXPECT_NE(entry2->GetKey(), entry1->GetKey()); 1494 entry1->Close(); 1495 entry2->Close(); 1496 1497 // And the second iterator should keep working. 1498 ASSERT_EQ(net::OK, iter2->OpenNextEntry(&entry2)); 1499 ASSERT_TRUE(NULL != entry2); 1500 entry2->Close(); 1501 } 1502 1503 TEST_F(DiskCacheBackendTest, FixEnumerators) { 1504 BackendFixEnumerators(); 1505 } 1506 1507 TEST_F(DiskCacheBackendTest, NewEvictionFixEnumerators) { 1508 SetNewEviction(); 1509 BackendFixEnumerators(); 1510 } 1511 1512 void DiskCacheBackendTest::BackendDoomRecent() { 1513 InitCache(); 1514 1515 disk_cache::Entry *entry; 1516 ASSERT_EQ(net::OK, CreateEntry("first", &entry)); 1517 entry->Close(); 1518 ASSERT_EQ(net::OK, CreateEntry("second", &entry)); 1519 entry->Close(); 1520 FlushQueueForTest(); 1521 1522 AddDelay(); 1523 Time middle = Time::Now(); 1524 1525 ASSERT_EQ(net::OK, CreateEntry("third", &entry)); 1526 entry->Close(); 1527 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry)); 1528 entry->Close(); 1529 FlushQueueForTest(); 1530 1531 AddDelay(); 1532 Time final = Time::Now(); 1533 1534 ASSERT_EQ(4, cache_->GetEntryCount()); 1535 EXPECT_EQ(net::OK, DoomEntriesSince(final)); 1536 ASSERT_EQ(4, cache_->GetEntryCount()); 1537 1538 EXPECT_EQ(net::OK, DoomEntriesSince(middle)); 1539 ASSERT_EQ(2, cache_->GetEntryCount()); 1540 1541 ASSERT_EQ(net::OK, OpenEntry("second", &entry)); 1542 entry->Close(); 1543 } 1544 1545 TEST_F(DiskCacheBackendTest, DoomRecent) { 1546 BackendDoomRecent(); 1547 } 1548 1549 TEST_F(DiskCacheBackendTest, NewEvictionDoomRecent) { 1550 SetNewEviction(); 1551 BackendDoomRecent(); 1552 } 1553 1554 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomRecent) { 1555 SetMemoryOnlyMode(); 1556 BackendDoomRecent(); 1557 } 1558 1559 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomEntriesSinceSparse) { 1560 SetMemoryOnlyMode(); 1561 base::Time start; 1562 InitSparseCache(&start, NULL); 1563 DoomEntriesSince(start); 1564 EXPECT_EQ(1, cache_->GetEntryCount()); 1565 } 1566 1567 TEST_F(DiskCacheBackendTest, DoomEntriesSinceSparse) { 1568 base::Time start; 1569 InitSparseCache(&start, NULL); 1570 DoomEntriesSince(start); 1571 // NOTE: BackendImpl counts child entries in its GetEntryCount(), while 1572 // MemBackendImpl does not. Thats why expected value differs here from 1573 // MemoryOnlyDoomEntriesSinceSparse. 1574 EXPECT_EQ(3, cache_->GetEntryCount()); 1575 } 1576 1577 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomAllSparse) { 1578 SetMemoryOnlyMode(); 1579 InitSparseCache(NULL, NULL); 1580 EXPECT_EQ(net::OK, DoomAllEntries()); 1581 EXPECT_EQ(0, cache_->GetEntryCount()); 1582 } 1583 1584 TEST_F(DiskCacheBackendTest, DoomAllSparse) { 1585 InitSparseCache(NULL, NULL); 1586 EXPECT_EQ(net::OK, DoomAllEntries()); 1587 EXPECT_EQ(0, cache_->GetEntryCount()); 1588 } 1589 1590 void DiskCacheBackendTest::BackendDoomBetween() { 1591 InitCache(); 1592 1593 disk_cache::Entry *entry; 1594 ASSERT_EQ(net::OK, CreateEntry("first", &entry)); 1595 entry->Close(); 1596 FlushQueueForTest(); 1597 1598 AddDelay(); 1599 Time middle_start = Time::Now(); 1600 1601 ASSERT_EQ(net::OK, CreateEntry("second", &entry)); 1602 entry->Close(); 1603 ASSERT_EQ(net::OK, CreateEntry("third", &entry)); 1604 entry->Close(); 1605 FlushQueueForTest(); 1606 1607 AddDelay(); 1608 Time middle_end = Time::Now(); 1609 1610 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry)); 1611 entry->Close(); 1612 ASSERT_EQ(net::OK, OpenEntry("fourth", &entry)); 1613 entry->Close(); 1614 FlushQueueForTest(); 1615 1616 AddDelay(); 1617 Time final = Time::Now(); 1618 1619 ASSERT_EQ(4, cache_->GetEntryCount()); 1620 EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, middle_end)); 1621 ASSERT_EQ(2, cache_->GetEntryCount()); 1622 1623 ASSERT_EQ(net::OK, OpenEntry("fourth", &entry)); 1624 entry->Close(); 1625 1626 EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, final)); 1627 ASSERT_EQ(1, cache_->GetEntryCount()); 1628 1629 ASSERT_EQ(net::OK, OpenEntry("first", &entry)); 1630 entry->Close(); 1631 } 1632 1633 TEST_F(DiskCacheBackendTest, DoomBetween) { 1634 BackendDoomBetween(); 1635 } 1636 1637 TEST_F(DiskCacheBackendTest, NewEvictionDoomBetween) { 1638 SetNewEviction(); 1639 BackendDoomBetween(); 1640 } 1641 1642 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomBetween) { 1643 SetMemoryOnlyMode(); 1644 BackendDoomBetween(); 1645 } 1646 1647 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomEntriesBetweenSparse) { 1648 SetMemoryOnlyMode(); 1649 base::Time start, end; 1650 InitSparseCache(&start, &end); 1651 DoomEntriesBetween(start, end); 1652 EXPECT_EQ(3, cache_->GetEntryCount()); 1653 1654 start = end; 1655 end = base::Time::Now(); 1656 DoomEntriesBetween(start, end); 1657 EXPECT_EQ(1, cache_->GetEntryCount()); 1658 } 1659 1660 TEST_F(DiskCacheBackendTest, DoomEntriesBetweenSparse) { 1661 base::Time start, end; 1662 InitSparseCache(&start, &end); 1663 DoomEntriesBetween(start, end); 1664 EXPECT_EQ(9, cache_->GetEntryCount()); 1665 1666 start = end; 1667 end = base::Time::Now(); 1668 DoomEntriesBetween(start, end); 1669 EXPECT_EQ(3, cache_->GetEntryCount()); 1670 } 1671 1672 void DiskCacheBackendTest::BackendTransaction(const std::string& name, 1673 int num_entries, bool load) { 1674 success_ = false; 1675 ASSERT_TRUE(CopyTestCache(name)); 1676 DisableFirstCleanup(); 1677 1678 uint32 mask; 1679 if (load) { 1680 mask = 0xf; 1681 SetMaxSize(0x100000); 1682 } else { 1683 // Clear the settings from the previous run. 1684 mask = 0; 1685 SetMaxSize(0); 1686 } 1687 SetMask(mask); 1688 1689 InitCache(); 1690 ASSERT_EQ(num_entries + 1, cache_->GetEntryCount()); 1691 1692 std::string key("the first key"); 1693 disk_cache::Entry* entry1; 1694 ASSERT_NE(net::OK, OpenEntry(key, &entry1)); 1695 1696 int actual = cache_->GetEntryCount(); 1697 if (num_entries != actual) { 1698 ASSERT_TRUE(load); 1699 // If there is a heavy load, inserting an entry will make another entry 1700 // dirty (on the hash bucket) so two entries are removed. 1701 ASSERT_EQ(num_entries - 1, actual); 1702 } 1703 1704 cache_.reset(); 1705 cache_impl_ = NULL; 1706 1707 ASSERT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, mask)); 1708 success_ = true; 1709 } 1710 1711 void DiskCacheBackendTest::BackendRecoverInsert() { 1712 // Tests with an empty cache. 1713 BackendTransaction("insert_empty1", 0, false); 1714 ASSERT_TRUE(success_) << "insert_empty1"; 1715 BackendTransaction("insert_empty2", 0, false); 1716 ASSERT_TRUE(success_) << "insert_empty2"; 1717 BackendTransaction("insert_empty3", 0, false); 1718 ASSERT_TRUE(success_) << "insert_empty3"; 1719 1720 // Tests with one entry on the cache. 1721 BackendTransaction("insert_one1", 1, false); 1722 ASSERT_TRUE(success_) << "insert_one1"; 1723 BackendTransaction("insert_one2", 1, false); 1724 ASSERT_TRUE(success_) << "insert_one2"; 1725 BackendTransaction("insert_one3", 1, false); 1726 ASSERT_TRUE(success_) << "insert_one3"; 1727 1728 // Tests with one hundred entries on the cache, tiny index. 1729 BackendTransaction("insert_load1", 100, true); 1730 ASSERT_TRUE(success_) << "insert_load1"; 1731 BackendTransaction("insert_load2", 100, true); 1732 ASSERT_TRUE(success_) << "insert_load2"; 1733 } 1734 1735 TEST_F(DiskCacheBackendTest, RecoverInsert) { 1736 BackendRecoverInsert(); 1737 } 1738 1739 TEST_F(DiskCacheBackendTest, NewEvictionRecoverInsert) { 1740 SetNewEviction(); 1741 BackendRecoverInsert(); 1742 } 1743 1744 void DiskCacheBackendTest::BackendRecoverRemove() { 1745 // Removing the only element. 1746 BackendTransaction("remove_one1", 0, false); 1747 ASSERT_TRUE(success_) << "remove_one1"; 1748 BackendTransaction("remove_one2", 0, false); 1749 ASSERT_TRUE(success_) << "remove_one2"; 1750 BackendTransaction("remove_one3", 0, false); 1751 ASSERT_TRUE(success_) << "remove_one3"; 1752 1753 // Removing the head. 1754 BackendTransaction("remove_head1", 1, false); 1755 ASSERT_TRUE(success_) << "remove_head1"; 1756 BackendTransaction("remove_head2", 1, false); 1757 ASSERT_TRUE(success_) << "remove_head2"; 1758 BackendTransaction("remove_head3", 1, false); 1759 ASSERT_TRUE(success_) << "remove_head3"; 1760 1761 // Removing the tail. 1762 BackendTransaction("remove_tail1", 1, false); 1763 ASSERT_TRUE(success_) << "remove_tail1"; 1764 BackendTransaction("remove_tail2", 1, false); 1765 ASSERT_TRUE(success_) << "remove_tail2"; 1766 BackendTransaction("remove_tail3", 1, false); 1767 ASSERT_TRUE(success_) << "remove_tail3"; 1768 1769 // Removing with one hundred entries on the cache, tiny index. 1770 BackendTransaction("remove_load1", 100, true); 1771 ASSERT_TRUE(success_) << "remove_load1"; 1772 BackendTransaction("remove_load2", 100, true); 1773 ASSERT_TRUE(success_) << "remove_load2"; 1774 BackendTransaction("remove_load3", 100, true); 1775 ASSERT_TRUE(success_) << "remove_load3"; 1776 1777 // This case cannot be reverted. 1778 BackendTransaction("remove_one4", 0, false); 1779 ASSERT_TRUE(success_) << "remove_one4"; 1780 BackendTransaction("remove_head4", 1, false); 1781 ASSERT_TRUE(success_) << "remove_head4"; 1782 } 1783 1784 #if defined(OS_WIN) 1785 // http://crbug.com/396392 1786 #define MAYBE_RecoverRemove DISABLED_RecoverRemove 1787 #else 1788 #define MAYBE_RecoverRemove RecoverRemove 1789 #endif 1790 TEST_F(DiskCacheBackendTest, MAYBE_RecoverRemove) { 1791 BackendRecoverRemove(); 1792 } 1793 1794 #if defined(OS_WIN) 1795 // http://crbug.com/396392 1796 #define MAYBE_NewEvictionRecoverRemove DISABLED_NewEvictionRecoverRemove 1797 #else 1798 #define MAYBE_NewEvictionRecoverRemove NewEvictionRecoverRemove 1799 #endif 1800 TEST_F(DiskCacheBackendTest, MAYBE_NewEvictionRecoverRemove) { 1801 SetNewEviction(); 1802 BackendRecoverRemove(); 1803 } 1804 1805 void DiskCacheBackendTest::BackendRecoverWithEviction() { 1806 success_ = false; 1807 ASSERT_TRUE(CopyTestCache("insert_load1")); 1808 DisableFirstCleanup(); 1809 1810 SetMask(0xf); 1811 SetMaxSize(0x1000); 1812 1813 // We should not crash here. 1814 InitCache(); 1815 DisableIntegrityCheck(); 1816 } 1817 1818 TEST_F(DiskCacheBackendTest, RecoverWithEviction) { 1819 BackendRecoverWithEviction(); 1820 } 1821 1822 TEST_F(DiskCacheBackendTest, NewEvictionRecoverWithEviction) { 1823 SetNewEviction(); 1824 BackendRecoverWithEviction(); 1825 } 1826 1827 // Tests that the |BackendImpl| fails to start with the wrong cache version. 1828 TEST_F(DiskCacheTest, WrongVersion) { 1829 ASSERT_TRUE(CopyTestCache("wrong_version")); 1830 base::Thread cache_thread("CacheThread"); 1831 ASSERT_TRUE(cache_thread.StartWithOptions( 1832 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 1833 net::TestCompletionCallback cb; 1834 1835 scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl( 1836 cache_path_, cache_thread.task_runner(), NULL)); 1837 int rv = cache->Init(cb.callback()); 1838 ASSERT_EQ(net::ERR_FAILED, cb.GetResult(rv)); 1839 } 1840 1841 class BadEntropyProvider : public base::FieldTrial::EntropyProvider { 1842 public: 1843 virtual ~BadEntropyProvider() {} 1844 1845 virtual double GetEntropyForTrial(const std::string& trial_name, 1846 uint32 randomization_seed) const OVERRIDE { 1847 return 0.5; 1848 } 1849 }; 1850 1851 // Tests that the disk cache successfully joins the control group, dropping the 1852 // existing cache in favour of a new empty cache. 1853 // Disabled on android since this test requires cache creator to create 1854 // blockfile caches. 1855 #if !defined(OS_ANDROID) 1856 TEST_F(DiskCacheTest, SimpleCacheControlJoin) { 1857 base::Thread cache_thread("CacheThread"); 1858 ASSERT_TRUE(cache_thread.StartWithOptions( 1859 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 1860 1861 scoped_ptr<disk_cache::BackendImpl> cache = 1862 CreateExistingEntryCache(cache_thread, cache_path_); 1863 ASSERT_TRUE(cache.get()); 1864 cache.reset(); 1865 1866 // Instantiate the SimpleCacheTrial, forcing this run into the 1867 // ExperimentControl group. 1868 base::FieldTrialList field_trial_list(new BadEntropyProvider()); 1869 base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial", 1870 "ExperimentControl"); 1871 net::TestCompletionCallback cb; 1872 scoped_ptr<disk_cache::Backend> base_cache; 1873 int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, 1874 net::CACHE_BACKEND_BLOCKFILE, 1875 cache_path_, 1876 0, 1877 true, 1878 cache_thread.task_runner(), 1879 NULL, 1880 &base_cache, 1881 cb.callback()); 1882 ASSERT_EQ(net::OK, cb.GetResult(rv)); 1883 EXPECT_EQ(0, base_cache->GetEntryCount()); 1884 } 1885 #endif 1886 1887 // Tests that the disk cache can restart in the control group preserving 1888 // existing entries. 1889 TEST_F(DiskCacheTest, SimpleCacheControlRestart) { 1890 // Instantiate the SimpleCacheTrial, forcing this run into the 1891 // ExperimentControl group. 1892 base::FieldTrialList field_trial_list(new BadEntropyProvider()); 1893 base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial", 1894 "ExperimentControl"); 1895 1896 base::Thread cache_thread("CacheThread"); 1897 ASSERT_TRUE(cache_thread.StartWithOptions( 1898 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 1899 1900 scoped_ptr<disk_cache::BackendImpl> cache = 1901 CreateExistingEntryCache(cache_thread, cache_path_); 1902 ASSERT_TRUE(cache.get()); 1903 1904 net::TestCompletionCallback cb; 1905 1906 const int kRestartCount = 5; 1907 for (int i = 0; i < kRestartCount; ++i) { 1908 cache.reset(new disk_cache::BackendImpl( 1909 cache_path_, cache_thread.message_loop_proxy(), NULL)); 1910 int rv = cache->Init(cb.callback()); 1911 ASSERT_EQ(net::OK, cb.GetResult(rv)); 1912 EXPECT_EQ(1, cache->GetEntryCount()); 1913 1914 disk_cache::Entry* entry = NULL; 1915 rv = cache->OpenEntry(kExistingEntryKey, &entry, cb.callback()); 1916 EXPECT_EQ(net::OK, cb.GetResult(rv)); 1917 EXPECT_TRUE(entry); 1918 entry->Close(); 1919 } 1920 } 1921 1922 // Tests that the disk cache can leave the control group preserving existing 1923 // entries. 1924 TEST_F(DiskCacheTest, SimpleCacheControlLeave) { 1925 base::Thread cache_thread("CacheThread"); 1926 ASSERT_TRUE(cache_thread.StartWithOptions( 1927 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 1928 1929 { 1930 // Instantiate the SimpleCacheTrial, forcing this run into the 1931 // ExperimentControl group. 1932 base::FieldTrialList field_trial_list(new BadEntropyProvider()); 1933 base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial", 1934 "ExperimentControl"); 1935 1936 scoped_ptr<disk_cache::BackendImpl> cache = 1937 CreateExistingEntryCache(cache_thread, cache_path_); 1938 ASSERT_TRUE(cache.get()); 1939 } 1940 1941 // Instantiate the SimpleCacheTrial, forcing this run into the 1942 // ExperimentNo group. 1943 base::FieldTrialList field_trial_list(new BadEntropyProvider()); 1944 base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial", "ExperimentNo"); 1945 net::TestCompletionCallback cb; 1946 1947 const int kRestartCount = 5; 1948 for (int i = 0; i < kRestartCount; ++i) { 1949 scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl( 1950 cache_path_, cache_thread.message_loop_proxy(), NULL)); 1951 int rv = cache->Init(cb.callback()); 1952 ASSERT_EQ(net::OK, cb.GetResult(rv)); 1953 EXPECT_EQ(1, cache->GetEntryCount()); 1954 1955 disk_cache::Entry* entry = NULL; 1956 rv = cache->OpenEntry(kExistingEntryKey, &entry, cb.callback()); 1957 EXPECT_EQ(net::OK, cb.GetResult(rv)); 1958 EXPECT_TRUE(entry); 1959 entry->Close(); 1960 } 1961 } 1962 1963 // Tests that the cache is properly restarted on recovery error. 1964 // Disabled on android since this test requires cache creator to create 1965 // blockfile caches. 1966 #if !defined(OS_ANDROID) 1967 TEST_F(DiskCacheBackendTest, DeleteOld) { 1968 ASSERT_TRUE(CopyTestCache("wrong_version")); 1969 SetNewEviction(); 1970 base::Thread cache_thread("CacheThread"); 1971 ASSERT_TRUE(cache_thread.StartWithOptions( 1972 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 1973 1974 net::TestCompletionCallback cb; 1975 bool prev = base::ThreadRestrictions::SetIOAllowed(false); 1976 base::FilePath path(cache_path_); 1977 int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, 1978 net::CACHE_BACKEND_BLOCKFILE, 1979 path, 1980 0, 1981 true, 1982 cache_thread.task_runner(), 1983 NULL, 1984 &cache_, 1985 cb.callback()); 1986 path.clear(); // Make sure path was captured by the previous call. 1987 ASSERT_EQ(net::OK, cb.GetResult(rv)); 1988 base::ThreadRestrictions::SetIOAllowed(prev); 1989 cache_.reset(); 1990 EXPECT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, mask_)); 1991 } 1992 #endif 1993 1994 // We want to be able to deal with messed up entries on disk. 1995 void DiskCacheBackendTest::BackendInvalidEntry2() { 1996 ASSERT_TRUE(CopyTestCache("bad_entry")); 1997 DisableFirstCleanup(); 1998 InitCache(); 1999 2000 disk_cache::Entry *entry1, *entry2; 2001 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1)); 2002 EXPECT_NE(net::OK, OpenEntry("some other key", &entry2)); 2003 entry1->Close(); 2004 2005 // CheckCacheIntegrity will fail at this point. 2006 DisableIntegrityCheck(); 2007 } 2008 2009 TEST_F(DiskCacheBackendTest, InvalidEntry2) { 2010 BackendInvalidEntry2(); 2011 } 2012 2013 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry2) { 2014 SetNewEviction(); 2015 BackendInvalidEntry2(); 2016 } 2017 2018 // Tests that we don't crash or hang when enumerating this cache. 2019 void DiskCacheBackendTest::BackendInvalidEntry3() { 2020 SetMask(0x1); // 2-entry table. 2021 SetMaxSize(0x3000); // 12 kB. 2022 DisableFirstCleanup(); 2023 InitCache(); 2024 2025 disk_cache::Entry* entry; 2026 scoped_ptr<TestIterator> iter = CreateIterator(); 2027 while (iter->OpenNextEntry(&entry) == net::OK) { 2028 entry->Close(); 2029 } 2030 } 2031 2032 TEST_F(DiskCacheBackendTest, InvalidEntry3) { 2033 ASSERT_TRUE(CopyTestCache("dirty_entry3")); 2034 BackendInvalidEntry3(); 2035 } 2036 2037 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry3) { 2038 ASSERT_TRUE(CopyTestCache("dirty_entry4")); 2039 SetNewEviction(); 2040 BackendInvalidEntry3(); 2041 DisableIntegrityCheck(); 2042 } 2043 2044 // Test that we handle a dirty entry on the LRU list, already replaced with 2045 // the same key, and with hash collisions. 2046 TEST_F(DiskCacheBackendTest, InvalidEntry4) { 2047 ASSERT_TRUE(CopyTestCache("dirty_entry3")); 2048 SetMask(0x1); // 2-entry table. 2049 SetMaxSize(0x3000); // 12 kB. 2050 DisableFirstCleanup(); 2051 InitCache(); 2052 2053 TrimForTest(false); 2054 } 2055 2056 // Test that we handle a dirty entry on the deleted list, already replaced with 2057 // the same key, and with hash collisions. 2058 TEST_F(DiskCacheBackendTest, InvalidEntry5) { 2059 ASSERT_TRUE(CopyTestCache("dirty_entry4")); 2060 SetNewEviction(); 2061 SetMask(0x1); // 2-entry table. 2062 SetMaxSize(0x3000); // 12 kB. 2063 DisableFirstCleanup(); 2064 InitCache(); 2065 2066 TrimDeletedListForTest(false); 2067 } 2068 2069 TEST_F(DiskCacheBackendTest, InvalidEntry6) { 2070 ASSERT_TRUE(CopyTestCache("dirty_entry5")); 2071 SetMask(0x1); // 2-entry table. 2072 SetMaxSize(0x3000); // 12 kB. 2073 DisableFirstCleanup(); 2074 InitCache(); 2075 2076 // There is a dirty entry (but marked as clean) at the end, pointing to a 2077 // deleted entry through the hash collision list. We should not re-insert the 2078 // deleted entry into the index table. 2079 2080 TrimForTest(false); 2081 // The cache should be clean (as detected by CheckCacheIntegrity). 2082 } 2083 2084 // Tests that we don't hang when there is a loop on the hash collision list. 2085 // The test cache could be a result of bug 69135. 2086 TEST_F(DiskCacheBackendTest, BadNextEntry1) { 2087 ASSERT_TRUE(CopyTestCache("list_loop2")); 2088 SetMask(0x1); // 2-entry table. 2089 SetMaxSize(0x3000); // 12 kB. 2090 DisableFirstCleanup(); 2091 InitCache(); 2092 2093 // The second entry points at itselft, and the first entry is not accessible 2094 // though the index, but it is at the head of the LRU. 2095 2096 disk_cache::Entry* entry; 2097 ASSERT_EQ(net::OK, CreateEntry("The first key", &entry)); 2098 entry->Close(); 2099 2100 TrimForTest(false); 2101 TrimForTest(false); 2102 ASSERT_EQ(net::OK, OpenEntry("The first key", &entry)); 2103 entry->Close(); 2104 EXPECT_EQ(1, cache_->GetEntryCount()); 2105 } 2106 2107 // Tests that we don't hang when there is a loop on the hash collision list. 2108 // The test cache could be a result of bug 69135. 2109 TEST_F(DiskCacheBackendTest, BadNextEntry2) { 2110 ASSERT_TRUE(CopyTestCache("list_loop3")); 2111 SetMask(0x1); // 2-entry table. 2112 SetMaxSize(0x3000); // 12 kB. 2113 DisableFirstCleanup(); 2114 InitCache(); 2115 2116 // There is a wide loop of 5 entries. 2117 2118 disk_cache::Entry* entry; 2119 ASSERT_NE(net::OK, OpenEntry("Not present key", &entry)); 2120 } 2121 2122 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry6) { 2123 ASSERT_TRUE(CopyTestCache("bad_rankings3")); 2124 DisableFirstCleanup(); 2125 SetNewEviction(); 2126 InitCache(); 2127 2128 // The second entry is dirty, but removing it should not corrupt the list. 2129 disk_cache::Entry* entry; 2130 ASSERT_NE(net::OK, OpenEntry("the second key", &entry)); 2131 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry)); 2132 2133 // This should not delete the cache. 2134 entry->Doom(); 2135 FlushQueueForTest(); 2136 entry->Close(); 2137 2138 ASSERT_EQ(net::OK, OpenEntry("some other key", &entry)); 2139 entry->Close(); 2140 } 2141 2142 // Tests handling of corrupt entries by keeping the rankings node around, with 2143 // a fatal failure. 2144 void DiskCacheBackendTest::BackendInvalidEntry7() { 2145 const int kSize = 0x3000; // 12 kB. 2146 SetMaxSize(kSize * 10); 2147 InitCache(); 2148 2149 std::string first("some key"); 2150 std::string second("something else"); 2151 disk_cache::Entry* entry; 2152 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 2153 entry->Close(); 2154 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 2155 2156 // Corrupt this entry. 2157 disk_cache::EntryImpl* entry_impl = 2158 static_cast<disk_cache::EntryImpl*>(entry); 2159 2160 entry_impl->rankings()->Data()->next = 0; 2161 entry_impl->rankings()->Store(); 2162 entry->Close(); 2163 FlushQueueForTest(); 2164 EXPECT_EQ(2, cache_->GetEntryCount()); 2165 2166 // This should detect the bad entry. 2167 EXPECT_NE(net::OK, OpenEntry(second, &entry)); 2168 EXPECT_EQ(1, cache_->GetEntryCount()); 2169 2170 // We should delete the cache. The list still has a corrupt node. 2171 scoped_ptr<TestIterator> iter = CreateIterator(); 2172 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); 2173 FlushQueueForTest(); 2174 EXPECT_EQ(0, cache_->GetEntryCount()); 2175 } 2176 2177 TEST_F(DiskCacheBackendTest, InvalidEntry7) { 2178 BackendInvalidEntry7(); 2179 } 2180 2181 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry7) { 2182 SetNewEviction(); 2183 BackendInvalidEntry7(); 2184 } 2185 2186 // Tests handling of corrupt entries by keeping the rankings node around, with 2187 // a non fatal failure. 2188 void DiskCacheBackendTest::BackendInvalidEntry8() { 2189 const int kSize = 0x3000; // 12 kB 2190 SetMaxSize(kSize * 10); 2191 InitCache(); 2192 2193 std::string first("some key"); 2194 std::string second("something else"); 2195 disk_cache::Entry* entry; 2196 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 2197 entry->Close(); 2198 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 2199 2200 // Corrupt this entry. 2201 disk_cache::EntryImpl* entry_impl = 2202 static_cast<disk_cache::EntryImpl*>(entry); 2203 2204 entry_impl->rankings()->Data()->contents = 0; 2205 entry_impl->rankings()->Store(); 2206 entry->Close(); 2207 FlushQueueForTest(); 2208 EXPECT_EQ(2, cache_->GetEntryCount()); 2209 2210 // This should detect the bad entry. 2211 EXPECT_NE(net::OK, OpenEntry(second, &entry)); 2212 EXPECT_EQ(1, cache_->GetEntryCount()); 2213 2214 // We should not delete the cache. 2215 scoped_ptr<TestIterator> iter = CreateIterator(); 2216 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); 2217 entry->Close(); 2218 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); 2219 EXPECT_EQ(1, cache_->GetEntryCount()); 2220 } 2221 2222 TEST_F(DiskCacheBackendTest, InvalidEntry8) { 2223 BackendInvalidEntry8(); 2224 } 2225 2226 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry8) { 2227 SetNewEviction(); 2228 BackendInvalidEntry8(); 2229 } 2230 2231 // Tests handling of corrupt entries detected by enumerations. Note that these 2232 // tests (xx9 to xx11) are basically just going though slightly different 2233 // codepaths so they are tighlty coupled with the code, but that is better than 2234 // not testing error handling code. 2235 void DiskCacheBackendTest::BackendInvalidEntry9(bool eviction) { 2236 const int kSize = 0x3000; // 12 kB. 2237 SetMaxSize(kSize * 10); 2238 InitCache(); 2239 2240 std::string first("some key"); 2241 std::string second("something else"); 2242 disk_cache::Entry* entry; 2243 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 2244 entry->Close(); 2245 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 2246 2247 // Corrupt this entry. 2248 disk_cache::EntryImpl* entry_impl = 2249 static_cast<disk_cache::EntryImpl*>(entry); 2250 2251 entry_impl->entry()->Data()->state = 0xbad; 2252 entry_impl->entry()->Store(); 2253 entry->Close(); 2254 FlushQueueForTest(); 2255 EXPECT_EQ(2, cache_->GetEntryCount()); 2256 2257 if (eviction) { 2258 TrimForTest(false); 2259 EXPECT_EQ(1, cache_->GetEntryCount()); 2260 TrimForTest(false); 2261 EXPECT_EQ(1, cache_->GetEntryCount()); 2262 } else { 2263 // We should detect the problem through the list, but we should not delete 2264 // the entry, just fail the iteration. 2265 scoped_ptr<TestIterator> iter = CreateIterator(); 2266 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); 2267 2268 // Now a full iteration will work, and return one entry. 2269 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); 2270 entry->Close(); 2271 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); 2272 2273 // This should detect what's left of the bad entry. 2274 EXPECT_NE(net::OK, OpenEntry(second, &entry)); 2275 EXPECT_EQ(2, cache_->GetEntryCount()); 2276 } 2277 DisableIntegrityCheck(); 2278 } 2279 2280 TEST_F(DiskCacheBackendTest, InvalidEntry9) { 2281 BackendInvalidEntry9(false); 2282 } 2283 2284 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry9) { 2285 SetNewEviction(); 2286 BackendInvalidEntry9(false); 2287 } 2288 2289 TEST_F(DiskCacheBackendTest, TrimInvalidEntry9) { 2290 BackendInvalidEntry9(true); 2291 } 2292 2293 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry9) { 2294 SetNewEviction(); 2295 BackendInvalidEntry9(true); 2296 } 2297 2298 // Tests handling of corrupt entries detected by enumerations. 2299 void DiskCacheBackendTest::BackendInvalidEntry10(bool eviction) { 2300 const int kSize = 0x3000; // 12 kB. 2301 SetMaxSize(kSize * 10); 2302 SetNewEviction(); 2303 InitCache(); 2304 2305 std::string first("some key"); 2306 std::string second("something else"); 2307 disk_cache::Entry* entry; 2308 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 2309 entry->Close(); 2310 ASSERT_EQ(net::OK, OpenEntry(first, &entry)); 2311 EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false)); 2312 entry->Close(); 2313 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 2314 2315 // Corrupt this entry. 2316 disk_cache::EntryImpl* entry_impl = 2317 static_cast<disk_cache::EntryImpl*>(entry); 2318 2319 entry_impl->entry()->Data()->state = 0xbad; 2320 entry_impl->entry()->Store(); 2321 entry->Close(); 2322 ASSERT_EQ(net::OK, CreateEntry("third", &entry)); 2323 entry->Close(); 2324 EXPECT_EQ(3, cache_->GetEntryCount()); 2325 2326 // We have: 2327 // List 0: third -> second (bad). 2328 // List 1: first. 2329 2330 if (eviction) { 2331 // Detection order: second -> first -> third. 2332 TrimForTest(false); 2333 EXPECT_EQ(3, cache_->GetEntryCount()); 2334 TrimForTest(false); 2335 EXPECT_EQ(2, cache_->GetEntryCount()); 2336 TrimForTest(false); 2337 EXPECT_EQ(1, cache_->GetEntryCount()); 2338 } else { 2339 // Detection order: third -> second -> first. 2340 // We should detect the problem through the list, but we should not delete 2341 // the entry. 2342 scoped_ptr<TestIterator> iter = CreateIterator(); 2343 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); 2344 entry->Close(); 2345 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); 2346 EXPECT_EQ(first, entry->GetKey()); 2347 entry->Close(); 2348 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); 2349 } 2350 DisableIntegrityCheck(); 2351 } 2352 2353 TEST_F(DiskCacheBackendTest, InvalidEntry10) { 2354 BackendInvalidEntry10(false); 2355 } 2356 2357 TEST_F(DiskCacheBackendTest, TrimInvalidEntry10) { 2358 BackendInvalidEntry10(true); 2359 } 2360 2361 // Tests handling of corrupt entries detected by enumerations. 2362 void DiskCacheBackendTest::BackendInvalidEntry11(bool eviction) { 2363 const int kSize = 0x3000; // 12 kB. 2364 SetMaxSize(kSize * 10); 2365 SetNewEviction(); 2366 InitCache(); 2367 2368 std::string first("some key"); 2369 std::string second("something else"); 2370 disk_cache::Entry* entry; 2371 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 2372 entry->Close(); 2373 ASSERT_EQ(net::OK, OpenEntry(first, &entry)); 2374 EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false)); 2375 entry->Close(); 2376 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 2377 entry->Close(); 2378 ASSERT_EQ(net::OK, OpenEntry(second, &entry)); 2379 EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false)); 2380 2381 // Corrupt this entry. 2382 disk_cache::EntryImpl* entry_impl = 2383 static_cast<disk_cache::EntryImpl*>(entry); 2384 2385 entry_impl->entry()->Data()->state = 0xbad; 2386 entry_impl->entry()->Store(); 2387 entry->Close(); 2388 ASSERT_EQ(net::OK, CreateEntry("third", &entry)); 2389 entry->Close(); 2390 FlushQueueForTest(); 2391 EXPECT_EQ(3, cache_->GetEntryCount()); 2392 2393 // We have: 2394 // List 0: third. 2395 // List 1: second (bad) -> first. 2396 2397 if (eviction) { 2398 // Detection order: third -> first -> second. 2399 TrimForTest(false); 2400 EXPECT_EQ(2, cache_->GetEntryCount()); 2401 TrimForTest(false); 2402 EXPECT_EQ(1, cache_->GetEntryCount()); 2403 TrimForTest(false); 2404 EXPECT_EQ(1, cache_->GetEntryCount()); 2405 } else { 2406 // Detection order: third -> second. 2407 // We should detect the problem through the list, but we should not delete 2408 // the entry, just fail the iteration. 2409 scoped_ptr<TestIterator> iter = CreateIterator(); 2410 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); 2411 entry->Close(); 2412 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); 2413 2414 // Now a full iteration will work, and return two entries. 2415 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); 2416 entry->Close(); 2417 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); 2418 entry->Close(); 2419 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); 2420 } 2421 DisableIntegrityCheck(); 2422 } 2423 2424 TEST_F(DiskCacheBackendTest, InvalidEntry11) { 2425 BackendInvalidEntry11(false); 2426 } 2427 2428 TEST_F(DiskCacheBackendTest, TrimInvalidEntry11) { 2429 BackendInvalidEntry11(true); 2430 } 2431 2432 // Tests handling of corrupt entries in the middle of a long eviction run. 2433 void DiskCacheBackendTest::BackendTrimInvalidEntry12() { 2434 const int kSize = 0x3000; // 12 kB 2435 SetMaxSize(kSize * 10); 2436 InitCache(); 2437 2438 std::string first("some key"); 2439 std::string second("something else"); 2440 disk_cache::Entry* entry; 2441 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 2442 entry->Close(); 2443 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 2444 2445 // Corrupt this entry. 2446 disk_cache::EntryImpl* entry_impl = 2447 static_cast<disk_cache::EntryImpl*>(entry); 2448 2449 entry_impl->entry()->Data()->state = 0xbad; 2450 entry_impl->entry()->Store(); 2451 entry->Close(); 2452 ASSERT_EQ(net::OK, CreateEntry("third", &entry)); 2453 entry->Close(); 2454 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry)); 2455 TrimForTest(true); 2456 EXPECT_EQ(1, cache_->GetEntryCount()); 2457 entry->Close(); 2458 DisableIntegrityCheck(); 2459 } 2460 2461 TEST_F(DiskCacheBackendTest, TrimInvalidEntry12) { 2462 BackendTrimInvalidEntry12(); 2463 } 2464 2465 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry12) { 2466 SetNewEviction(); 2467 BackendTrimInvalidEntry12(); 2468 } 2469 2470 // We want to be able to deal with messed up entries on disk. 2471 void DiskCacheBackendTest::BackendInvalidRankings2() { 2472 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2473 DisableFirstCleanup(); 2474 InitCache(); 2475 2476 disk_cache::Entry *entry1, *entry2; 2477 EXPECT_NE(net::OK, OpenEntry("the first key", &entry1)); 2478 ASSERT_EQ(net::OK, OpenEntry("some other key", &entry2)); 2479 entry2->Close(); 2480 2481 // CheckCacheIntegrity will fail at this point. 2482 DisableIntegrityCheck(); 2483 } 2484 2485 TEST_F(DiskCacheBackendTest, InvalidRankings2) { 2486 BackendInvalidRankings2(); 2487 } 2488 2489 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankings2) { 2490 SetNewEviction(); 2491 BackendInvalidRankings2(); 2492 } 2493 2494 // If the LRU is corrupt, we delete the cache. 2495 void DiskCacheBackendTest::BackendInvalidRankings() { 2496 disk_cache::Entry* entry; 2497 scoped_ptr<TestIterator> iter = CreateIterator(); 2498 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); 2499 entry->Close(); 2500 EXPECT_EQ(2, cache_->GetEntryCount()); 2501 2502 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); 2503 FlushQueueForTest(); // Allow the restart to finish. 2504 EXPECT_EQ(0, cache_->GetEntryCount()); 2505 } 2506 2507 TEST_F(DiskCacheBackendTest, InvalidRankingsSuccess) { 2508 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2509 DisableFirstCleanup(); 2510 InitCache(); 2511 BackendInvalidRankings(); 2512 } 2513 2514 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsSuccess) { 2515 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2516 DisableFirstCleanup(); 2517 SetNewEviction(); 2518 InitCache(); 2519 BackendInvalidRankings(); 2520 } 2521 2522 TEST_F(DiskCacheBackendTest, InvalidRankingsFailure) { 2523 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2524 DisableFirstCleanup(); 2525 InitCache(); 2526 SetTestMode(); // Fail cache reinitialization. 2527 BackendInvalidRankings(); 2528 } 2529 2530 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsFailure) { 2531 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2532 DisableFirstCleanup(); 2533 SetNewEviction(); 2534 InitCache(); 2535 SetTestMode(); // Fail cache reinitialization. 2536 BackendInvalidRankings(); 2537 } 2538 2539 // If the LRU is corrupt and we have open entries, we disable the cache. 2540 void DiskCacheBackendTest::BackendDisable() { 2541 disk_cache::Entry *entry1, *entry2; 2542 scoped_ptr<TestIterator> iter = CreateIterator(); 2543 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry1)); 2544 2545 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry2)); 2546 EXPECT_EQ(0, cache_->GetEntryCount()); 2547 EXPECT_NE(net::OK, CreateEntry("Something new", &entry2)); 2548 2549 entry1->Close(); 2550 FlushQueueForTest(); // Flushing the Close posts a task to restart the cache. 2551 FlushQueueForTest(); // This one actually allows that task to complete. 2552 2553 EXPECT_EQ(0, cache_->GetEntryCount()); 2554 } 2555 2556 TEST_F(DiskCacheBackendTest, DisableSuccess) { 2557 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2558 DisableFirstCleanup(); 2559 InitCache(); 2560 BackendDisable(); 2561 } 2562 2563 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess) { 2564 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2565 DisableFirstCleanup(); 2566 SetNewEviction(); 2567 InitCache(); 2568 BackendDisable(); 2569 } 2570 2571 TEST_F(DiskCacheBackendTest, DisableFailure) { 2572 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2573 DisableFirstCleanup(); 2574 InitCache(); 2575 SetTestMode(); // Fail cache reinitialization. 2576 BackendDisable(); 2577 } 2578 2579 TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure) { 2580 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2581 DisableFirstCleanup(); 2582 SetNewEviction(); 2583 InitCache(); 2584 SetTestMode(); // Fail cache reinitialization. 2585 BackendDisable(); 2586 } 2587 2588 // This is another type of corruption on the LRU; disable the cache. 2589 void DiskCacheBackendTest::BackendDisable2() { 2590 EXPECT_EQ(8, cache_->GetEntryCount()); 2591 2592 disk_cache::Entry* entry; 2593 scoped_ptr<TestIterator> iter = CreateIterator(); 2594 int count = 0; 2595 while (iter->OpenNextEntry(&entry) == net::OK) { 2596 ASSERT_TRUE(NULL != entry); 2597 entry->Close(); 2598 count++; 2599 ASSERT_LT(count, 9); 2600 }; 2601 2602 FlushQueueForTest(); 2603 EXPECT_EQ(0, cache_->GetEntryCount()); 2604 } 2605 2606 TEST_F(DiskCacheBackendTest, DisableSuccess2) { 2607 ASSERT_TRUE(CopyTestCache("list_loop")); 2608 DisableFirstCleanup(); 2609 InitCache(); 2610 BackendDisable2(); 2611 } 2612 2613 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess2) { 2614 ASSERT_TRUE(CopyTestCache("list_loop")); 2615 DisableFirstCleanup(); 2616 SetNewEviction(); 2617 InitCache(); 2618 BackendDisable2(); 2619 } 2620 2621 TEST_F(DiskCacheBackendTest, DisableFailure2) { 2622 ASSERT_TRUE(CopyTestCache("list_loop")); 2623 DisableFirstCleanup(); 2624 InitCache(); 2625 SetTestMode(); // Fail cache reinitialization. 2626 BackendDisable2(); 2627 } 2628 2629 TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure2) { 2630 ASSERT_TRUE(CopyTestCache("list_loop")); 2631 DisableFirstCleanup(); 2632 SetNewEviction(); 2633 InitCache(); 2634 SetTestMode(); // Fail cache reinitialization. 2635 BackendDisable2(); 2636 } 2637 2638 // If the index size changes when we disable the cache, we should not crash. 2639 void DiskCacheBackendTest::BackendDisable3() { 2640 disk_cache::Entry *entry1, *entry2; 2641 scoped_ptr<TestIterator> iter = CreateIterator(); 2642 EXPECT_EQ(2, cache_->GetEntryCount()); 2643 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry1)); 2644 entry1->Close(); 2645 2646 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry2)); 2647 FlushQueueForTest(); 2648 2649 ASSERT_EQ(net::OK, CreateEntry("Something new", &entry2)); 2650 entry2->Close(); 2651 2652 EXPECT_EQ(1, cache_->GetEntryCount()); 2653 } 2654 2655 TEST_F(DiskCacheBackendTest, DisableSuccess3) { 2656 ASSERT_TRUE(CopyTestCache("bad_rankings2")); 2657 DisableFirstCleanup(); 2658 SetMaxSize(20 * 1024 * 1024); 2659 InitCache(); 2660 BackendDisable3(); 2661 } 2662 2663 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess3) { 2664 ASSERT_TRUE(CopyTestCache("bad_rankings2")); 2665 DisableFirstCleanup(); 2666 SetMaxSize(20 * 1024 * 1024); 2667 SetNewEviction(); 2668 InitCache(); 2669 BackendDisable3(); 2670 } 2671 2672 // If we disable the cache, already open entries should work as far as possible. 2673 void DiskCacheBackendTest::BackendDisable4() { 2674 disk_cache::Entry *entry1, *entry2, *entry3, *entry4; 2675 scoped_ptr<TestIterator> iter = CreateIterator(); 2676 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry1)); 2677 2678 char key2[2000]; 2679 char key3[20000]; 2680 CacheTestFillBuffer(key2, sizeof(key2), true); 2681 CacheTestFillBuffer(key3, sizeof(key3), true); 2682 key2[sizeof(key2) - 1] = '\0'; 2683 key3[sizeof(key3) - 1] = '\0'; 2684 ASSERT_EQ(net::OK, CreateEntry(key2, &entry2)); 2685 ASSERT_EQ(net::OK, CreateEntry(key3, &entry3)); 2686 2687 const int kBufSize = 20000; 2688 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufSize)); 2689 memset(buf->data(), 0, kBufSize); 2690 EXPECT_EQ(100, WriteData(entry2, 0, 0, buf.get(), 100, false)); 2691 EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf.get(), kBufSize, false)); 2692 2693 // This line should disable the cache but not delete it. 2694 EXPECT_NE(net::OK, iter->OpenNextEntry(&entry4)); 2695 EXPECT_EQ(0, cache_->GetEntryCount()); 2696 2697 EXPECT_NE(net::OK, CreateEntry("cache is disabled", &entry4)); 2698 2699 EXPECT_EQ(100, ReadData(entry2, 0, 0, buf.get(), 100)); 2700 EXPECT_EQ(100, WriteData(entry2, 0, 0, buf.get(), 100, false)); 2701 EXPECT_EQ(100, WriteData(entry2, 1, 0, buf.get(), 100, false)); 2702 2703 EXPECT_EQ(kBufSize, ReadData(entry3, 0, 0, buf.get(), kBufSize)); 2704 EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf.get(), kBufSize, false)); 2705 EXPECT_EQ(kBufSize, WriteData(entry3, 1, 0, buf.get(), kBufSize, false)); 2706 2707 std::string key = entry2->GetKey(); 2708 EXPECT_EQ(sizeof(key2) - 1, key.size()); 2709 key = entry3->GetKey(); 2710 EXPECT_EQ(sizeof(key3) - 1, key.size()); 2711 2712 entry1->Close(); 2713 entry2->Close(); 2714 entry3->Close(); 2715 FlushQueueForTest(); // Flushing the Close posts a task to restart the cache. 2716 FlushQueueForTest(); // This one actually allows that task to complete. 2717 2718 EXPECT_EQ(0, cache_->GetEntryCount()); 2719 } 2720 2721 TEST_F(DiskCacheBackendTest, DisableSuccess4) { 2722 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2723 DisableFirstCleanup(); 2724 InitCache(); 2725 BackendDisable4(); 2726 } 2727 2728 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess4) { 2729 ASSERT_TRUE(CopyTestCache("bad_rankings")); 2730 DisableFirstCleanup(); 2731 SetNewEviction(); 2732 InitCache(); 2733 BackendDisable4(); 2734 } 2735 2736 TEST_F(DiskCacheTest, Backend_UsageStatsTimer) { 2737 MessageLoopHelper helper; 2738 2739 ASSERT_TRUE(CleanupCacheDir()); 2740 scoped_ptr<disk_cache::BackendImpl> cache; 2741 cache.reset(new disk_cache::BackendImpl( 2742 cache_path_, base::ThreadTaskRunnerHandle::Get(), NULL)); 2743 ASSERT_TRUE(NULL != cache.get()); 2744 cache->SetUnitTestMode(); 2745 ASSERT_EQ(net::OK, cache->SyncInit()); 2746 2747 // Wait for a callback that never comes... about 2 secs :). The message loop 2748 // has to run to allow invocation of the usage timer. 2749 helper.WaitUntilCacheIoFinished(1); 2750 } 2751 2752 TEST_F(DiskCacheBackendTest, TimerNotCreated) { 2753 ASSERT_TRUE(CopyTestCache("wrong_version")); 2754 2755 scoped_ptr<disk_cache::BackendImpl> cache; 2756 cache.reset(new disk_cache::BackendImpl( 2757 cache_path_, base::ThreadTaskRunnerHandle::Get(), NULL)); 2758 ASSERT_TRUE(NULL != cache.get()); 2759 cache->SetUnitTestMode(); 2760 ASSERT_NE(net::OK, cache->SyncInit()); 2761 2762 ASSERT_TRUE(NULL == cache->GetTimerForTest()); 2763 2764 DisableIntegrityCheck(); 2765 } 2766 2767 TEST_F(DiskCacheBackendTest, Backend_UsageStats) { 2768 InitCache(); 2769 disk_cache::Entry* entry; 2770 ASSERT_EQ(net::OK, CreateEntry("key", &entry)); 2771 entry->Close(); 2772 FlushQueueForTest(); 2773 2774 disk_cache::StatsItems stats; 2775 cache_->GetStats(&stats); 2776 EXPECT_FALSE(stats.empty()); 2777 2778 disk_cache::StatsItems::value_type hits("Create hit", "0x1"); 2779 EXPECT_EQ(1, std::count(stats.begin(), stats.end(), hits)); 2780 2781 cache_.reset(); 2782 2783 // Now open the cache and verify that the stats are still there. 2784 DisableFirstCleanup(); 2785 InitCache(); 2786 EXPECT_EQ(1, cache_->GetEntryCount()); 2787 2788 stats.clear(); 2789 cache_->GetStats(&stats); 2790 EXPECT_FALSE(stats.empty()); 2791 2792 EXPECT_EQ(1, std::count(stats.begin(), stats.end(), hits)); 2793 } 2794 2795 void DiskCacheBackendTest::BackendDoomAll() { 2796 InitCache(); 2797 2798 disk_cache::Entry *entry1, *entry2; 2799 ASSERT_EQ(net::OK, CreateEntry("first", &entry1)); 2800 ASSERT_EQ(net::OK, CreateEntry("second", &entry2)); 2801 entry1->Close(); 2802 entry2->Close(); 2803 2804 ASSERT_EQ(net::OK, CreateEntry("third", &entry1)); 2805 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2)); 2806 2807 ASSERT_EQ(4, cache_->GetEntryCount()); 2808 EXPECT_EQ(net::OK, DoomAllEntries()); 2809 ASSERT_EQ(0, cache_->GetEntryCount()); 2810 2811 // We should stop posting tasks at some point (if we post any). 2812 base::MessageLoop::current()->RunUntilIdle(); 2813 2814 disk_cache::Entry *entry3, *entry4; 2815 EXPECT_NE(net::OK, OpenEntry("third", &entry3)); 2816 ASSERT_EQ(net::OK, CreateEntry("third", &entry3)); 2817 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry4)); 2818 2819 EXPECT_EQ(net::OK, DoomAllEntries()); 2820 ASSERT_EQ(0, cache_->GetEntryCount()); 2821 2822 entry1->Close(); 2823 entry2->Close(); 2824 entry3->Doom(); // The entry should be already doomed, but this must work. 2825 entry3->Close(); 2826 entry4->Close(); 2827 2828 // Now try with all references released. 2829 ASSERT_EQ(net::OK, CreateEntry("third", &entry1)); 2830 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2)); 2831 entry1->Close(); 2832 entry2->Close(); 2833 2834 ASSERT_EQ(2, cache_->GetEntryCount()); 2835 EXPECT_EQ(net::OK, DoomAllEntries()); 2836 ASSERT_EQ(0, cache_->GetEntryCount()); 2837 2838 EXPECT_EQ(net::OK, DoomAllEntries()); 2839 } 2840 2841 TEST_F(DiskCacheBackendTest, DoomAll) { 2842 BackendDoomAll(); 2843 } 2844 2845 TEST_F(DiskCacheBackendTest, NewEvictionDoomAll) { 2846 SetNewEviction(); 2847 BackendDoomAll(); 2848 } 2849 2850 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomAll) { 2851 SetMemoryOnlyMode(); 2852 BackendDoomAll(); 2853 } 2854 2855 TEST_F(DiskCacheBackendTest, AppCacheOnlyDoomAll) { 2856 SetCacheType(net::APP_CACHE); 2857 BackendDoomAll(); 2858 } 2859 2860 TEST_F(DiskCacheBackendTest, ShaderCacheOnlyDoomAll) { 2861 SetCacheType(net::SHADER_CACHE); 2862 BackendDoomAll(); 2863 } 2864 2865 // If the index size changes when we doom the cache, we should not crash. 2866 void DiskCacheBackendTest::BackendDoomAll2() { 2867 EXPECT_EQ(2, cache_->GetEntryCount()); 2868 EXPECT_EQ(net::OK, DoomAllEntries()); 2869 2870 disk_cache::Entry* entry; 2871 ASSERT_EQ(net::OK, CreateEntry("Something new", &entry)); 2872 entry->Close(); 2873 2874 EXPECT_EQ(1, cache_->GetEntryCount()); 2875 } 2876 2877 TEST_F(DiskCacheBackendTest, DoomAll2) { 2878 ASSERT_TRUE(CopyTestCache("bad_rankings2")); 2879 DisableFirstCleanup(); 2880 SetMaxSize(20 * 1024 * 1024); 2881 InitCache(); 2882 BackendDoomAll2(); 2883 } 2884 2885 TEST_F(DiskCacheBackendTest, NewEvictionDoomAll2) { 2886 ASSERT_TRUE(CopyTestCache("bad_rankings2")); 2887 DisableFirstCleanup(); 2888 SetMaxSize(20 * 1024 * 1024); 2889 SetNewEviction(); 2890 InitCache(); 2891 BackendDoomAll2(); 2892 } 2893 2894 // We should be able to create the same entry on multiple simultaneous instances 2895 // of the cache. 2896 TEST_F(DiskCacheTest, MultipleInstances) { 2897 base::ScopedTempDir store1, store2; 2898 ASSERT_TRUE(store1.CreateUniqueTempDir()); 2899 ASSERT_TRUE(store2.CreateUniqueTempDir()); 2900 2901 base::Thread cache_thread("CacheThread"); 2902 ASSERT_TRUE(cache_thread.StartWithOptions( 2903 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 2904 net::TestCompletionCallback cb; 2905 2906 const int kNumberOfCaches = 2; 2907 scoped_ptr<disk_cache::Backend> cache[kNumberOfCaches]; 2908 2909 int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, 2910 net::CACHE_BACKEND_DEFAULT, 2911 store1.path(), 2912 0, 2913 false, 2914 cache_thread.task_runner(), 2915 NULL, 2916 &cache[0], 2917 cb.callback()); 2918 ASSERT_EQ(net::OK, cb.GetResult(rv)); 2919 rv = disk_cache::CreateCacheBackend(net::MEDIA_CACHE, 2920 net::CACHE_BACKEND_DEFAULT, 2921 store2.path(), 2922 0, 2923 false, 2924 cache_thread.task_runner(), 2925 NULL, 2926 &cache[1], 2927 cb.callback()); 2928 ASSERT_EQ(net::OK, cb.GetResult(rv)); 2929 2930 ASSERT_TRUE(cache[0].get() != NULL && cache[1].get() != NULL); 2931 2932 std::string key("the first key"); 2933 disk_cache::Entry* entry; 2934 for (int i = 0; i < kNumberOfCaches; i++) { 2935 rv = cache[i]->CreateEntry(key, &entry, cb.callback()); 2936 ASSERT_EQ(net::OK, cb.GetResult(rv)); 2937 entry->Close(); 2938 } 2939 } 2940 2941 // Test the six regions of the curve that determines the max cache size. 2942 TEST_F(DiskCacheTest, AutomaticMaxSize) { 2943 using disk_cache::kDefaultCacheSize; 2944 int64 large_size = kDefaultCacheSize; 2945 2946 // Region 1: expected = available * 0.8 2947 EXPECT_EQ((kDefaultCacheSize - 1) * 8 / 10, 2948 disk_cache::PreferredCacheSize(large_size - 1)); 2949 EXPECT_EQ(kDefaultCacheSize * 8 / 10, 2950 disk_cache::PreferredCacheSize(large_size)); 2951 EXPECT_EQ(kDefaultCacheSize - 1, 2952 disk_cache::PreferredCacheSize(large_size * 10 / 8 - 1)); 2953 2954 // Region 2: expected = default_size 2955 EXPECT_EQ(kDefaultCacheSize, 2956 disk_cache::PreferredCacheSize(large_size * 10 / 8)); 2957 EXPECT_EQ(kDefaultCacheSize, 2958 disk_cache::PreferredCacheSize(large_size * 10 - 1)); 2959 2960 // Region 3: expected = available * 0.1 2961 EXPECT_EQ(kDefaultCacheSize, 2962 disk_cache::PreferredCacheSize(large_size * 10)); 2963 EXPECT_EQ((kDefaultCacheSize * 25 - 1) / 10, 2964 disk_cache::PreferredCacheSize(large_size * 25 - 1)); 2965 2966 // Region 4: expected = default_size * 2.5 2967 EXPECT_EQ(kDefaultCacheSize * 25 / 10, 2968 disk_cache::PreferredCacheSize(large_size * 25)); 2969 EXPECT_EQ(kDefaultCacheSize * 25 / 10, 2970 disk_cache::PreferredCacheSize(large_size * 100 - 1)); 2971 EXPECT_EQ(kDefaultCacheSize * 25 / 10, 2972 disk_cache::PreferredCacheSize(large_size * 100)); 2973 EXPECT_EQ(kDefaultCacheSize * 25 / 10, 2974 disk_cache::PreferredCacheSize(large_size * 250 - 1)); 2975 2976 // Region 5: expected = available * 0.1 2977 int64 largest_size = kDefaultCacheSize * 4; 2978 EXPECT_EQ(kDefaultCacheSize * 25 / 10, 2979 disk_cache::PreferredCacheSize(large_size * 250)); 2980 EXPECT_EQ(largest_size - 1, 2981 disk_cache::PreferredCacheSize(largest_size * 100 - 1)); 2982 2983 // Region 6: expected = largest possible size 2984 EXPECT_EQ(largest_size, 2985 disk_cache::PreferredCacheSize(largest_size * 100)); 2986 EXPECT_EQ(largest_size, 2987 disk_cache::PreferredCacheSize(largest_size * 10000)); 2988 } 2989 2990 // Tests that we can "migrate" a running instance from one experiment group to 2991 // another. 2992 TEST_F(DiskCacheBackendTest, Histograms) { 2993 InitCache(); 2994 disk_cache::BackendImpl* backend_ = cache_impl_; // Needed be the macro. 2995 2996 for (int i = 1; i < 3; i++) { 2997 CACHE_UMA(HOURS, "FillupTime", i, 28); 2998 } 2999 } 3000 3001 // Make sure that we keep the total memory used by the internal buffers under 3002 // control. 3003 TEST_F(DiskCacheBackendTest, TotalBuffersSize1) { 3004 InitCache(); 3005 std::string key("the first key"); 3006 disk_cache::Entry* entry; 3007 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 3008 3009 const int kSize = 200; 3010 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 3011 CacheTestFillBuffer(buffer->data(), kSize, true); 3012 3013 for (int i = 0; i < 10; i++) { 3014 SCOPED_TRACE(i); 3015 // Allocate 2MB for this entry. 3016 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, true)); 3017 EXPECT_EQ(kSize, WriteData(entry, 1, 0, buffer.get(), kSize, true)); 3018 EXPECT_EQ(kSize, 3019 WriteData(entry, 0, 1024 * 1024, buffer.get(), kSize, false)); 3020 EXPECT_EQ(kSize, 3021 WriteData(entry, 1, 1024 * 1024, buffer.get(), kSize, false)); 3022 3023 // Delete one of the buffers and truncate the other. 3024 EXPECT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, true)); 3025 EXPECT_EQ(0, WriteData(entry, 1, 10, buffer.get(), 0, true)); 3026 3027 // Delete the second buffer, writing 10 bytes to disk. 3028 entry->Close(); 3029 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 3030 } 3031 3032 entry->Close(); 3033 EXPECT_EQ(0, cache_impl_->GetTotalBuffersSize()); 3034 } 3035 3036 // This test assumes at least 150MB of system memory. 3037 TEST_F(DiskCacheBackendTest, TotalBuffersSize2) { 3038 InitCache(); 3039 3040 const int kOneMB = 1024 * 1024; 3041 EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB)); 3042 EXPECT_EQ(kOneMB, cache_impl_->GetTotalBuffersSize()); 3043 3044 EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB)); 3045 EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize()); 3046 3047 EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB)); 3048 EXPECT_EQ(kOneMB * 3, cache_impl_->GetTotalBuffersSize()); 3049 3050 cache_impl_->BufferDeleted(kOneMB); 3051 EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize()); 3052 3053 // Check the upper limit. 3054 EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, 30 * kOneMB)); 3055 3056 for (int i = 0; i < 30; i++) 3057 cache_impl_->IsAllocAllowed(0, kOneMB); // Ignore the result. 3058 3059 EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, kOneMB)); 3060 } 3061 3062 // Tests that sharing of external files works and we are able to delete the 3063 // files when we need to. 3064 TEST_F(DiskCacheBackendTest, FileSharing) { 3065 InitCache(); 3066 3067 disk_cache::Addr address(0x80000001); 3068 ASSERT_TRUE(cache_impl_->CreateExternalFile(&address)); 3069 base::FilePath name = cache_impl_->GetFileName(address); 3070 3071 scoped_refptr<disk_cache::File> file(new disk_cache::File(false)); 3072 file->Init(name); 3073 3074 #if defined(OS_WIN) 3075 DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; 3076 DWORD access = GENERIC_READ | GENERIC_WRITE; 3077 base::win::ScopedHandle file2(CreateFile( 3078 name.value().c_str(), access, sharing, NULL, OPEN_EXISTING, 0, NULL)); 3079 EXPECT_FALSE(file2.IsValid()); 3080 3081 sharing |= FILE_SHARE_DELETE; 3082 file2.Set(CreateFile(name.value().c_str(), access, sharing, NULL, 3083 OPEN_EXISTING, 0, NULL)); 3084 EXPECT_TRUE(file2.IsValid()); 3085 #endif 3086 3087 EXPECT_TRUE(base::DeleteFile(name, false)); 3088 3089 // We should be able to use the file. 3090 const int kSize = 200; 3091 char buffer1[kSize]; 3092 char buffer2[kSize]; 3093 memset(buffer1, 't', kSize); 3094 memset(buffer2, 0, kSize); 3095 EXPECT_TRUE(file->Write(buffer1, kSize, 0)); 3096 EXPECT_TRUE(file->Read(buffer2, kSize, 0)); 3097 EXPECT_EQ(0, memcmp(buffer1, buffer2, kSize)); 3098 3099 EXPECT_TRUE(disk_cache::DeleteCacheFile(name)); 3100 } 3101 3102 TEST_F(DiskCacheBackendTest, UpdateRankForExternalCacheHit) { 3103 InitCache(); 3104 3105 disk_cache::Entry* entry; 3106 3107 for (int i = 0; i < 2; ++i) { 3108 std::string key = base::StringPrintf("key%d", i); 3109 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 3110 entry->Close(); 3111 } 3112 3113 // Ping the oldest entry. 3114 cache_->OnExternalCacheHit("key0"); 3115 3116 TrimForTest(false); 3117 3118 // Make sure the older key remains. 3119 EXPECT_EQ(1, cache_->GetEntryCount()); 3120 ASSERT_EQ(net::OK, OpenEntry("key0", &entry)); 3121 entry->Close(); 3122 } 3123 3124 TEST_F(DiskCacheBackendTest, ShaderCacheUpdateRankForExternalCacheHit) { 3125 SetCacheType(net::SHADER_CACHE); 3126 InitCache(); 3127 3128 disk_cache::Entry* entry; 3129 3130 for (int i = 0; i < 2; ++i) { 3131 std::string key = base::StringPrintf("key%d", i); 3132 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 3133 entry->Close(); 3134 } 3135 3136 // Ping the oldest entry. 3137 cache_->OnExternalCacheHit("key0"); 3138 3139 TrimForTest(false); 3140 3141 // Make sure the older key remains. 3142 EXPECT_EQ(1, cache_->GetEntryCount()); 3143 ASSERT_EQ(net::OK, OpenEntry("key0", &entry)); 3144 entry->Close(); 3145 } 3146 3147 // The Simple Cache backend requires a few guarantees from the filesystem like 3148 // atomic renaming of recently open files. Those guarantees are not provided in 3149 // general on Windows. 3150 #if defined(OS_POSIX) 3151 3152 TEST_F(DiskCacheBackendTest, SimpleCacheShutdownWithPendingCreate) { 3153 SetCacheType(net::APP_CACHE); 3154 SetSimpleCacheMode(); 3155 BackendShutdownWithPendingCreate(false); 3156 } 3157 3158 TEST_F(DiskCacheBackendTest, SimpleCacheShutdownWithPendingFileIO) { 3159 SetCacheType(net::APP_CACHE); 3160 SetSimpleCacheMode(); 3161 BackendShutdownWithPendingFileIO(false); 3162 } 3163 3164 TEST_F(DiskCacheBackendTest, SimpleCacheBasics) { 3165 SetSimpleCacheMode(); 3166 BackendBasics(); 3167 } 3168 3169 TEST_F(DiskCacheBackendTest, SimpleCacheAppCacheBasics) { 3170 SetCacheType(net::APP_CACHE); 3171 SetSimpleCacheMode(); 3172 BackendBasics(); 3173 } 3174 3175 TEST_F(DiskCacheBackendTest, SimpleCacheKeying) { 3176 SetSimpleCacheMode(); 3177 BackendKeying(); 3178 } 3179 3180 TEST_F(DiskCacheBackendTest, SimpleCacheAppCacheKeying) { 3181 SetSimpleCacheMode(); 3182 SetCacheType(net::APP_CACHE); 3183 BackendKeying(); 3184 } 3185 3186 TEST_F(DiskCacheBackendTest, DISABLED_SimpleCacheSetSize) { 3187 SetSimpleCacheMode(); 3188 BackendSetSize(); 3189 } 3190 3191 // MacOS has a default open file limit of 256 files, which is incompatible with 3192 // this simple cache test. 3193 #if defined(OS_MACOSX) 3194 #define SIMPLE_MAYBE_MACOS(TestName) DISABLED_ ## TestName 3195 #else 3196 #define SIMPLE_MAYBE_MACOS(TestName) TestName 3197 #endif 3198 3199 TEST_F(DiskCacheBackendTest, SIMPLE_MAYBE_MACOS(SimpleCacheLoad)) { 3200 SetMaxSize(0x100000); 3201 SetSimpleCacheMode(); 3202 BackendLoad(); 3203 } 3204 3205 TEST_F(DiskCacheBackendTest, SIMPLE_MAYBE_MACOS(SimpleCacheAppCacheLoad)) { 3206 SetCacheType(net::APP_CACHE); 3207 SetSimpleCacheMode(); 3208 SetMaxSize(0x100000); 3209 BackendLoad(); 3210 } 3211 3212 TEST_F(DiskCacheBackendTest, SimpleDoomRecent) { 3213 SetSimpleCacheMode(); 3214 BackendDoomRecent(); 3215 } 3216 3217 // crbug.com/330926, crbug.com/370677 3218 TEST_F(DiskCacheBackendTest, DISABLED_SimpleDoomBetween) { 3219 SetSimpleCacheMode(); 3220 BackendDoomBetween(); 3221 } 3222 3223 TEST_F(DiskCacheBackendTest, SimpleCacheDoomAll) { 3224 SetSimpleCacheMode(); 3225 BackendDoomAll(); 3226 } 3227 3228 TEST_F(DiskCacheBackendTest, SimpleCacheAppCacheOnlyDoomAll) { 3229 SetCacheType(net::APP_CACHE); 3230 SetSimpleCacheMode(); 3231 BackendDoomAll(); 3232 } 3233 3234 TEST_F(DiskCacheBackendTest, SimpleCacheOpenMissingFile) { 3235 SetSimpleCacheMode(); 3236 InitCache(); 3237 3238 const char* key = "the first key"; 3239 disk_cache::Entry* entry = NULL; 3240 3241 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 3242 ASSERT_TRUE(entry != NULL); 3243 entry->Close(); 3244 entry = NULL; 3245 3246 // To make sure the file creation completed we need to call open again so that 3247 // we block until it actually created the files. 3248 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 3249 ASSERT_TRUE(entry != NULL); 3250 entry->Close(); 3251 entry = NULL; 3252 3253 // Delete one of the files in the entry. 3254 base::FilePath to_delete_file = cache_path_.AppendASCII( 3255 disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0)); 3256 EXPECT_TRUE(base::PathExists(to_delete_file)); 3257 EXPECT_TRUE(disk_cache::DeleteCacheFile(to_delete_file)); 3258 3259 // Failing to open the entry should delete the rest of these files. 3260 ASSERT_EQ(net::ERR_FAILED, OpenEntry(key, &entry)); 3261 3262 // Confirm the rest of the files are gone. 3263 for (int i = 1; i < disk_cache::kSimpleEntryFileCount; ++i) { 3264 base::FilePath should_be_gone_file(cache_path_.AppendASCII( 3265 disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, i))); 3266 EXPECT_FALSE(base::PathExists(should_be_gone_file)); 3267 } 3268 } 3269 3270 TEST_F(DiskCacheBackendTest, SimpleCacheOpenBadFile) { 3271 SetSimpleCacheMode(); 3272 InitCache(); 3273 3274 const char* key = "the first key"; 3275 disk_cache::Entry* entry = NULL; 3276 3277 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 3278 disk_cache::Entry* null = NULL; 3279 ASSERT_NE(null, entry); 3280 entry->Close(); 3281 entry = NULL; 3282 3283 // To make sure the file creation completed we need to call open again so that 3284 // we block until it actually created the files. 3285 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 3286 ASSERT_NE(null, entry); 3287 entry->Close(); 3288 entry = NULL; 3289 3290 // Write an invalid header for stream 0 and stream 1. 3291 base::FilePath entry_file1_path = cache_path_.AppendASCII( 3292 disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0)); 3293 3294 disk_cache::SimpleFileHeader header; 3295 header.initial_magic_number = GG_UINT64_C(0xbadf00d); 3296 EXPECT_EQ( 3297 implicit_cast<int>(sizeof(header)), 3298 base::WriteFile(entry_file1_path, reinterpret_cast<char*>(&header), 3299 sizeof(header))); 3300 ASSERT_EQ(net::ERR_FAILED, OpenEntry(key, &entry)); 3301 } 3302 3303 // Tests that the Simple Cache Backend fails to initialize with non-matching 3304 // file structure on disk. 3305 TEST_F(DiskCacheBackendTest, SimpleCacheOverBlockfileCache) { 3306 // Create a cache structure with the |BackendImpl|. 3307 InitCache(); 3308 disk_cache::Entry* entry; 3309 const int kSize = 50; 3310 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 3311 CacheTestFillBuffer(buffer->data(), kSize, false); 3312 ASSERT_EQ(net::OK, CreateEntry("key", &entry)); 3313 ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false)); 3314 entry->Close(); 3315 cache_.reset(); 3316 3317 // Check that the |SimpleBackendImpl| does not favor this structure. 3318 base::Thread cache_thread("CacheThread"); 3319 ASSERT_TRUE(cache_thread.StartWithOptions( 3320 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 3321 disk_cache::SimpleBackendImpl* simple_cache = 3322 new disk_cache::SimpleBackendImpl( 3323 cache_path_, 0, net::DISK_CACHE, cache_thread.task_runner(), NULL); 3324 net::TestCompletionCallback cb; 3325 int rv = simple_cache->Init(cb.callback()); 3326 EXPECT_NE(net::OK, cb.GetResult(rv)); 3327 delete simple_cache; 3328 DisableIntegrityCheck(); 3329 } 3330 3331 // Tests that the |BackendImpl| refuses to initialize on top of the files 3332 // generated by the Simple Cache Backend. 3333 TEST_F(DiskCacheBackendTest, BlockfileCacheOverSimpleCache) { 3334 // Create a cache structure with the |SimpleBackendImpl|. 3335 SetSimpleCacheMode(); 3336 InitCache(); 3337 disk_cache::Entry* entry; 3338 const int kSize = 50; 3339 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 3340 CacheTestFillBuffer(buffer->data(), kSize, false); 3341 ASSERT_EQ(net::OK, CreateEntry("key", &entry)); 3342 ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false)); 3343 entry->Close(); 3344 cache_.reset(); 3345 3346 // Check that the |BackendImpl| does not favor this structure. 3347 base::Thread cache_thread("CacheThread"); 3348 ASSERT_TRUE(cache_thread.StartWithOptions( 3349 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 3350 disk_cache::BackendImpl* cache = new disk_cache::BackendImpl( 3351 cache_path_, base::ThreadTaskRunnerHandle::Get(), NULL); 3352 cache->SetUnitTestMode(); 3353 net::TestCompletionCallback cb; 3354 int rv = cache->Init(cb.callback()); 3355 EXPECT_NE(net::OK, cb.GetResult(rv)); 3356 delete cache; 3357 DisableIntegrityCheck(); 3358 } 3359 3360 TEST_F(DiskCacheBackendTest, SimpleCacheFixEnumerators) { 3361 SetSimpleCacheMode(); 3362 BackendFixEnumerators(); 3363 } 3364 3365 // Tests basic functionality of the SimpleBackend implementation of the 3366 // enumeration API. 3367 TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationBasics) { 3368 SetSimpleCacheMode(); 3369 InitCache(); 3370 std::set<std::string> key_pool; 3371 ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool)); 3372 3373 // Check that enumeration returns all entries. 3374 std::set<std::string> keys_to_match(key_pool); 3375 scoped_ptr<TestIterator> iter = CreateIterator(); 3376 size_t count = 0; 3377 ASSERT_TRUE(EnumerateAndMatchKeys(-1, iter.get(), &keys_to_match, &count)); 3378 iter.reset(); 3379 EXPECT_EQ(key_pool.size(), count); 3380 EXPECT_TRUE(keys_to_match.empty()); 3381 3382 // Check that opening entries does not affect enumeration. 3383 keys_to_match = key_pool; 3384 iter = CreateIterator(); 3385 count = 0; 3386 disk_cache::Entry* entry_opened_before; 3387 ASSERT_EQ(net::OK, OpenEntry(*(key_pool.begin()), &entry_opened_before)); 3388 ASSERT_TRUE(EnumerateAndMatchKeys(key_pool.size()/2, 3389 iter.get(), 3390 &keys_to_match, 3391 &count)); 3392 3393 disk_cache::Entry* entry_opened_middle; 3394 ASSERT_EQ(net::OK, 3395 OpenEntry(*(keys_to_match.begin()), &entry_opened_middle)); 3396 ASSERT_TRUE(EnumerateAndMatchKeys(-1, iter.get(), &keys_to_match, &count)); 3397 iter.reset(); 3398 entry_opened_before->Close(); 3399 entry_opened_middle->Close(); 3400 3401 EXPECT_EQ(key_pool.size(), count); 3402 EXPECT_TRUE(keys_to_match.empty()); 3403 } 3404 3405 // Tests that the enumerations are not affected by dooming an entry in the 3406 // middle. 3407 TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationWhileDoomed) { 3408 SetSimpleCacheMode(); 3409 InitCache(); 3410 std::set<std::string> key_pool; 3411 ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool)); 3412 3413 // Check that enumeration returns all entries but the doomed one. 3414 std::set<std::string> keys_to_match(key_pool); 3415 scoped_ptr<TestIterator> iter = CreateIterator(); 3416 size_t count = 0; 3417 ASSERT_TRUE(EnumerateAndMatchKeys(key_pool.size()/2, 3418 iter.get(), 3419 &keys_to_match, 3420 &count)); 3421 3422 std::string key_to_delete = *(keys_to_match.begin()); 3423 DoomEntry(key_to_delete); 3424 keys_to_match.erase(key_to_delete); 3425 key_pool.erase(key_to_delete); 3426 ASSERT_TRUE(EnumerateAndMatchKeys(-1, iter.get(), &keys_to_match, &count)); 3427 iter.reset(); 3428 3429 EXPECT_EQ(key_pool.size(), count); 3430 EXPECT_TRUE(keys_to_match.empty()); 3431 } 3432 3433 // Tests that enumerations are not affected by corrupt files. 3434 TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationCorruption) { 3435 SetSimpleCacheMode(); 3436 InitCache(); 3437 std::set<std::string> key_pool; 3438 ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool)); 3439 3440 // Create a corrupt entry. The write/read sequence ensures that the entry will 3441 // have been created before corrupting the platform files, in the case of 3442 // optimistic operations. 3443 const std::string key = "the key"; 3444 disk_cache::Entry* corrupted_entry; 3445 3446 ASSERT_EQ(net::OK, CreateEntry(key, &corrupted_entry)); 3447 ASSERT_TRUE(corrupted_entry); 3448 const int kSize = 50; 3449 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 3450 CacheTestFillBuffer(buffer->data(), kSize, false); 3451 ASSERT_EQ(kSize, 3452 WriteData(corrupted_entry, 0, 0, buffer.get(), kSize, false)); 3453 ASSERT_EQ(kSize, ReadData(corrupted_entry, 0, 0, buffer.get(), kSize)); 3454 corrupted_entry->Close(); 3455 3456 EXPECT_TRUE(disk_cache::simple_util::CreateCorruptFileForTests( 3457 key, cache_path_)); 3458 EXPECT_EQ(key_pool.size() + 1, 3459 implicit_cast<size_t>(cache_->GetEntryCount())); 3460 3461 // Check that enumeration returns all entries but the corrupt one. 3462 std::set<std::string> keys_to_match(key_pool); 3463 scoped_ptr<TestIterator> iter = CreateIterator(); 3464 size_t count = 0; 3465 ASSERT_TRUE(EnumerateAndMatchKeys(-1, iter.get(), &keys_to_match, &count)); 3466 iter.reset(); 3467 3468 EXPECT_EQ(key_pool.size(), count); 3469 EXPECT_TRUE(keys_to_match.empty()); 3470 } 3471 3472 // Tests that enumerations don't leak memory when the backend is destructed 3473 // mid-enumeration. 3474 TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationDestruction) { 3475 SetSimpleCacheMode(); 3476 InitCache(); 3477 std::set<std::string> key_pool; 3478 ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool)); 3479 3480 scoped_ptr<TestIterator> iter = CreateIterator(); 3481 disk_cache::Entry* entry = NULL; 3482 ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); 3483 EXPECT_TRUE(entry); 3484 disk_cache::ScopedEntryPtr entry_closer(entry); 3485 3486 cache_.reset(); 3487 // This test passes if we don't leak memory. 3488 } 3489 3490 #endif // defined(OS_POSIX) 3491