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 int 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
) override
{
73 disk_write_entry_set_
= entry_set
;
76 void GetAndResetDiskWriteEntrySet(SimpleIndex::EntrySet
* entry_set
) {
77 entry_set
->swap(disk_write_entry_set_
);
80 const base::Closure
& load_callback() const { return load_callback_
; }
81 SimpleIndexLoadResult
* load_result() const { return load_result_
; }
82 int load_index_entries_calls() const { return load_index_entries_calls_
; }
83 int disk_writes() const { return disk_writes_
; }
86 base::Closure load_callback_
;
87 SimpleIndexLoadResult
* load_result_
;
88 int load_index_entries_calls_
;
90 SimpleIndex::EntrySet disk_write_entry_set_
;
93 class SimpleIndexTest
: public testing::Test
, public SimpleIndexDelegate
{
96 : hashes_(base::Bind(&HashesInitializer
)),
97 doom_entries_calls_(0) {}
99 static uint64
HashesInitializer(size_t hash_index
) {
100 return disk_cache::simple_util::GetEntryHashKey(
101 base::StringPrintf("key%d", static_cast<int>(hash_index
)));
104 void SetUp() override
{
105 scoped_ptr
<MockSimpleIndexFile
> index_file(new MockSimpleIndexFile());
106 index_file_
= index_file
->AsWeakPtr();
108 new SimpleIndex(NULL
, this, net::DISK_CACHE
, index_file
.Pass()));
110 index_
->Initialize(base::Time());
113 void WaitForTimeChange() {
114 const base::Time initial_time
= base::Time::Now();
116 base::PlatformThread::YieldCurrentThread();
117 } while (base::Time::Now() -
118 initial_time
< base::TimeDelta::FromSeconds(1));
121 // From SimpleIndexDelegate:
122 void DoomEntries(std::vector
<uint64
>* entry_hashes
,
123 const net::CompletionCallback
& callback
) override
{
124 std::for_each(entry_hashes
->begin(), entry_hashes
->end(),
125 std::bind1st(std::mem_fun(&SimpleIndex::Remove
),
127 last_doom_entry_hashes_
= *entry_hashes
;
128 ++doom_entries_calls_
;
131 // Redirect to allow single "friend" declaration in base class.
132 bool GetEntryForTesting(uint64 key
, EntryMetadata
* metadata
) {
133 SimpleIndex::EntrySet::iterator it
= index_
->entries_set_
.find(key
);
134 if (index_
->entries_set_
.end() == it
)
136 *metadata
= it
->second
;
140 void InsertIntoIndexFileReturn(uint64 hash_key
,
141 base::Time last_used_time
,
143 index_file_
->load_result()->entries
.insert(std::make_pair(
144 hash_key
, EntryMetadata(last_used_time
, entry_size
)));
147 void ReturnIndexFile() {
148 index_file_
->load_result()->did_load
= true;
149 index_file_
->load_callback().Run();
152 // Non-const for timer manipulation.
153 SimpleIndex
* index() { return index_
.get(); }
154 const MockSimpleIndexFile
* index_file() const { return index_file_
.get(); }
156 const std::vector
<uint64
>& last_doom_entry_hashes() const {
157 return last_doom_entry_hashes_
;
159 int doom_entries_calls() const { return doom_entries_calls_
; }
162 const simple_util::ImmutableArray
<uint64
, 16> hashes_
;
163 scoped_ptr
<SimpleIndex
> index_
;
164 base::WeakPtr
<MockSimpleIndexFile
> index_file_
;
166 std::vector
<uint64
> last_doom_entry_hashes_
;
167 int doom_entries_calls_
;
170 TEST_F(EntryMetadataTest
, Basics
) {
171 EntryMetadata entry_metadata
;
172 EXPECT_EQ(base::Time(), entry_metadata
.GetLastUsedTime());
173 EXPECT_EQ(0, entry_metadata
.GetEntrySize());
175 entry_metadata
= NewEntryMetadataWithValues();
176 CheckEntryMetadataValues(entry_metadata
);
178 const base::Time new_time
= base::Time::Now();
179 entry_metadata
.SetLastUsedTime(new_time
);
181 EXPECT_LT(new_time
- base::TimeDelta::FromSeconds(2),
182 entry_metadata
.GetLastUsedTime());
183 EXPECT_GT(new_time
+ base::TimeDelta::FromSeconds(2),
184 entry_metadata
.GetLastUsedTime());
187 TEST_F(EntryMetadataTest
, Serialize
) {
188 EntryMetadata entry_metadata
= NewEntryMetadataWithValues();
191 entry_metadata
.Serialize(&pickle
);
193 PickleIterator
it(pickle
);
194 EntryMetadata new_entry_metadata
;
195 new_entry_metadata
.Deserialize(&it
);
196 CheckEntryMetadataValues(new_entry_metadata
);
199 TEST_F(SimpleIndexTest
, IndexSizeCorrectOnMerge
) {
200 index()->SetMaxSize(100);
201 index()->Insert(hashes_
.at
<2>());
202 index()->UpdateEntrySize(hashes_
.at
<2>(), 2);
203 index()->Insert(hashes_
.at
<3>());
204 index()->UpdateEntrySize(hashes_
.at
<3>(), 3);
205 index()->Insert(hashes_
.at
<4>());
206 index()->UpdateEntrySize(hashes_
.at
<4>(), 4);
207 EXPECT_EQ(9U, index()->cache_size_
);
209 scoped_ptr
<SimpleIndexLoadResult
> result(new SimpleIndexLoadResult());
210 result
->did_load
= true;
211 index()->MergeInitializingSet(result
.Pass());
213 EXPECT_EQ(9U, index()->cache_size_
);
215 scoped_ptr
<SimpleIndexLoadResult
> result(new SimpleIndexLoadResult());
216 result
->did_load
= true;
217 const uint64 new_hash_key
= hashes_
.at
<11>();
218 result
->entries
.insert(
219 std::make_pair(new_hash_key
, EntryMetadata(base::Time::Now(), 11)));
220 const uint64 redundant_hash_key
= hashes_
.at
<4>();
221 result
->entries
.insert(std::make_pair(redundant_hash_key
,
222 EntryMetadata(base::Time::Now(), 4)));
223 index()->MergeInitializingSet(result
.Pass());
225 EXPECT_EQ(2U + 3U + 4U + 11U, index()->cache_size_
);
228 // State of index changes as expected with an insert and a remove.
229 TEST_F(SimpleIndexTest
, BasicInsertRemove
) {
230 // Confirm blank state.
231 EntryMetadata metadata
;
232 EXPECT_EQ(base::Time(), metadata
.GetLastUsedTime());
233 EXPECT_EQ(0, metadata
.GetEntrySize());
235 // Confirm state after insert.
236 index()->Insert(hashes_
.at
<1>());
237 ASSERT_TRUE(GetEntryForTesting(hashes_
.at
<1>(), &metadata
));
238 base::Time
now(base::Time::Now());
239 EXPECT_LT(now
- base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
240 EXPECT_GT(now
+ base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
241 EXPECT_EQ(0, metadata
.GetEntrySize());
243 // Confirm state after remove.
244 metadata
= EntryMetadata();
245 index()->Remove(hashes_
.at
<1>());
246 EXPECT_FALSE(GetEntryForTesting(hashes_
.at
<1>(), &metadata
));
247 EXPECT_EQ(base::Time(), metadata
.GetLastUsedTime());
248 EXPECT_EQ(0, metadata
.GetEntrySize());
251 TEST_F(SimpleIndexTest
, Has
) {
252 // Confirm the base index has dispatched the request for index entries.
253 EXPECT_TRUE(index_file_
.get());
254 EXPECT_EQ(1, index_file_
->load_index_entries_calls());
256 // Confirm "Has()" always returns true before the callback is called.
257 const uint64 kHash1
= hashes_
.at
<1>();
258 EXPECT_TRUE(index()->Has(kHash1
));
259 index()->Insert(kHash1
);
260 EXPECT_TRUE(index()->Has(kHash1
));
261 index()->Remove(kHash1
);
262 // TODO(rdsmith): Maybe return false on explicitly removed entries?
263 EXPECT_TRUE(index()->Has(kHash1
));
267 // Confirm "Has() returns conditionally now.
268 EXPECT_FALSE(index()->Has(kHash1
));
269 index()->Insert(kHash1
);
270 EXPECT_TRUE(index()->Has(kHash1
));
271 index()->Remove(kHash1
);
274 TEST_F(SimpleIndexTest
, UseIfExists
) {
275 // Confirm the base index has dispatched the request for index entries.
276 EXPECT_TRUE(index_file_
.get());
277 EXPECT_EQ(1, index_file_
->load_index_entries_calls());
279 // Confirm "UseIfExists()" always returns true before the callback is called
280 // and updates mod time if the entry was really there.
281 const uint64 kHash1
= hashes_
.at
<1>();
282 EntryMetadata metadata1
, metadata2
;
283 EXPECT_TRUE(index()->UseIfExists(kHash1
));
284 EXPECT_FALSE(GetEntryForTesting(kHash1
, &metadata1
));
285 index()->Insert(kHash1
);
286 EXPECT_TRUE(index()->UseIfExists(kHash1
));
287 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata1
));
289 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata2
));
290 EXPECT_EQ(metadata1
.GetLastUsedTime(), metadata2
.GetLastUsedTime());
291 EXPECT_TRUE(index()->UseIfExists(kHash1
));
292 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata2
));
293 EXPECT_LT(metadata1
.GetLastUsedTime(), metadata2
.GetLastUsedTime());
294 index()->Remove(kHash1
);
295 EXPECT_TRUE(index()->UseIfExists(kHash1
));
299 // Confirm "UseIfExists() returns conditionally now
300 EXPECT_FALSE(index()->UseIfExists(kHash1
));
301 EXPECT_FALSE(GetEntryForTesting(kHash1
, &metadata1
));
302 index()->Insert(kHash1
);
303 EXPECT_TRUE(index()->UseIfExists(kHash1
));
304 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata1
));
306 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata2
));
307 EXPECT_EQ(metadata1
.GetLastUsedTime(), metadata2
.GetLastUsedTime());
308 EXPECT_TRUE(index()->UseIfExists(kHash1
));
309 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata2
));
310 EXPECT_LT(metadata1
.GetLastUsedTime(), metadata2
.GetLastUsedTime());
311 index()->Remove(kHash1
);
312 EXPECT_FALSE(index()->UseIfExists(kHash1
));
315 TEST_F(SimpleIndexTest
, UpdateEntrySize
) {
316 base::Time
now(base::Time::Now());
318 index()->SetMaxSize(1000);
320 const uint64 kHash1
= hashes_
.at
<1>();
321 InsertIntoIndexFileReturn(kHash1
, now
- base::TimeDelta::FromDays(2), 475);
324 EntryMetadata metadata
;
325 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata
));
327 now
- base::TimeDelta::FromDays(2) - base::TimeDelta::FromSeconds(1),
328 metadata
.GetLastUsedTime());
330 now
- base::TimeDelta::FromDays(2) + base::TimeDelta::FromSeconds(1),
331 metadata
.GetLastUsedTime());
332 EXPECT_EQ(475, metadata
.GetEntrySize());
334 index()->UpdateEntrySize(kHash1
, 600u);
335 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata
));
336 EXPECT_EQ(600, metadata
.GetEntrySize());
337 EXPECT_EQ(1, index()->GetEntryCount());
340 TEST_F(SimpleIndexTest
, GetEntryCount
) {
341 EXPECT_EQ(0, index()->GetEntryCount());
342 index()->Insert(hashes_
.at
<1>());
343 EXPECT_EQ(1, index()->GetEntryCount());
344 index()->Insert(hashes_
.at
<2>());
345 EXPECT_EQ(2, index()->GetEntryCount());
346 index()->Insert(hashes_
.at
<3>());
347 EXPECT_EQ(3, index()->GetEntryCount());
348 index()->Insert(hashes_
.at
<3>());
349 EXPECT_EQ(3, index()->GetEntryCount());
350 index()->Remove(hashes_
.at
<2>());
351 EXPECT_EQ(2, index()->GetEntryCount());
352 index()->Insert(hashes_
.at
<4>());
353 EXPECT_EQ(3, index()->GetEntryCount());
354 index()->Remove(hashes_
.at
<3>());
355 EXPECT_EQ(2, index()->GetEntryCount());
356 index()->Remove(hashes_
.at
<3>());
357 EXPECT_EQ(2, index()->GetEntryCount());
358 index()->Remove(hashes_
.at
<1>());
359 EXPECT_EQ(1, index()->GetEntryCount());
360 index()->Remove(hashes_
.at
<4>());
361 EXPECT_EQ(0, index()->GetEntryCount());
364 // Confirm that we get the results we expect from a simple init.
365 TEST_F(SimpleIndexTest
, BasicInit
) {
366 base::Time
now(base::Time::Now());
368 InsertIntoIndexFileReturn(hashes_
.at
<1>(),
369 now
- base::TimeDelta::FromDays(2),
371 InsertIntoIndexFileReturn(hashes_
.at
<2>(),
372 now
- base::TimeDelta::FromDays(3),
377 EntryMetadata metadata
;
378 EXPECT_TRUE(GetEntryForTesting(hashes_
.at
<1>(), &metadata
));
380 now
- base::TimeDelta::FromDays(2) - base::TimeDelta::FromSeconds(1),
381 metadata
.GetLastUsedTime());
383 now
- base::TimeDelta::FromDays(2) + base::TimeDelta::FromSeconds(1),
384 metadata
.GetLastUsedTime());
385 EXPECT_EQ(10, metadata
.GetEntrySize());
386 EXPECT_TRUE(GetEntryForTesting(hashes_
.at
<2>(), &metadata
));
388 now
- base::TimeDelta::FromDays(3) - base::TimeDelta::FromSeconds(1),
389 metadata
.GetLastUsedTime());
391 now
- base::TimeDelta::FromDays(3) + base::TimeDelta::FromSeconds(1),
392 metadata
.GetLastUsedTime());
393 EXPECT_EQ(100, metadata
.GetEntrySize());
396 // Remove something that's going to come in from the loaded index.
397 TEST_F(SimpleIndexTest
, RemoveBeforeInit
) {
398 const uint64 kHash1
= hashes_
.at
<1>();
399 index()->Remove(kHash1
);
401 InsertIntoIndexFileReturn(kHash1
,
402 base::Time::Now() - base::TimeDelta::FromDays(2),
406 EXPECT_FALSE(index()->Has(kHash1
));
409 // Insert something that's going to come in from the loaded index; correct
411 TEST_F(SimpleIndexTest
, InsertBeforeInit
) {
412 const uint64 kHash1
= hashes_
.at
<1>();
413 index()->Insert(kHash1
);
415 InsertIntoIndexFileReturn(kHash1
,
416 base::Time::Now() - base::TimeDelta::FromDays(2),
420 EntryMetadata metadata
;
421 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata
));
422 base::Time
now(base::Time::Now());
423 EXPECT_LT(now
- base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
424 EXPECT_GT(now
+ base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
425 EXPECT_EQ(0, metadata
.GetEntrySize());
428 // Insert and Remove something that's going to come in from the loaded index.
429 TEST_F(SimpleIndexTest
, InsertRemoveBeforeInit
) {
430 const uint64 kHash1
= hashes_
.at
<1>();
431 index()->Insert(kHash1
);
432 index()->Remove(kHash1
);
434 InsertIntoIndexFileReturn(kHash1
,
435 base::Time::Now() - base::TimeDelta::FromDays(2),
439 EXPECT_FALSE(index()->Has(kHash1
));
442 // Insert and Remove something that's going to come in from the loaded index.
443 TEST_F(SimpleIndexTest
, RemoveInsertBeforeInit
) {
444 const uint64 kHash1
= hashes_
.at
<1>();
445 index()->Remove(kHash1
);
446 index()->Insert(kHash1
);
448 InsertIntoIndexFileReturn(kHash1
,
449 base::Time::Now() - base::TimeDelta::FromDays(2),
453 EntryMetadata metadata
;
454 EXPECT_TRUE(GetEntryForTesting(kHash1
, &metadata
));
455 base::Time
now(base::Time::Now());
456 EXPECT_LT(now
- base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
457 EXPECT_GT(now
+ base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
458 EXPECT_EQ(0, metadata
.GetEntrySize());
461 // Do all above tests at once + a non-conflict to test for cross-key
463 TEST_F(SimpleIndexTest
, AllInitConflicts
) {
464 base::Time
now(base::Time::Now());
466 index()->Remove(hashes_
.at
<1>());
467 InsertIntoIndexFileReturn(hashes_
.at
<1>(),
468 now
- base::TimeDelta::FromDays(2),
470 index()->Insert(hashes_
.at
<2>());
471 InsertIntoIndexFileReturn(hashes_
.at
<2>(),
472 now
- base::TimeDelta::FromDays(3),
474 index()->Insert(hashes_
.at
<3>());
475 index()->Remove(hashes_
.at
<3>());
476 InsertIntoIndexFileReturn(hashes_
.at
<3>(),
477 now
- base::TimeDelta::FromDays(4),
479 index()->Remove(hashes_
.at
<4>());
480 index()->Insert(hashes_
.at
<4>());
481 InsertIntoIndexFileReturn(hashes_
.at
<4>(),
482 now
- base::TimeDelta::FromDays(5),
484 InsertIntoIndexFileReturn(hashes_
.at
<5>(),
485 now
- base::TimeDelta::FromDays(6),
490 EXPECT_FALSE(index()->Has(hashes_
.at
<1>()));
492 EntryMetadata metadata
;
493 EXPECT_TRUE(GetEntryForTesting(hashes_
.at
<2>(), &metadata
));
494 EXPECT_LT(now
- base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
495 EXPECT_GT(now
+ base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
496 EXPECT_EQ(0, metadata
.GetEntrySize());
498 EXPECT_FALSE(index()->Has(hashes_
.at
<3>()));
500 EXPECT_TRUE(GetEntryForTesting(hashes_
.at
<4>(), &metadata
));
501 EXPECT_LT(now
- base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
502 EXPECT_GT(now
+ base::TimeDelta::FromMinutes(1), metadata
.GetLastUsedTime());
503 EXPECT_EQ(0, metadata
.GetEntrySize());
505 EXPECT_TRUE(GetEntryForTesting(hashes_
.at
<5>(), &metadata
));
508 now
- base::TimeDelta::FromDays(6) + base::TimeDelta::FromSeconds(1),
509 metadata
.GetLastUsedTime());
511 now
- base::TimeDelta::FromDays(6) - base::TimeDelta::FromSeconds(1),
512 metadata
.GetLastUsedTime());
514 EXPECT_EQ(100000, metadata
.GetEntrySize());
517 TEST_F(SimpleIndexTest
, BasicEviction
) {
518 base::Time
now(base::Time::Now());
519 index()->SetMaxSize(1000);
520 InsertIntoIndexFileReturn(hashes_
.at
<1>(),
521 now
- base::TimeDelta::FromDays(2),
523 index()->Insert(hashes_
.at
<2>());
524 index()->UpdateEntrySize(hashes_
.at
<2>(), 475);
529 index()->Insert(hashes_
.at
<3>());
530 // Confirm index is as expected: No eviction, everything there.
531 EXPECT_EQ(3, index()->GetEntryCount());
532 EXPECT_EQ(0, doom_entries_calls());
533 EXPECT_TRUE(index()->Has(hashes_
.at
<1>()));
534 EXPECT_TRUE(index()->Has(hashes_
.at
<2>()));
535 EXPECT_TRUE(index()->Has(hashes_
.at
<3>()));
537 // Trigger an eviction, and make sure the right things are tossed.
538 // TODO(rdsmith): This is dependent on the innards of the implementation
539 // as to at exactly what point we trigger eviction. Not sure how to fix
541 index()->UpdateEntrySize(hashes_
.at
<3>(), 475);
542 EXPECT_EQ(1, doom_entries_calls());
543 EXPECT_EQ(1, index()->GetEntryCount());
544 EXPECT_FALSE(index()->Has(hashes_
.at
<1>()));
545 EXPECT_FALSE(index()->Has(hashes_
.at
<2>()));
546 EXPECT_TRUE(index()->Has(hashes_
.at
<3>()));
547 ASSERT_EQ(2u, last_doom_entry_hashes().size());
550 // Confirm all the operations queue a disk write at some point in the
552 TEST_F(SimpleIndexTest
, DiskWriteQueued
) {
553 index()->SetMaxSize(1000);
556 EXPECT_FALSE(index()->write_to_disk_timer_
.IsRunning());
558 const uint64 kHash1
= hashes_
.at
<1>();
559 index()->Insert(kHash1
);
560 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
561 index()->write_to_disk_timer_
.Stop();
562 EXPECT_FALSE(index()->write_to_disk_timer_
.IsRunning());
564 index()->UseIfExists(kHash1
);
565 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
566 index()->write_to_disk_timer_
.Stop();
568 index()->UpdateEntrySize(kHash1
, 20);
569 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
570 index()->write_to_disk_timer_
.Stop();
572 index()->Remove(kHash1
);
573 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
574 index()->write_to_disk_timer_
.Stop();
577 TEST_F(SimpleIndexTest
, DiskWriteExecuted
) {
578 index()->SetMaxSize(1000);
581 EXPECT_FALSE(index()->write_to_disk_timer_
.IsRunning());
583 const uint64 kHash1
= hashes_
.at
<1>();
584 index()->Insert(kHash1
);
585 index()->UpdateEntrySize(kHash1
, 20);
586 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
587 base::Closure
user_task(index()->write_to_disk_timer_
.user_task());
588 index()->write_to_disk_timer_
.Stop();
590 EXPECT_EQ(0, index_file_
->disk_writes());
592 EXPECT_EQ(1, index_file_
->disk_writes());
593 SimpleIndex::EntrySet entry_set
;
594 index_file_
->GetAndResetDiskWriteEntrySet(&entry_set
);
596 uint64 hash_key
= kHash1
;
597 base::Time
now(base::Time::Now());
598 ASSERT_EQ(1u, entry_set
.size());
599 EXPECT_EQ(hash_key
, entry_set
.begin()->first
);
600 const EntryMetadata
& entry1(entry_set
.begin()->second
);
601 EXPECT_LT(now
- base::TimeDelta::FromMinutes(1), entry1
.GetLastUsedTime());
602 EXPECT_GT(now
+ base::TimeDelta::FromMinutes(1), entry1
.GetLastUsedTime());
603 EXPECT_EQ(20, entry1
.GetEntrySize());
606 TEST_F(SimpleIndexTest
, DiskWritePostponed
) {
607 index()->SetMaxSize(1000);
610 EXPECT_FALSE(index()->write_to_disk_timer_
.IsRunning());
612 index()->Insert(hashes_
.at
<1>());
613 index()->UpdateEntrySize(hashes_
.at
<1>(), 20);
614 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
615 base::TimeTicks
expected_trigger(
616 index()->write_to_disk_timer_
.desired_run_time());
619 EXPECT_EQ(expected_trigger
, index()->write_to_disk_timer_
.desired_run_time());
620 index()->Insert(hashes_
.at
<2>());
621 index()->UpdateEntrySize(hashes_
.at
<2>(), 40);
622 EXPECT_TRUE(index()->write_to_disk_timer_
.IsRunning());
623 EXPECT_LT(expected_trigger
, index()->write_to_disk_timer_
.desired_run_time());
624 index()->write_to_disk_timer_
.Stop();
627 } // namespace disk_cache