1// Copyright (c) 2011 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/string_util.h" 8#include "base/stringprintf.h" 9#include "base/third_party/dynamic_annotations/dynamic_annotations.h" 10#include "base/threading/platform_thread.h" 11#include "net/base/io_buffer.h" 12#include "net/base/net_errors.h" 13#include "net/base/test_completion_callback.h" 14#include "net/disk_cache/backend_impl.h" 15#include "net/disk_cache/cache_util.h" 16#include "net/disk_cache/disk_cache_test_base.h" 17#include "net/disk_cache/disk_cache_test_util.h" 18#include "net/disk_cache/histogram_macros.h" 19#include "net/disk_cache/mapped_file.h" 20#include "net/disk_cache/mem_backend_impl.h" 21#include "testing/gtest/include/gtest/gtest.h" 22 23#if defined(OS_WIN) 24#include "base/win/scoped_handle.h" 25#endif 26 27using base::Time; 28 29// Tests that can run with different types of caches. 30class DiskCacheBackendTest : public DiskCacheTestWithCache { 31 protected: 32 void BackendBasics(); 33 void BackendKeying(); 34 void BackendSetSize(); 35 void BackendLoad(); 36 void BackendValidEntry(); 37 void BackendInvalidEntry(); 38 void BackendInvalidEntryRead(); 39 void BackendInvalidEntryWithLoad(); 40 void BackendTrimInvalidEntry(); 41 void BackendTrimInvalidEntry2(); 42 void BackendEnumerations(); 43 void BackendEnumerations2(); 44 void BackendInvalidEntryEnumeration(); 45 void BackendFixEnumerators(); 46 void BackendDoomRecent(); 47 void BackendDoomBetween(); 48 void BackendTransaction(const std::string& name, int num_entries, bool load); 49 void BackendRecoverInsert(); 50 void BackendRecoverRemove(); 51 void BackendRecoverWithEviction(); 52 void BackendInvalidEntry2(); 53 void BackendInvalidEntry3(); 54 void BackendNotMarkedButDirty(const std::string& name); 55 void BackendDoomAll(); 56 void BackendDoomAll2(); 57 void BackendInvalidRankings(); 58 void BackendInvalidRankings2(); 59 void BackendDisable(); 60 void BackendDisable2(); 61 void BackendDisable3(); 62 void BackendDisable4(); 63}; 64 65void DiskCacheBackendTest::BackendBasics() { 66 InitCache(); 67 disk_cache::Entry *entry1 = NULL, *entry2 = NULL; 68 EXPECT_NE(net::OK, OpenEntry("the first key", &entry1)); 69 ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1)); 70 ASSERT_TRUE(NULL != entry1); 71 entry1->Close(); 72 entry1 = NULL; 73 74 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1)); 75 ASSERT_TRUE(NULL != entry1); 76 entry1->Close(); 77 entry1 = NULL; 78 79 EXPECT_NE(net::OK, CreateEntry("the first key", &entry1)); 80 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1)); 81 EXPECT_NE(net::OK, OpenEntry("some other key", &entry2)); 82 ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2)); 83 ASSERT_TRUE(NULL != entry1); 84 ASSERT_TRUE(NULL != entry2); 85 EXPECT_EQ(2, cache_->GetEntryCount()); 86 87 disk_cache::Entry* entry3 = NULL; 88 ASSERT_EQ(net::OK, OpenEntry("some other key", &entry3)); 89 ASSERT_TRUE(NULL != entry3); 90 EXPECT_TRUE(entry2 == entry3); 91 EXPECT_EQ(2, cache_->GetEntryCount()); 92 93 EXPECT_EQ(net::OK, DoomEntry("some other key")); 94 EXPECT_EQ(1, cache_->GetEntryCount()); 95 entry1->Close(); 96 entry2->Close(); 97 entry3->Close(); 98 99 EXPECT_EQ(net::OK, DoomEntry("the first key")); 100 EXPECT_EQ(0, cache_->GetEntryCount()); 101 102 ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1)); 103 ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2)); 104 entry1->Doom(); 105 entry1->Close(); 106 EXPECT_EQ(net::OK, DoomEntry("some other key")); 107 EXPECT_EQ(0, cache_->GetEntryCount()); 108 entry2->Close(); 109} 110 111TEST_F(DiskCacheBackendTest, Basics) { 112 BackendBasics(); 113} 114 115TEST_F(DiskCacheBackendTest, NewEvictionBasics) { 116 SetNewEviction(); 117 BackendBasics(); 118} 119 120TEST_F(DiskCacheBackendTest, MemoryOnlyBasics) { 121 SetMemoryOnlyMode(); 122 BackendBasics(); 123} 124 125TEST_F(DiskCacheBackendTest, AppCacheBasics) { 126 SetCacheType(net::APP_CACHE); 127 BackendBasics(); 128} 129 130void DiskCacheBackendTest::BackendKeying() { 131 InitCache(); 132 const char* kName1 = "the first key"; 133 const char* kName2 = "the first Key"; 134 disk_cache::Entry *entry1, *entry2; 135 ASSERT_EQ(net::OK, CreateEntry(kName1, &entry1)); 136 137 ASSERT_EQ(net::OK, CreateEntry(kName2, &entry2)); 138 EXPECT_TRUE(entry1 != entry2) << "Case sensitive"; 139 entry2->Close(); 140 141 char buffer[30]; 142 base::strlcpy(buffer, kName1, arraysize(buffer)); 143 ASSERT_EQ(net::OK, OpenEntry(buffer, &entry2)); 144 EXPECT_TRUE(entry1 == entry2); 145 entry2->Close(); 146 147 base::strlcpy(buffer + 1, kName1, arraysize(buffer) - 1); 148 ASSERT_EQ(net::OK, OpenEntry(buffer + 1, &entry2)); 149 EXPECT_TRUE(entry1 == entry2); 150 entry2->Close(); 151 152 base::strlcpy(buffer + 3, kName1, arraysize(buffer) - 3); 153 ASSERT_EQ(net::OK, OpenEntry(buffer + 3, &entry2)); 154 EXPECT_TRUE(entry1 == entry2); 155 entry2->Close(); 156 157 // Now verify long keys. 158 char buffer2[20000]; 159 memset(buffer2, 's', sizeof(buffer2)); 160 buffer2[1023] = '\0'; 161 ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on block file"; 162 entry2->Close(); 163 164 buffer2[1023] = 'g'; 165 buffer2[19999] = '\0'; 166 ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on external file"; 167 entry2->Close(); 168 entry1->Close(); 169} 170 171TEST_F(DiskCacheBackendTest, Keying) { 172 BackendKeying(); 173} 174 175TEST_F(DiskCacheBackendTest, NewEvictionKeying) { 176 SetNewEviction(); 177 BackendKeying(); 178} 179 180TEST_F(DiskCacheBackendTest, MemoryOnlyKeying) { 181 SetMemoryOnlyMode(); 182 BackendKeying(); 183} 184 185TEST_F(DiskCacheBackendTest, AppCacheKeying) { 186 SetCacheType(net::APP_CACHE); 187 BackendKeying(); 188} 189 190TEST_F(DiskCacheTest, CreateBackend) { 191 TestCompletionCallback cb; 192 193 { 194 FilePath path = GetCacheFilePath(); 195 ASSERT_TRUE(DeleteCache(path)); 196 base::Thread cache_thread("CacheThread"); 197 ASSERT_TRUE(cache_thread.StartWithOptions( 198 base::Thread::Options(MessageLoop::TYPE_IO, 0))); 199 200 // Test the private factory methods. 201 disk_cache::Backend* cache = NULL; 202 int rv = disk_cache::BackendImpl::CreateBackend( 203 path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom, 204 cache_thread.message_loop_proxy(), NULL, &cache, &cb); 205 ASSERT_EQ(net::OK, cb.GetResult(rv)); 206 ASSERT_TRUE(cache); 207 delete cache; 208 209 cache = disk_cache::MemBackendImpl::CreateBackend(0, NULL); 210 ASSERT_TRUE(cache); 211 delete cache; 212 cache = NULL; 213 214 // Now test the public API. 215 rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path, 0, false, 216 cache_thread.message_loop_proxy(), 217 NULL, &cache, &cb); 218 ASSERT_EQ(net::OK, cb.GetResult(rv)); 219 ASSERT_TRUE(cache); 220 delete cache; 221 cache = NULL; 222 223 rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE, FilePath(), 0, false, 224 NULL, NULL, &cache, &cb); 225 ASSERT_EQ(net::OK, cb.GetResult(rv)); 226 ASSERT_TRUE(cache); 227 delete cache; 228 } 229 230 MessageLoop::current()->RunAllPending(); 231} 232 233TEST_F(DiskCacheBackendTest, ExternalFiles) { 234 InitCache(); 235 // First, let's create a file on the folder. 236 FilePath filename = GetCacheFilePath().AppendASCII("f_000001"); 237 238 const int kSize = 50; 239 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize)); 240 CacheTestFillBuffer(buffer1->data(), kSize, false); 241 ASSERT_EQ(kSize, file_util::WriteFile(filename, buffer1->data(), kSize)); 242 243 // Now let's create a file with the cache. 244 disk_cache::Entry* entry; 245 ASSERT_EQ(net::OK, CreateEntry("key", &entry)); 246 ASSERT_EQ(0, WriteData(entry, 0, 20000, buffer1, 0, false)); 247 entry->Close(); 248 249 // And verify that the first file is still there. 250 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize)); 251 ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize)); 252 EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize)); 253} 254 255// Tests that we deal with file-level pending operations at destruction time. 256TEST_F(DiskCacheTest, ShutdownWithPendingIO) { 257 TestCompletionCallback cb; 258 259 { 260 FilePath path = GetCacheFilePath(); 261 ASSERT_TRUE(DeleteCache(path)); 262 base::Thread cache_thread("CacheThread"); 263 ASSERT_TRUE(cache_thread.StartWithOptions( 264 base::Thread::Options(MessageLoop::TYPE_IO, 0))); 265 266 disk_cache::Backend* cache; 267 int rv = disk_cache::BackendImpl::CreateBackend( 268 path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom, 269 base::MessageLoopProxy::CreateForCurrentThread(), NULL, 270 &cache, &cb); 271 ASSERT_EQ(net::OK, cb.GetResult(rv)); 272 273 disk_cache::EntryImpl* entry; 274 rv = cache->CreateEntry("some key", 275 reinterpret_cast<disk_cache::Entry**>(&entry), &cb); 276 ASSERT_EQ(net::OK, cb.GetResult(rv)); 277 278 const int kSize = 25000; 279 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 280 CacheTestFillBuffer(buffer->data(), kSize, false); 281 282 for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) { 283 // We are using the current thread as the cache thread because we want to 284 // be able to call directly this method to make sure that the OS (instead 285 // of us switching thread) is returning IO pending. 286 rv = entry->WriteDataImpl(0, i, buffer, kSize, &cb, false); 287 if (rv == net::ERR_IO_PENDING) 288 break; 289 EXPECT_EQ(kSize, rv); 290 } 291 292 // Don't call Close() to avoid going through the queue or we'll deadlock 293 // waiting for the operation to finish. 294 entry->Release(); 295 296 // The cache destructor will see one pending operation here. 297 delete cache; 298 299 if (rv == net::ERR_IO_PENDING) { 300 EXPECT_TRUE(cb.have_result()); 301 } 302 } 303 304 MessageLoop::current()->RunAllPending(); 305} 306 307// Tests that we deal with background-thread pending operations. 308TEST_F(DiskCacheTest, ShutdownWithPendingIO2) { 309 TestCompletionCallback cb; 310 311 { 312 FilePath path = GetCacheFilePath(); 313 ASSERT_TRUE(DeleteCache(path)); 314 base::Thread cache_thread("CacheThread"); 315 ASSERT_TRUE(cache_thread.StartWithOptions( 316 base::Thread::Options(MessageLoop::TYPE_IO, 0))); 317 318 disk_cache::Backend* cache; 319 int rv = disk_cache::BackendImpl::CreateBackend( 320 path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom, 321 cache_thread.message_loop_proxy(), NULL, &cache, &cb); 322 ASSERT_EQ(net::OK, cb.GetResult(rv)); 323 324 disk_cache::Entry* entry; 325 rv = cache->CreateEntry("some key", &entry, &cb); 326 ASSERT_EQ(net::OK, cb.GetResult(rv)); 327 328 const int kSize = 25000; 329 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 330 CacheTestFillBuffer(buffer->data(), kSize, false); 331 332 rv = entry->WriteData(0, 0, buffer, kSize, &cb, false); 333 EXPECT_EQ(net::ERR_IO_PENDING, rv); 334 335 entry->Close(); 336 337 // The cache destructor will see two pending operations here. 338 delete cache; 339 } 340 341 MessageLoop::current()->RunAllPending(); 342} 343 344TEST_F(DiskCacheTest, TruncatedIndex) { 345 FilePath path = GetCacheFilePath(); 346 ASSERT_TRUE(DeleteCache(path)); 347 FilePath index = path.AppendASCII("index"); 348 ASSERT_EQ(5, file_util::WriteFile(index, "hello", 5)); 349 350 base::Thread cache_thread("CacheThread"); 351 ASSERT_TRUE(cache_thread.StartWithOptions( 352 base::Thread::Options(MessageLoop::TYPE_IO, 0))); 353 TestCompletionCallback cb; 354 355 disk_cache::Backend* backend = NULL; 356 int rv = disk_cache::BackendImpl::CreateBackend( 357 path, false, 0, net::DISK_CACHE, disk_cache::kNone, 358 cache_thread.message_loop_proxy(), NULL, &backend, &cb); 359 ASSERT_NE(net::OK, cb.GetResult(rv)); 360 361 ASSERT_TRUE(backend == NULL); 362 delete backend; 363} 364 365void DiskCacheBackendTest::BackendSetSize() { 366 SetDirectMode(); 367 const int cache_size = 0x10000; // 64 kB 368 SetMaxSize(cache_size); 369 InitCache(); 370 371 std::string first("some key"); 372 std::string second("something else"); 373 disk_cache::Entry* entry; 374 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 375 376 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(cache_size)); 377 memset(buffer->data(), 0, cache_size); 378 EXPECT_EQ(cache_size / 10, WriteData(entry, 0, 0, buffer, cache_size / 10, 379 false)) << "normal file"; 380 381 EXPECT_EQ(net::ERR_FAILED, WriteData(entry, 1, 0, buffer, cache_size / 5, 382 false)) << "file size above the limit"; 383 384 // By doubling the total size, we make this file cacheable. 385 SetMaxSize(cache_size * 2); 386 EXPECT_EQ(cache_size / 5, WriteData(entry, 1, 0, buffer, cache_size / 5, 387 false)); 388 389 // Let's fill up the cache!. 390 SetMaxSize(cache_size * 10); 391 EXPECT_EQ(cache_size * 3 / 4, WriteData(entry, 0, 0, buffer, 392 cache_size * 3 / 4, false)); 393 entry->Close(); 394 FlushQueueForTest(); 395 396 SetMaxSize(cache_size); 397 398 // The cache is 95% full. 399 400 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 401 EXPECT_EQ(cache_size / 10, WriteData(entry, 0, 0, buffer, cache_size / 10, 402 false)); 403 404 disk_cache::Entry* entry2; 405 ASSERT_EQ(net::OK, CreateEntry("an extra key", &entry2)); 406 EXPECT_EQ(cache_size / 10, WriteData(entry2, 0, 0, buffer, cache_size / 10, 407 false)); 408 entry2->Close(); // This will trigger the cache trim. 409 410 EXPECT_NE(net::OK, OpenEntry(first, &entry2)); 411 412 FlushQueueForTest(); // Make sure that we are done trimming the cache. 413 FlushQueueForTest(); // We may have posted two tasks to evict stuff. 414 415 entry->Close(); 416 ASSERT_EQ(net::OK, OpenEntry(second, &entry)); 417 EXPECT_EQ(cache_size / 10, entry->GetDataSize(0)); 418 entry->Close(); 419} 420 421TEST_F(DiskCacheBackendTest, SetSize) { 422 BackendSetSize(); 423} 424 425TEST_F(DiskCacheBackendTest, NewEvictionSetSize) { 426 SetNewEviction(); 427 BackendSetSize(); 428} 429 430TEST_F(DiskCacheBackendTest, MemoryOnlySetSize) { 431 SetMemoryOnlyMode(); 432 BackendSetSize(); 433} 434 435void DiskCacheBackendTest::BackendLoad() { 436 InitCache(); 437 int seed = static_cast<int>(Time::Now().ToInternalValue()); 438 srand(seed); 439 440 disk_cache::Entry* entries[100]; 441 for (int i = 0; i < 100; i++) { 442 std::string key = GenerateKey(true); 443 ASSERT_EQ(net::OK, CreateEntry(key, &entries[i])); 444 } 445 EXPECT_EQ(100, cache_->GetEntryCount()); 446 447 for (int i = 0; i < 100; i++) { 448 int source1 = rand() % 100; 449 int source2 = rand() % 100; 450 disk_cache::Entry* temp = entries[source1]; 451 entries[source1] = entries[source2]; 452 entries[source2] = temp; 453 } 454 455 for (int i = 0; i < 100; i++) { 456 disk_cache::Entry* entry; 457 ASSERT_EQ(net::OK, OpenEntry(entries[i]->GetKey(), &entry)); 458 EXPECT_TRUE(entry == entries[i]); 459 entry->Close(); 460 entries[i]->Doom(); 461 entries[i]->Close(); 462 } 463 FlushQueueForTest(); 464 EXPECT_EQ(0, cache_->GetEntryCount()); 465} 466 467TEST_F(DiskCacheBackendTest, Load) { 468 // Work with a tiny index table (16 entries) 469 SetMask(0xf); 470 SetMaxSize(0x100000); 471 BackendLoad(); 472} 473 474TEST_F(DiskCacheBackendTest, NewEvictionLoad) { 475 SetNewEviction(); 476 // Work with a tiny index table (16 entries) 477 SetMask(0xf); 478 SetMaxSize(0x100000); 479 BackendLoad(); 480} 481 482TEST_F(DiskCacheBackendTest, MemoryOnlyLoad) { 483 // Work with a tiny index table (16 entries) 484 SetMaxSize(0x100000); 485 SetMemoryOnlyMode(); 486 BackendLoad(); 487} 488 489TEST_F(DiskCacheBackendTest, AppCacheLoad) { 490 SetCacheType(net::APP_CACHE); 491 // Work with a tiny index table (16 entries) 492 SetMask(0xf); 493 SetMaxSize(0x100000); 494 BackendLoad(); 495} 496 497TEST_F(DiskCacheBackendTest, NewEvictionTrim) { 498 SetNewEviction(); 499 SetDirectMode(); 500 InitCache(); 501 502 disk_cache::Entry* entry; 503 for (int i = 0; i < 100; i++) { 504 std::string name(StringPrintf("Key %d", i)); 505 ASSERT_EQ(net::OK, CreateEntry(name, &entry)); 506 entry->Close(); 507 if (i < 90) { 508 // Entries 0 to 89 are in list 1; 90 to 99 are in list 0. 509 ASSERT_EQ(net::OK, OpenEntry(name, &entry)); 510 entry->Close(); 511 } 512 } 513 514 // The first eviction must come from list 1 (10% limit), the second must come 515 // from list 0. 516 TrimForTest(false); 517 EXPECT_NE(net::OK, OpenEntry("Key 0", &entry)); 518 TrimForTest(false); 519 EXPECT_NE(net::OK, OpenEntry("Key 90", &entry)); 520 521 // Double check that we still have the list tails. 522 ASSERT_EQ(net::OK, OpenEntry("Key 1", &entry)); 523 entry->Close(); 524 ASSERT_EQ(net::OK, OpenEntry("Key 91", &entry)); 525 entry->Close(); 526} 527 528// Before looking for invalid entries, let's check a valid entry. 529void DiskCacheBackendTest::BackendValidEntry() { 530 SetDirectMode(); 531 InitCache(); 532 533 std::string key("Some key"); 534 disk_cache::Entry* entry; 535 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 536 537 const int kSize = 50; 538 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize)); 539 memset(buffer1->data(), 0, kSize); 540 base::strlcpy(buffer1->data(), "And the data to save", kSize); 541 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer1, kSize, false)); 542 entry->Close(); 543 SimulateCrash(); 544 545 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 546 547 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize)); 548 memset(buffer2->data(), 0, kSize); 549 EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer2, kSize)); 550 entry->Close(); 551 EXPECT_STREQ(buffer1->data(), buffer2->data()); 552} 553 554TEST_F(DiskCacheBackendTest, ValidEntry) { 555 BackendValidEntry(); 556} 557 558TEST_F(DiskCacheBackendTest, NewEvictionValidEntry) { 559 SetNewEviction(); 560 BackendValidEntry(); 561} 562 563// The same logic of the previous test (ValidEntry), but this time force the 564// entry to be invalid, simulating a crash in the middle. 565// We'll be leaking memory from this test. 566void DiskCacheBackendTest::BackendInvalidEntry() { 567 // Use the implementation directly... we need to simulate a crash. 568 SetDirectMode(); 569 InitCache(); 570 571 std::string key("Some key"); 572 disk_cache::Entry* entry; 573 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 574 575 const int kSize = 50; 576 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 577 memset(buffer->data(), 0, kSize); 578 base::strlcpy(buffer->data(), "And the data to save", kSize); 579 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false)); 580 SimulateCrash(); 581 582 EXPECT_NE(net::OK, OpenEntry(key, &entry)); 583 EXPECT_EQ(0, cache_->GetEntryCount()); 584} 585 586// This and the other intentionally leaky tests below are excluded from 587// purify and valgrind runs by naming them in the files 588// net/data/purify/net_unittests.exe.gtest.txt and 589// net/data/valgrind/net_unittests.gtest.txt 590// The scripts tools/{purify,valgrind}/chrome_tests.sh 591// read those files and pass the appropriate --gtest_filter to net_unittests. 592TEST_F(DiskCacheBackendTest, InvalidEntry) { 593 BackendInvalidEntry(); 594} 595 596// We'll be leaking memory from this test. 597TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry) { 598 SetNewEviction(); 599 BackendInvalidEntry(); 600} 601 602// We'll be leaking memory from this test. 603TEST_F(DiskCacheBackendTest, AppCacheInvalidEntry) { 604 SetCacheType(net::APP_CACHE); 605 BackendInvalidEntry(); 606} 607 608// Almost the same test, but this time crash the cache after reading an entry. 609// We'll be leaking memory from this test. 610void DiskCacheBackendTest::BackendInvalidEntryRead() { 611 // Use the implementation directly... we need to simulate a crash. 612 SetDirectMode(); 613 InitCache(); 614 615 std::string key("Some key"); 616 disk_cache::Entry* entry; 617 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 618 619 const int kSize = 50; 620 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 621 memset(buffer->data(), 0, kSize); 622 base::strlcpy(buffer->data(), "And the data to save", kSize); 623 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false)); 624 entry->Close(); 625 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 626 EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer, kSize)); 627 628 SimulateCrash(); 629 630 if (type_ == net::APP_CACHE) { 631 // Reading an entry and crashing should not make it dirty. 632 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 633 EXPECT_EQ(1, cache_->GetEntryCount()); 634 entry->Close(); 635 } else { 636 EXPECT_NE(net::OK, OpenEntry(key, &entry)); 637 EXPECT_EQ(0, cache_->GetEntryCount()); 638 } 639} 640 641// We'll be leaking memory from this test. 642TEST_F(DiskCacheBackendTest, InvalidEntryRead) { 643 BackendInvalidEntryRead(); 644} 645 646// We'll be leaking memory from this test. 647TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryRead) { 648 SetNewEviction(); 649 BackendInvalidEntryRead(); 650} 651 652// We'll be leaking memory from this test. 653TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryRead) { 654 SetCacheType(net::APP_CACHE); 655 BackendInvalidEntryRead(); 656} 657 658// We'll be leaking memory from this test. 659void DiskCacheBackendTest::BackendInvalidEntryWithLoad() { 660 // Work with a tiny index table (16 entries) 661 SetMask(0xf); 662 SetMaxSize(0x100000); 663 InitCache(); 664 665 int seed = static_cast<int>(Time::Now().ToInternalValue()); 666 srand(seed); 667 668 const int kNumEntries = 100; 669 disk_cache::Entry* entries[kNumEntries]; 670 for (int i = 0; i < kNumEntries; i++) { 671 std::string key = GenerateKey(true); 672 ASSERT_EQ(net::OK, CreateEntry(key, &entries[i])); 673 } 674 EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); 675 676 for (int i = 0; i < kNumEntries; i++) { 677 int source1 = rand() % kNumEntries; 678 int source2 = rand() % kNumEntries; 679 disk_cache::Entry* temp = entries[source1]; 680 entries[source1] = entries[source2]; 681 entries[source2] = temp; 682 } 683 684 std::string keys[kNumEntries]; 685 for (int i = 0; i < kNumEntries; i++) { 686 keys[i] = entries[i]->GetKey(); 687 if (i < kNumEntries / 2) 688 entries[i]->Close(); 689 } 690 691 SimulateCrash(); 692 693 for (int i = kNumEntries / 2; i < kNumEntries; i++) { 694 disk_cache::Entry* entry; 695 EXPECT_NE(net::OK, OpenEntry(keys[i], &entry)); 696 } 697 698 for (int i = 0; i < kNumEntries / 2; i++) { 699 disk_cache::Entry* entry; 700 EXPECT_EQ(net::OK, OpenEntry(keys[i], &entry)); 701 entry->Close(); 702 } 703 704 EXPECT_EQ(kNumEntries / 2, cache_->GetEntryCount()); 705} 706 707// We'll be leaking memory from this test. 708TEST_F(DiskCacheBackendTest, InvalidEntryWithLoad) { 709 BackendInvalidEntryWithLoad(); 710} 711 712// We'll be leaking memory from this test. 713TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryWithLoad) { 714 SetNewEviction(); 715 BackendInvalidEntryWithLoad(); 716} 717 718// We'll be leaking memory from this test. 719TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryWithLoad) { 720 SetCacheType(net::APP_CACHE); 721 BackendInvalidEntryWithLoad(); 722} 723 724// We'll be leaking memory from this test. 725void DiskCacheBackendTest::BackendTrimInvalidEntry() { 726 // Use the implementation directly... we need to simulate a crash. 727 SetDirectMode(); 728 729 const int kSize = 0x3000; // 12 kB 730 SetMaxSize(kSize * 10); 731 InitCache(); 732 733 std::string first("some key"); 734 std::string second("something else"); 735 disk_cache::Entry* entry; 736 ASSERT_EQ(net::OK, CreateEntry(first, &entry)); 737 738 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 739 memset(buffer->data(), 0, kSize); 740 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false)); 741 742 // Simulate a crash. 743 SimulateCrash(); 744 745 ASSERT_EQ(net::OK, CreateEntry(second, &entry)); 746 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false)); 747 748 EXPECT_EQ(2, cache_->GetEntryCount()); 749 SetMaxSize(kSize); 750 entry->Close(); // Trim the cache. 751 FlushQueueForTest(); 752 753 // If we evicted the entry in less than 20mS, we have one entry in the cache; 754 // if it took more than that, we posted a task and we'll delete the second 755 // entry too. 756 MessageLoop::current()->RunAllPending(); 757 758 // This may be not thread-safe in general, but for now it's OK so add some 759 // ThreadSanitizer annotations to ignore data races on cache_. 760 // See http://crbug.com/55970 761 ANNOTATE_IGNORE_READS_BEGIN(); 762 EXPECT_GE(1, cache_->GetEntryCount()); 763 ANNOTATE_IGNORE_READS_END(); 764 765 EXPECT_NE(net::OK, OpenEntry(first, &entry)); 766} 767 768// We'll be leaking memory from this test. 769TEST_F(DiskCacheBackendTest, TrimInvalidEntry) { 770 BackendTrimInvalidEntry(); 771} 772 773// We'll be leaking memory from this test. 774TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry) { 775 SetNewEviction(); 776 BackendTrimInvalidEntry(); 777} 778 779// We'll be leaking memory from this test. 780void DiskCacheBackendTest::BackendTrimInvalidEntry2() { 781 // Use the implementation directly... we need to simulate a crash. 782 SetDirectMode(); 783 SetMask(0xf); // 16-entry table. 784 785 const int kSize = 0x3000; // 12 kB 786 SetMaxSize(kSize * 40); 787 InitCache(); 788 789 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 790 memset(buffer->data(), 0, kSize); 791 disk_cache::Entry* entry; 792 793 // Writing 32 entries to this cache chains most of them. 794 for (int i = 0; i < 32; i++) { 795 std::string key(base::StringPrintf("some key %d", i)); 796 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 797 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false)); 798 entry->Close(); 799 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 800 // Note that we are not closing the entries. 801 } 802 803 // Simulate a crash. 804 SimulateCrash(); 805 806 ASSERT_EQ(net::OK, CreateEntry("Something else", &entry)); 807 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false)); 808 809 EXPECT_EQ(33, cache_->GetEntryCount()); 810 SetMaxSize(kSize); 811 812 // For the new eviction code, all corrupt entries are on the second list so 813 // they are not going away that easy. 814 if (new_eviction_) { 815 EXPECT_EQ(net::OK, DoomAllEntries()); 816 } 817 818 entry->Close(); // Trim the cache. 819 FlushQueueForTest(); 820 821 // We may abort the eviction before cleaning up everything. 822 MessageLoop::current()->RunAllPending(); 823 EXPECT_GE(30, cache_->GetEntryCount()); 824} 825 826// We'll be leaking memory from this test. 827TEST_F(DiskCacheBackendTest, TrimInvalidEntry2) { 828 BackendTrimInvalidEntry2(); 829} 830 831// We'll be leaking memory from this test. 832TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry2) { 833 SetNewEviction(); 834 BackendTrimInvalidEntry2(); 835} 836 837void DiskCacheBackendTest::BackendEnumerations() { 838 InitCache(); 839 Time initial = Time::Now(); 840 int seed = static_cast<int>(initial.ToInternalValue()); 841 srand(seed); 842 843 const int kNumEntries = 100; 844 for (int i = 0; i < kNumEntries; i++) { 845 std::string key = GenerateKey(true); 846 disk_cache::Entry* entry; 847 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 848 entry->Close(); 849 } 850 EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); 851 Time final = Time::Now(); 852 853 disk_cache::Entry* entry; 854 void* iter = NULL; 855 int count = 0; 856 Time last_modified[kNumEntries]; 857 Time last_used[kNumEntries]; 858 while (OpenNextEntry(&iter, &entry) == net::OK) { 859 ASSERT_TRUE(NULL != entry); 860 if (count < kNumEntries) { 861 last_modified[count] = entry->GetLastModified(); 862 last_used[count] = entry->GetLastUsed(); 863 EXPECT_TRUE(initial <= last_modified[count]); 864 EXPECT_TRUE(final >= last_modified[count]); 865 } 866 867 entry->Close(); 868 count++; 869 }; 870 EXPECT_EQ(kNumEntries, count); 871 872 iter = NULL; 873 count = 0; 874 // The previous enumeration should not have changed the timestamps. 875 while (OpenNextEntry(&iter, &entry) == net::OK) { 876 ASSERT_TRUE(NULL != entry); 877 if (count < kNumEntries) { 878 EXPECT_TRUE(last_modified[count] == entry->GetLastModified()); 879 EXPECT_TRUE(last_used[count] == entry->GetLastUsed()); 880 } 881 entry->Close(); 882 count++; 883 }; 884 EXPECT_EQ(kNumEntries, count); 885} 886 887TEST_F(DiskCacheBackendTest, Enumerations) { 888 BackendEnumerations(); 889} 890 891TEST_F(DiskCacheBackendTest, NewEvictionEnumerations) { 892 SetNewEviction(); 893 BackendEnumerations(); 894} 895 896TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations) { 897 SetMemoryOnlyMode(); 898 BackendEnumerations(); 899} 900 901// Flaky, http://crbug.com/74387. 902TEST_F(DiskCacheBackendTest, FLAKY_AppCacheEnumerations) { 903 SetCacheType(net::APP_CACHE); 904 BackendEnumerations(); 905} 906 907// Verifies enumerations while entries are open. 908void DiskCacheBackendTest::BackendEnumerations2() { 909 InitCache(); 910 const std::string first("first"); 911 const std::string second("second"); 912 disk_cache::Entry *entry1, *entry2; 913 ASSERT_EQ(net::OK, CreateEntry(first, &entry1)); 914 entry1->Close(); 915 ASSERT_EQ(net::OK, CreateEntry(second, &entry2)); 916 entry2->Close(); 917 918 // Make sure that the timestamp is not the same. 919 base::PlatformThread::Sleep(20); 920 ASSERT_EQ(net::OK, OpenEntry(second, &entry1)); 921 void* iter = NULL; 922 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2)); 923 EXPECT_EQ(entry2->GetKey(), second); 924 925 // Two entries and the iterator pointing at "first". 926 entry1->Close(); 927 entry2->Close(); 928 929 // The iterator should still be valid, so we should not crash. 930 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2)); 931 EXPECT_EQ(entry2->GetKey(), first); 932 entry2->Close(); 933 cache_->EndEnumeration(&iter); 934 935 // Modify the oldest entry and get the newest element. 936 ASSERT_EQ(net::OK, OpenEntry(first, &entry1)); 937 EXPECT_EQ(0, WriteData(entry1, 0, 200, NULL, 0, false)); 938 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2)); 939 if (type_ == net::APP_CACHE) { 940 // The list is not updated. 941 EXPECT_EQ(entry2->GetKey(), second); 942 } else { 943 EXPECT_EQ(entry2->GetKey(), first); 944 } 945 946 entry1->Close(); 947 entry2->Close(); 948 cache_->EndEnumeration(&iter); 949} 950 951TEST_F(DiskCacheBackendTest, Enumerations2) { 952 BackendEnumerations2(); 953} 954 955TEST_F(DiskCacheBackendTest, NewEvictionEnumerations2) { 956 SetNewEviction(); 957 BackendEnumerations2(); 958} 959 960TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations2) { 961 SetMemoryOnlyMode(); 962 BackendEnumerations2(); 963} 964 965TEST_F(DiskCacheBackendTest, AppCacheEnumerations2) { 966 SetCacheType(net::APP_CACHE); 967 BackendEnumerations2(); 968} 969 970// Verify handling of invalid entries while doing enumerations. 971// We'll be leaking memory from this test. 972void DiskCacheBackendTest::BackendInvalidEntryEnumeration() { 973 // Use the implementation directly... we need to simulate a crash. 974 SetDirectMode(); 975 InitCache(); 976 977 std::string key("Some key"); 978 disk_cache::Entry *entry, *entry1, *entry2; 979 ASSERT_EQ(net::OK, CreateEntry(key, &entry1)); 980 981 const int kSize = 50; 982 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize)); 983 memset(buffer1->data(), 0, kSize); 984 base::strlcpy(buffer1->data(), "And the data to save", kSize); 985 EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1, kSize, false)); 986 entry1->Close(); 987 ASSERT_EQ(net::OK, OpenEntry(key, &entry1)); 988 EXPECT_EQ(kSize, ReadData(entry1, 0, 0, buffer1, kSize)); 989 990 std::string key2("Another key"); 991 ASSERT_EQ(net::OK, CreateEntry(key2, &entry2)); 992 entry2->Close(); 993 ASSERT_EQ(2, cache_->GetEntryCount()); 994 995 SimulateCrash(); 996 997 void* iter = NULL; 998 int count = 0; 999 while (OpenNextEntry(&iter, &entry) == net::OK) { 1000 ASSERT_TRUE(NULL != entry); 1001 EXPECT_EQ(key2, entry->GetKey()); 1002 entry->Close(); 1003 count++; 1004 }; 1005 EXPECT_EQ(1, count); 1006 EXPECT_EQ(1, cache_->GetEntryCount()); 1007} 1008 1009// We'll be leaking memory from this test. 1010TEST_F(DiskCacheBackendTest, InvalidEntryEnumeration) { 1011 BackendInvalidEntryEnumeration(); 1012} 1013 1014// We'll be leaking memory from this test. 1015TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryEnumeration) { 1016 SetNewEviction(); 1017 BackendInvalidEntryEnumeration(); 1018} 1019 1020// Tests that if for some reason entries are modified close to existing cache 1021// iterators, we don't generate fatal errors or reset the cache. 1022void DiskCacheBackendTest::BackendFixEnumerators() { 1023 InitCache(); 1024 1025 int seed = static_cast<int>(Time::Now().ToInternalValue()); 1026 srand(seed); 1027 1028 const int kNumEntries = 10; 1029 for (int i = 0; i < kNumEntries; i++) { 1030 std::string key = GenerateKey(true); 1031 disk_cache::Entry* entry; 1032 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 1033 entry->Close(); 1034 } 1035 EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); 1036 1037 disk_cache::Entry *entry1, *entry2; 1038 void* iter1 = NULL; 1039 void* iter2 = NULL; 1040 ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1)); 1041 ASSERT_TRUE(NULL != entry1); 1042 entry1->Close(); 1043 entry1 = NULL; 1044 1045 // Let's go to the middle of the list. 1046 for (int i = 0; i < kNumEntries / 2; i++) { 1047 if (entry1) 1048 entry1->Close(); 1049 ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1)); 1050 ASSERT_TRUE(NULL != entry1); 1051 1052 ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2)); 1053 ASSERT_TRUE(NULL != entry2); 1054 entry2->Close(); 1055 } 1056 1057 // Messing up with entry1 will modify entry2->next. 1058 entry1->Doom(); 1059 ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2)); 1060 ASSERT_TRUE(NULL != entry2); 1061 1062 // The link entry2->entry1 should be broken. 1063 EXPECT_NE(entry2->GetKey(), entry1->GetKey()); 1064 entry1->Close(); 1065 entry2->Close(); 1066 1067 // And the second iterator should keep working. 1068 ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2)); 1069 ASSERT_TRUE(NULL != entry2); 1070 entry2->Close(); 1071 1072 cache_->EndEnumeration(&iter1); 1073 cache_->EndEnumeration(&iter2); 1074} 1075 1076TEST_F(DiskCacheBackendTest, FixEnumerators) { 1077 BackendFixEnumerators(); 1078} 1079 1080TEST_F(DiskCacheBackendTest, NewEvictionFixEnumerators) { 1081 SetNewEviction(); 1082 BackendFixEnumerators(); 1083} 1084 1085void DiskCacheBackendTest::BackendDoomRecent() { 1086 InitCache(); 1087 Time initial = Time::Now(); 1088 1089 disk_cache::Entry *entry; 1090 ASSERT_EQ(net::OK, CreateEntry("first", &entry)); 1091 entry->Close(); 1092 ASSERT_EQ(net::OK, CreateEntry("second", &entry)); 1093 entry->Close(); 1094 1095 base::PlatformThread::Sleep(20); 1096 Time middle = Time::Now(); 1097 1098 ASSERT_EQ(net::OK, CreateEntry("third", &entry)); 1099 entry->Close(); 1100 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry)); 1101 entry->Close(); 1102 1103 base::PlatformThread::Sleep(20); 1104 Time final = Time::Now(); 1105 1106 ASSERT_EQ(4, cache_->GetEntryCount()); 1107 EXPECT_EQ(net::OK, DoomEntriesSince(final)); 1108 ASSERT_EQ(4, cache_->GetEntryCount()); 1109 1110 EXPECT_EQ(net::OK, DoomEntriesSince(middle)); 1111 ASSERT_EQ(2, cache_->GetEntryCount()); 1112 1113 ASSERT_EQ(net::OK, OpenEntry("second", &entry)); 1114 entry->Close(); 1115} 1116 1117TEST_F(DiskCacheBackendTest, DoomRecent) { 1118 BackendDoomRecent(); 1119} 1120 1121TEST_F(DiskCacheBackendTest, NewEvictionDoomRecent) { 1122 SetNewEviction(); 1123 BackendDoomRecent(); 1124} 1125 1126TEST_F(DiskCacheBackendTest, MemoryOnlyDoomRecent) { 1127 SetMemoryOnlyMode(); 1128 BackendDoomRecent(); 1129} 1130 1131void DiskCacheBackendTest::BackendDoomBetween() { 1132 InitCache(); 1133 Time initial = Time::Now(); 1134 1135 disk_cache::Entry *entry; 1136 ASSERT_EQ(net::OK, CreateEntry("first", &entry)); 1137 entry->Close(); 1138 1139 base::PlatformThread::Sleep(20); 1140 Time middle_start = Time::Now(); 1141 1142 ASSERT_EQ(net::OK, CreateEntry("second", &entry)); 1143 entry->Close(); 1144 ASSERT_EQ(net::OK, CreateEntry("third", &entry)); 1145 entry->Close(); 1146 1147 base::PlatformThread::Sleep(20); 1148 Time middle_end = Time::Now(); 1149 1150 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry)); 1151 entry->Close(); 1152 ASSERT_EQ(net::OK, OpenEntry("fourth", &entry)); 1153 entry->Close(); 1154 1155 base::PlatformThread::Sleep(20); 1156 Time final = Time::Now(); 1157 1158 ASSERT_EQ(4, cache_->GetEntryCount()); 1159 EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, middle_end)); 1160 ASSERT_EQ(2, cache_->GetEntryCount()); 1161 1162 ASSERT_EQ(net::OK, OpenEntry("fourth", &entry)); 1163 entry->Close(); 1164 1165 EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, final)); 1166 ASSERT_EQ(1, cache_->GetEntryCount()); 1167 1168 ASSERT_EQ(net::OK, OpenEntry("first", &entry)); 1169 entry->Close(); 1170} 1171 1172TEST_F(DiskCacheBackendTest, DoomBetween) { 1173 BackendDoomBetween(); 1174} 1175 1176TEST_F(DiskCacheBackendTest, NewEvictionDoomBetween) { 1177 SetNewEviction(); 1178 BackendDoomBetween(); 1179} 1180 1181TEST_F(DiskCacheBackendTest, MemoryOnlyDoomBetween) { 1182 SetMemoryOnlyMode(); 1183 BackendDoomBetween(); 1184} 1185 1186void DiskCacheBackendTest::BackendTransaction(const std::string& name, 1187 int num_entries, bool load) { 1188 success_ = false; 1189 ASSERT_TRUE(CopyTestCache(name)); 1190 DisableFirstCleanup(); 1191 1192 if (load) { 1193 SetMask(0xf); 1194 SetMaxSize(0x100000); 1195 } else { 1196 // Clear the settings from the previous run. 1197 SetMask(0); 1198 SetMaxSize(0); 1199 } 1200 1201 InitCache(); 1202 ASSERT_EQ(num_entries + 1, cache_->GetEntryCount()); 1203 1204 std::string key("the first key"); 1205 disk_cache::Entry* entry1; 1206 ASSERT_NE(net::OK, OpenEntry(key, &entry1)); 1207 1208 int actual = cache_->GetEntryCount(); 1209 if (num_entries != actual) { 1210 ASSERT_TRUE(load); 1211 // If there is a heavy load, inserting an entry will make another entry 1212 // dirty (on the hash bucket) so two entries are removed. 1213 ASSERT_EQ(num_entries - 1, actual); 1214 } 1215 1216 delete cache_; 1217 cache_ = NULL; 1218 cache_impl_ = NULL; 1219 1220 ASSERT_TRUE(CheckCacheIntegrity(GetCacheFilePath(), new_eviction_)); 1221 success_ = true; 1222} 1223 1224void DiskCacheBackendTest::BackendRecoverInsert() { 1225 // Tests with an empty cache. 1226 BackendTransaction("insert_empty1", 0, false); 1227 ASSERT_TRUE(success_) << "insert_empty1"; 1228 BackendTransaction("insert_empty2", 0, false); 1229 ASSERT_TRUE(success_) << "insert_empty2"; 1230 BackendTransaction("insert_empty3", 0, false); 1231 ASSERT_TRUE(success_) << "insert_empty3"; 1232 1233 // Tests with one entry on the cache. 1234 BackendTransaction("insert_one1", 1, false); 1235 ASSERT_TRUE(success_) << "insert_one1"; 1236 BackendTransaction("insert_one2", 1, false); 1237 ASSERT_TRUE(success_) << "insert_one2"; 1238 BackendTransaction("insert_one3", 1, false); 1239 ASSERT_TRUE(success_) << "insert_one3"; 1240 1241 // Tests with one hundred entries on the cache, tiny index. 1242 BackendTransaction("insert_load1", 100, true); 1243 ASSERT_TRUE(success_) << "insert_load1"; 1244 BackendTransaction("insert_load2", 100, true); 1245 ASSERT_TRUE(success_) << "insert_load2"; 1246} 1247 1248TEST_F(DiskCacheBackendTest, RecoverInsert) { 1249 BackendRecoverInsert(); 1250} 1251 1252TEST_F(DiskCacheBackendTest, NewEvictionRecoverInsert) { 1253 SetNewEviction(); 1254 BackendRecoverInsert(); 1255} 1256 1257void DiskCacheBackendTest::BackendRecoverRemove() { 1258 // Removing the only element. 1259 BackendTransaction("remove_one1", 0, false); 1260 ASSERT_TRUE(success_) << "remove_one1"; 1261 BackendTransaction("remove_one2", 0, false); 1262 ASSERT_TRUE(success_) << "remove_one2"; 1263 BackendTransaction("remove_one3", 0, false); 1264 ASSERT_TRUE(success_) << "remove_one3"; 1265 1266 // Removing the head. 1267 BackendTransaction("remove_head1", 1, false); 1268 ASSERT_TRUE(success_) << "remove_head1"; 1269 BackendTransaction("remove_head2", 1, false); 1270 ASSERT_TRUE(success_) << "remove_head2"; 1271 BackendTransaction("remove_head3", 1, false); 1272 ASSERT_TRUE(success_) << "remove_head3"; 1273 1274 // Removing the tail. 1275 BackendTransaction("remove_tail1", 1, false); 1276 ASSERT_TRUE(success_) << "remove_tail1"; 1277 BackendTransaction("remove_tail2", 1, false); 1278 ASSERT_TRUE(success_) << "remove_tail2"; 1279 BackendTransaction("remove_tail3", 1, false); 1280 ASSERT_TRUE(success_) << "remove_tail3"; 1281 1282 // Removing with one hundred entries on the cache, tiny index. 1283 BackendTransaction("remove_load1", 100, true); 1284 ASSERT_TRUE(success_) << "remove_load1"; 1285 BackendTransaction("remove_load2", 100, true); 1286 ASSERT_TRUE(success_) << "remove_load2"; 1287 BackendTransaction("remove_load3", 100, true); 1288 ASSERT_TRUE(success_) << "remove_load3"; 1289 1290 // This case cannot be reverted. 1291 BackendTransaction("remove_one4", 0, false); 1292 ASSERT_TRUE(success_) << "remove_one4"; 1293 BackendTransaction("remove_head4", 1, false); 1294 ASSERT_TRUE(success_) << "remove_head4"; 1295} 1296 1297TEST_F(DiskCacheBackendTest, RecoverRemove) { 1298 BackendRecoverRemove(); 1299} 1300 1301TEST_F(DiskCacheBackendTest, NewEvictionRecoverRemove) { 1302 SetNewEviction(); 1303 BackendRecoverRemove(); 1304} 1305 1306void DiskCacheBackendTest::BackendRecoverWithEviction() { 1307 success_ = false; 1308 ASSERT_TRUE(CopyTestCache("insert_load1")); 1309 DisableFirstCleanup(); 1310 1311 SetMask(0xf); 1312 SetMaxSize(0x1000); 1313 1314 // We should not crash here. 1315 InitCache(); 1316 DisableIntegrityCheck(); 1317} 1318 1319TEST_F(DiskCacheBackendTest, RecoverWithEviction) { 1320 BackendRecoverWithEviction(); 1321} 1322 1323TEST_F(DiskCacheBackendTest, NewEvictionRecoverWithEviction) { 1324 SetNewEviction(); 1325 BackendRecoverWithEviction(); 1326} 1327 1328// Tests dealing with cache files that cannot be recovered. 1329TEST_F(DiskCacheTest, DeleteOld) { 1330 ASSERT_TRUE(CopyTestCache("wrong_version")); 1331 FilePath path = GetCacheFilePath(); 1332 base::Thread cache_thread("CacheThread"); 1333 ASSERT_TRUE(cache_thread.StartWithOptions( 1334 base::Thread::Options(MessageLoop::TYPE_IO, 0))); 1335 TestCompletionCallback cb; 1336 1337 disk_cache::Backend* cache; 1338 int rv = disk_cache::BackendImpl::CreateBackend( 1339 path, true, 0, net::DISK_CACHE, disk_cache::kNoRandom, 1340 cache_thread.message_loop_proxy(), NULL, &cache, &cb); 1341 ASSERT_EQ(net::OK, cb.GetResult(rv)); 1342 1343 MessageLoopHelper helper; 1344 1345 ASSERT_TRUE(NULL != cache); 1346 ASSERT_EQ(0, cache->GetEntryCount()); 1347 1348 delete cache; 1349} 1350 1351// We want to be able to deal with messed up entries on disk. 1352void DiskCacheBackendTest::BackendInvalidEntry2() { 1353 ASSERT_TRUE(CopyTestCache("bad_entry")); 1354 DisableFirstCleanup(); 1355 InitCache(); 1356 1357 disk_cache::Entry *entry1, *entry2; 1358 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1)); 1359 EXPECT_NE(net::OK, OpenEntry("some other key", &entry2)); 1360 entry1->Close(); 1361 1362 // CheckCacheIntegrity will fail at this point. 1363 DisableIntegrityCheck(); 1364} 1365 1366TEST_F(DiskCacheBackendTest, InvalidEntry2) { 1367 BackendInvalidEntry2(); 1368} 1369 1370TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry2) { 1371 SetNewEviction(); 1372 BackendInvalidEntry2(); 1373} 1374 1375// Tests that we don't crash or hang when enumerating this cache. 1376void DiskCacheBackendTest::BackendInvalidEntry3() { 1377 SetMask(0x1); // 2-entry table. 1378 SetMaxSize(0x3000); // 12 kB. 1379 DisableFirstCleanup(); 1380 InitCache(); 1381 1382 disk_cache::Entry* entry; 1383 void* iter = NULL; 1384 while (OpenNextEntry(&iter, &entry) == net::OK) { 1385 entry->Close(); 1386 } 1387} 1388 1389TEST_F(DiskCacheBackendTest, InvalidEntry3) { 1390 ASSERT_TRUE(CopyTestCache("dirty_entry3")); 1391 BackendInvalidEntry3(); 1392} 1393 1394TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry3) { 1395 ASSERT_TRUE(CopyTestCache("dirty_entry4")); 1396 SetNewEviction(); 1397 BackendInvalidEntry3(); 1398 DisableIntegrityCheck(); 1399} 1400 1401// Test that we handle a dirty entry on the LRU list, already replaced with 1402// the same key, and with hash collisions. 1403TEST_F(DiskCacheBackendTest, InvalidEntry4) { 1404 ASSERT_TRUE(CopyTestCache("dirty_entry3")); 1405 SetMask(0x1); // 2-entry table. 1406 SetMaxSize(0x3000); // 12 kB. 1407 DisableFirstCleanup(); 1408 InitCache(); 1409 1410 TrimForTest(false); 1411} 1412 1413// Test that we handle a dirty entry on the deleted list, already replaced with 1414// the same key, and with hash collisions. 1415TEST_F(DiskCacheBackendTest, InvalidEntry5) { 1416 ASSERT_TRUE(CopyTestCache("dirty_entry4")); 1417 SetNewEviction(); 1418 SetMask(0x1); // 2-entry table. 1419 SetMaxSize(0x3000); // 12 kB. 1420 DisableFirstCleanup(); 1421 InitCache(); 1422 1423 TrimDeletedListForTest(false); 1424} 1425 1426TEST_F(DiskCacheBackendTest, InvalidEntry6) { 1427 ASSERT_TRUE(CopyTestCache("dirty_entry5")); 1428 SetMask(0x1); // 2-entry table. 1429 SetMaxSize(0x3000); // 12 kB. 1430 DisableFirstCleanup(); 1431 InitCache(); 1432 1433 // There is a dirty entry (but marked as clean) at the end, pointing to a 1434 // deleted entry through the hash collision list. We should not re-insert the 1435 // deleted entry into the index table. 1436 1437 TrimForTest(false); 1438 // The cache should be clean (as detected by CheckCacheIntegrity). 1439} 1440 1441// Tests that we don't hang when there is a loop on the hash collision list. 1442// The test cache could be a result of bug 69135. 1443TEST_F(DiskCacheBackendTest, BadNextEntry1) { 1444 ASSERT_TRUE(CopyTestCache("list_loop2")); 1445 SetMask(0x1); // 2-entry table. 1446 SetMaxSize(0x3000); // 12 kB. 1447 DisableFirstCleanup(); 1448 InitCache(); 1449 1450 // The second entry points at itselft, and the first entry is not accessible 1451 // though the index, but it is at the head of the LRU. 1452 1453 disk_cache::Entry* entry; 1454 ASSERT_EQ(net::OK, CreateEntry("The first key", &entry)); 1455 entry->Close(); 1456 1457 TrimForTest(false); 1458 TrimForTest(false); 1459 ASSERT_EQ(net::OK, OpenEntry("The first key", &entry)); 1460 entry->Close(); 1461 EXPECT_EQ(1, cache_->GetEntryCount()); 1462} 1463 1464// Tests that we don't hang when there is a loop on the hash collision list. 1465// The test cache could be a result of bug 69135. 1466TEST_F(DiskCacheBackendTest, BadNextEntry2) { 1467 ASSERT_TRUE(CopyTestCache("list_loop3")); 1468 SetMask(0x1); // 2-entry table. 1469 SetMaxSize(0x3000); // 12 kB. 1470 DisableFirstCleanup(); 1471 InitCache(); 1472 1473 // There is a wide loop of 5 entries. 1474 1475 disk_cache::Entry* entry; 1476 ASSERT_NE(net::OK, OpenEntry("Not present key", &entry)); 1477} 1478 1479TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry6) { 1480 ASSERT_TRUE(CopyTestCache("bad_rankings3")); 1481 DisableFirstCleanup(); 1482 SetNewEviction(); 1483 InitCache(); 1484 1485 // The second entry is dirty, but removing it should not corrupt the list. 1486 disk_cache::Entry* entry; 1487 ASSERT_NE(net::OK, OpenEntry("the second key", &entry)); 1488 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry)); 1489 1490 // This should not delete the cache. 1491 entry->Doom(); 1492 FlushQueueForTest(); 1493 entry->Close(); 1494 1495 ASSERT_EQ(net::OK, OpenEntry("some other key", &entry)); 1496 entry->Close(); 1497} 1498 1499// We want to be able to deal with abnormal dirty entries. 1500void DiskCacheBackendTest::BackendNotMarkedButDirty(const std::string& name) { 1501 ASSERT_TRUE(CopyTestCache(name)); 1502 DisableFirstCleanup(); 1503 InitCache(); 1504 1505 disk_cache::Entry *entry1, *entry2; 1506 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1)); 1507 EXPECT_NE(net::OK, OpenEntry("some other key", &entry2)); 1508 entry1->Close(); 1509} 1510 1511TEST_F(DiskCacheBackendTest, NotMarkedButDirty) { 1512 BackendNotMarkedButDirty("dirty_entry"); 1513} 1514 1515TEST_F(DiskCacheBackendTest, NewEvictionNotMarkedButDirty) { 1516 SetNewEviction(); 1517 BackendNotMarkedButDirty("dirty_entry"); 1518} 1519 1520TEST_F(DiskCacheBackendTest, NotMarkedButDirty2) { 1521 BackendNotMarkedButDirty("dirty_entry2"); 1522} 1523 1524TEST_F(DiskCacheBackendTest, NewEvictionNotMarkedButDirty2) { 1525 SetNewEviction(); 1526 BackendNotMarkedButDirty("dirty_entry2"); 1527} 1528 1529// We want to be able to deal with messed up entries on disk. 1530void DiskCacheBackendTest::BackendInvalidRankings2() { 1531 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1532 FilePath path = GetCacheFilePath(); 1533 DisableFirstCleanup(); 1534 InitCache(); 1535 1536 disk_cache::Entry *entry1, *entry2; 1537 EXPECT_NE(net::OK, OpenEntry("the first key", &entry1)); 1538 ASSERT_EQ(net::OK, OpenEntry("some other key", &entry2)); 1539 entry2->Close(); 1540 1541 // CheckCacheIntegrity will fail at this point. 1542 DisableIntegrityCheck(); 1543} 1544 1545TEST_F(DiskCacheBackendTest, InvalidRankings2) { 1546 BackendInvalidRankings2(); 1547} 1548 1549TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankings2) { 1550 SetNewEviction(); 1551 BackendInvalidRankings2(); 1552} 1553 1554// If the LRU is corrupt, we delete the cache. 1555void DiskCacheBackendTest::BackendInvalidRankings() { 1556 disk_cache::Entry* entry; 1557 void* iter = NULL; 1558 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); 1559 entry->Close(); 1560 EXPECT_EQ(2, cache_->GetEntryCount()); 1561 1562 EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); 1563 FlushQueueForTest(); // Allow the restart to finish. 1564 EXPECT_EQ(0, cache_->GetEntryCount()); 1565} 1566 1567TEST_F(DiskCacheBackendTest, InvalidRankingsSuccess) { 1568 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1569 DisableFirstCleanup(); 1570 SetDirectMode(); 1571 InitCache(); 1572 BackendInvalidRankings(); 1573} 1574 1575TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsSuccess) { 1576 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1577 DisableFirstCleanup(); 1578 SetDirectMode(); 1579 SetNewEviction(); 1580 InitCache(); 1581 BackendInvalidRankings(); 1582} 1583 1584TEST_F(DiskCacheBackendTest, InvalidRankingsFailure) { 1585 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1586 DisableFirstCleanup(); 1587 SetDirectMode(); 1588 InitCache(); 1589 SetTestMode(); // Fail cache reinitialization. 1590 BackendInvalidRankings(); 1591} 1592 1593TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsFailure) { 1594 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1595 DisableFirstCleanup(); 1596 SetDirectMode(); 1597 SetNewEviction(); 1598 InitCache(); 1599 SetTestMode(); // Fail cache reinitialization. 1600 BackendInvalidRankings(); 1601} 1602 1603// If the LRU is corrupt and we have open entries, we disable the cache. 1604void DiskCacheBackendTest::BackendDisable() { 1605 disk_cache::Entry *entry1, *entry2; 1606 void* iter = NULL; 1607 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1)); 1608 1609 EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2)); 1610 EXPECT_EQ(0, cache_->GetEntryCount()); 1611 EXPECT_NE(net::OK, CreateEntry("Something new", &entry2)); 1612 1613 entry1->Close(); 1614 FlushQueueForTest(); // Flushing the Close posts a task to restart the cache. 1615 FlushQueueForTest(); // This one actually allows that task to complete. 1616 1617 EXPECT_EQ(0, cache_->GetEntryCount()); 1618} 1619 1620TEST_F(DiskCacheBackendTest, DisableSuccess) { 1621 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1622 DisableFirstCleanup(); 1623 SetDirectMode(); 1624 InitCache(); 1625 BackendDisable(); 1626} 1627 1628TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess) { 1629 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1630 DisableFirstCleanup(); 1631 SetDirectMode(); 1632 SetNewEviction(); 1633 InitCache(); 1634 BackendDisable(); 1635} 1636 1637TEST_F(DiskCacheBackendTest, DisableFailure) { 1638 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1639 DisableFirstCleanup(); 1640 SetDirectMode(); 1641 InitCache(); 1642 SetTestMode(); // Fail cache reinitialization. 1643 BackendDisable(); 1644} 1645 1646TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure) { 1647 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1648 DisableFirstCleanup(); 1649 SetDirectMode(); 1650 SetNewEviction(); 1651 InitCache(); 1652 SetTestMode(); // Fail cache reinitialization. 1653 BackendDisable(); 1654} 1655 1656// This is another type of corruption on the LRU; disable the cache. 1657void DiskCacheBackendTest::BackendDisable2() { 1658 EXPECT_EQ(8, cache_->GetEntryCount()); 1659 1660 disk_cache::Entry* entry; 1661 void* iter = NULL; 1662 int count = 0; 1663 while (OpenNextEntry(&iter, &entry) == net::OK) { 1664 ASSERT_TRUE(NULL != entry); 1665 entry->Close(); 1666 count++; 1667 ASSERT_LT(count, 9); 1668 }; 1669 1670 FlushQueueForTest(); 1671 EXPECT_EQ(0, cache_->GetEntryCount()); 1672} 1673 1674TEST_F(DiskCacheBackendTest, DisableSuccess2) { 1675 ASSERT_TRUE(CopyTestCache("list_loop")); 1676 DisableFirstCleanup(); 1677 SetDirectMode(); 1678 InitCache(); 1679 BackendDisable2(); 1680} 1681 1682TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess2) { 1683 ASSERT_TRUE(CopyTestCache("list_loop")); 1684 DisableFirstCleanup(); 1685 SetNewEviction(); 1686 SetDirectMode(); 1687 InitCache(); 1688 BackendDisable2(); 1689} 1690 1691TEST_F(DiskCacheBackendTest, DisableFailure2) { 1692 ASSERT_TRUE(CopyTestCache("list_loop")); 1693 DisableFirstCleanup(); 1694 SetDirectMode(); 1695 InitCache(); 1696 SetTestMode(); // Fail cache reinitialization. 1697 BackendDisable2(); 1698} 1699 1700TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure2) { 1701 ASSERT_TRUE(CopyTestCache("list_loop")); 1702 DisableFirstCleanup(); 1703 SetDirectMode(); 1704 SetNewEviction(); 1705 InitCache(); 1706 SetTestMode(); // Fail cache reinitialization. 1707 BackendDisable2(); 1708} 1709 1710// If the index size changes when we disable the cache, we should not crash. 1711void DiskCacheBackendTest::BackendDisable3() { 1712 disk_cache::Entry *entry1, *entry2; 1713 void* iter = NULL; 1714 EXPECT_EQ(2, cache_->GetEntryCount()); 1715 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1)); 1716 entry1->Close(); 1717 1718 EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2)); 1719 FlushQueueForTest(); 1720 1721 ASSERT_EQ(net::OK, CreateEntry("Something new", &entry2)); 1722 entry2->Close(); 1723 1724 EXPECT_EQ(1, cache_->GetEntryCount()); 1725} 1726 1727TEST_F(DiskCacheBackendTest, DisableSuccess3) { 1728 ASSERT_TRUE(CopyTestCache("bad_rankings2")); 1729 DisableFirstCleanup(); 1730 SetMaxSize(20 * 1024 * 1024); 1731 InitCache(); 1732 BackendDisable3(); 1733} 1734 1735TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess3) { 1736 ASSERT_TRUE(CopyTestCache("bad_rankings2")); 1737 DisableFirstCleanup(); 1738 SetMaxSize(20 * 1024 * 1024); 1739 SetNewEviction(); 1740 InitCache(); 1741 BackendDisable3(); 1742} 1743 1744// If we disable the cache, already open entries should work as far as possible. 1745void DiskCacheBackendTest::BackendDisable4() { 1746 disk_cache::Entry *entry1, *entry2, *entry3, *entry4; 1747 void* iter = NULL; 1748 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1)); 1749 1750 char key2[2000]; 1751 char key3[20000]; 1752 CacheTestFillBuffer(key2, sizeof(key2), true); 1753 CacheTestFillBuffer(key3, sizeof(key3), true); 1754 key2[sizeof(key2) - 1] = '\0'; 1755 key3[sizeof(key3) - 1] = '\0'; 1756 ASSERT_EQ(net::OK, CreateEntry(key2, &entry2)); 1757 ASSERT_EQ(net::OK, CreateEntry(key3, &entry3)); 1758 1759 const int kBufSize = 20000; 1760 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufSize)); 1761 memset(buf->data(), 0, kBufSize); 1762 EXPECT_EQ(100, WriteData(entry2, 0, 0, buf, 100, false)); 1763 EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf, kBufSize, false)); 1764 1765 // This line should disable the cache but not delete it. 1766 EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry4)); 1767 EXPECT_EQ(0, cache_->GetEntryCount()); 1768 1769 EXPECT_NE(net::OK, CreateEntry("cache is disabled", &entry4)); 1770 1771 EXPECT_EQ(100, ReadData(entry2, 0, 0, buf, 100)); 1772 EXPECT_EQ(100, WriteData(entry2, 0, 0, buf, 100, false)); 1773 EXPECT_EQ(100, WriteData(entry2, 1, 0, buf, 100, false)); 1774 1775 EXPECT_EQ(kBufSize, ReadData(entry3, 0, 0, buf, kBufSize)); 1776 EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf, kBufSize, false)); 1777 EXPECT_EQ(kBufSize, WriteData(entry3, 1, 0, buf, kBufSize, false)); 1778 1779 std::string key = entry2->GetKey(); 1780 EXPECT_EQ(sizeof(key2) - 1, key.size()); 1781 key = entry3->GetKey(); 1782 EXPECT_EQ(sizeof(key3) - 1, key.size()); 1783 1784 entry1->Close(); 1785 entry2->Close(); 1786 entry3->Close(); 1787 FlushQueueForTest(); // Flushing the Close posts a task to restart the cache. 1788 FlushQueueForTest(); // This one actually allows that task to complete. 1789 1790 EXPECT_EQ(0, cache_->GetEntryCount()); 1791} 1792 1793TEST_F(DiskCacheBackendTest, DisableSuccess4) { 1794 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1795 DisableFirstCleanup(); 1796 SetDirectMode(); 1797 InitCache(); 1798 BackendDisable4(); 1799} 1800 1801TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess4) { 1802 ASSERT_TRUE(CopyTestCache("bad_rankings")); 1803 DisableFirstCleanup(); 1804 SetDirectMode(); 1805 SetNewEviction(); 1806 InitCache(); 1807 BackendDisable4(); 1808} 1809 1810TEST_F(DiskCacheTest, Backend_UsageStats) { 1811 MessageLoopHelper helper; 1812 1813 FilePath path = GetCacheFilePath(); 1814 ASSERT_TRUE(DeleteCache(path)); 1815 scoped_ptr<disk_cache::BackendImpl> cache; 1816 cache.reset(new disk_cache::BackendImpl( 1817 path, base::MessageLoopProxy::CreateForCurrentThread(), 1818 NULL)); 1819 ASSERT_TRUE(NULL != cache.get()); 1820 cache->SetUnitTestMode(); 1821 ASSERT_EQ(net::OK, cache->SyncInit()); 1822 1823 // Wait for a callback that never comes... about 2 secs :). The message loop 1824 // has to run to allow invocation of the usage timer. 1825 helper.WaitUntilCacheIoFinished(1); 1826} 1827 1828void DiskCacheBackendTest::BackendDoomAll() { 1829 InitCache(); 1830 Time initial = Time::Now(); 1831 1832 disk_cache::Entry *entry1, *entry2; 1833 ASSERT_EQ(net::OK, CreateEntry("first", &entry1)); 1834 ASSERT_EQ(net::OK, CreateEntry("second", &entry2)); 1835 entry1->Close(); 1836 entry2->Close(); 1837 1838 ASSERT_EQ(net::OK, CreateEntry("third", &entry1)); 1839 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2)); 1840 1841 ASSERT_EQ(4, cache_->GetEntryCount()); 1842 EXPECT_EQ(net::OK, DoomAllEntries()); 1843 ASSERT_EQ(0, cache_->GetEntryCount()); 1844 1845 // We should stop posting tasks at some point (if we post any). 1846 MessageLoop::current()->RunAllPending(); 1847 1848 disk_cache::Entry *entry3, *entry4; 1849 ASSERT_EQ(net::OK, CreateEntry("third", &entry3)); 1850 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry4)); 1851 1852 EXPECT_EQ(net::OK, DoomAllEntries()); 1853 ASSERT_EQ(0, cache_->GetEntryCount()); 1854 1855 entry1->Close(); 1856 entry2->Close(); 1857 entry3->Doom(); // The entry should be already doomed, but this must work. 1858 entry3->Close(); 1859 entry4->Close(); 1860 1861 // Now try with all references released. 1862 ASSERT_EQ(net::OK, CreateEntry("third", &entry1)); 1863 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2)); 1864 entry1->Close(); 1865 entry2->Close(); 1866 1867 ASSERT_EQ(2, cache_->GetEntryCount()); 1868 EXPECT_EQ(net::OK, DoomAllEntries()); 1869 ASSERT_EQ(0, cache_->GetEntryCount()); 1870} 1871 1872TEST_F(DiskCacheBackendTest, DoomAll) { 1873 BackendDoomAll(); 1874} 1875 1876TEST_F(DiskCacheBackendTest, NewEvictionDoomAll) { 1877 SetNewEviction(); 1878 BackendDoomAll(); 1879} 1880 1881TEST_F(DiskCacheBackendTest, MemoryOnlyDoomAll) { 1882 SetMemoryOnlyMode(); 1883 BackendDoomAll(); 1884} 1885 1886TEST_F(DiskCacheBackendTest, AppCacheOnlyDoomAll) { 1887 SetCacheType(net::APP_CACHE); 1888 BackendDoomAll(); 1889} 1890 1891// If the index size changes when we doom the cache, we should not crash. 1892void DiskCacheBackendTest::BackendDoomAll2() { 1893 EXPECT_EQ(2, cache_->GetEntryCount()); 1894 EXPECT_EQ(net::OK, DoomAllEntries()); 1895 1896 disk_cache::Entry* entry; 1897 ASSERT_EQ(net::OK, CreateEntry("Something new", &entry)); 1898 entry->Close(); 1899 1900 EXPECT_EQ(1, cache_->GetEntryCount()); 1901} 1902 1903TEST_F(DiskCacheBackendTest, DoomAll2) { 1904 ASSERT_TRUE(CopyTestCache("bad_rankings2")); 1905 DisableFirstCleanup(); 1906 SetMaxSize(20 * 1024 * 1024); 1907 InitCache(); 1908 BackendDoomAll2(); 1909} 1910 1911TEST_F(DiskCacheBackendTest, NewEvictionDoomAll2) { 1912 ASSERT_TRUE(CopyTestCache("bad_rankings2")); 1913 DisableFirstCleanup(); 1914 SetMaxSize(20 * 1024 * 1024); 1915 SetNewEviction(); 1916 InitCache(); 1917 BackendDoomAll2(); 1918} 1919 1920// We should be able to create the same entry on multiple simultaneous instances 1921// of the cache. 1922TEST_F(DiskCacheTest, MultipleInstances) { 1923 ScopedTestCache store1; 1924 ScopedTestCache store2("cache_test2"); 1925 ScopedTestCache store3("cache_test3"); 1926 base::Thread cache_thread("CacheThread"); 1927 ASSERT_TRUE(cache_thread.StartWithOptions( 1928 base::Thread::Options(MessageLoop::TYPE_IO, 0))); 1929 TestCompletionCallback cb; 1930 1931 const int kNumberOfCaches = 2; 1932 disk_cache::Backend* cache[kNumberOfCaches]; 1933 1934 int rv = disk_cache::BackendImpl::CreateBackend( 1935 store1.path(), false, 0, net::DISK_CACHE, disk_cache::kNone, 1936 cache_thread.message_loop_proxy(), NULL, &cache[0], &cb); 1937 ASSERT_EQ(net::OK, cb.GetResult(rv)); 1938 rv = disk_cache::BackendImpl::CreateBackend( 1939 store2.path(), false, 0, net::MEDIA_CACHE, disk_cache::kNone, 1940 cache_thread.message_loop_proxy(), NULL, &cache[1], &cb); 1941 ASSERT_EQ(net::OK, cb.GetResult(rv)); 1942 1943 ASSERT_TRUE(cache[0] != NULL && cache[1] != NULL); 1944 1945 std::string key("the first key"); 1946 disk_cache::Entry* entry; 1947 for (int i = 0; i < kNumberOfCaches; i++) { 1948 rv = cache[i]->CreateEntry(key, &entry, &cb); 1949 ASSERT_EQ(net::OK, cb.GetResult(rv)); 1950 entry->Close(); 1951 } 1952 delete cache[0]; 1953 delete cache[1]; 1954} 1955 1956// Test the six regions of the curve that determines the max cache size. 1957TEST_F(DiskCacheTest, AutomaticMaxSize) { 1958 const int kDefaultSize = 80 * 1024 * 1024; 1959 int64 large_size = kDefaultSize; 1960 int64 largest_size = kint32max; 1961 1962 // Region 1: expected = available * 0.8 1963 EXPECT_EQ((kDefaultSize - 1) * 8 / 10, 1964 disk_cache::PreferedCacheSize(large_size - 1)); 1965 EXPECT_EQ(kDefaultSize * 8 / 10, 1966 disk_cache::PreferedCacheSize(large_size)); 1967 EXPECT_EQ(kDefaultSize - 1, 1968 disk_cache::PreferedCacheSize(large_size * 10 / 8 - 1)); 1969 1970 // Region 2: expected = default_size 1971 EXPECT_EQ(kDefaultSize, 1972 disk_cache::PreferedCacheSize(large_size * 10 / 8)); 1973 EXPECT_EQ(kDefaultSize, 1974 disk_cache::PreferedCacheSize(large_size * 10 - 1)); 1975 1976 // Region 3: expected = available * 0.1 1977 EXPECT_EQ(kDefaultSize, 1978 disk_cache::PreferedCacheSize(large_size * 10)); 1979 EXPECT_EQ((kDefaultSize * 25 - 1) / 10, 1980 disk_cache::PreferedCacheSize(large_size * 25 - 1)); 1981 1982 // Region 4: expected = default_size * 2.5 1983 EXPECT_EQ(kDefaultSize * 25 / 10, 1984 disk_cache::PreferedCacheSize(large_size * 25)); 1985 EXPECT_EQ(kDefaultSize * 25 / 10, 1986 disk_cache::PreferedCacheSize(large_size * 100 - 1)); 1987 EXPECT_EQ(kDefaultSize * 25 / 10, 1988 disk_cache::PreferedCacheSize(large_size * 100)); 1989 EXPECT_EQ(kDefaultSize * 25 / 10, 1990 disk_cache::PreferedCacheSize(large_size * 250 - 1)); 1991 1992 // Region 5: expected = available * 0.1 1993 EXPECT_EQ(kDefaultSize * 25 / 10, 1994 disk_cache::PreferedCacheSize(large_size * 250)); 1995 EXPECT_EQ(kint32max - 1, 1996 disk_cache::PreferedCacheSize(largest_size * 100 - 1)); 1997 1998 // Region 6: expected = kint32max 1999 EXPECT_EQ(kint32max, 2000 disk_cache::PreferedCacheSize(largest_size * 100)); 2001 EXPECT_EQ(kint32max, 2002 disk_cache::PreferedCacheSize(largest_size * 10000)); 2003} 2004 2005// Tests that we can "migrate" a running instance from one experiment group to 2006// another. 2007TEST_F(DiskCacheBackendTest, Histograms) { 2008 SetDirectMode(); 2009 InitCache(); 2010 disk_cache::BackendImpl* backend_ = cache_impl_; // Needed be the macro. 2011 2012 for (int i = 1; i < 3; i++) { 2013 CACHE_UMA(HOURS, "FillupTime", i, 28); 2014 } 2015} 2016 2017// Make sure that we keep the total memory used by the internal buffers under 2018// control. 2019TEST_F(DiskCacheBackendTest, TotalBuffersSize1) { 2020 SetDirectMode(); 2021 InitCache(); 2022 std::string key("the first key"); 2023 disk_cache::Entry* entry; 2024 ASSERT_EQ(net::OK, CreateEntry(key, &entry)); 2025 2026 const int kSize = 200; 2027 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); 2028 CacheTestFillBuffer(buffer->data(), kSize, true); 2029 2030 for (int i = 0; i < 10; i++) { 2031 SCOPED_TRACE(i); 2032 // Allocate 2MB for this entry. 2033 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, true)); 2034 EXPECT_EQ(kSize, WriteData(entry, 1, 0, buffer, kSize, true)); 2035 EXPECT_EQ(kSize, WriteData(entry, 0, 1024 * 1024, buffer, kSize, false)); 2036 EXPECT_EQ(kSize, WriteData(entry, 1, 1024 * 1024, buffer, kSize, false)); 2037 2038 // Delete one of the buffers and truncate the other. 2039 EXPECT_EQ(0, WriteData(entry, 0, 0, buffer, 0, true)); 2040 EXPECT_EQ(0, WriteData(entry, 1, 10, buffer, 0, true)); 2041 2042 // Delete the second buffer, writing 10 bytes to disk. 2043 entry->Close(); 2044 ASSERT_EQ(net::OK, OpenEntry(key, &entry)); 2045 } 2046 2047 entry->Close(); 2048 EXPECT_EQ(0, cache_impl_->GetTotalBuffersSize()); 2049} 2050 2051// This test assumes at least 150MB of system memory. 2052TEST_F(DiskCacheBackendTest, TotalBuffersSize2) { 2053 SetDirectMode(); 2054 InitCache(); 2055 2056 const int kOneMB = 1024 * 1024; 2057 EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB)); 2058 EXPECT_EQ(kOneMB, cache_impl_->GetTotalBuffersSize()); 2059 2060 EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB)); 2061 EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize()); 2062 2063 EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB)); 2064 EXPECT_EQ(kOneMB * 3, cache_impl_->GetTotalBuffersSize()); 2065 2066 cache_impl_->BufferDeleted(kOneMB); 2067 EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize()); 2068 2069 // Check the upper limit. 2070 EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, 30 * kOneMB)); 2071 2072 for (int i = 0; i < 30; i++) 2073 cache_impl_->IsAllocAllowed(0, kOneMB); // Ignore the result. 2074 2075 EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, kOneMB)); 2076} 2077 2078// Tests that sharing of external files works and we are able to delete the 2079// files when we need to. 2080TEST_F(DiskCacheBackendTest, FileSharing) { 2081 SetDirectMode(); 2082 InitCache(); 2083 2084 disk_cache::Addr address(0x80000001); 2085 ASSERT_TRUE(cache_impl_->CreateExternalFile(&address)); 2086 FilePath name = cache_impl_->GetFileName(address); 2087 2088 scoped_refptr<disk_cache::File> file(new disk_cache::File(false)); 2089 file->Init(name); 2090 2091#if defined(OS_WIN) 2092 DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; 2093 DWORD access = GENERIC_READ | GENERIC_WRITE; 2094 base::win::ScopedHandle file2(CreateFile( 2095 name.value().c_str(), access, sharing, NULL, OPEN_EXISTING, 0, NULL)); 2096 EXPECT_FALSE(file2.IsValid()); 2097 2098 sharing |= FILE_SHARE_DELETE; 2099 file2.Set(CreateFile(name.value().c_str(), access, sharing, NULL, 2100 OPEN_EXISTING, 0, NULL)); 2101 EXPECT_TRUE(file2.IsValid()); 2102#endif 2103 2104 EXPECT_TRUE(file_util::Delete(name, false)); 2105 2106 // We should be able to use the file. 2107 const int kSize = 200; 2108 char buffer1[kSize]; 2109 char buffer2[kSize]; 2110 memset(buffer1, 't', kSize); 2111 memset(buffer2, 0, kSize); 2112 EXPECT_TRUE(file->Write(buffer1, kSize, 0)); 2113 EXPECT_TRUE(file->Read(buffer2, kSize, 0)); 2114 EXPECT_EQ(0, memcmp(buffer1, buffer2, kSize)); 2115 2116 EXPECT_TRUE(disk_cache::DeleteCacheFile(name)); 2117} 2118