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.
8 #include "base/files/scoped_temp_dir.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"
26 namespace disk_cache
{
29 const base::Time kTestLastUsedTime
=
30 base::Time::UnixEpoch() + base::TimeDelta::FromDays(20);
31 const uint64 kTestEntrySize
= 789;
36 class EntryMetadataTest
: public testing::Test
{
38 EntryMetadata
NewEntryMetadataWithValues() {
39 return EntryMetadata(kTestLastUsedTime
, kTestEntrySize
);
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());
51 class MockSimpleIndexFile
: public SimpleIndexFile
,
52 public base::SupportsWeakPtr
<MockSimpleIndexFile
> {
55 : SimpleIndexFile(NULL
, NULL
, net::DISK_CACHE
, base::FilePath()),
57 load_index_entries_calls_(0),
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_
;
68 void WriteToDisk(const SimpleIndex::EntrySet
& entry_set
,
70 const base::TimeTicks
& start
,
71 bool app_on_background
,
72 const base::Closure
& callback
) override
{
74 disk_write_entry_set_
= entry_set
;
77 void GetAndResetDiskWriteEntrySet(SimpleIndex::EntrySet
* entry_set
) {
78 entry_set
->swap(disk_write_entry_set_
);
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_
; }
87 base::Closure load_callback_
;
88 SimpleIndexLoadResult
* load_result_
;
89 int load_index_entries_calls_
;
91 SimpleIndex::EntrySet disk_write_entry_set_
;
94 class SimpleIndexTest
: public testing::Test
, public SimpleIndexDelegate
{
97 : hashes_(base::Bind(&HashesInitializer
)),
98 doom_entries_calls_(0) {}
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
)));
105 void SetUp() override
{
106 scoped_ptr
<MockSimpleIndexFile
> index_file(new MockSimpleIndexFile());
107 index_file_
= index_file
->AsWeakPtr();
109 new SimpleIndex(NULL
, this, net::DISK_CACHE
, index_file
.Pass()));
111 index_
->Initialize(base::Time());
114 void WaitForTimeChange() {
115 const base::Time initial_time
= base::Time::Now();
117 base::PlatformThread::YieldCurrentThread();
118 } while (base::Time::Now() -
119 initial_time
< base::TimeDelta::FromSeconds(1));
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
),
128 last_doom_entry_hashes_
= *entry_hashes
;
129 ++doom_entries_calls_
;
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
)
137 *metadata
= it
->second
;
141 void InsertIntoIndexFileReturn(uint64 hash_key
,
142 base::Time last_used_time
,
144 index_file_
->load_result()->entries
.insert(std::make_pair(
145 hash_key
, EntryMetadata(last_used_time
, entry_size
)));
148 void ReturnIndexFile() {
149 index_file_
->load_result()->did_load
= true;
150 index_file_
->load_callback().Run();
153 // Non-const for timer manipulation.
154 SimpleIndex
* index() { return index_
.get(); }
155 const MockSimpleIndexFile
* index_file() const { return index_file_
.get(); }
157 const std::vector
<uint64
>& last_doom_entry_hashes() const {
158 return last_doom_entry_hashes_
;
160 int doom_entries_calls() const { return doom_entries_calls_
; }
163 const simple_util::ImmutableArray
<uint64
, 16> hashes_
;
164 scoped_ptr
<SimpleIndex
> index_
;
165 base::WeakPtr
<MockSimpleIndexFile
> index_file_
;
167 std::vector
<uint64
> last_doom_entry_hashes_
;
168 int doom_entries_calls_
;
171 TEST_F(EntryMetadataTest
, Basics
) {
172 EntryMetadata entry_metadata
;
173 EXPECT_EQ(base::Time(), entry_metadata
.GetLastUsedTime());
174 EXPECT_EQ(0U, entry_metadata
.GetEntrySize());
176 entry_metadata
= NewEntryMetadataWithValues();
177 CheckEntryMetadataValues(entry_metadata
);
179 const base::Time new_time
= base::Time::Now();
180 entry_metadata
.SetLastUsedTime(new_time
);
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());
188 TEST_F(EntryMetadataTest
, Serialize
) {
189 EntryMetadata entry_metadata
= NewEntryMetadataWithValues();
192 entry_metadata
.Serialize(&pickle
);
194 PickleIterator
it(pickle
);
195 EntryMetadata new_entry_metadata
;
196 new_entry_metadata
.Deserialize(&it
);
197 CheckEntryMetadataValues(new_entry_metadata
);
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_
);
210 scoped_ptr
<SimpleIndexLoadResult
> result(new SimpleIndexLoadResult());
211 result
->did_load
= true;
212 index()->MergeInitializingSet(result
.Pass());
214 EXPECT_EQ(9U, index()->cache_size_
);
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());
226 EXPECT_EQ(2U + 3U + 4U + 11U, index()->cache_size_
);
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());
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());
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());
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());
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
));
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
);
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());
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
));
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
));
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
));
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
));
316 TEST_F(SimpleIndexTest
, UpdateEntrySize
) {
317 base::Time
now(base::Time::Now());
319 index()->SetMaxSize(1000);
321 const uint64 kHash1
= hashes_
.at
<1>();
322 InsertIntoIndexFileReturn(kHash1
, now
- base::TimeDelta::FromDays(2), 475);
325 EntryMetadata metadata
;
326 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata
));
328 now
- base::TimeDelta::FromDays(2) - base::TimeDelta::FromSeconds(1),
329 metadata
.GetLastUsedTime());
331 now
- base::TimeDelta::FromDays(2) + base::TimeDelta::FromSeconds(1),
332 metadata
.GetLastUsedTime());
333 EXPECT_EQ(475U, metadata
.GetEntrySize());
335 index()->UpdateEntrySize(kHash1
, 600u);
336 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata
));
337 EXPECT_EQ(600U, metadata
.GetEntrySize());
338 EXPECT_EQ(1, index()->GetEntryCount());
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());
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());
369 InsertIntoIndexFileReturn(hashes_
.at
<1>(),
370 now
- base::TimeDelta::FromDays(2),
372 InsertIntoIndexFileReturn(hashes_
.at
<2>(),
373 now
- base::TimeDelta::FromDays(3),
378 EntryMetadata metadata
;
379 EXPECT_TRUE(GetEntryForTesting(hashes_
.at
<1>(), &metadata
));
381 now
- base::TimeDelta::FromDays(2) - base::TimeDelta::FromSeconds(1),
382 metadata
.GetLastUsedTime());
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
));
389 now
- base::TimeDelta::FromDays(3) - base::TimeDelta::FromSeconds(1),
390 metadata
.GetLastUsedTime());
392 now
- base::TimeDelta::FromDays(3) + base::TimeDelta::FromSeconds(1),
393 metadata
.GetLastUsedTime());
394 EXPECT_EQ(100U, metadata
.GetEntrySize());
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
);
402 InsertIntoIndexFileReturn(kHash1
,
403 base::Time::Now() - base::TimeDelta::FromDays(2),
407 EXPECT_FALSE(index()->Has(kHash1
));
410 // Insert something that's going to come in from the loaded index; correct
412 TEST_F(SimpleIndexTest
, InsertBeforeInit
) {
413 const uint64 kHash1
= hashes_
.at
<1>();
414 index()->Insert(kHash1
);
416 InsertIntoIndexFileReturn(kHash1
,
417 base::Time::Now() - base::TimeDelta::FromDays(2),
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());
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
);
435 InsertIntoIndexFileReturn(kHash1
,
436 base::Time::Now() - base::TimeDelta::FromDays(2),
440 EXPECT_FALSE(index()->Has(kHash1
));
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
);
449 InsertIntoIndexFileReturn(kHash1
,
450 base::Time::Now() - base::TimeDelta::FromDays(2),
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());
462 // Do all above tests at once + a non-conflict to test for cross-key
464 TEST_F(SimpleIndexTest
, AllInitConflicts
) {
465 base::Time
now(base::Time::Now());
467 index()->Remove(hashes_
.at
<1>());
468 InsertIntoIndexFileReturn(hashes_
.at
<1>(),
469 now
- base::TimeDelta::FromDays(2),
471 index()->Insert(hashes_
.at
<2>());
472 InsertIntoIndexFileReturn(hashes_
.at
<2>(),
473 now
- base::TimeDelta::FromDays(3),
475 index()->Insert(hashes_
.at
<3>());
476 index()->Remove(hashes_
.at
<3>());
477 InsertIntoIndexFileReturn(hashes_
.at
<3>(),
478 now
- base::TimeDelta::FromDays(4),
480 index()->Remove(hashes_
.at
<4>());
481 index()->Insert(hashes_
.at
<4>());
482 InsertIntoIndexFileReturn(hashes_
.at
<4>(),
483 now
- base::TimeDelta::FromDays(5),
485 InsertIntoIndexFileReturn(hashes_
.at
<5>(),
486 now
- base::TimeDelta::FromDays(6),
491 EXPECT_FALSE(index()->Has(hashes_
.at
<1>()));
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());
499 EXPECT_FALSE(index()->Has(hashes_
.at
<3>()));
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());
506 EXPECT_TRUE(GetEntryForTesting(hashes_
.at
<5>(), &metadata
));
509 now
- base::TimeDelta::FromDays(6) + base::TimeDelta::FromSeconds(1),
510 metadata
.GetLastUsedTime());
512 now
- base::TimeDelta::FromDays(6) - base::TimeDelta::FromSeconds(1),
513 metadata
.GetLastUsedTime());
515 EXPECT_EQ(100000U, metadata
.GetEntrySize());
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),
524 index()->Insert(hashes_
.at
<2>());
525 index()->UpdateEntrySize(hashes_
.at
<2>(), 475);
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>()));
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
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());
551 // Confirm all the operations queue a disk write at some point in the
553 TEST_F(SimpleIndexTest
, DiskWriteQueued
) {
554 index()->SetMaxSize(1000);
557 EXPECT_FALSE(index()->write_to_disk_timer_
.IsRunning());
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());
565 index()->UseIfExists(kHash1
);
566 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
567 index()->write_to_disk_timer_
.Stop();
569 index()->UpdateEntrySize(kHash1
, 20);
570 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
571 index()->write_to_disk_timer_
.Stop();
573 index()->Remove(kHash1
);
574 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
575 index()->write_to_disk_timer_
.Stop();
578 TEST_F(SimpleIndexTest
, DiskWriteExecuted
) {
579 index()->SetMaxSize(1000);
582 EXPECT_FALSE(index()->write_to_disk_timer_
.IsRunning());
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();
591 EXPECT_EQ(0, index_file_
->disk_writes());
593 EXPECT_EQ(1, index_file_
->disk_writes());
594 SimpleIndex::EntrySet entry_set
;
595 index_file_
->GetAndResetDiskWriteEntrySet(&entry_set
);
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());
607 TEST_F(SimpleIndexTest
, DiskWritePostponed
) {
608 index()->SetMaxSize(1000);
611 EXPECT_FALSE(index()->write_to_disk_timer_
.IsRunning());
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());
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();
628 } // namespace disk_cache