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