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.
5 #include "base/file_util.h"
6 #include "base/files/scoped_temp_dir.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"
22 using disk_cache::SimpleIndexFile
;
23 using disk_cache::SimpleIndex
;
25 namespace disk_cache
{
27 TEST(IndexMetadataTest
, Basics
) {
28 SimpleIndexFile::IndexMetadata index_metadata
;
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_
);
35 EXPECT_TRUE(index_metadata
.CheckIndexMetadata());
38 TEST(IndexMetadataTest
, Serialize
) {
39 SimpleIndexFile::IndexMetadata
index_metadata(123, 456);
41 index_metadata
.Serialize(&pickle
);
42 PickleIterator
it(pickle
);
43 SimpleIndexFile::IndexMetadata new_index_metadata
;
44 new_index_metadata
.Deserialize(&it
);
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_
);
52 EXPECT_TRUE(new_index_metadata
.CheckIndexMetadata());
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
{
59 using SimpleIndexFile::Deserialize
;
60 using SimpleIndexFile::IsIndexFileStale
;
61 using SimpleIndexFile::Serialize
;
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() {
70 const base::FilePath
& GetIndexFilePath() const {
75 class SimpleIndexFileTest
: public testing::Test
{
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_
;
83 SimpleIndexFileTest() : callback_called_(false) {}
85 base::Closure
GetCallback() {
86 return base::Bind(&SimpleIndexFileTest::LoadIndexEntriesCallback
,
87 base::Unretained(this));
90 bool callback_called() { return callback_called_
; }
93 void LoadIndexEntriesCallback() {
94 EXPECT_FALSE(callback_called_
);
95 callback_called_
= true;
98 bool callback_called_
;
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
];
107 SimpleIndexFile::IndexMetadata
index_metadata(static_cast<uint64
>(kNumHashes
),
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
);
116 scoped_ptr
<Pickle
> pickle
= WrappedSimpleIndexFile::Serialize(
117 index_metadata
, entries
);
118 EXPECT_TRUE(pickle
.get() != NULL
);
120 SimpleIndexLoadResult deserialize_result
;
121 WrappedSimpleIndexFile::Deserialize(static_cast<const char*>(pickle
->data()),
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());
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
]));
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();
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
,
146 const std::string kDummyData
= "nothing to be seen here";
147 EXPECT_EQ(static_cast<int>(kDummyData
.size()),
148 file_util::WriteFile(index_path
,
151 ASSERT_TRUE(simple_util::GetMTime(cache_path
, &cache_mtime
));
152 EXPECT_FALSE(WrappedSimpleIndexFile::IsIndexFileStale(cache_mtime
,
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
,
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
,
170 TEST_F(SimpleIndexFileTest
, WriteThenLoadIndex
) {
171 base::ScopedTempDir cache_dir
;
172 ASSERT_TRUE(cache_dir
.CreateUniqueTempDir());
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
);
185 const uint64 kCacheSize
= 456U;
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()));
194 WrappedSimpleIndexFile
simple_index_file(cache_dir
.path());
195 base::Time fake_cache_mtime
;
196 ASSERT_TRUE(simple_util::GetMTime(simple_index_file
.GetIndexFilePath(),
198 SimpleIndexLoadResult load_index_result
;
199 simple_index_file
.LoadIndexEntries(fake_cache_mtime
,
202 base::RunLoop().RunUntilIdle();
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
);
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
]));
214 TEST_F(SimpleIndexFileTest
, LoadCorruptIndex
) {
215 base::ScopedTempDir cache_dir
;
216 ASSERT_TRUE(cache_dir
.CreateUniqueTempDir());
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
,
225 base::Time fake_cache_mtime
;
226 ASSERT_TRUE(simple_util::GetMTime(simple_index_file
.GetIndexFilePath(),
228 EXPECT_FALSE(WrappedSimpleIndexFile::IsIndexFileStale(fake_cache_mtime
,
231 SimpleIndexLoadResult load_index_result
;
232 simple_index_file
.LoadIndexEntries(fake_cache_mtime
,
235 base::RunLoop().RunUntilIdle();
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
);
243 } // namespace disk_cache