Home | History | Annotate | Download | only in disk_cache
      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