1 // Copyright (c) 2006-2008 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/file_util.h" 7 #include "base/path_service.h" 8 #include "base/platform_thread.h" 9 #include "base/string_util.h" 10 #include "net/base/io_buffer.h" 11 #include "net/base/net_errors.h" 12 #include "net/base/test_completion_callback.h" 13 #include "net/disk_cache/backend_impl.h" 14 #include "net/disk_cache/disk_cache_test_base.h" 15 #include "net/disk_cache/disk_cache_test_util.h" 16 #include "net/disk_cache/mapped_file.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 using base::Time; 20 21 namespace { 22 23 // Copies a set of cache files from the data folder to the test folder. 24 bool CopyTestCache(const std::wstring& name) { 25 FilePath path; 26 PathService::Get(base::DIR_SOURCE_ROOT, &path); 27 path = path.AppendASCII("net"); 28 path = path.AppendASCII("data"); 29 path = path.AppendASCII("cache_tests"); 30 path = path.Append(FilePath::FromWStringHack(name)); 31 32 FilePath dest = GetCacheFilePath(); 33 if (!DeleteCache(dest)) 34 return false; 35 return file_util::CopyDirectory(path, dest, false); 36 } 37 38 } // namespace 39 40 // Tests that can run with different types of caches. 41 class DiskCacheBackendTest : public DiskCacheTestWithCache { 42 protected: 43 void BackendBasics(); 44 void BackendKeying(); 45 void BackendSetSize(); 46 void BackendLoad(); 47 void BackendValidEntry(); 48 void BackendInvalidEntry(); 49 void BackendInvalidEntryRead(); 50 void BackendInvalidEntryWithLoad(); 51 void BackendTrimInvalidEntry(); 52 void BackendTrimInvalidEntry2(); 53 void BackendEnumerations(); 54 void BackendEnumerations2(); 55 void BackendInvalidEntryEnumeration(); 56 void BackendFixEnumerators(); 57 void BackendDoomRecent(); 58 void BackendDoomBetween(); 59 void BackendTransaction(const std::wstring& name, int num_entries, bool load); 60 void BackendRecoverInsert(); 61 void BackendRecoverRemove(); 62 void BackendInvalidEntry2(); 63 void BackendNotMarkedButDirty(const std::wstring& name); 64 void BackendDoomAll(); 65 void BackendDoomAll2(); 66 void BackendInvalidRankings(); 67 void BackendInvalidRankings2(); 68 void BackendDisable(); 69 void BackendDisable2(); 70 void BackendDisable3(); 71 void BackendDisable4(); 72 }; 73 74 void DiskCacheBackendTest::BackendBasics() { 75 InitCache(); 76 disk_cache::Entry *entry1 = NULL, *entry2 = NULL; 77 EXPECT_FALSE(cache_->OpenEntry("the first key", &entry1)); 78 ASSERT_TRUE(cache_->CreateEntry("the first key", &entry1)); 79 ASSERT_TRUE(NULL != entry1); 80 entry1->Close(); 81 entry1 = NULL; 82 83 ASSERT_TRUE(cache_->OpenEntry("the first key", &entry1)); 84 ASSERT_TRUE(NULL != entry1); 85 entry1->Close(); 86 entry1 = NULL; 87 88 EXPECT_FALSE(cache_->CreateEntry("the first key", &entry1)); 89 ASSERT_TRUE(cache_->OpenEntry("the first key", &entry1)); 90 EXPECT_FALSE(cache_->OpenEntry("some other key", &entry2)); 91 ASSERT_TRUE(cache_->CreateEntry("some other key", &entry2)); 92 ASSERT_TRUE(NULL != entry1); 93 ASSERT_TRUE(NULL != entry2); 94 EXPECT_EQ(2, cache_->GetEntryCount()); 95 96 disk_cache::Entry* entry3 = NULL; 97 ASSERT_TRUE(cache_->OpenEntry("some other key", &entry3)); 98 ASSERT_TRUE(NULL != entry3); 99 EXPECT_TRUE(entry2 == entry3); 100 EXPECT_EQ(2, cache_->GetEntryCount()); 101 102 EXPECT_TRUE(cache_->DoomEntry("some other key")); 103 EXPECT_EQ(1, cache_->GetEntryCount()); 104 entry1->Close(); 105 entry2->Close(); 106 entry3->Close(); 107 108 EXPECT_TRUE(cache_->DoomEntry("the first key")); 109 EXPECT_EQ(0, cache_->GetEntryCount()); 110 111 ASSERT_TRUE(cache_->CreateEntry("the first key", &entry1)); 112 ASSERT_TRUE(cache_->CreateEntry("some other key", &entry2)); 113 entry1->Doom(); 114 entry1->Close(); 115 EXPECT_TRUE(cache_->DoomEntry("some other key")); 116 EXPECT_EQ(0, cache_->GetEntryCount()); 117 entry2->Close(); 118 } 119 120 TEST_F(DiskCacheBackendTest, Basics) { 121 BackendBasics(); 122 } 123 124 TEST_F(DiskCacheBackendTest, NewEvictionBasics) { 125 SetNewEviction(); 126 BackendBasics(); 127 } 128 129 TEST_F(DiskCacheBackendTest, MemoryOnlyBasics) { 130 SetMemoryOnlyMode(); 131 BackendBasics(); 132 } 133 134 void DiskCacheBackendTest::BackendKeying() { 135 InitCache(); 136 const char* kName1 = "the first key"; 137 const char* kName2 = "the first Key"; 138 disk_cache::Entry *entry1, *entry2; 139 ASSERT_TRUE(cache_->CreateEntry(kName1, &entry1)); 140 141 ASSERT_TRUE(cache_->CreateEntry(kName2, &entry2)); 142 EXPECT_TRUE(entry1 != entry2) << "Case sensitive"; 143 entry2->Close(); 144 145 char buffer[30]; 146 base::strlcpy(buffer, kName1, arraysize(buffer)); 147 ASSERT_TRUE(cache_->OpenEntry(buffer, &entry2)); 148 EXPECT_TRUE(entry1 == entry2); 149 entry2->Close(); 150 151 base::strlcpy(buffer + 1, kName1, arraysize(buffer) - 1); 152 ASSERT_TRUE(cache_->OpenEntry(buffer + 1, &entry2)); 153 EXPECT_TRUE(entry1 == entry2); 154 entry2->Close(); 155 156 base::strlcpy(buffer + 3, kName1, arraysize(buffer) - 3); 157 ASSERT_TRUE(cache_->OpenEntry(buffer + 3, &entry2)); 158 EXPECT_TRUE(entry1 == entry2); 159 entry2->Close(); 160 161 // Now verify long keys. 162 char buffer2[20000]; 163 memset(buffer2, 's', sizeof(buffer2)); 164 buffer2[1023] = '\0'; 165 ASSERT_TRUE(cache_->CreateEntry(buffer2, &entry2)) << "key on block file"; 166 entry2->Close(); 167 168 buffer2[1023] = 'g'; 169 buffer2[19999] = '\0'; 170 ASSERT_TRUE(cache_->CreateEntry(buffer2, &entry2)) << "key on external file"; 171 entry2->Close(); 172 entry1->Close(); 173 } 174 175 TEST_F(DiskCacheBackendTest, Keying) { 176 BackendKeying(); 177 } 178 179 TEST_F(DiskCacheBackendTest, NewEvictionKeying) { 180 SetNewEviction(); 181 BackendKeying(); 182 } 183 184 TEST_F(DiskCacheBackendTest, MemoryOnlyKeying) { 185 SetMemoryOnlyMode(); 186 BackendKeying(); 187 } 188 189 TEST_F(DiskCacheBackendTest, ExternalFiles) { 190 InitCache(); 191 // First, lets create a file on the folder. 192 FilePath filename = GetCacheFilePath().AppendASCII("f_000001"); 193 194 const int kSize = 50; 195 scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize); 196 CacheTestFillBuffer(buffer1->data(), kSize, false); 197 ASSERT_EQ(kSize, file_util::WriteFile(filename, buffer1->data(), kSize)); 198 199 // Now let's create a file with the cache. 200 disk_cache::Entry* entry; 201 ASSERT_TRUE(cache_->CreateEntry("key", &entry)); 202 ASSERT_EQ(0, entry->WriteData(0, 20000, buffer1, 0, NULL, false)); 203 entry->Close(); 204 205 // And verify that the first file is still there. 206 scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize); 207 ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize)); 208 EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize)); 209 } 210 211 TEST_F(DiskCacheTest, ShutdownWithPendingIO) { 212 TestCompletionCallback callback; 213 214 { 215 FilePath path = GetCacheFilePath(); 216 ASSERT_TRUE(DeleteCache(path)); 217 218 disk_cache::Backend* cache = 219 disk_cache::CreateCacheBackend(path, false, 0, net::DISK_CACHE); 220 221 disk_cache::Entry* entry; 222 ASSERT_TRUE(cache->CreateEntry("some key", &entry)); 223 224 const int kSize = 25000; 225 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); 226 CacheTestFillBuffer(buffer->data(), kSize, false); 227 228 for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) { 229 int rv = entry->WriteData(0, i, buffer, kSize, &callback, false); 230 if (rv == net::ERR_IO_PENDING) 231 break; 232 EXPECT_EQ(kSize, rv); 233 } 234 235 entry->Close(); 236 237 // The cache destructor will see one pending operation here. 238 delete cache; 239 } 240 241 MessageLoop::current()->RunAllPending(); 242 } 243 244 void DiskCacheBackendTest::BackendSetSize() { 245 SetDirectMode(); 246 const int cache_size = 0x10000; // 64 kB 247 SetMaxSize(cache_size); 248 InitCache(); 249 250 std::string first("some key"); 251 std::string second("something else"); 252 disk_cache::Entry* entry; 253 ASSERT_TRUE(cache_->CreateEntry(first, &entry)); 254 255 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(cache_size); 256 memset(buffer->data(), 0, cache_size); 257 EXPECT_EQ(cache_size / 10, entry->WriteData(0, 0, buffer, cache_size / 10, 258 NULL, false)) << "normal file"; 259 260 EXPECT_EQ(net::ERR_FAILED, entry->WriteData(1, 0, buffer, cache_size / 5, 261 NULL, false)) << "file size above the limit"; 262 263 // By doubling the total size, we make this file cacheable. 264 SetMaxSize(cache_size * 2); 265 EXPECT_EQ(cache_size / 5, entry->WriteData(1, 0, buffer, cache_size / 5, 266 NULL, false)); 267 268 // Let's fill up the cache!. 269 SetMaxSize(cache_size * 10); 270 EXPECT_EQ(cache_size * 3 / 4, entry->WriteData(0, 0, buffer, 271 cache_size * 3 / 4, NULL, false)); 272 entry->Close(); 273 274 SetMaxSize(cache_size); 275 276 // The cache is 95% full. 277 278 ASSERT_TRUE(cache_->CreateEntry(second, &entry)); 279 EXPECT_EQ(cache_size / 10, entry->WriteData(0, 0, buffer, cache_size / 10, 280 NULL, false)) << "trim the cache"; 281 entry->Close(); 282 283 EXPECT_FALSE(cache_->OpenEntry(first, &entry)); 284 ASSERT_TRUE(cache_->OpenEntry(second, &entry)); 285 EXPECT_EQ(cache_size / 10, entry->GetDataSize(0)); 286 entry->Close(); 287 } 288 289 TEST_F(DiskCacheBackendTest, SetSize) { 290 BackendSetSize(); 291 } 292 293 TEST_F(DiskCacheBackendTest, NewEvictionSetSize) { 294 SetNewEviction(); 295 BackendSetSize(); 296 } 297 298 TEST_F(DiskCacheBackendTest, MemoryOnlySetSize) { 299 SetMemoryOnlyMode(); 300 BackendSetSize(); 301 } 302 303 void DiskCacheBackendTest::BackendLoad() { 304 InitCache(); 305 int seed = static_cast<int>(Time::Now().ToInternalValue()); 306 srand(seed); 307 308 disk_cache::Entry* entries[100]; 309 for (int i = 0; i < 100; i++) { 310 std::string key = GenerateKey(true); 311 ASSERT_TRUE(cache_->CreateEntry(key, &entries[i])); 312 } 313 EXPECT_EQ(100, cache_->GetEntryCount()); 314 315 for (int i = 0; i < 100; i++) { 316 int source1 = rand() % 100; 317 int source2 = rand() % 100; 318 disk_cache::Entry* temp = entries[source1]; 319 entries[source1] = entries[source2]; 320 entries[source2] = temp; 321 } 322 323 for (int i = 0; i < 100; i++) { 324 disk_cache::Entry* entry; 325 ASSERT_TRUE(cache_->OpenEntry(entries[i]->GetKey(), &entry)); 326 EXPECT_TRUE(entry == entries[i]); 327 entry->Close(); 328 entries[i]->Doom(); 329 entries[i]->Close(); 330 } 331 EXPECT_EQ(0, cache_->GetEntryCount()); 332 } 333 334 TEST_F(DiskCacheBackendTest, Load) { 335 // Work with a tiny index table (16 entries) 336 SetMask(0xf); 337 SetMaxSize(0x100000); 338 BackendLoad(); 339 } 340 341 TEST_F(DiskCacheBackendTest, NewEvictionLoad) { 342 SetNewEviction(); 343 // Work with a tiny index table (16 entries) 344 SetMask(0xf); 345 SetMaxSize(0x100000); 346 BackendLoad(); 347 } 348 349 TEST_F(DiskCacheBackendTest, MemoryOnlyLoad) { 350 // Work with a tiny index table (16 entries) 351 SetMaxSize(0x100000); 352 SetMemoryOnlyMode(); 353 BackendLoad(); 354 } 355 356 // Before looking for invalid entries, let's check a valid entry. 357 void DiskCacheBackendTest::BackendValidEntry() { 358 SetDirectMode(); 359 InitCache(); 360 361 std::string key("Some key"); 362 disk_cache::Entry* entry1; 363 ASSERT_TRUE(cache_->CreateEntry(key, &entry1)); 364 365 const int kSize = 50; 366 scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize); 367 memset(buffer1->data(), 0, kSize); 368 base::strlcpy(buffer1->data(), "And the data to save", kSize); 369 EXPECT_EQ(kSize, entry1->WriteData(0, 0, buffer1, kSize, NULL, false)); 370 entry1->Close(); 371 SimulateCrash(); 372 373 ASSERT_TRUE(cache_->OpenEntry(key, &entry1)); 374 375 scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize); 376 memset(buffer2->data(), 0, kSize); 377 EXPECT_EQ(kSize, entry1->ReadData(0, 0, buffer2, kSize, NULL)); 378 entry1->Close(); 379 EXPECT_STREQ(buffer1->data(), buffer2->data()); 380 } 381 382 TEST_F(DiskCacheBackendTest, ValidEntry) { 383 BackendValidEntry(); 384 } 385 386 TEST_F(DiskCacheBackendTest, NewEvictionValidEntry) { 387 SetNewEviction(); 388 BackendValidEntry(); 389 } 390 391 // The same logic of the previous test (ValidEntry), but this time force the 392 // entry to be invalid, simulating a crash in the middle. 393 // We'll be leaking memory from this test. 394 void DiskCacheBackendTest::BackendInvalidEntry() { 395 // Use the implementation directly... we need to simulate a crash. 396 SetDirectMode(); 397 InitCache(); 398 399 std::string key("Some key"); 400 disk_cache::Entry* entry1; 401 ASSERT_TRUE(cache_->CreateEntry(key, &entry1)); 402 403 const int kSize = 50; 404 scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize); 405 memset(buffer1->data(), 0, kSize); 406 base::strlcpy(buffer1->data(), "And the data to save", kSize); 407 EXPECT_EQ(kSize, entry1->WriteData(0, 0, buffer1, kSize, NULL, false)); 408 SimulateCrash(); 409 410 EXPECT_FALSE(cache_->OpenEntry(key, &entry1)); 411 EXPECT_EQ(0, cache_->GetEntryCount()); 412 } 413 414 // This and the other intentionally leaky tests below are excluded from 415 // purify and valgrind runs by naming them in the files 416 // net/data/purify/net_unittests.exe.gtest.txt and 417 // net/data/valgrind/net_unittests.gtest.txt 418 // The scripts tools/{purify,valgrind}/chrome_tests.sh 419 // read those files and pass the appropriate --gtest_filter to net_unittests. 420 TEST_F(DiskCacheBackendTest, InvalidEntry) { 421 BackendInvalidEntry(); 422 } 423 424 // We'll be leaking memory from this test. 425 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry) { 426 SetNewEviction(); 427 BackendInvalidEntry(); 428 } 429 430 // Almost the same test, but this time crash the cache after reading an entry. 431 // We'll be leaking memory from this test. 432 void DiskCacheBackendTest::BackendInvalidEntryRead() { 433 // Use the implementation directly... we need to simulate a crash. 434 SetDirectMode(); 435 InitCache(); 436 437 std::string key("Some key"); 438 disk_cache::Entry* entry1; 439 ASSERT_TRUE(cache_->CreateEntry(key, &entry1)); 440 441 const int kSize = 50; 442 scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize); 443 memset(buffer1->data(), 0, kSize); 444 base::strlcpy(buffer1->data(), "And the data to save", kSize); 445 EXPECT_EQ(kSize, entry1->WriteData(0, 0, buffer1, kSize, NULL, false)); 446 entry1->Close(); 447 ASSERT_TRUE(cache_->OpenEntry(key, &entry1)); 448 EXPECT_EQ(kSize, entry1->ReadData(0, 0, buffer1, kSize, NULL)); 449 450 SimulateCrash(); 451 452 EXPECT_FALSE(cache_->OpenEntry(key, &entry1)); 453 EXPECT_EQ(0, cache_->GetEntryCount()); 454 } 455 456 // We'll be leaking memory from this test. 457 TEST_F(DiskCacheBackendTest, InvalidEntryRead) { 458 BackendInvalidEntryRead(); 459 } 460 461 // We'll be leaking memory from this test. 462 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryRead) { 463 SetNewEviction(); 464 BackendInvalidEntryRead(); 465 } 466 467 // We'll be leaking memory from this test. 468 void DiskCacheBackendTest::BackendInvalidEntryWithLoad() { 469 // Work with a tiny index table (16 entries) 470 SetMask(0xf); 471 SetMaxSize(0x100000); 472 InitCache(); 473 474 int seed = static_cast<int>(Time::Now().ToInternalValue()); 475 srand(seed); 476 477 const int kNumEntries = 100; 478 disk_cache::Entry* entries[kNumEntries]; 479 for (int i = 0; i < kNumEntries; i++) { 480 std::string key = GenerateKey(true); 481 ASSERT_TRUE(cache_->CreateEntry(key, &entries[i])); 482 } 483 EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); 484 485 for (int i = 0; i < kNumEntries; i++) { 486 int source1 = rand() % kNumEntries; 487 int source2 = rand() % kNumEntries; 488 disk_cache::Entry* temp = entries[source1]; 489 entries[source1] = entries[source2]; 490 entries[source2] = temp; 491 } 492 493 std::string keys[kNumEntries]; 494 for (int i = 0; i < kNumEntries; i++) { 495 keys[i] = entries[i]->GetKey(); 496 if (i < kNumEntries / 2) 497 entries[i]->Close(); 498 } 499 500 SimulateCrash(); 501 502 for (int i = kNumEntries / 2; i < kNumEntries; i++) { 503 disk_cache::Entry* entry; 504 EXPECT_FALSE(cache_->OpenEntry(keys[i], &entry)); 505 } 506 507 for (int i = 0; i < kNumEntries / 2; i++) { 508 disk_cache::Entry* entry; 509 EXPECT_TRUE(cache_->OpenEntry(keys[i], &entry)); 510 entry->Close(); 511 } 512 513 EXPECT_EQ(kNumEntries / 2, cache_->GetEntryCount()); 514 } 515 516 // We'll be leaking memory from this test. 517 TEST_F(DiskCacheBackendTest, InvalidEntryWithLoad) { 518 BackendInvalidEntryWithLoad(); 519 } 520 521 // We'll be leaking memory from this test. 522 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryWithLoad) { 523 SetNewEviction(); 524 BackendInvalidEntryWithLoad(); 525 } 526 527 // We'll be leaking memory from this test. 528 void DiskCacheBackendTest::BackendTrimInvalidEntry() { 529 // Use the implementation directly... we need to simulate a crash. 530 SetDirectMode(); 531 532 const int kSize = 0x3000; // 12 kB 533 SetMaxSize(kSize * 10); 534 InitCache(); 535 536 std::string first("some key"); 537 std::string second("something else"); 538 disk_cache::Entry* entry; 539 ASSERT_TRUE(cache_->CreateEntry(first, &entry)); 540 541 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); 542 memset(buffer->data(), 0, kSize); 543 EXPECT_EQ(kSize, entry->WriteData(0, 0, buffer, kSize, NULL, false)); 544 545 // Simulate a crash. 546 SimulateCrash(); 547 548 ASSERT_TRUE(cache_->CreateEntry(second, &entry)); 549 EXPECT_EQ(kSize, entry->WriteData(0, 0, buffer, kSize, NULL, false)); 550 551 EXPECT_EQ(2, cache_->GetEntryCount()); 552 SetMaxSize(kSize); 553 entry->Close(); // Trim the cache. 554 555 // If we evicted the entry in less than 20mS, we have one entry in the cache; 556 // if it took more than that, we posted a task and we'll delete the second 557 // entry too. 558 MessageLoop::current()->RunAllPending(); 559 EXPECT_GE(1, cache_->GetEntryCount()); 560 EXPECT_FALSE(cache_->OpenEntry(first, &entry)); 561 } 562 563 // We'll be leaking memory from this test. 564 TEST_F(DiskCacheBackendTest, TrimInvalidEntry) { 565 BackendTrimInvalidEntry(); 566 } 567 568 // We'll be leaking memory from this test. 569 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry) { 570 SetNewEviction(); 571 BackendTrimInvalidEntry(); 572 } 573 574 // We'll be leaking memory from this test. 575 void DiskCacheBackendTest::BackendTrimInvalidEntry2() { 576 // Use the implementation directly... we need to simulate a crash. 577 SetDirectMode(); 578 SetMask(0xf); // 16-entry table. 579 580 const int kSize = 0x3000; // 12 kB 581 SetMaxSize(kSize * 40); 582 InitCache(); 583 584 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); 585 memset(buffer->data(), 0, kSize); 586 disk_cache::Entry* entry; 587 588 // Writing 32 entries to this cache chains most of them. 589 for (int i = 0; i < 32; i++) { 590 std::string key(StringPrintf("some key %d", i)); 591 ASSERT_TRUE(cache_->CreateEntry(key, &entry)); 592 EXPECT_EQ(kSize, entry->WriteData(0, 0, buffer, kSize, NULL, false)); 593 entry->Close(); 594 ASSERT_TRUE(cache_->OpenEntry(key, &entry)); 595 // Note that we are not closing the entries. 596 } 597 598 // Simulate a crash. 599 SimulateCrash(); 600 601 ASSERT_TRUE(cache_->CreateEntry("Something else", &entry)); 602 EXPECT_EQ(kSize, entry->WriteData(0, 0, buffer, kSize, NULL, false)); 603 604 EXPECT_EQ(33, cache_->GetEntryCount()); 605 SetMaxSize(kSize); 606 607 // For the new eviction code, all corrupt entries are on the second list so 608 // they are not going away that easy. 609 if (new_eviction_) 610 cache_->DoomAllEntries(); 611 612 entry->Close(); // Trim the cache. 613 614 // We may abort the eviction before cleaning up everything. 615 MessageLoop::current()->RunAllPending(); 616 EXPECT_GE(30, cache_->GetEntryCount()); 617 } 618 619 // We'll be leaking memory from this test. 620 TEST_F(DiskCacheBackendTest, TrimInvalidEntry2) { 621 BackendTrimInvalidEntry2(); 622 } 623 624 // We'll be leaking memory from this test. 625 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry2) { 626 SetNewEviction(); 627 BackendTrimInvalidEntry2(); 628 } 629 630 void DiskCacheBackendTest::BackendEnumerations() { 631 InitCache(); 632 Time initial = Time::Now(); 633 int seed = static_cast<int>(initial.ToInternalValue()); 634 srand(seed); 635 636 const int kNumEntries = 100; 637 for (int i = 0; i < kNumEntries; i++) { 638 std::string key = GenerateKey(true); 639 disk_cache::Entry* entry; 640 ASSERT_TRUE(cache_->CreateEntry(key, &entry)); 641 entry->Close(); 642 } 643 EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); 644 Time final = Time::Now(); 645 646 disk_cache::Entry* entry; 647 void* iter = NULL; 648 int count = 0; 649 Time last_modified[kNumEntries]; 650 Time last_used[kNumEntries]; 651 while (cache_->OpenNextEntry(&iter, &entry)) { 652 ASSERT_TRUE(NULL != entry); 653 if (count < kNumEntries) { 654 last_modified[count] = entry->GetLastModified(); 655 last_used[count] = entry->GetLastUsed(); 656 EXPECT_TRUE(initial <= last_modified[count]); 657 EXPECT_TRUE(final >= last_modified[count]); 658 } 659 660 entry->Close(); 661 count++; 662 }; 663 EXPECT_EQ(kNumEntries, count); 664 665 iter = NULL; 666 count = 0; 667 // The previous enumeration should not have changed the timestamps. 668 while (cache_->OpenNextEntry(&iter, &entry)) { 669 ASSERT_TRUE(NULL != entry); 670 if (count < kNumEntries) { 671 EXPECT_TRUE(last_modified[count] == entry->GetLastModified()); 672 EXPECT_TRUE(last_used[count] == entry->GetLastUsed()); 673 } 674 entry->Close(); 675 count++; 676 }; 677 EXPECT_EQ(kNumEntries, count); 678 } 679 680 TEST_F(DiskCacheBackendTest, Enumerations) { 681 BackendEnumerations(); 682 } 683 684 TEST_F(DiskCacheBackendTest, NewEvictionEnumerations) { 685 SetNewEviction(); 686 BackendEnumerations(); 687 } 688 689 TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations) { 690 SetMemoryOnlyMode(); 691 BackendEnumerations(); 692 } 693 694 // Verifies enumerations while entries are open. 695 void DiskCacheBackendTest::BackendEnumerations2() { 696 InitCache(); 697 const std::string first("first"); 698 const std::string second("second"); 699 disk_cache::Entry *entry1, *entry2; 700 ASSERT_TRUE(cache_->CreateEntry(first, &entry1)); 701 entry1->Close(); 702 ASSERT_TRUE(cache_->CreateEntry(second, &entry2)); 703 entry2->Close(); 704 705 // Make sure that the timestamp is not the same. 706 PlatformThread::Sleep(20); 707 ASSERT_TRUE(cache_->OpenEntry(second, &entry1)); 708 void* iter = NULL; 709 ASSERT_TRUE(cache_->OpenNextEntry(&iter, &entry2)); 710 ASSERT_EQ(entry2->GetKey(), second); 711 712 // Two entries and the iterator pointing at "first". 713 entry1->Close(); 714 entry2->Close(); 715 716 // The iterator should still be valid, se we should not crash. 717 ASSERT_TRUE(cache_->OpenNextEntry(&iter, &entry2)); 718 ASSERT_EQ(entry2->GetKey(), first); 719 entry2->Close(); 720 cache_->EndEnumeration(&iter); 721 } 722 723 TEST_F(DiskCacheBackendTest, Enumerations2) { 724 BackendEnumerations2(); 725 } 726 727 TEST_F(DiskCacheBackendTest, NewEvictionEnumerations2) { 728 SetNewEviction(); 729 BackendEnumerations2(); 730 } 731 732 TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations2) { 733 SetMemoryOnlyMode(); 734 BackendEnumerations2(); 735 } 736 737 738 // Verify handling of invalid entries while doing enumerations. 739 // We'll be leaking memory from this test. 740 void DiskCacheBackendTest::BackendInvalidEntryEnumeration() { 741 // Use the implementation directly... we need to simulate a crash. 742 SetDirectMode(); 743 InitCache(); 744 745 std::string key("Some key"); 746 disk_cache::Entry *entry, *entry1, *entry2; 747 ASSERT_TRUE(cache_->CreateEntry(key, &entry1)); 748 749 const int kSize = 50; 750 scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize); 751 memset(buffer1->data(), 0, kSize); 752 base::strlcpy(buffer1->data(), "And the data to save", kSize); 753 EXPECT_EQ(kSize, entry1->WriteData(0, 0, buffer1, kSize, NULL, false)); 754 entry1->Close(); 755 ASSERT_TRUE(cache_->OpenEntry(key, &entry1)); 756 EXPECT_EQ(kSize, entry1->ReadData(0, 0, buffer1, kSize, NULL)); 757 758 std::string key2("Another key"); 759 ASSERT_TRUE(cache_->CreateEntry(key2, &entry2)); 760 entry2->Close(); 761 ASSERT_EQ(2, cache_->GetEntryCount()); 762 763 SimulateCrash(); 764 765 void* iter = NULL; 766 int count = 0; 767 while (cache_->OpenNextEntry(&iter, &entry)) { 768 ASSERT_TRUE(NULL != entry); 769 EXPECT_EQ(key2, entry->GetKey()); 770 entry->Close(); 771 count++; 772 }; 773 EXPECT_EQ(1, count); 774 EXPECT_EQ(1, cache_->GetEntryCount()); 775 } 776 777 // We'll be leaking memory from this test. 778 TEST_F(DiskCacheBackendTest, InvalidEntryEnumeration) { 779 BackendInvalidEntryEnumeration(); 780 } 781 782 // We'll be leaking memory from this test. 783 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryEnumeration) { 784 SetNewEviction(); 785 BackendInvalidEntryEnumeration(); 786 } 787 788 // Tests that if for some reason entries are modified close to existing cache 789 // iterators, we don't generate fatal errors or reset the cache. 790 void DiskCacheBackendTest::BackendFixEnumerators() { 791 InitCache(); 792 793 int seed = static_cast<int>(Time::Now().ToInternalValue()); 794 srand(seed); 795 796 const int kNumEntries = 10; 797 for (int i = 0; i < kNumEntries; i++) { 798 std::string key = GenerateKey(true); 799 disk_cache::Entry* entry; 800 ASSERT_TRUE(cache_->CreateEntry(key, &entry)); 801 entry->Close(); 802 } 803 EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); 804 805 disk_cache::Entry *entry1, *entry2; 806 void* iter1 = NULL; 807 void* iter2 = NULL; 808 ASSERT_TRUE(cache_->OpenNextEntry(&iter1, &entry1)); 809 ASSERT_TRUE(NULL != entry1); 810 entry1->Close(); 811 entry1 = NULL; 812 813 // Let's go to the middle of the list. 814 for (int i = 0; i < kNumEntries / 2; i++) { 815 if (entry1) 816 entry1->Close(); 817 ASSERT_TRUE(cache_->OpenNextEntry(&iter1, &entry1)); 818 ASSERT_TRUE(NULL != entry1); 819 820 ASSERT_TRUE(cache_->OpenNextEntry(&iter2, &entry2)); 821 ASSERT_TRUE(NULL != entry2); 822 entry2->Close(); 823 } 824 825 // Messing up with entry1 will modify entry2->next. 826 entry1->Doom(); 827 ASSERT_TRUE(cache_->OpenNextEntry(&iter2, &entry2)); 828 ASSERT_TRUE(NULL != entry2); 829 830 // The link entry2->entry1 should be broken. 831 EXPECT_NE(entry2->GetKey(), entry1->GetKey()); 832 entry1->Close(); 833 entry2->Close(); 834 835 // And the second iterator should keep working. 836 ASSERT_TRUE(cache_->OpenNextEntry(&iter2, &entry2)); 837 ASSERT_TRUE(NULL != entry2); 838 entry2->Close(); 839 840 cache_->EndEnumeration(&iter1); 841 cache_->EndEnumeration(&iter2); 842 } 843 844 TEST_F(DiskCacheBackendTest, FixEnumerators) { 845 BackendFixEnumerators(); 846 } 847 848 TEST_F(DiskCacheBackendTest, NewEvictionFixEnumerators) { 849 SetNewEviction(); 850 BackendFixEnumerators(); 851 } 852 853 void DiskCacheBackendTest::BackendDoomRecent() { 854 InitCache(); 855 Time initial = Time::Now(); 856 857 disk_cache::Entry *entry; 858 ASSERT_TRUE(cache_->CreateEntry("first", &entry)); 859 entry->Close(); 860 ASSERT_TRUE(cache_->CreateEntry("second", &entry)); 861 entry->Close(); 862 863 PlatformThread::Sleep(20); 864 Time middle = Time::Now(); 865 866 ASSERT_TRUE(cache_->CreateEntry("third", &entry)); 867 entry->Close(); 868 ASSERT_TRUE(cache_->CreateEntry("fourth", &entry)); 869 entry->Close(); 870 871 PlatformThread::Sleep(20); 872 Time final = Time::Now(); 873 874 ASSERT_EQ(4, cache_->GetEntryCount()); 875 EXPECT_TRUE(cache_->DoomEntriesSince(final)); 876 ASSERT_EQ(4, cache_->GetEntryCount()); 877 878 EXPECT_TRUE(cache_->DoomEntriesSince(middle)); 879 ASSERT_EQ(2, cache_->GetEntryCount()); 880 881 ASSERT_TRUE(cache_->OpenEntry("second", &entry)); 882 entry->Close(); 883 } 884 885 TEST_F(DiskCacheBackendTest, DoomRecent) { 886 BackendDoomRecent(); 887 } 888 889 TEST_F(DiskCacheBackendTest, NewEvictionDoomRecent) { 890 SetNewEviction(); 891 BackendDoomRecent(); 892 } 893 894 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomRecent) { 895 SetMemoryOnlyMode(); 896 BackendDoomRecent(); 897 } 898 899 void DiskCacheBackendTest::BackendDoomBetween() { 900 InitCache(); 901 Time initial = Time::Now(); 902 903 disk_cache::Entry *entry; 904 ASSERT_TRUE(cache_->CreateEntry("first", &entry)); 905 entry->Close(); 906 907 PlatformThread::Sleep(20); 908 Time middle_start = Time::Now(); 909 910 ASSERT_TRUE(cache_->CreateEntry("second", &entry)); 911 entry->Close(); 912 ASSERT_TRUE(cache_->CreateEntry("third", &entry)); 913 entry->Close(); 914 915 PlatformThread::Sleep(20); 916 Time middle_end = Time::Now(); 917 918 ASSERT_TRUE(cache_->CreateEntry("fourth", &entry)); 919 entry->Close(); 920 ASSERT_TRUE(cache_->OpenEntry("fourth", &entry)); 921 entry->Close(); 922 923 PlatformThread::Sleep(20); 924 Time final = Time::Now(); 925 926 ASSERT_EQ(4, cache_->GetEntryCount()); 927 EXPECT_TRUE(cache_->DoomEntriesBetween(middle_start, middle_end)); 928 ASSERT_EQ(2, cache_->GetEntryCount()); 929 930 ASSERT_TRUE(cache_->OpenEntry("fourth", &entry)); 931 entry->Close(); 932 933 EXPECT_TRUE(cache_->DoomEntriesBetween(middle_start, final)); 934 ASSERT_EQ(1, cache_->GetEntryCount()); 935 936 ASSERT_TRUE(cache_->OpenEntry("first", &entry)); 937 entry->Close(); 938 } 939 940 TEST_F(DiskCacheBackendTest, DoomBetween) { 941 BackendDoomBetween(); 942 } 943 944 TEST_F(DiskCacheBackendTest, NewEvictionDoomBetween) { 945 SetNewEviction(); 946 BackendDoomBetween(); 947 } 948 949 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomBetween) { 950 SetMemoryOnlyMode(); 951 BackendDoomBetween(); 952 } 953 954 void DiskCacheBackendTest::BackendTransaction(const std::wstring& name, 955 int num_entries, bool load) { 956 success_ = false; 957 ASSERT_TRUE(CopyTestCache(name)); 958 DisableFirstCleanup(); 959 960 if (load) { 961 SetMask(0xf); 962 SetMaxSize(0x100000); 963 } else { 964 // Clear the settings from the previous run. 965 SetMask(0); 966 SetMaxSize(0); 967 } 968 969 InitCache(); 970 ASSERT_EQ(num_entries + 1, cache_->GetEntryCount()); 971 972 std::string key("the first key"); 973 disk_cache::Entry* entry1; 974 ASSERT_FALSE(cache_->OpenEntry(key, &entry1)); 975 976 int actual = cache_->GetEntryCount(); 977 if (num_entries != actual) { 978 ASSERT_TRUE(load); 979 // If there is a heavy load, inserting an entry will make another entry 980 // dirty (on the hash bucket) so two entries are removed. 981 ASSERT_EQ(num_entries - 1, actual); 982 } 983 984 delete cache_; 985 cache_ = NULL; 986 cache_impl_ = NULL; 987 988 ASSERT_TRUE(CheckCacheIntegrity(GetCacheFilePath(), new_eviction_)); 989 success_ = true; 990 } 991 992 void DiskCacheBackendTest::BackendRecoverInsert() { 993 // Tests with an empty cache. 994 BackendTransaction(L"insert_empty1", 0, false); 995 ASSERT_TRUE(success_) << "insert_empty1"; 996 BackendTransaction(L"insert_empty2", 0, false); 997 ASSERT_TRUE(success_) << "insert_empty2"; 998 BackendTransaction(L"insert_empty3", 0, false); 999 ASSERT_TRUE(success_) << "insert_empty3"; 1000 1001 // Tests with one entry on the cache. 1002 BackendTransaction(L"insert_one1", 1, false); 1003 ASSERT_TRUE(success_) << "insert_one1"; 1004 BackendTransaction(L"insert_one2", 1, false); 1005 ASSERT_TRUE(success_) << "insert_one2"; 1006 BackendTransaction(L"insert_one3", 1, false); 1007 ASSERT_TRUE(success_) << "insert_one3"; 1008 1009 // Tests with one hundred entries on the cache, tiny index. 1010 BackendTransaction(L"insert_load1", 100, true); 1011 ASSERT_TRUE(success_) << "insert_load1"; 1012 BackendTransaction(L"insert_load2", 100, true); 1013 ASSERT_TRUE(success_) << "insert_load2"; 1014 } 1015 1016 TEST_F(DiskCacheBackendTest, RecoverInsert) { 1017 BackendRecoverInsert(); 1018 } 1019 1020 TEST_F(DiskCacheBackendTest, NewEvictionRecoverInsert) { 1021 SetNewEviction(); 1022 BackendRecoverInsert(); 1023 } 1024 1025 void DiskCacheBackendTest::BackendRecoverRemove() { 1026 // Removing the only element. 1027 BackendTransaction(L"remove_one1", 0, false); 1028 ASSERT_TRUE(success_) << "remove_one1"; 1029 BackendTransaction(L"remove_one2", 0, false); 1030 ASSERT_TRUE(success_) << "remove_one2"; 1031 BackendTransaction(L"remove_one3", 0, false); 1032 ASSERT_TRUE(success_) << "remove_one3"; 1033 1034 // Removing the head. 1035 BackendTransaction(L"remove_head1", 1, false); 1036 ASSERT_TRUE(success_) << "remove_head1"; 1037 BackendTransaction(L"remove_head2", 1, false); 1038 ASSERT_TRUE(success_) << "remove_head2"; 1039 BackendTransaction(L"remove_head3", 1, false); 1040 ASSERT_TRUE(success_) << "remove_head3"; 1041 1042 // Removing the tail. 1043 BackendTransaction(L"remove_tail1", 1, false); 1044 ASSERT_TRUE(success_) << "remove_tail1"; 1045 BackendTransaction(L"remove_tail2", 1, false); 1046 ASSERT_TRUE(success_) << "remove_tail2"; 1047 BackendTransaction(L"remove_tail3", 1, false); 1048 ASSERT_TRUE(success_) << "remove_tail3"; 1049 1050 // Removing with one hundred entries on the cache, tiny index. 1051 BackendTransaction(L"remove_load1", 100, true); 1052 ASSERT_TRUE(success_) << "remove_load1"; 1053 BackendTransaction(L"remove_load2", 100, true); 1054 ASSERT_TRUE(success_) << "remove_load2"; 1055 BackendTransaction(L"remove_load3", 100, true); 1056 ASSERT_TRUE(success_) << "remove_load3"; 1057 1058 #ifdef NDEBUG 1059 // This case cannot be reverted, so it will assert on debug builds. 1060 BackendTransaction(L"remove_one4", 0, false); 1061 ASSERT_TRUE(success_) << "remove_one4"; 1062 BackendTransaction(L"remove_head4", 1, false); 1063 ASSERT_TRUE(success_) << "remove_head4"; 1064 #endif 1065 } 1066 1067 TEST_F(DiskCacheBackendTest, RecoverRemove) { 1068 BackendRecoverRemove(); 1069 } 1070 1071 TEST_F(DiskCacheBackendTest, NewEvictionRecoverRemove) { 1072 SetNewEviction(); 1073 BackendRecoverRemove(); 1074 } 1075 1076 // Tests dealing with cache files that cannot be recovered. 1077 TEST_F(DiskCacheTest, Backend_DeleteOld) { 1078 ASSERT_TRUE(CopyTestCache(L"wrong_version")); 1079 FilePath path = GetCacheFilePath(); 1080 scoped_ptr<disk_cache::Backend> cache; 1081 cache.reset(disk_cache::CreateCacheBackend(path, true, 0, net::DISK_CACHE)); 1082 1083 MessageLoopHelper helper; 1084 1085 ASSERT_TRUE(NULL != cache.get()); 1086 ASSERT_EQ(0, cache->GetEntryCount()); 1087 1088 // Wait for a callback that never comes... about 2 secs :). The message loop 1089 // has to run to allow destruction of the cleaner thread. 1090 helper.WaitUntilCacheIoFinished(1); 1091 } 1092 1093 // We want to be able to deal with messed up entries on disk. 1094 void DiskCacheBackendTest::BackendInvalidEntry2() { 1095 ASSERT_TRUE(CopyTestCache(L"bad_entry")); 1096 DisableFirstCleanup(); 1097 InitCache(); 1098 1099 disk_cache::Entry *entry1, *entry2; 1100 ASSERT_TRUE(cache_->OpenEntry("the first key", &entry1)); 1101 EXPECT_FALSE(cache_->OpenEntry("some other key", &entry2)); 1102 entry1->Close(); 1103 1104 // CheckCacheIntegrity will fail at this point. 1105 DisableIntegrityCheck(); 1106 } 1107 1108 TEST_F(DiskCacheBackendTest, InvalidEntry2) { 1109 BackendInvalidEntry2(); 1110 } 1111 1112 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry2) { 1113 SetNewEviction(); 1114 BackendInvalidEntry2(); 1115 } 1116 1117 // We want to be able to deal with abnormal dirty entries. 1118 void DiskCacheBackendTest::BackendNotMarkedButDirty(const std::wstring& name) { 1119 ASSERT_TRUE(CopyTestCache(name)); 1120 DisableFirstCleanup(); 1121 InitCache(); 1122 1123 disk_cache::Entry *entry1, *entry2; 1124 ASSERT_TRUE(cache_->OpenEntry("the first key", &entry1)); 1125 EXPECT_FALSE(cache_->OpenEntry("some other key", &entry2)); 1126 entry1->Close(); 1127 } 1128 1129 TEST_F(DiskCacheBackendTest, NotMarkedButDirty) { 1130 BackendNotMarkedButDirty(L"dirty_entry"); 1131 } 1132 1133 TEST_F(DiskCacheBackendTest, NewEvictionNotMarkedButDirty) { 1134 SetNewEviction(); 1135 BackendNotMarkedButDirty(L"dirty_entry"); 1136 } 1137 1138 TEST_F(DiskCacheBackendTest, NotMarkedButDirty2) { 1139 BackendNotMarkedButDirty(L"dirty_entry2"); 1140 } 1141 1142 TEST_F(DiskCacheBackendTest, NewEvictionNotMarkedButDirty2) { 1143 SetNewEviction(); 1144 BackendNotMarkedButDirty(L"dirty_entry2"); 1145 } 1146 1147 // We want to be able to deal with messed up entries on disk. 1148 void DiskCacheBackendTest::BackendInvalidRankings2() { 1149 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1150 FilePath path = GetCacheFilePath(); 1151 DisableFirstCleanup(); 1152 InitCache(); 1153 1154 disk_cache::Entry *entry1, *entry2; 1155 EXPECT_FALSE(cache_->OpenEntry("the first key", &entry1)); 1156 ASSERT_TRUE(cache_->OpenEntry("some other key", &entry2)); 1157 entry2->Close(); 1158 1159 // CheckCacheIntegrity will fail at this point. 1160 DisableIntegrityCheck(); 1161 } 1162 1163 TEST_F(DiskCacheBackendTest, InvalidRankings2) { 1164 BackendInvalidRankings2(); 1165 } 1166 1167 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankings2) { 1168 SetNewEviction(); 1169 BackendInvalidRankings2(); 1170 } 1171 1172 // If the LRU is corrupt, we delete the cache. 1173 void DiskCacheBackendTest::BackendInvalidRankings() { 1174 disk_cache::Entry* entry; 1175 void* iter = NULL; 1176 ASSERT_TRUE(cache_->OpenNextEntry(&iter, &entry)); 1177 entry->Close(); 1178 EXPECT_EQ(2, cache_->GetEntryCount()); 1179 1180 EXPECT_FALSE(cache_->OpenNextEntry(&iter, &entry)); 1181 MessageLoop::current()->RunAllPending(); 1182 EXPECT_EQ(0, cache_->GetEntryCount()); 1183 } 1184 1185 TEST_F(DiskCacheBackendTest, InvalidRankingsSuccess) { 1186 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1187 DisableFirstCleanup(); 1188 SetDirectMode(); 1189 InitCache(); 1190 BackendInvalidRankings(); 1191 } 1192 1193 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsSuccess) { 1194 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1195 DisableFirstCleanup(); 1196 SetDirectMode(); 1197 SetNewEviction(); 1198 InitCache(); 1199 BackendInvalidRankings(); 1200 } 1201 1202 TEST_F(DiskCacheBackendTest, InvalidRankingsFailure) { 1203 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1204 DisableFirstCleanup(); 1205 SetDirectMode(); 1206 InitCache(); 1207 SetTestMode(); // Fail cache reinitialization. 1208 BackendInvalidRankings(); 1209 } 1210 1211 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsFailure) { 1212 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1213 DisableFirstCleanup(); 1214 SetDirectMode(); 1215 SetNewEviction(); 1216 InitCache(); 1217 SetTestMode(); // Fail cache reinitialization. 1218 BackendInvalidRankings(); 1219 } 1220 1221 // If the LRU is corrupt and we have open entries, we disable the cache. 1222 void DiskCacheBackendTest::BackendDisable() { 1223 disk_cache::Entry *entry1, *entry2; 1224 void* iter = NULL; 1225 ASSERT_TRUE(cache_->OpenNextEntry(&iter, &entry1)); 1226 1227 EXPECT_FALSE(cache_->OpenNextEntry(&iter, &entry2)); 1228 EXPECT_EQ(2, cache_->GetEntryCount()); 1229 EXPECT_FALSE(cache_->CreateEntry("Something new", &entry2)); 1230 1231 entry1->Close(); 1232 MessageLoop::current()->RunAllPending(); 1233 1234 EXPECT_EQ(0, cache_->GetEntryCount()); 1235 } 1236 1237 TEST_F(DiskCacheBackendTest, DisableSuccess) { 1238 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1239 DisableFirstCleanup(); 1240 SetDirectMode(); 1241 InitCache(); 1242 BackendDisable(); 1243 } 1244 1245 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess) { 1246 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1247 DisableFirstCleanup(); 1248 SetDirectMode(); 1249 SetNewEviction(); 1250 InitCache(); 1251 BackendDisable(); 1252 } 1253 1254 TEST_F(DiskCacheBackendTest, DisableFailure) { 1255 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1256 DisableFirstCleanup(); 1257 SetDirectMode(); 1258 InitCache(); 1259 SetTestMode(); // Fail cache reinitialization. 1260 BackendDisable(); 1261 } 1262 1263 TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure) { 1264 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1265 DisableFirstCleanup(); 1266 SetDirectMode(); 1267 SetNewEviction(); 1268 InitCache(); 1269 SetTestMode(); // Fail cache reinitialization. 1270 BackendDisable(); 1271 } 1272 1273 // This is another type of corruption on the LRU; disable the cache. 1274 void DiskCacheBackendTest::BackendDisable2() { 1275 EXPECT_EQ(8, cache_->GetEntryCount()); 1276 1277 disk_cache::Entry* entry; 1278 void* iter = NULL; 1279 int count = 0; 1280 while (cache_->OpenNextEntry(&iter, &entry)) { 1281 ASSERT_TRUE(NULL != entry); 1282 entry->Close(); 1283 count++; 1284 ASSERT_LT(count, 9); 1285 }; 1286 1287 MessageLoop::current()->RunAllPending(); 1288 EXPECT_EQ(0, cache_->GetEntryCount()); 1289 } 1290 1291 TEST_F(DiskCacheBackendTest, DisableSuccess2) { 1292 ASSERT_TRUE(CopyTestCache(L"list_loop")); 1293 DisableFirstCleanup(); 1294 SetDirectMode(); 1295 InitCache(); 1296 BackendDisable2(); 1297 } 1298 1299 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess2) { 1300 ASSERT_TRUE(CopyTestCache(L"list_loop")); 1301 DisableFirstCleanup(); 1302 SetNewEviction(); 1303 SetDirectMode(); 1304 InitCache(); 1305 BackendDisable2(); 1306 } 1307 1308 TEST_F(DiskCacheBackendTest, DisableFailure2) { 1309 ASSERT_TRUE(CopyTestCache(L"list_loop")); 1310 DisableFirstCleanup(); 1311 SetDirectMode(); 1312 InitCache(); 1313 SetTestMode(); // Fail cache reinitialization. 1314 BackendDisable2(); 1315 } 1316 1317 TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure2) { 1318 ASSERT_TRUE(CopyTestCache(L"list_loop")); 1319 DisableFirstCleanup(); 1320 SetDirectMode(); 1321 SetNewEviction(); 1322 InitCache(); 1323 SetTestMode(); // Fail cache reinitialization. 1324 BackendDisable2(); 1325 } 1326 1327 // If the index size changes when we disable the cache, we should not crash. 1328 void DiskCacheBackendTest::BackendDisable3() { 1329 disk_cache::Entry *entry1, *entry2; 1330 void* iter = NULL; 1331 EXPECT_EQ(2, cache_->GetEntryCount()); 1332 ASSERT_TRUE(cache_->OpenNextEntry(&iter, &entry1)); 1333 entry1->Close(); 1334 1335 EXPECT_FALSE(cache_->OpenNextEntry(&iter, &entry2)); 1336 MessageLoop::current()->RunAllPending(); 1337 1338 ASSERT_TRUE(cache_->CreateEntry("Something new", &entry2)); 1339 entry2->Close(); 1340 1341 EXPECT_EQ(1, cache_->GetEntryCount()); 1342 } 1343 1344 TEST_F(DiskCacheBackendTest, DisableSuccess3) { 1345 ASSERT_TRUE(CopyTestCache(L"bad_rankings2")); 1346 DisableFirstCleanup(); 1347 SetMaxSize(20 * 1024 * 1024); 1348 InitCache(); 1349 BackendDisable3(); 1350 } 1351 1352 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess3) { 1353 ASSERT_TRUE(CopyTestCache(L"bad_rankings2")); 1354 DisableFirstCleanup(); 1355 SetMaxSize(20 * 1024 * 1024); 1356 SetNewEviction(); 1357 InitCache(); 1358 BackendDisable3(); 1359 } 1360 1361 // If we disable the cache, already open entries should work as far as possible. 1362 void DiskCacheBackendTest::BackendDisable4() { 1363 disk_cache::Entry *entry1, *entry2, *entry3, *entry4; 1364 void* iter = NULL; 1365 ASSERT_TRUE(cache_->OpenNextEntry(&iter, &entry1)); 1366 1367 char key2[2000]; 1368 char key3[20000]; 1369 CacheTestFillBuffer(key2, sizeof(key2), true); 1370 CacheTestFillBuffer(key3, sizeof(key3), true); 1371 key2[sizeof(key2) - 1] = '\0'; 1372 key3[sizeof(key3) - 1] = '\0'; 1373 ASSERT_TRUE(cache_->CreateEntry(key2, &entry2)); 1374 ASSERT_TRUE(cache_->CreateEntry(key3, &entry3)); 1375 1376 const int kBufSize = 20000; 1377 scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kBufSize); 1378 memset(buf->data(), 0, kBufSize); 1379 EXPECT_EQ(100, entry2->WriteData(0, 0, buf, 100, NULL, false)); 1380 EXPECT_EQ(kBufSize, entry3->WriteData(0, 0, buf, kBufSize, NULL, false)); 1381 1382 // This line should disable the cache but not delete it. 1383 EXPECT_FALSE(cache_->OpenNextEntry(&iter, &entry4)); 1384 EXPECT_EQ(4, cache_->GetEntryCount()); 1385 1386 EXPECT_FALSE(cache_->CreateEntry("cache is disabled", &entry4)); 1387 1388 EXPECT_EQ(100, entry2->ReadData(0, 0, buf, 100, NULL)); 1389 EXPECT_EQ(100, entry2->WriteData(0, 0, buf, 100, NULL, false)); 1390 EXPECT_EQ(100, entry2->WriteData(1, 0, buf, 100, NULL, false)); 1391 1392 EXPECT_EQ(kBufSize, entry3->ReadData(0, 0, buf, kBufSize, NULL)); 1393 EXPECT_EQ(kBufSize, entry3->WriteData(0, 0, buf, kBufSize, NULL, false)); 1394 EXPECT_EQ(kBufSize, entry3->WriteData(1, 0, buf, kBufSize, NULL, false)); 1395 1396 std::string key = entry2->GetKey(); 1397 EXPECT_EQ(sizeof(key2) - 1, key.size()); 1398 key = entry3->GetKey(); 1399 EXPECT_EQ(sizeof(key3) - 1, key.size()); 1400 1401 entry1->Close(); 1402 entry2->Close(); 1403 entry3->Close(); 1404 MessageLoop::current()->RunAllPending(); 1405 1406 EXPECT_EQ(0, cache_->GetEntryCount()); 1407 } 1408 1409 TEST_F(DiskCacheBackendTest, DisableSuccess4) { 1410 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1411 DisableFirstCleanup(); 1412 SetDirectMode(); 1413 InitCache(); 1414 BackendDisable4(); 1415 } 1416 1417 // Flaky, http://crbug.com/21110. 1418 // TODO(rvargas): Add more debugging code to help identify the root cause. 1419 TEST_F(DiskCacheBackendTest, FLAKY_NewEvictionDisableSuccess4) { 1420 ASSERT_TRUE(CopyTestCache(L"bad_rankings")); 1421 DisableFirstCleanup(); 1422 SetDirectMode(); 1423 SetNewEviction(); 1424 InitCache(); 1425 BackendDisable4(); 1426 } 1427 1428 TEST_F(DiskCacheTest, Backend_UsageStats) { 1429 MessageLoopHelper helper; 1430 1431 FilePath path = GetCacheFilePath(); 1432 ASSERT_TRUE(DeleteCache(path)); 1433 scoped_ptr<disk_cache::BackendImpl> cache; 1434 cache.reset(new disk_cache::BackendImpl(path)); 1435 ASSERT_TRUE(NULL != cache.get()); 1436 cache->SetUnitTestMode(); 1437 ASSERT_TRUE(cache->Init()); 1438 1439 // Wait for a callback that never comes... about 2 secs :). The message loop 1440 // has to run to allow invocation of the usage timer. 1441 helper.WaitUntilCacheIoFinished(1); 1442 } 1443 1444 void DiskCacheBackendTest::BackendDoomAll() { 1445 InitCache(); 1446 Time initial = Time::Now(); 1447 1448 disk_cache::Entry *entry1, *entry2; 1449 ASSERT_TRUE(cache_->CreateEntry("first", &entry1)); 1450 ASSERT_TRUE(cache_->CreateEntry("second", &entry2)); 1451 entry1->Close(); 1452 entry2->Close(); 1453 1454 ASSERT_TRUE(cache_->CreateEntry("third", &entry1)); 1455 ASSERT_TRUE(cache_->CreateEntry("fourth", &entry2)); 1456 1457 ASSERT_EQ(4, cache_->GetEntryCount()); 1458 EXPECT_TRUE(cache_->DoomAllEntries()); 1459 ASSERT_EQ(0, cache_->GetEntryCount()); 1460 1461 disk_cache::Entry *entry3, *entry4; 1462 ASSERT_TRUE(cache_->CreateEntry("third", &entry3)); 1463 ASSERT_TRUE(cache_->CreateEntry("fourth", &entry4)); 1464 1465 EXPECT_TRUE(cache_->DoomAllEntries()); 1466 ASSERT_EQ(0, cache_->GetEntryCount()); 1467 1468 entry1->Close(); 1469 entry2->Close(); 1470 entry3->Doom(); // The entry should be already doomed, but this must work. 1471 entry3->Close(); 1472 entry4->Close(); 1473 1474 // Now try with all references released. 1475 ASSERT_TRUE(cache_->CreateEntry("third", &entry1)); 1476 ASSERT_TRUE(cache_->CreateEntry("fourth", &entry2)); 1477 entry1->Close(); 1478 entry2->Close(); 1479 1480 ASSERT_EQ(2, cache_->GetEntryCount()); 1481 EXPECT_TRUE(cache_->DoomAllEntries()); 1482 ASSERT_EQ(0, cache_->GetEntryCount()); 1483 } 1484 1485 TEST_F(DiskCacheBackendTest, DoomAll) { 1486 BackendDoomAll(); 1487 } 1488 1489 TEST_F(DiskCacheBackendTest, NewEvictionDoomAll) { 1490 SetNewEviction(); 1491 BackendDoomAll(); 1492 } 1493 1494 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomAll) { 1495 SetMemoryOnlyMode(); 1496 BackendDoomAll(); 1497 } 1498 1499 // If the index size changes when we doom the cache, we should not crash. 1500 void DiskCacheBackendTest::BackendDoomAll2() { 1501 EXPECT_EQ(2, cache_->GetEntryCount()); 1502 EXPECT_TRUE(cache_->DoomAllEntries()); 1503 1504 disk_cache::Entry* entry; 1505 ASSERT_TRUE(cache_->CreateEntry("Something new", &entry)); 1506 entry->Close(); 1507 1508 EXPECT_EQ(1, cache_->GetEntryCount()); 1509 } 1510 1511 TEST_F(DiskCacheBackendTest, DoomAll2) { 1512 ASSERT_TRUE(CopyTestCache(L"bad_rankings2")); 1513 DisableFirstCleanup(); 1514 SetMaxSize(20 * 1024 * 1024); 1515 InitCache(); 1516 BackendDoomAll2(); 1517 } 1518 1519 TEST_F(DiskCacheBackendTest, NewEvictionDoomAll2) { 1520 ASSERT_TRUE(CopyTestCache(L"bad_rankings2")); 1521 DisableFirstCleanup(); 1522 SetMaxSize(20 * 1024 * 1024); 1523 SetNewEviction(); 1524 InitCache(); 1525 BackendDoomAll2(); 1526 } 1527 1528 // We should be able to create the same entry on multiple simultaneous instances 1529 // of the cache. 1530 TEST_F(DiskCacheTest, MultipleInstances) { 1531 ScopedTestCache store1; 1532 ScopedTestCache store2("cache_test2"); 1533 ScopedTestCache store3("cache_test3"); 1534 1535 const int kNumberOfCaches = 2; 1536 scoped_ptr<disk_cache::Backend> cache[kNumberOfCaches]; 1537 1538 cache[0].reset(disk_cache::CreateCacheBackend(store1.path(), false, 0, 1539 net::DISK_CACHE)); 1540 cache[1].reset(disk_cache::CreateCacheBackend(store2.path(), false, 0, 1541 net::MEDIA_CACHE)); 1542 1543 ASSERT_TRUE(cache[0].get() != NULL && cache[1].get() != NULL); 1544 1545 std::string key("the first key"); 1546 disk_cache::Entry* entry; 1547 for (int i = 0; i < kNumberOfCaches; i++) { 1548 ASSERT_TRUE(cache[i]->CreateEntry(key, &entry)); 1549 entry->Close(); 1550 } 1551 } 1552 1553 // Test the four regions of the curve that determines the max cache size. 1554 TEST_F(DiskCacheTest, AutomaticMaxSize) { 1555 const int kDefaultSize = 80 * 1024 * 1024; 1556 int64 large_size = kDefaultSize; 1557 1558 EXPECT_EQ(kDefaultSize, disk_cache::PreferedCacheSize(large_size)); 1559 EXPECT_EQ((kDefaultSize / 2) * 8 / 10, 1560 disk_cache::PreferedCacheSize(large_size / 2)); 1561 1562 EXPECT_EQ(kDefaultSize, disk_cache::PreferedCacheSize(large_size * 2)); 1563 EXPECT_EQ(kDefaultSize, disk_cache::PreferedCacheSize(large_size * 4)); 1564 EXPECT_EQ(kDefaultSize, disk_cache::PreferedCacheSize(large_size * 10)); 1565 1566 EXPECT_EQ(kDefaultSize * 2, disk_cache::PreferedCacheSize(large_size * 20)); 1567 EXPECT_EQ(kDefaultSize * 5 / 2, 1568 disk_cache::PreferedCacheSize(large_size * 50 / 2)); 1569 1570 EXPECT_EQ(kDefaultSize * 5 / 2, 1571 disk_cache::PreferedCacheSize(large_size * 51 / 2)); 1572 EXPECT_EQ(kDefaultSize * 5 / 2, 1573 disk_cache::PreferedCacheSize(large_size * 100 / 2)); 1574 EXPECT_EQ(kDefaultSize * 5 / 2, 1575 disk_cache::PreferedCacheSize(large_size * 500 / 2)); 1576 1577 EXPECT_EQ(kDefaultSize * 6 / 2, 1578 disk_cache::PreferedCacheSize(large_size * 600 / 2)); 1579 EXPECT_EQ(kDefaultSize * 7 / 2, 1580 disk_cache::PreferedCacheSize(large_size * 700 / 2)); 1581 } 1582