Home | History | Annotate | Download | only in simple
      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/file_util.h"
      6 #include "base/files/scoped_temp_dir.h"
      7 #include "base/hash.h"
      8 #include "base/logging.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/message_loop/message_loop_proxy.h"
     11 #include "base/pickle.h"
     12 #include "base/run_loop.h"
     13 #include "base/strings/stringprintf.h"
     14 #include "base/time/time.h"
     15 #include "net/disk_cache/simple/simple_entry_format.h"
     16 #include "net/disk_cache/simple/simple_index.h"
     17 #include "net/disk_cache/simple/simple_index_file.h"
     18 #include "net/disk_cache/simple/simple_util.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 using base::Time;
     22 using disk_cache::SimpleIndexFile;
     23 using disk_cache::SimpleIndex;
     24 
     25 namespace disk_cache {
     26 
     27 TEST(IndexMetadataTest, Basics) {
     28   SimpleIndexFile::IndexMetadata index_metadata;
     29 
     30   EXPECT_EQ(disk_cache::kSimpleIndexMagicNumber, index_metadata.magic_number_);
     31   EXPECT_EQ(disk_cache::kSimpleVersion, index_metadata.version_);
     32   EXPECT_EQ(0U, index_metadata.GetNumberOfEntries());
     33   EXPECT_EQ(0U, index_metadata.cache_size_);
     34 
     35   EXPECT_TRUE(index_metadata.CheckIndexMetadata());
     36 }
     37 
     38 TEST(IndexMetadataTest, Serialize) {
     39   SimpleIndexFile::IndexMetadata index_metadata(123, 456);
     40   Pickle pickle;
     41   index_metadata.Serialize(&pickle);
     42   PickleIterator it(pickle);
     43   SimpleIndexFile::IndexMetadata new_index_metadata;
     44   new_index_metadata.Deserialize(&it);
     45 
     46   EXPECT_EQ(new_index_metadata.magic_number_, index_metadata.magic_number_);
     47   EXPECT_EQ(new_index_metadata.version_, index_metadata.version_);
     48   EXPECT_EQ(new_index_metadata.GetNumberOfEntries(),
     49             index_metadata.GetNumberOfEntries());
     50   EXPECT_EQ(new_index_metadata.cache_size_, index_metadata.cache_size_);
     51 
     52   EXPECT_TRUE(new_index_metadata.CheckIndexMetadata());
     53 }
     54 
     55 // This friend derived class is able to reexport its ancestors private methods
     56 // as public, for use in tests.
     57 class WrappedSimpleIndexFile : public SimpleIndexFile {
     58  public:
     59   using SimpleIndexFile::Deserialize;
     60   using SimpleIndexFile::IsIndexFileStale;
     61   using SimpleIndexFile::Serialize;
     62 
     63   explicit WrappedSimpleIndexFile(const base::FilePath& index_file_directory)
     64       : SimpleIndexFile(base::MessageLoopProxy::current().get(),
     65                         base::MessageLoopProxy::current().get(),
     66                         index_file_directory) {}
     67   virtual ~WrappedSimpleIndexFile() {
     68   }
     69 
     70   const base::FilePath& GetIndexFilePath() const {
     71     return index_file_;
     72   }
     73 };
     74 
     75 class SimpleIndexFileTest : public testing::Test {
     76  public:
     77   bool CompareTwoEntryMetadata(const EntryMetadata& a, const EntryMetadata& b) {
     78     return a.last_used_time_ == b.last_used_time_ &&
     79            a.entry_size_ == b.entry_size_;
     80   }
     81 
     82  protected:
     83   SimpleIndexFileTest() : callback_called_(false) {}
     84 
     85   base::Closure GetCallback() {
     86     return base::Bind(&SimpleIndexFileTest::LoadIndexEntriesCallback,
     87                       base::Unretained(this));
     88   }
     89 
     90   bool callback_called() { return callback_called_; }
     91 
     92  private:
     93   void LoadIndexEntriesCallback() {
     94     EXPECT_FALSE(callback_called_);
     95     callback_called_ = true;
     96   }
     97 
     98   bool callback_called_;
     99 };
    100 
    101 TEST_F(SimpleIndexFileTest, Serialize) {
    102   SimpleIndex::EntrySet entries;
    103   static const uint64 kHashes[] = { 11, 22, 33 };
    104   static const size_t kNumHashes = arraysize(kHashes);
    105   EntryMetadata metadata_entries[kNumHashes];
    106 
    107   SimpleIndexFile::IndexMetadata index_metadata(static_cast<uint64>(kNumHashes),
    108                                                 456);
    109   for (size_t i = 0; i < kNumHashes; ++i) {
    110     uint64 hash = kHashes[i];
    111     metadata_entries[i] =
    112         EntryMetadata(Time::FromInternalValue(hash), hash);
    113     SimpleIndex::InsertInEntrySet(hash, metadata_entries[i], &entries);
    114   }
    115 
    116   scoped_ptr<Pickle> pickle = WrappedSimpleIndexFile::Serialize(
    117       index_metadata, entries);
    118   EXPECT_TRUE(pickle.get() != NULL);
    119 
    120   SimpleIndexLoadResult deserialize_result;
    121   WrappedSimpleIndexFile::Deserialize(static_cast<const char*>(pickle->data()),
    122                                      pickle->size(),
    123                                      &deserialize_result);
    124   EXPECT_TRUE(deserialize_result.did_load);
    125   const SimpleIndex::EntrySet& new_entries = deserialize_result.entries;
    126   EXPECT_EQ(entries.size(), new_entries.size());
    127 
    128   for (size_t i = 0; i < kNumHashes; ++i) {
    129     SimpleIndex::EntrySet::const_iterator it = new_entries.find(kHashes[i]);
    130     EXPECT_TRUE(new_entries.end() != it);
    131     EXPECT_TRUE(CompareTwoEntryMetadata(it->second, metadata_entries[i]));
    132   }
    133 }
    134 
    135 TEST_F(SimpleIndexFileTest, IsIndexFileStale) {
    136   base::ScopedTempDir cache_dir;
    137   ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
    138   base::Time cache_mtime;
    139   const base::FilePath cache_path = cache_dir.path();
    140 
    141   ASSERT_TRUE(simple_util::GetMTime(cache_path, &cache_mtime));
    142   WrappedSimpleIndexFile simple_index_file(cache_path);
    143   const base::FilePath& index_path = simple_index_file.GetIndexFilePath();
    144   EXPECT_TRUE(WrappedSimpleIndexFile::IsIndexFileStale(cache_mtime,
    145                                                        index_path));
    146   const std::string kDummyData = "nothing to be seen here";
    147   EXPECT_EQ(static_cast<int>(kDummyData.size()),
    148             file_util::WriteFile(index_path,
    149                                  kDummyData.data(),
    150                                  kDummyData.size()));
    151   ASSERT_TRUE(simple_util::GetMTime(cache_path, &cache_mtime));
    152   EXPECT_FALSE(WrappedSimpleIndexFile::IsIndexFileStale(cache_mtime,
    153                                                         index_path));
    154 
    155   const base::Time past_time = base::Time::Now() -
    156       base::TimeDelta::FromSeconds(10);
    157   EXPECT_TRUE(file_util::TouchFile(index_path, past_time, past_time));
    158   EXPECT_TRUE(file_util::TouchFile(cache_path, past_time, past_time));
    159   ASSERT_TRUE(simple_util::GetMTime(cache_path, &cache_mtime));
    160   EXPECT_FALSE(WrappedSimpleIndexFile::IsIndexFileStale(cache_mtime,
    161                                                         index_path));
    162   const base::Time even_older =
    163       past_time - base::TimeDelta::FromSeconds(10);
    164   EXPECT_TRUE(file_util::TouchFile(index_path, even_older, even_older));
    165   EXPECT_TRUE(WrappedSimpleIndexFile::IsIndexFileStale(cache_mtime,
    166                                                        index_path));
    167 
    168 }
    169 
    170 TEST_F(SimpleIndexFileTest, WriteThenLoadIndex) {
    171   base::ScopedTempDir cache_dir;
    172   ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
    173 
    174   SimpleIndex::EntrySet entries;
    175   static const uint64 kHashes[] = { 11, 22, 33 };
    176   static const size_t kNumHashes = arraysize(kHashes);
    177   EntryMetadata metadata_entries[kNumHashes];
    178   for (size_t i = 0; i < kNumHashes; ++i) {
    179     uint64 hash = kHashes[i];
    180     metadata_entries[i] =
    181         EntryMetadata(Time::FromInternalValue(hash), hash);
    182     SimpleIndex::InsertInEntrySet(hash, metadata_entries[i], &entries);
    183   }
    184 
    185   const uint64 kCacheSize = 456U;
    186   {
    187     WrappedSimpleIndexFile simple_index_file(cache_dir.path());
    188     simple_index_file.WriteToDisk(entries, kCacheSize,
    189                                   base::TimeTicks(), false);
    190     base::RunLoop().RunUntilIdle();
    191     EXPECT_TRUE(base::PathExists(simple_index_file.GetIndexFilePath()));
    192   }
    193 
    194   WrappedSimpleIndexFile simple_index_file(cache_dir.path());
    195   base::Time fake_cache_mtime;
    196   ASSERT_TRUE(simple_util::GetMTime(simple_index_file.GetIndexFilePath(),
    197                                     &fake_cache_mtime));
    198   SimpleIndexLoadResult load_index_result;
    199   simple_index_file.LoadIndexEntries(fake_cache_mtime,
    200                                      GetCallback(),
    201                                      &load_index_result);
    202   base::RunLoop().RunUntilIdle();
    203 
    204   EXPECT_TRUE(base::PathExists(simple_index_file.GetIndexFilePath()));
    205   ASSERT_TRUE(callback_called());
    206   EXPECT_TRUE(load_index_result.did_load);
    207   EXPECT_FALSE(load_index_result.flush_required);
    208 
    209   EXPECT_EQ(kNumHashes, load_index_result.entries.size());
    210   for (size_t i = 0; i < kNumHashes; ++i)
    211     EXPECT_EQ(1U, load_index_result.entries.count(kHashes[i]));
    212 }
    213 
    214 TEST_F(SimpleIndexFileTest, LoadCorruptIndex) {
    215   base::ScopedTempDir cache_dir;
    216   ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
    217 
    218   WrappedSimpleIndexFile simple_index_file(cache_dir.path());
    219   const base::FilePath& index_path = simple_index_file.GetIndexFilePath();
    220   const std::string kDummyData = "nothing to be seen here";
    221   EXPECT_EQ(static_cast<int>(kDummyData.size()),
    222             file_util::WriteFile(index_path,
    223                                  kDummyData.data(),
    224                                  kDummyData.size()));
    225   base::Time fake_cache_mtime;
    226   ASSERT_TRUE(simple_util::GetMTime(simple_index_file.GetIndexFilePath(),
    227                                     &fake_cache_mtime));
    228   EXPECT_FALSE(WrappedSimpleIndexFile::IsIndexFileStale(fake_cache_mtime,
    229                                                         index_path));
    230 
    231   SimpleIndexLoadResult load_index_result;
    232   simple_index_file.LoadIndexEntries(fake_cache_mtime,
    233                                      GetCallback(),
    234                                      &load_index_result);
    235   base::RunLoop().RunUntilIdle();
    236 
    237   EXPECT_FALSE(base::PathExists(index_path));
    238   ASSERT_TRUE(callback_called());
    239   EXPECT_TRUE(load_index_result.did_load);
    240   EXPECT_TRUE(load_index_result.flush_required);
    241 }
    242 
    243 }  // namespace disk_cache
    244