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 |