| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013 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 <algorithm> | |
| 6 #include <functional> | |
| 7 | |
| 8 #include "base/files/scoped_temp_dir.h" | |
| 9 #include "base/hash.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "base/memory/scoped_ptr.h" | |
| 12 #include "base/pickle.h" | |
| 13 #include "base/sha1.h" | |
| 14 #include "base/strings/stringprintf.h" | |
| 15 #include "base/task_runner.h" | |
| 16 #include "base/threading/platform_thread.h" | |
| 17 #include "base/time/time.h" | |
| 18 #include "net/base/cache_type.h" | |
| 19 #include "net/disk_cache/simple/simple_index.h" | |
| 20 #include "net/disk_cache/simple/simple_index_delegate.h" | |
| 21 #include "net/disk_cache/simple/simple_index_file.h" | |
| 22 #include "net/disk_cache/simple/simple_test_util.h" | |
| 23 #include "net/disk_cache/simple/simple_util.h" | |
| 24 #include "testing/gtest/include/gtest/gtest.h" | |
| 25 | |
| 26 namespace disk_cache { | |
| 27 namespace { | |
| 28 | |
| 29 const base::Time kTestLastUsedTime = | |
| 30 base::Time::UnixEpoch() + base::TimeDelta::FromDays(20); | |
| 31 const uint64 kTestEntrySize = 789; | |
| 32 | |
| 33 } // namespace | |
| 34 | |
| 35 | |
| 36 class EntryMetadataTest : public testing::Test { | |
| 37 public: | |
| 38 EntryMetadata NewEntryMetadataWithValues() { | |
| 39 return EntryMetadata(kTestLastUsedTime, kTestEntrySize); | |
| 40 } | |
| 41 | |
| 42 void CheckEntryMetadataValues(const EntryMetadata& entry_metadata) { | |
| 43 EXPECT_LT(kTestLastUsedTime - base::TimeDelta::FromSeconds(2), | |
| 44 entry_metadata.GetLastUsedTime()); | |
| 45 EXPECT_GT(kTestLastUsedTime + base::TimeDelta::FromSeconds(2), | |
| 46 entry_metadata.GetLastUsedTime()); | |
| 47 EXPECT_EQ(kTestEntrySize, entry_metadata.GetEntrySize()); | |
| 48 } | |
| 49 }; | |
| 50 | |
| 51 class MockSimpleIndexFile : public SimpleIndexFile, | |
| 52 public base::SupportsWeakPtr<MockSimpleIndexFile> { | |
| 53 public: | |
| 54 MockSimpleIndexFile() | |
| 55 : SimpleIndexFile(NULL, NULL, net::DISK_CACHE, base::FilePath()), | |
| 56 load_result_(NULL), | |
| 57 load_index_entries_calls_(0), | |
| 58 disk_writes_(0) {} | |
| 59 | |
| 60 void LoadIndexEntries(base::Time cache_last_modified, | |
| 61 const base::Closure& callback, | |
| 62 SimpleIndexLoadResult* out_load_result) override { | |
| 63 load_callback_ = callback; | |
| 64 load_result_ = out_load_result; | |
| 65 ++load_index_entries_calls_; | |
| 66 } | |
| 67 | |
| 68 void WriteToDisk(const SimpleIndex::EntrySet& entry_set, | |
| 69 uint64 cache_size, | |
| 70 const base::TimeTicks& start, | |
| 71 bool app_on_background, | |
| 72 const base::Closure& callback) override { | |
| 73 disk_writes_++; | |
| 74 disk_write_entry_set_ = entry_set; | |
| 75 } | |
| 76 | |
| 77 void GetAndResetDiskWriteEntrySet(SimpleIndex::EntrySet* entry_set) { | |
| 78 entry_set->swap(disk_write_entry_set_); | |
| 79 } | |
| 80 | |
| 81 const base::Closure& load_callback() const { return load_callback_; } | |
| 82 SimpleIndexLoadResult* load_result() const { return load_result_; } | |
| 83 int load_index_entries_calls() const { return load_index_entries_calls_; } | |
| 84 int disk_writes() const { return disk_writes_; } | |
| 85 | |
| 86 private: | |
| 87 base::Closure load_callback_; | |
| 88 SimpleIndexLoadResult* load_result_; | |
| 89 int load_index_entries_calls_; | |
| 90 int disk_writes_; | |
| 91 SimpleIndex::EntrySet disk_write_entry_set_; | |
| 92 }; | |
| 93 | |
| 94 class SimpleIndexTest : public testing::Test, public SimpleIndexDelegate { | |
| 95 protected: | |
| 96 SimpleIndexTest() | |
| 97 : hashes_(base::Bind(&HashesInitializer)), | |
| 98 doom_entries_calls_(0) {} | |
| 99 | |
| 100 static uint64 HashesInitializer(size_t hash_index) { | |
| 101 return disk_cache::simple_util::GetEntryHashKey( | |
| 102 base::StringPrintf("key%d", static_cast<int>(hash_index))); | |
| 103 } | |
| 104 | |
| 105 void SetUp() override { | |
| 106 scoped_ptr<MockSimpleIndexFile> index_file(new MockSimpleIndexFile()); | |
| 107 index_file_ = index_file->AsWeakPtr(); | |
| 108 index_.reset( | |
| 109 new SimpleIndex(NULL, this, net::DISK_CACHE, index_file.Pass())); | |
| 110 | |
| 111 index_->Initialize(base::Time()); | |
| 112 } | |
| 113 | |
| 114 void WaitForTimeChange() { | |
| 115 const base::Time initial_time = base::Time::Now(); | |
| 116 do { | |
| 117 base::PlatformThread::YieldCurrentThread(); | |
| 118 } while (base::Time::Now() - | |
| 119 initial_time < base::TimeDelta::FromSeconds(1)); | |
| 120 } | |
| 121 | |
| 122 // From SimpleIndexDelegate: | |
| 123 void DoomEntries(std::vector<uint64>* entry_hashes, | |
| 124 const net::CompletionCallback& callback) override { | |
| 125 std::for_each(entry_hashes->begin(), entry_hashes->end(), | |
| 126 std::bind1st(std::mem_fun(&SimpleIndex::Remove), | |
| 127 index_.get())); | |
| 128 last_doom_entry_hashes_ = *entry_hashes; | |
| 129 ++doom_entries_calls_; | |
| 130 } | |
| 131 | |
| 132 // Redirect to allow single "friend" declaration in base class. | |
| 133 bool GetEntryForTesting(uint64 key, EntryMetadata* metadata) { | |
| 134 SimpleIndex::EntrySet::iterator it = index_->entries_set_.find(key); | |
| 135 if (index_->entries_set_.end() == it) | |
| 136 return false; | |
| 137 *metadata = it->second; | |
| 138 return true; | |
| 139 } | |
| 140 | |
| 141 void InsertIntoIndexFileReturn(uint64 hash_key, | |
| 142 base::Time last_used_time, | |
| 143 int entry_size) { | |
| 144 index_file_->load_result()->entries.insert(std::make_pair( | |
| 145 hash_key, EntryMetadata(last_used_time, entry_size))); | |
| 146 } | |
| 147 | |
| 148 void ReturnIndexFile() { | |
| 149 index_file_->load_result()->did_load = true; | |
| 150 index_file_->load_callback().Run(); | |
| 151 } | |
| 152 | |
| 153 // Non-const for timer manipulation. | |
| 154 SimpleIndex* index() { return index_.get(); } | |
| 155 const MockSimpleIndexFile* index_file() const { return index_file_.get(); } | |
| 156 | |
| 157 const std::vector<uint64>& last_doom_entry_hashes() const { | |
| 158 return last_doom_entry_hashes_; | |
| 159 } | |
| 160 int doom_entries_calls() const { return doom_entries_calls_; } | |
| 161 | |
| 162 | |
| 163 const simple_util::ImmutableArray<uint64, 16> hashes_; | |
| 164 scoped_ptr<SimpleIndex> index_; | |
| 165 base::WeakPtr<MockSimpleIndexFile> index_file_; | |
| 166 | |
| 167 std::vector<uint64> last_doom_entry_hashes_; | |
| 168 int doom_entries_calls_; | |
| 169 }; | |
| 170 | |
| 171 TEST_F(EntryMetadataTest, Basics) { | |
| 172 EntryMetadata entry_metadata; | |
| 173 EXPECT_EQ(base::Time(), entry_metadata.GetLastUsedTime()); | |
| 174 EXPECT_EQ(0U, entry_metadata.GetEntrySize()); | |
| 175 | |
| 176 entry_metadata = NewEntryMetadataWithValues(); | |
| 177 CheckEntryMetadataValues(entry_metadata); | |
| 178 | |
| 179 const base::Time new_time = base::Time::Now(); | |
| 180 entry_metadata.SetLastUsedTime(new_time); | |
| 181 | |
| 182 EXPECT_LT(new_time - base::TimeDelta::FromSeconds(2), | |
| 183 entry_metadata.GetLastUsedTime()); | |
| 184 EXPECT_GT(new_time + base::TimeDelta::FromSeconds(2), | |
| 185 entry_metadata.GetLastUsedTime()); | |
| 186 } | |
| 187 | |
| 188 TEST_F(EntryMetadataTest, Serialize) { | |
| 189 EntryMetadata entry_metadata = NewEntryMetadataWithValues(); | |
| 190 | |
| 191 Pickle pickle; | |
| 192 entry_metadata.Serialize(&pickle); | |
| 193 | |
| 194 PickleIterator it(pickle); | |
| 195 EntryMetadata new_entry_metadata; | |
| 196 new_entry_metadata.Deserialize(&it); | |
| 197 CheckEntryMetadataValues(new_entry_metadata); | |
| 198 } | |
| 199 | |
| 200 TEST_F(SimpleIndexTest, IndexSizeCorrectOnMerge) { | |
| 201 index()->SetMaxSize(100); | |
| 202 index()->Insert(hashes_.at<2>()); | |
| 203 index()->UpdateEntrySize(hashes_.at<2>(), 2); | |
| 204 index()->Insert(hashes_.at<3>()); | |
| 205 index()->UpdateEntrySize(hashes_.at<3>(), 3); | |
| 206 index()->Insert(hashes_.at<4>()); | |
| 207 index()->UpdateEntrySize(hashes_.at<4>(), 4); | |
| 208 EXPECT_EQ(9U, index()->cache_size_); | |
| 209 { | |
| 210 scoped_ptr<SimpleIndexLoadResult> result(new SimpleIndexLoadResult()); | |
| 211 result->did_load = true; | |
| 212 index()->MergeInitializingSet(result.Pass()); | |
| 213 } | |
| 214 EXPECT_EQ(9U, index()->cache_size_); | |
| 215 { | |
| 216 scoped_ptr<SimpleIndexLoadResult> result(new SimpleIndexLoadResult()); | |
| 217 result->did_load = true; | |
| 218 const uint64 new_hash_key = hashes_.at<11>(); | |
| 219 result->entries.insert( | |
| 220 std::make_pair(new_hash_key, EntryMetadata(base::Time::Now(), 11))); | |
| 221 const uint64 redundant_hash_key = hashes_.at<4>(); | |
| 222 result->entries.insert(std::make_pair(redundant_hash_key, | |
| 223 EntryMetadata(base::Time::Now(), 4))); | |
| 224 index()->MergeInitializingSet(result.Pass()); | |
| 225 } | |
| 226 EXPECT_EQ(2U + 3U + 4U + 11U, index()->cache_size_); | |
| 227 } | |
| 228 | |
| 229 // State of index changes as expected with an insert and a remove. | |
| 230 TEST_F(SimpleIndexTest, BasicInsertRemove) { | |
| 231 // Confirm blank state. | |
| 232 EntryMetadata metadata; | |
| 233 EXPECT_EQ(base::Time(), metadata.GetLastUsedTime()); | |
| 234 EXPECT_EQ(0U, metadata.GetEntrySize()); | |
| 235 | |
| 236 // Confirm state after insert. | |
| 237 index()->Insert(hashes_.at<1>()); | |
| 238 ASSERT_TRUE(GetEntryForTesting(hashes_.at<1>(), &metadata)); | |
| 239 base::Time now(base::Time::Now()); | |
| 240 EXPECT_LT(now - base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 241 EXPECT_GT(now + base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 242 EXPECT_EQ(0U, metadata.GetEntrySize()); | |
| 243 | |
| 244 // Confirm state after remove. | |
| 245 metadata = EntryMetadata(); | |
| 246 index()->Remove(hashes_.at<1>()); | |
| 247 EXPECT_FALSE(GetEntryForTesting(hashes_.at<1>(), &metadata)); | |
| 248 EXPECT_EQ(base::Time(), metadata.GetLastUsedTime()); | |
| 249 EXPECT_EQ(0U, metadata.GetEntrySize()); | |
| 250 } | |
| 251 | |
| 252 TEST_F(SimpleIndexTest, Has) { | |
| 253 // Confirm the base index has dispatched the request for index entries. | |
| 254 EXPECT_TRUE(index_file_.get()); | |
| 255 EXPECT_EQ(1, index_file_->load_index_entries_calls()); | |
| 256 | |
| 257 // Confirm "Has()" always returns true before the callback is called. | |
| 258 const uint64 kHash1 = hashes_.at<1>(); | |
| 259 EXPECT_TRUE(index()->Has(kHash1)); | |
| 260 index()->Insert(kHash1); | |
| 261 EXPECT_TRUE(index()->Has(kHash1)); | |
| 262 index()->Remove(kHash1); | |
| 263 // TODO(rdsmith): Maybe return false on explicitly removed entries? | |
| 264 EXPECT_TRUE(index()->Has(kHash1)); | |
| 265 | |
| 266 ReturnIndexFile(); | |
| 267 | |
| 268 // Confirm "Has() returns conditionally now. | |
| 269 EXPECT_FALSE(index()->Has(kHash1)); | |
| 270 index()->Insert(kHash1); | |
| 271 EXPECT_TRUE(index()->Has(kHash1)); | |
| 272 index()->Remove(kHash1); | |
| 273 } | |
| 274 | |
| 275 TEST_F(SimpleIndexTest, UseIfExists) { | |
| 276 // Confirm the base index has dispatched the request for index entries. | |
| 277 EXPECT_TRUE(index_file_.get()); | |
| 278 EXPECT_EQ(1, index_file_->load_index_entries_calls()); | |
| 279 | |
| 280 // Confirm "UseIfExists()" always returns true before the callback is called | |
| 281 // and updates mod time if the entry was really there. | |
| 282 const uint64 kHash1 = hashes_.at<1>(); | |
| 283 EntryMetadata metadata1, metadata2; | |
| 284 EXPECT_TRUE(index()->UseIfExists(kHash1)); | |
| 285 EXPECT_FALSE(GetEntryForTesting(kHash1, &metadata1)); | |
| 286 index()->Insert(kHash1); | |
| 287 EXPECT_TRUE(index()->UseIfExists(kHash1)); | |
| 288 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata1)); | |
| 289 WaitForTimeChange(); | |
| 290 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata2)); | |
| 291 EXPECT_EQ(metadata1.GetLastUsedTime(), metadata2.GetLastUsedTime()); | |
| 292 EXPECT_TRUE(index()->UseIfExists(kHash1)); | |
| 293 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata2)); | |
| 294 EXPECT_LT(metadata1.GetLastUsedTime(), metadata2.GetLastUsedTime()); | |
| 295 index()->Remove(kHash1); | |
| 296 EXPECT_TRUE(index()->UseIfExists(kHash1)); | |
| 297 | |
| 298 ReturnIndexFile(); | |
| 299 | |
| 300 // Confirm "UseIfExists() returns conditionally now | |
| 301 EXPECT_FALSE(index()->UseIfExists(kHash1)); | |
| 302 EXPECT_FALSE(GetEntryForTesting(kHash1, &metadata1)); | |
| 303 index()->Insert(kHash1); | |
| 304 EXPECT_TRUE(index()->UseIfExists(kHash1)); | |
| 305 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata1)); | |
| 306 WaitForTimeChange(); | |
| 307 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata2)); | |
| 308 EXPECT_EQ(metadata1.GetLastUsedTime(), metadata2.GetLastUsedTime()); | |
| 309 EXPECT_TRUE(index()->UseIfExists(kHash1)); | |
| 310 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata2)); | |
| 311 EXPECT_LT(metadata1.GetLastUsedTime(), metadata2.GetLastUsedTime()); | |
| 312 index()->Remove(kHash1); | |
| 313 EXPECT_FALSE(index()->UseIfExists(kHash1)); | |
| 314 } | |
| 315 | |
| 316 TEST_F(SimpleIndexTest, UpdateEntrySize) { | |
| 317 base::Time now(base::Time::Now()); | |
| 318 | |
| 319 index()->SetMaxSize(1000); | |
| 320 | |
| 321 const uint64 kHash1 = hashes_.at<1>(); | |
| 322 InsertIntoIndexFileReturn(kHash1, now - base::TimeDelta::FromDays(2), 475); | |
| 323 ReturnIndexFile(); | |
| 324 | |
| 325 EntryMetadata metadata; | |
| 326 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata)); | |
| 327 EXPECT_LT( | |
| 328 now - base::TimeDelta::FromDays(2) - base::TimeDelta::FromSeconds(1), | |
| 329 metadata.GetLastUsedTime()); | |
| 330 EXPECT_GT( | |
| 331 now - base::TimeDelta::FromDays(2) + base::TimeDelta::FromSeconds(1), | |
| 332 metadata.GetLastUsedTime()); | |
| 333 EXPECT_EQ(475U, metadata.GetEntrySize()); | |
| 334 | |
| 335 index()->UpdateEntrySize(kHash1, 600u); | |
| 336 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata)); | |
| 337 EXPECT_EQ(600U, metadata.GetEntrySize()); | |
| 338 EXPECT_EQ(1, index()->GetEntryCount()); | |
| 339 } | |
| 340 | |
| 341 TEST_F(SimpleIndexTest, GetEntryCount) { | |
| 342 EXPECT_EQ(0, index()->GetEntryCount()); | |
| 343 index()->Insert(hashes_.at<1>()); | |
| 344 EXPECT_EQ(1, index()->GetEntryCount()); | |
| 345 index()->Insert(hashes_.at<2>()); | |
| 346 EXPECT_EQ(2, index()->GetEntryCount()); | |
| 347 index()->Insert(hashes_.at<3>()); | |
| 348 EXPECT_EQ(3, index()->GetEntryCount()); | |
| 349 index()->Insert(hashes_.at<3>()); | |
| 350 EXPECT_EQ(3, index()->GetEntryCount()); | |
| 351 index()->Remove(hashes_.at<2>()); | |
| 352 EXPECT_EQ(2, index()->GetEntryCount()); | |
| 353 index()->Insert(hashes_.at<4>()); | |
| 354 EXPECT_EQ(3, index()->GetEntryCount()); | |
| 355 index()->Remove(hashes_.at<3>()); | |
| 356 EXPECT_EQ(2, index()->GetEntryCount()); | |
| 357 index()->Remove(hashes_.at<3>()); | |
| 358 EXPECT_EQ(2, index()->GetEntryCount()); | |
| 359 index()->Remove(hashes_.at<1>()); | |
| 360 EXPECT_EQ(1, index()->GetEntryCount()); | |
| 361 index()->Remove(hashes_.at<4>()); | |
| 362 EXPECT_EQ(0, index()->GetEntryCount()); | |
| 363 } | |
| 364 | |
| 365 // Confirm that we get the results we expect from a simple init. | |
| 366 TEST_F(SimpleIndexTest, BasicInit) { | |
| 367 base::Time now(base::Time::Now()); | |
| 368 | |
| 369 InsertIntoIndexFileReturn(hashes_.at<1>(), | |
| 370 now - base::TimeDelta::FromDays(2), | |
| 371 10u); | |
| 372 InsertIntoIndexFileReturn(hashes_.at<2>(), | |
| 373 now - base::TimeDelta::FromDays(3), | |
| 374 100u); | |
| 375 | |
| 376 ReturnIndexFile(); | |
| 377 | |
| 378 EntryMetadata metadata; | |
| 379 EXPECT_TRUE(GetEntryForTesting(hashes_.at<1>(), &metadata)); | |
| 380 EXPECT_LT( | |
| 381 now - base::TimeDelta::FromDays(2) - base::TimeDelta::FromSeconds(1), | |
| 382 metadata.GetLastUsedTime()); | |
| 383 EXPECT_GT( | |
| 384 now - base::TimeDelta::FromDays(2) + base::TimeDelta::FromSeconds(1), | |
| 385 metadata.GetLastUsedTime()); | |
| 386 EXPECT_EQ(10U, metadata.GetEntrySize()); | |
| 387 EXPECT_TRUE(GetEntryForTesting(hashes_.at<2>(), &metadata)); | |
| 388 EXPECT_LT( | |
| 389 now - base::TimeDelta::FromDays(3) - base::TimeDelta::FromSeconds(1), | |
| 390 metadata.GetLastUsedTime()); | |
| 391 EXPECT_GT( | |
| 392 now - base::TimeDelta::FromDays(3) + base::TimeDelta::FromSeconds(1), | |
| 393 metadata.GetLastUsedTime()); | |
| 394 EXPECT_EQ(100U, metadata.GetEntrySize()); | |
| 395 } | |
| 396 | |
| 397 // Remove something that's going to come in from the loaded index. | |
| 398 TEST_F(SimpleIndexTest, RemoveBeforeInit) { | |
| 399 const uint64 kHash1 = hashes_.at<1>(); | |
| 400 index()->Remove(kHash1); | |
| 401 | |
| 402 InsertIntoIndexFileReturn(kHash1, | |
| 403 base::Time::Now() - base::TimeDelta::FromDays(2), | |
| 404 10u); | |
| 405 ReturnIndexFile(); | |
| 406 | |
| 407 EXPECT_FALSE(index()->Has(kHash1)); | |
| 408 } | |
| 409 | |
| 410 // Insert something that's going to come in from the loaded index; correct | |
| 411 // result? | |
| 412 TEST_F(SimpleIndexTest, InsertBeforeInit) { | |
| 413 const uint64 kHash1 = hashes_.at<1>(); | |
| 414 index()->Insert(kHash1); | |
| 415 | |
| 416 InsertIntoIndexFileReturn(kHash1, | |
| 417 base::Time::Now() - base::TimeDelta::FromDays(2), | |
| 418 10u); | |
| 419 ReturnIndexFile(); | |
| 420 | |
| 421 EntryMetadata metadata; | |
| 422 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata)); | |
| 423 base::Time now(base::Time::Now()); | |
| 424 EXPECT_LT(now - base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 425 EXPECT_GT(now + base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 426 EXPECT_EQ(0U, metadata.GetEntrySize()); | |
| 427 } | |
| 428 | |
| 429 // Insert and Remove something that's going to come in from the loaded index. | |
| 430 TEST_F(SimpleIndexTest, InsertRemoveBeforeInit) { | |
| 431 const uint64 kHash1 = hashes_.at<1>(); | |
| 432 index()->Insert(kHash1); | |
| 433 index()->Remove(kHash1); | |
| 434 | |
| 435 InsertIntoIndexFileReturn(kHash1, | |
| 436 base::Time::Now() - base::TimeDelta::FromDays(2), | |
| 437 10u); | |
| 438 ReturnIndexFile(); | |
| 439 | |
| 440 EXPECT_FALSE(index()->Has(kHash1)); | |
| 441 } | |
| 442 | |
| 443 // Insert and Remove something that's going to come in from the loaded index. | |
| 444 TEST_F(SimpleIndexTest, RemoveInsertBeforeInit) { | |
| 445 const uint64 kHash1 = hashes_.at<1>(); | |
| 446 index()->Remove(kHash1); | |
| 447 index()->Insert(kHash1); | |
| 448 | |
| 449 InsertIntoIndexFileReturn(kHash1, | |
| 450 base::Time::Now() - base::TimeDelta::FromDays(2), | |
| 451 10u); | |
| 452 ReturnIndexFile(); | |
| 453 | |
| 454 EntryMetadata metadata; | |
| 455 EXPECT_TRUE(GetEntryForTesting(kHash1, &metadata)); | |
| 456 base::Time now(base::Time::Now()); | |
| 457 EXPECT_LT(now - base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 458 EXPECT_GT(now + base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 459 EXPECT_EQ(0U, metadata.GetEntrySize()); | |
| 460 } | |
| 461 | |
| 462 // Do all above tests at once + a non-conflict to test for cross-key | |
| 463 // interactions. | |
| 464 TEST_F(SimpleIndexTest, AllInitConflicts) { | |
| 465 base::Time now(base::Time::Now()); | |
| 466 | |
| 467 index()->Remove(hashes_.at<1>()); | |
| 468 InsertIntoIndexFileReturn(hashes_.at<1>(), | |
| 469 now - base::TimeDelta::FromDays(2), | |
| 470 10u); | |
| 471 index()->Insert(hashes_.at<2>()); | |
| 472 InsertIntoIndexFileReturn(hashes_.at<2>(), | |
| 473 now - base::TimeDelta::FromDays(3), | |
| 474 100u); | |
| 475 index()->Insert(hashes_.at<3>()); | |
| 476 index()->Remove(hashes_.at<3>()); | |
| 477 InsertIntoIndexFileReturn(hashes_.at<3>(), | |
| 478 now - base::TimeDelta::FromDays(4), | |
| 479 1000u); | |
| 480 index()->Remove(hashes_.at<4>()); | |
| 481 index()->Insert(hashes_.at<4>()); | |
| 482 InsertIntoIndexFileReturn(hashes_.at<4>(), | |
| 483 now - base::TimeDelta::FromDays(5), | |
| 484 10000u); | |
| 485 InsertIntoIndexFileReturn(hashes_.at<5>(), | |
| 486 now - base::TimeDelta::FromDays(6), | |
| 487 100000u); | |
| 488 | |
| 489 ReturnIndexFile(); | |
| 490 | |
| 491 EXPECT_FALSE(index()->Has(hashes_.at<1>())); | |
| 492 | |
| 493 EntryMetadata metadata; | |
| 494 EXPECT_TRUE(GetEntryForTesting(hashes_.at<2>(), &metadata)); | |
| 495 EXPECT_LT(now - base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 496 EXPECT_GT(now + base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 497 EXPECT_EQ(0U, metadata.GetEntrySize()); | |
| 498 | |
| 499 EXPECT_FALSE(index()->Has(hashes_.at<3>())); | |
| 500 | |
| 501 EXPECT_TRUE(GetEntryForTesting(hashes_.at<4>(), &metadata)); | |
| 502 EXPECT_LT(now - base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 503 EXPECT_GT(now + base::TimeDelta::FromMinutes(1), metadata.GetLastUsedTime()); | |
| 504 EXPECT_EQ(0U, metadata.GetEntrySize()); | |
| 505 | |
| 506 EXPECT_TRUE(GetEntryForTesting(hashes_.at<5>(), &metadata)); | |
| 507 | |
| 508 EXPECT_GT( | |
| 509 now - base::TimeDelta::FromDays(6) + base::TimeDelta::FromSeconds(1), | |
| 510 metadata.GetLastUsedTime()); | |
| 511 EXPECT_LT( | |
| 512 now - base::TimeDelta::FromDays(6) - base::TimeDelta::FromSeconds(1), | |
| 513 metadata.GetLastUsedTime()); | |
| 514 | |
| 515 EXPECT_EQ(100000U, metadata.GetEntrySize()); | |
| 516 } | |
| 517 | |
| 518 TEST_F(SimpleIndexTest, BasicEviction) { | |
| 519 base::Time now(base::Time::Now()); | |
| 520 index()->SetMaxSize(1000); | |
| 521 InsertIntoIndexFileReturn(hashes_.at<1>(), | |
| 522 now - base::TimeDelta::FromDays(2), | |
| 523 475u); | |
| 524 index()->Insert(hashes_.at<2>()); | |
| 525 index()->UpdateEntrySize(hashes_.at<2>(), 475); | |
| 526 ReturnIndexFile(); | |
| 527 | |
| 528 WaitForTimeChange(); | |
| 529 | |
| 530 index()->Insert(hashes_.at<3>()); | |
| 531 // Confirm index is as expected: No eviction, everything there. | |
| 532 EXPECT_EQ(3, index()->GetEntryCount()); | |
| 533 EXPECT_EQ(0, doom_entries_calls()); | |
| 534 EXPECT_TRUE(index()->Has(hashes_.at<1>())); | |
| 535 EXPECT_TRUE(index()->Has(hashes_.at<2>())); | |
| 536 EXPECT_TRUE(index()->Has(hashes_.at<3>())); | |
| 537 | |
| 538 // Trigger an eviction, and make sure the right things are tossed. | |
| 539 // TODO(rdsmith): This is dependent on the innards of the implementation | |
| 540 // as to at exactly what point we trigger eviction. Not sure how to fix | |
| 541 // that. | |
| 542 index()->UpdateEntrySize(hashes_.at<3>(), 475); | |
| 543 EXPECT_EQ(1, doom_entries_calls()); | |
| 544 EXPECT_EQ(1, index()->GetEntryCount()); | |
| 545 EXPECT_FALSE(index()->Has(hashes_.at<1>())); | |
| 546 EXPECT_FALSE(index()->Has(hashes_.at<2>())); | |
| 547 EXPECT_TRUE(index()->Has(hashes_.at<3>())); | |
| 548 ASSERT_EQ(2u, last_doom_entry_hashes().size()); | |
| 549 } | |
| 550 | |
| 551 // Confirm all the operations queue a disk write at some point in the | |
| 552 // future. | |
| 553 TEST_F(SimpleIndexTest, DiskWriteQueued) { | |
| 554 index()->SetMaxSize(1000); | |
| 555 ReturnIndexFile(); | |
| 556 | |
| 557 EXPECT_FALSE(index()->write_to_disk_timer_.IsRunning()); | |
| 558 | |
| 559 const uint64 kHash1 = hashes_.at<1>(); | |
| 560 index()->Insert(kHash1); | |
| 561 EXPECT_TRUE(index()->write_to_disk_timer_.IsRunning()); | |
| 562 index()->write_to_disk_timer_.Stop(); | |
| 563 EXPECT_FALSE(index()->write_to_disk_timer_.IsRunning()); | |
| 564 | |
| 565 index()->UseIfExists(kHash1); | |
| 566 EXPECT_TRUE(index()->write_to_disk_timer_.IsRunning()); | |
| 567 index()->write_to_disk_timer_.Stop(); | |
| 568 | |
| 569 index()->UpdateEntrySize(kHash1, 20); | |
| 570 EXPECT_TRUE(index()->write_to_disk_timer_.IsRunning()); | |
| 571 index()->write_to_disk_timer_.Stop(); | |
| 572 | |
| 573 index()->Remove(kHash1); | |
| 574 EXPECT_TRUE(index()->write_to_disk_timer_.IsRunning()); | |
| 575 index()->write_to_disk_timer_.Stop(); | |
| 576 } | |
| 577 | |
| 578 TEST_F(SimpleIndexTest, DiskWriteExecuted) { | |
| 579 index()->SetMaxSize(1000); | |
| 580 ReturnIndexFile(); | |
| 581 | |
| 582 EXPECT_FALSE(index()->write_to_disk_timer_.IsRunning()); | |
| 583 | |
| 584 const uint64 kHash1 = hashes_.at<1>(); | |
| 585 index()->Insert(kHash1); | |
| 586 index()->UpdateEntrySize(kHash1, 20); | |
| 587 EXPECT_TRUE(index()->write_to_disk_timer_.IsRunning()); | |
| 588 base::Closure user_task(index()->write_to_disk_timer_.user_task()); | |
| 589 index()->write_to_disk_timer_.Stop(); | |
| 590 | |
| 591 EXPECT_EQ(0, index_file_->disk_writes()); | |
| 592 user_task.Run(); | |
| 593 EXPECT_EQ(1, index_file_->disk_writes()); | |
| 594 SimpleIndex::EntrySet entry_set; | |
| 595 index_file_->GetAndResetDiskWriteEntrySet(&entry_set); | |
| 596 | |
| 597 uint64 hash_key = kHash1; | |
| 598 base::Time now(base::Time::Now()); | |
| 599 ASSERT_EQ(1u, entry_set.size()); | |
| 600 EXPECT_EQ(hash_key, entry_set.begin()->first); | |
| 601 const EntryMetadata& entry1(entry_set.begin()->second); | |
| 602 EXPECT_LT(now - base::TimeDelta::FromMinutes(1), entry1.GetLastUsedTime()); | |
| 603 EXPECT_GT(now + base::TimeDelta::FromMinutes(1), entry1.GetLastUsedTime()); | |
| 604 EXPECT_EQ(20U, entry1.GetEntrySize()); | |
| 605 } | |
| 606 | |
| 607 TEST_F(SimpleIndexTest, DiskWritePostponed) { | |
| 608 index()->SetMaxSize(1000); | |
| 609 ReturnIndexFile(); | |
| 610 | |
| 611 EXPECT_FALSE(index()->write_to_disk_timer_.IsRunning()); | |
| 612 | |
| 613 index()->Insert(hashes_.at<1>()); | |
| 614 index()->UpdateEntrySize(hashes_.at<1>(), 20); | |
| 615 EXPECT_TRUE(index()->write_to_disk_timer_.IsRunning()); | |
| 616 base::TimeTicks expected_trigger( | |
| 617 index()->write_to_disk_timer_.desired_run_time()); | |
| 618 | |
| 619 WaitForTimeChange(); | |
| 620 EXPECT_EQ(expected_trigger, index()->write_to_disk_timer_.desired_run_time()); | |
| 621 index()->Insert(hashes_.at<2>()); | |
| 622 index()->UpdateEntrySize(hashes_.at<2>(), 40); | |
| 623 EXPECT_TRUE(index()->write_to_disk_timer_.IsRunning()); | |
| 624 EXPECT_LT(expected_trigger, index()->write_to_disk_timer_.desired_run_time()); | |
| 625 index()->write_to_disk_timer_.Stop(); | |
| 626 } | |
| 627 | |
| 628 } // namespace disk_cache | |
| OLD | NEW |