1 // Copyright (c) 2011 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/basictypes.h"
6 #include "base/file_util.h"
7 #include "base/string_util.h"
8 #include "base/stringprintf.h"
9 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
10 #include "base/threading/platform_thread.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/disk_cache/backend_impl.h"
15 #include "net/disk_cache/cache_util.h"
16 #include "net/disk_cache/disk_cache_test_base.h"
17 #include "net/disk_cache/disk_cache_test_util.h"
18 #include "net/disk_cache/histogram_macros.h"
19 #include "net/disk_cache/mapped_file.h"
20 #include "net/disk_cache/mem_backend_impl.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 #if defined(OS_WIN)
24 #include "base/win/scoped_handle.h"
25 #endif
26
27 using base::Time;
28
29 // Tests that can run with different types of caches.
30 class DiskCacheBackendTest : public DiskCacheTestWithCache {
31 protected:
32 void BackendBasics();
33 void BackendKeying();
34 void BackendSetSize();
35 void BackendLoad();
36 void BackendValidEntry();
37 void BackendInvalidEntry();
38 void BackendInvalidEntryRead();
39 void BackendInvalidEntryWithLoad();
40 void BackendTrimInvalidEntry();
41 void BackendTrimInvalidEntry2();
42 void BackendEnumerations();
43 void BackendEnumerations2();
44 void BackendInvalidEntryEnumeration();
45 void BackendFixEnumerators();
46 void BackendDoomRecent();
47 void BackendDoomBetween();
48 void BackendTransaction(const std::string& name, int num_entries, bool load);
49 void BackendRecoverInsert();
50 void BackendRecoverRemove();
51 void BackendRecoverWithEviction();
52 void BackendInvalidEntry2();
53 void BackendInvalidEntry3();
54 void BackendNotMarkedButDirty(const std::string& name);
55 void BackendDoomAll();
56 void BackendDoomAll2();
57 void BackendInvalidRankings();
58 void BackendInvalidRankings2();
59 void BackendDisable();
60 void BackendDisable2();
61 void BackendDisable3();
62 void BackendDisable4();
63 };
64
BackendBasics()65 void DiskCacheBackendTest::BackendBasics() {
66 InitCache();
67 disk_cache::Entry *entry1 = NULL, *entry2 = NULL;
68 EXPECT_NE(net::OK, OpenEntry("the first key", &entry1));
69 ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1));
70 ASSERT_TRUE(NULL != entry1);
71 entry1->Close();
72 entry1 = NULL;
73
74 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
75 ASSERT_TRUE(NULL != entry1);
76 entry1->Close();
77 entry1 = NULL;
78
79 EXPECT_NE(net::OK, CreateEntry("the first key", &entry1));
80 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
81 EXPECT_NE(net::OK, OpenEntry("some other key", &entry2));
82 ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2));
83 ASSERT_TRUE(NULL != entry1);
84 ASSERT_TRUE(NULL != entry2);
85 EXPECT_EQ(2, cache_->GetEntryCount());
86
87 disk_cache::Entry* entry3 = NULL;
88 ASSERT_EQ(net::OK, OpenEntry("some other key", &entry3));
89 ASSERT_TRUE(NULL != entry3);
90 EXPECT_TRUE(entry2 == entry3);
91 EXPECT_EQ(2, cache_->GetEntryCount());
92
93 EXPECT_EQ(net::OK, DoomEntry("some other key"));
94 EXPECT_EQ(1, cache_->GetEntryCount());
95 entry1->Close();
96 entry2->Close();
97 entry3->Close();
98
99 EXPECT_EQ(net::OK, DoomEntry("the first key"));
100 EXPECT_EQ(0, cache_->GetEntryCount());
101
102 ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1));
103 ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2));
104 entry1->Doom();
105 entry1->Close();
106 EXPECT_EQ(net::OK, DoomEntry("some other key"));
107 EXPECT_EQ(0, cache_->GetEntryCount());
108 entry2->Close();
109 }
110
TEST_F(DiskCacheBackendTest,Basics)111 TEST_F(DiskCacheBackendTest, Basics) {
112 BackendBasics();
113 }
114
TEST_F(DiskCacheBackendTest,NewEvictionBasics)115 TEST_F(DiskCacheBackendTest, NewEvictionBasics) {
116 SetNewEviction();
117 BackendBasics();
118 }
119
TEST_F(DiskCacheBackendTest,MemoryOnlyBasics)120 TEST_F(DiskCacheBackendTest, MemoryOnlyBasics) {
121 SetMemoryOnlyMode();
122 BackendBasics();
123 }
124
TEST_F(DiskCacheBackendTest,AppCacheBasics)125 TEST_F(DiskCacheBackendTest, AppCacheBasics) {
126 SetCacheType(net::APP_CACHE);
127 BackendBasics();
128 }
129
BackendKeying()130 void DiskCacheBackendTest::BackendKeying() {
131 InitCache();
132 const char* kName1 = "the first key";
133 const char* kName2 = "the first Key";
134 disk_cache::Entry *entry1, *entry2;
135 ASSERT_EQ(net::OK, CreateEntry(kName1, &entry1));
136
137 ASSERT_EQ(net::OK, CreateEntry(kName2, &entry2));
138 EXPECT_TRUE(entry1 != entry2) << "Case sensitive";
139 entry2->Close();
140
141 char buffer[30];
142 base::strlcpy(buffer, kName1, arraysize(buffer));
143 ASSERT_EQ(net::OK, OpenEntry(buffer, &entry2));
144 EXPECT_TRUE(entry1 == entry2);
145 entry2->Close();
146
147 base::strlcpy(buffer + 1, kName1, arraysize(buffer) - 1);
148 ASSERT_EQ(net::OK, OpenEntry(buffer + 1, &entry2));
149 EXPECT_TRUE(entry1 == entry2);
150 entry2->Close();
151
152 base::strlcpy(buffer + 3, kName1, arraysize(buffer) - 3);
153 ASSERT_EQ(net::OK, OpenEntry(buffer + 3, &entry2));
154 EXPECT_TRUE(entry1 == entry2);
155 entry2->Close();
156
157 // Now verify long keys.
158 char buffer2[20000];
159 memset(buffer2, 's', sizeof(buffer2));
160 buffer2[1023] = '\0';
161 ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on block file";
162 entry2->Close();
163
164 buffer2[1023] = 'g';
165 buffer2[19999] = '\0';
166 ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on external file";
167 entry2->Close();
168 entry1->Close();
169 }
170
TEST_F(DiskCacheBackendTest,Keying)171 TEST_F(DiskCacheBackendTest, Keying) {
172 BackendKeying();
173 }
174
TEST_F(DiskCacheBackendTest,NewEvictionKeying)175 TEST_F(DiskCacheBackendTest, NewEvictionKeying) {
176 SetNewEviction();
177 BackendKeying();
178 }
179
TEST_F(DiskCacheBackendTest,MemoryOnlyKeying)180 TEST_F(DiskCacheBackendTest, MemoryOnlyKeying) {
181 SetMemoryOnlyMode();
182 BackendKeying();
183 }
184
TEST_F(DiskCacheBackendTest,AppCacheKeying)185 TEST_F(DiskCacheBackendTest, AppCacheKeying) {
186 SetCacheType(net::APP_CACHE);
187 BackendKeying();
188 }
189
TEST_F(DiskCacheTest,CreateBackend)190 TEST_F(DiskCacheTest, CreateBackend) {
191 TestCompletionCallback cb;
192
193 {
194 FilePath path = GetCacheFilePath();
195 ASSERT_TRUE(DeleteCache(path));
196 base::Thread cache_thread("CacheThread");
197 ASSERT_TRUE(cache_thread.StartWithOptions(
198 base::Thread::Options(MessageLoop::TYPE_IO, 0)));
199
200 // Test the private factory methods.
201 disk_cache::Backend* cache = NULL;
202 int rv = disk_cache::BackendImpl::CreateBackend(
203 path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom,
204 cache_thread.message_loop_proxy(), NULL, &cache, &cb);
205 ASSERT_EQ(net::OK, cb.GetResult(rv));
206 ASSERT_TRUE(cache);
207 delete cache;
208
209 cache = disk_cache::MemBackendImpl::CreateBackend(0, NULL);
210 ASSERT_TRUE(cache);
211 delete cache;
212 cache = NULL;
213
214 // Now test the public API.
215 rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path, 0, false,
216 cache_thread.message_loop_proxy(),
217 NULL, &cache, &cb);
218 ASSERT_EQ(net::OK, cb.GetResult(rv));
219 ASSERT_TRUE(cache);
220 delete cache;
221 cache = NULL;
222
223 rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE, FilePath(), 0, false,
224 NULL, NULL, &cache, &cb);
225 ASSERT_EQ(net::OK, cb.GetResult(rv));
226 ASSERT_TRUE(cache);
227 delete cache;
228 }
229
230 MessageLoop::current()->RunAllPending();
231 }
232
TEST_F(DiskCacheBackendTest,ExternalFiles)233 TEST_F(DiskCacheBackendTest, ExternalFiles) {
234 InitCache();
235 // First, let's create a file on the folder.
236 FilePath filename = GetCacheFilePath().AppendASCII("f_000001");
237
238 const int kSize = 50;
239 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
240 CacheTestFillBuffer(buffer1->data(), kSize, false);
241 ASSERT_EQ(kSize, file_util::WriteFile(filename, buffer1->data(), kSize));
242
243 // Now let's create a file with the cache.
244 disk_cache::Entry* entry;
245 ASSERT_EQ(net::OK, CreateEntry("key", &entry));
246 ASSERT_EQ(0, WriteData(entry, 0, 20000, buffer1, 0, false));
247 entry->Close();
248
249 // And verify that the first file is still there.
250 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
251 ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize));
252 EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize));
253 }
254
255 // Tests that we deal with file-level pending operations at destruction time.
TEST_F(DiskCacheTest,ShutdownWithPendingIO)256 TEST_F(DiskCacheTest, ShutdownWithPendingIO) {
257 TestCompletionCallback cb;
258
259 {
260 FilePath path = GetCacheFilePath();
261 ASSERT_TRUE(DeleteCache(path));
262 base::Thread cache_thread("CacheThread");
263 ASSERT_TRUE(cache_thread.StartWithOptions(
264 base::Thread::Options(MessageLoop::TYPE_IO, 0)));
265
266 disk_cache::Backend* cache;
267 int rv = disk_cache::BackendImpl::CreateBackend(
268 path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom,
269 base::MessageLoopProxy::CreateForCurrentThread(), NULL,
270 &cache, &cb);
271 ASSERT_EQ(net::OK, cb.GetResult(rv));
272
273 disk_cache::EntryImpl* entry;
274 rv = cache->CreateEntry("some key",
275 reinterpret_cast<disk_cache::Entry**>(&entry), &cb);
276 ASSERT_EQ(net::OK, cb.GetResult(rv));
277
278 const int kSize = 25000;
279 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
280 CacheTestFillBuffer(buffer->data(), kSize, false);
281
282 for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) {
283 // We are using the current thread as the cache thread because we want to
284 // be able to call directly this method to make sure that the OS (instead
285 // of us switching thread) is returning IO pending.
286 rv = entry->WriteDataImpl(0, i, buffer, kSize, &cb, false);
287 if (rv == net::ERR_IO_PENDING)
288 break;
289 EXPECT_EQ(kSize, rv);
290 }
291
292 // Don't call Close() to avoid going through the queue or we'll deadlock
293 // waiting for the operation to finish.
294 entry->Release();
295
296 // The cache destructor will see one pending operation here.
297 delete cache;
298
299 if (rv == net::ERR_IO_PENDING) {
300 EXPECT_TRUE(cb.have_result());
301 }
302 }
303
304 MessageLoop::current()->RunAllPending();
305 }
306
307 // Tests that we deal with background-thread pending operations.
TEST_F(DiskCacheTest,ShutdownWithPendingIO2)308 TEST_F(DiskCacheTest, ShutdownWithPendingIO2) {
309 TestCompletionCallback cb;
310
311 {
312 FilePath path = GetCacheFilePath();
313 ASSERT_TRUE(DeleteCache(path));
314 base::Thread cache_thread("CacheThread");
315 ASSERT_TRUE(cache_thread.StartWithOptions(
316 base::Thread::Options(MessageLoop::TYPE_IO, 0)));
317
318 disk_cache::Backend* cache;
319 int rv = disk_cache::BackendImpl::CreateBackend(
320 path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom,
321 cache_thread.message_loop_proxy(), NULL, &cache, &cb);
322 ASSERT_EQ(net::OK, cb.GetResult(rv));
323
324 disk_cache::Entry* entry;
325 rv = cache->CreateEntry("some key", &entry, &cb);
326 ASSERT_EQ(net::OK, cb.GetResult(rv));
327
328 const int kSize = 25000;
329 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
330 CacheTestFillBuffer(buffer->data(), kSize, false);
331
332 rv = entry->WriteData(0, 0, buffer, kSize, &cb, false);
333 EXPECT_EQ(net::ERR_IO_PENDING, rv);
334
335 entry->Close();
336
337 // The cache destructor will see two pending operations here.
338 delete cache;
339 }
340
341 MessageLoop::current()->RunAllPending();
342 }
343
TEST_F(DiskCacheTest,TruncatedIndex)344 TEST_F(DiskCacheTest, TruncatedIndex) {
345 FilePath path = GetCacheFilePath();
346 ASSERT_TRUE(DeleteCache(path));
347 FilePath index = path.AppendASCII("index");
348 ASSERT_EQ(5, file_util::WriteFile(index, "hello", 5));
349
350 base::Thread cache_thread("CacheThread");
351 ASSERT_TRUE(cache_thread.StartWithOptions(
352 base::Thread::Options(MessageLoop::TYPE_IO, 0)));
353 TestCompletionCallback cb;
354
355 disk_cache::Backend* backend = NULL;
356 int rv = disk_cache::BackendImpl::CreateBackend(
357 path, false, 0, net::DISK_CACHE, disk_cache::kNone,
358 cache_thread.message_loop_proxy(), NULL, &backend, &cb);
359 ASSERT_NE(net::OK, cb.GetResult(rv));
360
361 ASSERT_TRUE(backend == NULL);
362 delete backend;
363 }
364
BackendSetSize()365 void DiskCacheBackendTest::BackendSetSize() {
366 SetDirectMode();
367 const int cache_size = 0x10000; // 64 kB
368 SetMaxSize(cache_size);
369 InitCache();
370
371 std::string first("some key");
372 std::string second("something else");
373 disk_cache::Entry* entry;
374 ASSERT_EQ(net::OK, CreateEntry(first, &entry));
375
376 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(cache_size));
377 memset(buffer->data(), 0, cache_size);
378 EXPECT_EQ(cache_size / 10, WriteData(entry, 0, 0, buffer, cache_size / 10,
379 false)) << "normal file";
380
381 EXPECT_EQ(net::ERR_FAILED, WriteData(entry, 1, 0, buffer, cache_size / 5,
382 false)) << "file size above the limit";
383
384 // By doubling the total size, we make this file cacheable.
385 SetMaxSize(cache_size * 2);
386 EXPECT_EQ(cache_size / 5, WriteData(entry, 1, 0, buffer, cache_size / 5,
387 false));
388
389 // Let's fill up the cache!.
390 SetMaxSize(cache_size * 10);
391 EXPECT_EQ(cache_size * 3 / 4, WriteData(entry, 0, 0, buffer,
392 cache_size * 3 / 4, false));
393 entry->Close();
394 FlushQueueForTest();
395
396 SetMaxSize(cache_size);
397
398 // The cache is 95% full.
399
400 ASSERT_EQ(net::OK, CreateEntry(second, &entry));
401 EXPECT_EQ(cache_size / 10, WriteData(entry, 0, 0, buffer, cache_size / 10,
402 false));
403
404 disk_cache::Entry* entry2;
405 ASSERT_EQ(net::OK, CreateEntry("an extra key", &entry2));
406 EXPECT_EQ(cache_size / 10, WriteData(entry2, 0, 0, buffer, cache_size / 10,
407 false));
408 entry2->Close(); // This will trigger the cache trim.
409
410 EXPECT_NE(net::OK, OpenEntry(first, &entry2));
411
412 FlushQueueForTest(); // Make sure that we are done trimming the cache.
413 FlushQueueForTest(); // We may have posted two tasks to evict stuff.
414
415 entry->Close();
416 ASSERT_EQ(net::OK, OpenEntry(second, &entry));
417 EXPECT_EQ(cache_size / 10, entry->GetDataSize(0));
418 entry->Close();
419 }
420
TEST_F(DiskCacheBackendTest,SetSize)421 TEST_F(DiskCacheBackendTest, SetSize) {
422 BackendSetSize();
423 }
424
TEST_F(DiskCacheBackendTest,NewEvictionSetSize)425 TEST_F(DiskCacheBackendTest, NewEvictionSetSize) {
426 SetNewEviction();
427 BackendSetSize();
428 }
429
TEST_F(DiskCacheBackendTest,MemoryOnlySetSize)430 TEST_F(DiskCacheBackendTest, MemoryOnlySetSize) {
431 SetMemoryOnlyMode();
432 BackendSetSize();
433 }
434
BackendLoad()435 void DiskCacheBackendTest::BackendLoad() {
436 InitCache();
437 int seed = static_cast<int>(Time::Now().ToInternalValue());
438 srand(seed);
439
440 disk_cache::Entry* entries[100];
441 for (int i = 0; i < 100; i++) {
442 std::string key = GenerateKey(true);
443 ASSERT_EQ(net::OK, CreateEntry(key, &entries[i]));
444 }
445 EXPECT_EQ(100, cache_->GetEntryCount());
446
447 for (int i = 0; i < 100; i++) {
448 int source1 = rand() % 100;
449 int source2 = rand() % 100;
450 disk_cache::Entry* temp = entries[source1];
451 entries[source1] = entries[source2];
452 entries[source2] = temp;
453 }
454
455 for (int i = 0; i < 100; i++) {
456 disk_cache::Entry* entry;
457 ASSERT_EQ(net::OK, OpenEntry(entries[i]->GetKey(), &entry));
458 EXPECT_TRUE(entry == entries[i]);
459 entry->Close();
460 entries[i]->Doom();
461 entries[i]->Close();
462 }
463 FlushQueueForTest();
464 EXPECT_EQ(0, cache_->GetEntryCount());
465 }
466
TEST_F(DiskCacheBackendTest,Load)467 TEST_F(DiskCacheBackendTest, Load) {
468 // Work with a tiny index table (16 entries)
469 SetMask(0xf);
470 SetMaxSize(0x100000);
471 BackendLoad();
472 }
473
TEST_F(DiskCacheBackendTest,NewEvictionLoad)474 TEST_F(DiskCacheBackendTest, NewEvictionLoad) {
475 SetNewEviction();
476 // Work with a tiny index table (16 entries)
477 SetMask(0xf);
478 SetMaxSize(0x100000);
479 BackendLoad();
480 }
481
TEST_F(DiskCacheBackendTest,MemoryOnlyLoad)482 TEST_F(DiskCacheBackendTest, MemoryOnlyLoad) {
483 // Work with a tiny index table (16 entries)
484 SetMaxSize(0x100000);
485 SetMemoryOnlyMode();
486 BackendLoad();
487 }
488
TEST_F(DiskCacheBackendTest,AppCacheLoad)489 TEST_F(DiskCacheBackendTest, AppCacheLoad) {
490 SetCacheType(net::APP_CACHE);
491 // Work with a tiny index table (16 entries)
492 SetMask(0xf);
493 SetMaxSize(0x100000);
494 BackendLoad();
495 }
496
497 // Before looking for invalid entries, let's check a valid entry.
BackendValidEntry()498 void DiskCacheBackendTest::BackendValidEntry() {
499 SetDirectMode();
500 InitCache();
501
502 std::string key("Some key");
503 disk_cache::Entry* entry;
504 ASSERT_EQ(net::OK, CreateEntry(key, &entry));
505
506 const int kSize = 50;
507 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
508 memset(buffer1->data(), 0, kSize);
509 base::strlcpy(buffer1->data(), "And the data to save", kSize);
510 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer1, kSize, false));
511 entry->Close();
512 SimulateCrash();
513
514 ASSERT_EQ(net::OK, OpenEntry(key, &entry));
515
516 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
517 memset(buffer2->data(), 0, kSize);
518 EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer2, kSize));
519 entry->Close();
520 EXPECT_STREQ(buffer1->data(), buffer2->data());
521 }
522
TEST_F(DiskCacheBackendTest,ValidEntry)523 TEST_F(DiskCacheBackendTest, ValidEntry) {
524 BackendValidEntry();
525 }
526
TEST_F(DiskCacheBackendTest,NewEvictionValidEntry)527 TEST_F(DiskCacheBackendTest, NewEvictionValidEntry) {
528 SetNewEviction();
529 BackendValidEntry();
530 }
531
532 // The same logic of the previous test (ValidEntry), but this time force the
533 // entry to be invalid, simulating a crash in the middle.
534 // We'll be leaking memory from this test.
BackendInvalidEntry()535 void DiskCacheBackendTest::BackendInvalidEntry() {
536 // Use the implementation directly... we need to simulate a crash.
537 SetDirectMode();
538 InitCache();
539
540 std::string key("Some key");
541 disk_cache::Entry* entry;
542 ASSERT_EQ(net::OK, CreateEntry(key, &entry));
543
544 const int kSize = 50;
545 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
546 memset(buffer->data(), 0, kSize);
547 base::strlcpy(buffer->data(), "And the data to save", kSize);
548 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false));
549 SimulateCrash();
550
551 EXPECT_NE(net::OK, OpenEntry(key, &entry));
552 EXPECT_EQ(0, cache_->GetEntryCount());
553 }
554
555 // This and the other intentionally leaky tests below are excluded from
556 // purify and valgrind runs by naming them in the files
557 // net/data/purify/net_unittests.exe.gtest.txt and
558 // net/data/valgrind/net_unittests.gtest.txt
559 // The scripts tools/{purify,valgrind}/chrome_tests.sh
560 // read those files and pass the appropriate --gtest_filter to net_unittests.
TEST_F(DiskCacheBackendTest,InvalidEntry)561 TEST_F(DiskCacheBackendTest, InvalidEntry) {
562 BackendInvalidEntry();
563 }
564
565 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,NewEvictionInvalidEntry)566 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry) {
567 SetNewEviction();
568 BackendInvalidEntry();
569 }
570
571 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,AppCacheInvalidEntry)572 TEST_F(DiskCacheBackendTest, AppCacheInvalidEntry) {
573 SetCacheType(net::APP_CACHE);
574 BackendInvalidEntry();
575 }
576
577 // Almost the same test, but this time crash the cache after reading an entry.
578 // We'll be leaking memory from this test.
BackendInvalidEntryRead()579 void DiskCacheBackendTest::BackendInvalidEntryRead() {
580 // Use the implementation directly... we need to simulate a crash.
581 SetDirectMode();
582 InitCache();
583
584 std::string key("Some key");
585 disk_cache::Entry* entry;
586 ASSERT_EQ(net::OK, CreateEntry(key, &entry));
587
588 const int kSize = 50;
589 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
590 memset(buffer->data(), 0, kSize);
591 base::strlcpy(buffer->data(), "And the data to save", kSize);
592 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false));
593 entry->Close();
594 ASSERT_EQ(net::OK, OpenEntry(key, &entry));
595 EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer, kSize));
596
597 SimulateCrash();
598
599 if (type_ == net::APP_CACHE) {
600 // Reading an entry and crashing should not make it dirty.
601 ASSERT_EQ(net::OK, OpenEntry(key, &entry));
602 EXPECT_EQ(1, cache_->GetEntryCount());
603 entry->Close();
604 } else {
605 EXPECT_NE(net::OK, OpenEntry(key, &entry));
606 EXPECT_EQ(0, cache_->GetEntryCount());
607 }
608 }
609
610 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,InvalidEntryRead)611 TEST_F(DiskCacheBackendTest, InvalidEntryRead) {
612 BackendInvalidEntryRead();
613 }
614
615 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,NewEvictionInvalidEntryRead)616 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryRead) {
617 SetNewEviction();
618 BackendInvalidEntryRead();
619 }
620
621 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,AppCacheInvalidEntryRead)622 TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryRead) {
623 SetCacheType(net::APP_CACHE);
624 BackendInvalidEntryRead();
625 }
626
627 // We'll be leaking memory from this test.
BackendInvalidEntryWithLoad()628 void DiskCacheBackendTest::BackendInvalidEntryWithLoad() {
629 // Work with a tiny index table (16 entries)
630 SetMask(0xf);
631 SetMaxSize(0x100000);
632 InitCache();
633
634 int seed = static_cast<int>(Time::Now().ToInternalValue());
635 srand(seed);
636
637 const int kNumEntries = 100;
638 disk_cache::Entry* entries[kNumEntries];
639 for (int i = 0; i < kNumEntries; i++) {
640 std::string key = GenerateKey(true);
641 ASSERT_EQ(net::OK, CreateEntry(key, &entries[i]));
642 }
643 EXPECT_EQ(kNumEntries, cache_->GetEntryCount());
644
645 for (int i = 0; i < kNumEntries; i++) {
646 int source1 = rand() % kNumEntries;
647 int source2 = rand() % kNumEntries;
648 disk_cache::Entry* temp = entries[source1];
649 entries[source1] = entries[source2];
650 entries[source2] = temp;
651 }
652
653 std::string keys[kNumEntries];
654 for (int i = 0; i < kNumEntries; i++) {
655 keys[i] = entries[i]->GetKey();
656 if (i < kNumEntries / 2)
657 entries[i]->Close();
658 }
659
660 SimulateCrash();
661
662 for (int i = kNumEntries / 2; i < kNumEntries; i++) {
663 disk_cache::Entry* entry;
664 EXPECT_NE(net::OK, OpenEntry(keys[i], &entry));
665 }
666
667 for (int i = 0; i < kNumEntries / 2; i++) {
668 disk_cache::Entry* entry;
669 EXPECT_EQ(net::OK, OpenEntry(keys[i], &entry));
670 entry->Close();
671 }
672
673 EXPECT_EQ(kNumEntries / 2, cache_->GetEntryCount());
674 }
675
676 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,InvalidEntryWithLoad)677 TEST_F(DiskCacheBackendTest, InvalidEntryWithLoad) {
678 BackendInvalidEntryWithLoad();
679 }
680
681 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,NewEvictionInvalidEntryWithLoad)682 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryWithLoad) {
683 SetNewEviction();
684 BackendInvalidEntryWithLoad();
685 }
686
687 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,AppCacheInvalidEntryWithLoad)688 TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryWithLoad) {
689 SetCacheType(net::APP_CACHE);
690 BackendInvalidEntryWithLoad();
691 }
692
693 // We'll be leaking memory from this test.
BackendTrimInvalidEntry()694 void DiskCacheBackendTest::BackendTrimInvalidEntry() {
695 // Use the implementation directly... we need to simulate a crash.
696 SetDirectMode();
697
698 const int kSize = 0x3000; // 12 kB
699 SetMaxSize(kSize * 10);
700 InitCache();
701
702 std::string first("some key");
703 std::string second("something else");
704 disk_cache::Entry* entry;
705 ASSERT_EQ(net::OK, CreateEntry(first, &entry));
706
707 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
708 memset(buffer->data(), 0, kSize);
709 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false));
710
711 // Simulate a crash.
712 SimulateCrash();
713
714 ASSERT_EQ(net::OK, CreateEntry(second, &entry));
715 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false));
716
717 EXPECT_EQ(2, cache_->GetEntryCount());
718 SetMaxSize(kSize);
719 entry->Close(); // Trim the cache.
720 FlushQueueForTest();
721
722 // If we evicted the entry in less than 20mS, we have one entry in the cache;
723 // if it took more than that, we posted a task and we'll delete the second
724 // entry too.
725 MessageLoop::current()->RunAllPending();
726
727 // This may be not thread-safe in general, but for now it's OK so add some
728 // ThreadSanitizer annotations to ignore data races on cache_.
729 // See http://crbug.com/55970
730 ANNOTATE_IGNORE_READS_BEGIN();
731 EXPECT_GE(1, cache_->GetEntryCount());
732 ANNOTATE_IGNORE_READS_END();
733
734 EXPECT_NE(net::OK, OpenEntry(first, &entry));
735 }
736
737 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,TrimInvalidEntry)738 TEST_F(DiskCacheBackendTest, TrimInvalidEntry) {
739 BackendTrimInvalidEntry();
740 }
741
742 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,NewEvictionTrimInvalidEntry)743 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry) {
744 SetNewEviction();
745 BackendTrimInvalidEntry();
746 }
747
748 // We'll be leaking memory from this test.
BackendTrimInvalidEntry2()749 void DiskCacheBackendTest::BackendTrimInvalidEntry2() {
750 // Use the implementation directly... we need to simulate a crash.
751 SetDirectMode();
752 SetMask(0xf); // 16-entry table.
753
754 const int kSize = 0x3000; // 12 kB
755 SetMaxSize(kSize * 40);
756 InitCache();
757
758 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
759 memset(buffer->data(), 0, kSize);
760 disk_cache::Entry* entry;
761
762 // Writing 32 entries to this cache chains most of them.
763 for (int i = 0; i < 32; i++) {
764 std::string key(base::StringPrintf("some key %d", i));
765 ASSERT_EQ(net::OK, CreateEntry(key, &entry));
766 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false));
767 entry->Close();
768 ASSERT_EQ(net::OK, OpenEntry(key, &entry));
769 // Note that we are not closing the entries.
770 }
771
772 // Simulate a crash.
773 SimulateCrash();
774
775 ASSERT_EQ(net::OK, CreateEntry("Something else", &entry));
776 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false));
777
778 EXPECT_EQ(33, cache_->GetEntryCount());
779 SetMaxSize(kSize);
780
781 // For the new eviction code, all corrupt entries are on the second list so
782 // they are not going away that easy.
783 if (new_eviction_) {
784 EXPECT_EQ(net::OK, DoomAllEntries());
785 }
786
787 entry->Close(); // Trim the cache.
788 FlushQueueForTest();
789
790 // We may abort the eviction before cleaning up everything.
791 MessageLoop::current()->RunAllPending();
792 EXPECT_GE(30, cache_->GetEntryCount());
793 }
794
795 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,TrimInvalidEntry2)796 TEST_F(DiskCacheBackendTest, TrimInvalidEntry2) {
797 BackendTrimInvalidEntry2();
798 }
799
800 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,NewEvictionTrimInvalidEntry2)801 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry2) {
802 SetNewEviction();
803 BackendTrimInvalidEntry2();
804 }
805
BackendEnumerations()806 void DiskCacheBackendTest::BackendEnumerations() {
807 InitCache();
808 Time initial = Time::Now();
809 int seed = static_cast<int>(initial.ToInternalValue());
810 srand(seed);
811
812 const int kNumEntries = 100;
813 for (int i = 0; i < kNumEntries; i++) {
814 std::string key = GenerateKey(true);
815 disk_cache::Entry* entry;
816 ASSERT_EQ(net::OK, CreateEntry(key, &entry));
817 entry->Close();
818 }
819 EXPECT_EQ(kNumEntries, cache_->GetEntryCount());
820 Time final = Time::Now();
821
822 disk_cache::Entry* entry;
823 void* iter = NULL;
824 int count = 0;
825 Time last_modified[kNumEntries];
826 Time last_used[kNumEntries];
827 while (OpenNextEntry(&iter, &entry) == net::OK) {
828 ASSERT_TRUE(NULL != entry);
829 if (count < kNumEntries) {
830 last_modified[count] = entry->GetLastModified();
831 last_used[count] = entry->GetLastUsed();
832 EXPECT_TRUE(initial <= last_modified[count]);
833 EXPECT_TRUE(final >= last_modified[count]);
834 }
835
836 entry->Close();
837 count++;
838 };
839 EXPECT_EQ(kNumEntries, count);
840
841 iter = NULL;
842 count = 0;
843 // The previous enumeration should not have changed the timestamps.
844 while (OpenNextEntry(&iter, &entry) == net::OK) {
845 ASSERT_TRUE(NULL != entry);
846 if (count < kNumEntries) {
847 EXPECT_TRUE(last_modified[count] == entry->GetLastModified());
848 EXPECT_TRUE(last_used[count] == entry->GetLastUsed());
849 }
850 entry->Close();
851 count++;
852 };
853 EXPECT_EQ(kNumEntries, count);
854 }
855
TEST_F(DiskCacheBackendTest,Enumerations)856 TEST_F(DiskCacheBackendTest, Enumerations) {
857 BackendEnumerations();
858 }
859
TEST_F(DiskCacheBackendTest,NewEvictionEnumerations)860 TEST_F(DiskCacheBackendTest, NewEvictionEnumerations) {
861 SetNewEviction();
862 BackendEnumerations();
863 }
864
TEST_F(DiskCacheBackendTest,MemoryOnlyEnumerations)865 TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations) {
866 SetMemoryOnlyMode();
867 BackendEnumerations();
868 }
869
870 // Flaky, http://crbug.com/74387.
TEST_F(DiskCacheBackendTest,FLAKY_AppCacheEnumerations)871 TEST_F(DiskCacheBackendTest, FLAKY_AppCacheEnumerations) {
872 SetCacheType(net::APP_CACHE);
873 BackendEnumerations();
874 }
875
876 // Verifies enumerations while entries are open.
BackendEnumerations2()877 void DiskCacheBackendTest::BackendEnumerations2() {
878 InitCache();
879 const std::string first("first");
880 const std::string second("second");
881 disk_cache::Entry *entry1, *entry2;
882 ASSERT_EQ(net::OK, CreateEntry(first, &entry1));
883 entry1->Close();
884 ASSERT_EQ(net::OK, CreateEntry(second, &entry2));
885 entry2->Close();
886
887 // Make sure that the timestamp is not the same.
888 base::PlatformThread::Sleep(20);
889 ASSERT_EQ(net::OK, OpenEntry(second, &entry1));
890 void* iter = NULL;
891 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
892 EXPECT_EQ(entry2->GetKey(), second);
893
894 // Two entries and the iterator pointing at "first".
895 entry1->Close();
896 entry2->Close();
897
898 // The iterator should still be valid, so we should not crash.
899 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
900 EXPECT_EQ(entry2->GetKey(), first);
901 entry2->Close();
902 cache_->EndEnumeration(&iter);
903
904 // Modify the oldest entry and get the newest element.
905 ASSERT_EQ(net::OK, OpenEntry(first, &entry1));
906 EXPECT_EQ(0, WriteData(entry1, 0, 200, NULL, 0, false));
907 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
908 if (type_ == net::APP_CACHE) {
909 // The list is not updated.
910 EXPECT_EQ(entry2->GetKey(), second);
911 } else {
912 EXPECT_EQ(entry2->GetKey(), first);
913 }
914
915 entry1->Close();
916 entry2->Close();
917 cache_->EndEnumeration(&iter);
918 }
919
TEST_F(DiskCacheBackendTest,Enumerations2)920 TEST_F(DiskCacheBackendTest, Enumerations2) {
921 BackendEnumerations2();
922 }
923
TEST_F(DiskCacheBackendTest,NewEvictionEnumerations2)924 TEST_F(DiskCacheBackendTest, NewEvictionEnumerations2) {
925 SetNewEviction();
926 BackendEnumerations2();
927 }
928
TEST_F(DiskCacheBackendTest,MemoryOnlyEnumerations2)929 TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations2) {
930 SetMemoryOnlyMode();
931 BackendEnumerations2();
932 }
933
TEST_F(DiskCacheBackendTest,AppCacheEnumerations2)934 TEST_F(DiskCacheBackendTest, AppCacheEnumerations2) {
935 SetCacheType(net::APP_CACHE);
936 BackendEnumerations2();
937 }
938
939 // Verify handling of invalid entries while doing enumerations.
940 // We'll be leaking memory from this test.
BackendInvalidEntryEnumeration()941 void DiskCacheBackendTest::BackendInvalidEntryEnumeration() {
942 // Use the implementation directly... we need to simulate a crash.
943 SetDirectMode();
944 InitCache();
945
946 std::string key("Some key");
947 disk_cache::Entry *entry, *entry1, *entry2;
948 ASSERT_EQ(net::OK, CreateEntry(key, &entry1));
949
950 const int kSize = 50;
951 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
952 memset(buffer1->data(), 0, kSize);
953 base::strlcpy(buffer1->data(), "And the data to save", kSize);
954 EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1, kSize, false));
955 entry1->Close();
956 ASSERT_EQ(net::OK, OpenEntry(key, &entry1));
957 EXPECT_EQ(kSize, ReadData(entry1, 0, 0, buffer1, kSize));
958
959 std::string key2("Another key");
960 ASSERT_EQ(net::OK, CreateEntry(key2, &entry2));
961 entry2->Close();
962 ASSERT_EQ(2, cache_->GetEntryCount());
963
964 SimulateCrash();
965
966 void* iter = NULL;
967 int count = 0;
968 while (OpenNextEntry(&iter, &entry) == net::OK) {
969 ASSERT_TRUE(NULL != entry);
970 EXPECT_EQ(key2, entry->GetKey());
971 entry->Close();
972 count++;
973 };
974 EXPECT_EQ(1, count);
975 EXPECT_EQ(1, cache_->GetEntryCount());
976 }
977
978 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,InvalidEntryEnumeration)979 TEST_F(DiskCacheBackendTest, InvalidEntryEnumeration) {
980 BackendInvalidEntryEnumeration();
981 }
982
983 // We'll be leaking memory from this test.
TEST_F(DiskCacheBackendTest,NewEvictionInvalidEntryEnumeration)984 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryEnumeration) {
985 SetNewEviction();
986 BackendInvalidEntryEnumeration();
987 }
988
989 // Tests that if for some reason entries are modified close to existing cache
990 // iterators, we don't generate fatal errors or reset the cache.
BackendFixEnumerators()991 void DiskCacheBackendTest::BackendFixEnumerators() {
992 InitCache();
993
994 int seed = static_cast<int>(Time::Now().ToInternalValue());
995 srand(seed);
996
997 const int kNumEntries = 10;
998 for (int i = 0; i < kNumEntries; i++) {
999 std::string key = GenerateKey(true);
1000 disk_cache::Entry* entry;
1001 ASSERT_EQ(net::OK, CreateEntry(key, &entry));
1002 entry->Close();
1003 }
1004 EXPECT_EQ(kNumEntries, cache_->GetEntryCount());
1005
1006 disk_cache::Entry *entry1, *entry2;
1007 void* iter1 = NULL;
1008 void* iter2 = NULL;
1009 ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1));
1010 ASSERT_TRUE(NULL != entry1);
1011 entry1->Close();
1012 entry1 = NULL;
1013
1014 // Let's go to the middle of the list.
1015 for (int i = 0; i < kNumEntries / 2; i++) {
1016 if (entry1)
1017 entry1->Close();
1018 ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1));
1019 ASSERT_TRUE(NULL != entry1);
1020
1021 ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2));
1022 ASSERT_TRUE(NULL != entry2);
1023 entry2->Close();
1024 }
1025
1026 // Messing up with entry1 will modify entry2->next.
1027 entry1->Doom();
1028 ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2));
1029 ASSERT_TRUE(NULL != entry2);
1030
1031 // The link entry2->entry1 should be broken.
1032 EXPECT_NE(entry2->GetKey(), entry1->GetKey());
1033 entry1->Close();
1034 entry2->Close();
1035
1036 // And the second iterator should keep working.
1037 ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2));
1038 ASSERT_TRUE(NULL != entry2);
1039 entry2->Close();
1040
1041 cache_->EndEnumeration(&iter1);
1042 cache_->EndEnumeration(&iter2);
1043 }
1044
TEST_F(DiskCacheBackendTest,FixEnumerators)1045 TEST_F(DiskCacheBackendTest, FixEnumerators) {
1046 BackendFixEnumerators();
1047 }
1048
TEST_F(DiskCacheBackendTest,NewEvictionFixEnumerators)1049 TEST_F(DiskCacheBackendTest, NewEvictionFixEnumerators) {
1050 SetNewEviction();
1051 BackendFixEnumerators();
1052 }
1053
BackendDoomRecent()1054 void DiskCacheBackendTest::BackendDoomRecent() {
1055 InitCache();
1056 Time initial = Time::Now();
1057
1058 disk_cache::Entry *entry;
1059 ASSERT_EQ(net::OK, CreateEntry("first", &entry));
1060 entry->Close();
1061 ASSERT_EQ(net::OK, CreateEntry("second", &entry));
1062 entry->Close();
1063
1064 base::PlatformThread::Sleep(20);
1065 Time middle = Time::Now();
1066
1067 ASSERT_EQ(net::OK, CreateEntry("third", &entry));
1068 entry->Close();
1069 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry));
1070 entry->Close();
1071
1072 base::PlatformThread::Sleep(20);
1073 Time final = Time::Now();
1074
1075 ASSERT_EQ(4, cache_->GetEntryCount());
1076 EXPECT_EQ(net::OK, DoomEntriesSince(final));
1077 ASSERT_EQ(4, cache_->GetEntryCount());
1078
1079 EXPECT_EQ(net::OK, DoomEntriesSince(middle));
1080 ASSERT_EQ(2, cache_->GetEntryCount());
1081
1082 ASSERT_EQ(net::OK, OpenEntry("second", &entry));
1083 entry->Close();
1084 }
1085
TEST_F(DiskCacheBackendTest,DoomRecent)1086 TEST_F(DiskCacheBackendTest, DoomRecent) {
1087 BackendDoomRecent();
1088 }
1089
TEST_F(DiskCacheBackendTest,NewEvictionDoomRecent)1090 TEST_F(DiskCacheBackendTest, NewEvictionDoomRecent) {
1091 SetNewEviction();
1092 BackendDoomRecent();
1093 }
1094
TEST_F(DiskCacheBackendTest,MemoryOnlyDoomRecent)1095 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomRecent) {
1096 SetMemoryOnlyMode();
1097 BackendDoomRecent();
1098 }
1099
BackendDoomBetween()1100 void DiskCacheBackendTest::BackendDoomBetween() {
1101 InitCache();
1102 Time initial = Time::Now();
1103
1104 disk_cache::Entry *entry;
1105 ASSERT_EQ(net::OK, CreateEntry("first", &entry));
1106 entry->Close();
1107
1108 base::PlatformThread::Sleep(20);
1109 Time middle_start = Time::Now();
1110
1111 ASSERT_EQ(net::OK, CreateEntry("second", &entry));
1112 entry->Close();
1113 ASSERT_EQ(net::OK, CreateEntry("third", &entry));
1114 entry->Close();
1115
1116 base::PlatformThread::Sleep(20);
1117 Time middle_end = Time::Now();
1118
1119 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry));
1120 entry->Close();
1121 ASSERT_EQ(net::OK, OpenEntry("fourth", &entry));
1122 entry->Close();
1123
1124 base::PlatformThread::Sleep(20);
1125 Time final = Time::Now();
1126
1127 ASSERT_EQ(4, cache_->GetEntryCount());
1128 EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, middle_end));
1129 ASSERT_EQ(2, cache_->GetEntryCount());
1130
1131 ASSERT_EQ(net::OK, OpenEntry("fourth", &entry));
1132 entry->Close();
1133
1134 EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, final));
1135 ASSERT_EQ(1, cache_->GetEntryCount());
1136
1137 ASSERT_EQ(net::OK, OpenEntry("first", &entry));
1138 entry->Close();
1139 }
1140
TEST_F(DiskCacheBackendTest,DoomBetween)1141 TEST_F(DiskCacheBackendTest, DoomBetween) {
1142 BackendDoomBetween();
1143 }
1144
TEST_F(DiskCacheBackendTest,NewEvictionDoomBetween)1145 TEST_F(DiskCacheBackendTest, NewEvictionDoomBetween) {
1146 SetNewEviction();
1147 BackendDoomBetween();
1148 }
1149
TEST_F(DiskCacheBackendTest,MemoryOnlyDoomBetween)1150 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomBetween) {
1151 SetMemoryOnlyMode();
1152 BackendDoomBetween();
1153 }
1154
BackendTransaction(const std::string & name,int num_entries,bool load)1155 void DiskCacheBackendTest::BackendTransaction(const std::string& name,
1156 int num_entries, bool load) {
1157 success_ = false;
1158 ASSERT_TRUE(CopyTestCache(name));
1159 DisableFirstCleanup();
1160
1161 if (load) {
1162 SetMask(0xf);
1163 SetMaxSize(0x100000);
1164 } else {
1165 // Clear the settings from the previous run.
1166 SetMask(0);
1167 SetMaxSize(0);
1168 }
1169
1170 InitCache();
1171 ASSERT_EQ(num_entries + 1, cache_->GetEntryCount());
1172
1173 std::string key("the first key");
1174 disk_cache::Entry* entry1;
1175 ASSERT_NE(net::OK, OpenEntry(key, &entry1));
1176
1177 int actual = cache_->GetEntryCount();
1178 if (num_entries != actual) {
1179 ASSERT_TRUE(load);
1180 // If there is a heavy load, inserting an entry will make another entry
1181 // dirty (on the hash bucket) so two entries are removed.
1182 ASSERT_EQ(num_entries - 1, actual);
1183 }
1184
1185 delete cache_;
1186 cache_ = NULL;
1187 cache_impl_ = NULL;
1188
1189 ASSERT_TRUE(CheckCacheIntegrity(GetCacheFilePath(), new_eviction_));
1190 success_ = true;
1191 }
1192
BackendRecoverInsert()1193 void DiskCacheBackendTest::BackendRecoverInsert() {
1194 // Tests with an empty cache.
1195 BackendTransaction("insert_empty1", 0, false);
1196 ASSERT_TRUE(success_) << "insert_empty1";
1197 BackendTransaction("insert_empty2", 0, false);
1198 ASSERT_TRUE(success_) << "insert_empty2";
1199 BackendTransaction("insert_empty3", 0, false);
1200 ASSERT_TRUE(success_) << "insert_empty3";
1201
1202 // Tests with one entry on the cache.
1203 BackendTransaction("insert_one1", 1, false);
1204 ASSERT_TRUE(success_) << "insert_one1";
1205 BackendTransaction("insert_one2", 1, false);
1206 ASSERT_TRUE(success_) << "insert_one2";
1207 BackendTransaction("insert_one3", 1, false);
1208 ASSERT_TRUE(success_) << "insert_one3";
1209
1210 // Tests with one hundred entries on the cache, tiny index.
1211 BackendTransaction("insert_load1", 100, true);
1212 ASSERT_TRUE(success_) << "insert_load1";
1213 BackendTransaction("insert_load2", 100, true);
1214 ASSERT_TRUE(success_) << "insert_load2";
1215 }
1216
TEST_F(DiskCacheBackendTest,RecoverInsert)1217 TEST_F(DiskCacheBackendTest, RecoverInsert) {
1218 BackendRecoverInsert();
1219 }
1220
TEST_F(DiskCacheBackendTest,NewEvictionRecoverInsert)1221 TEST_F(DiskCacheBackendTest, NewEvictionRecoverInsert) {
1222 SetNewEviction();
1223 BackendRecoverInsert();
1224 }
1225
BackendRecoverRemove()1226 void DiskCacheBackendTest::BackendRecoverRemove() {
1227 // Removing the only element.
1228 BackendTransaction("remove_one1", 0, false);
1229 ASSERT_TRUE(success_) << "remove_one1";
1230 BackendTransaction("remove_one2", 0, false);
1231 ASSERT_TRUE(success_) << "remove_one2";
1232 BackendTransaction("remove_one3", 0, false);
1233 ASSERT_TRUE(success_) << "remove_one3";
1234
1235 // Removing the head.
1236 BackendTransaction("remove_head1", 1, false);
1237 ASSERT_TRUE(success_) << "remove_head1";
1238 BackendTransaction("remove_head2", 1, false);
1239 ASSERT_TRUE(success_) << "remove_head2";
1240 BackendTransaction("remove_head3", 1, false);
1241 ASSERT_TRUE(success_) << "remove_head3";
1242
1243 // Removing the tail.
1244 BackendTransaction("remove_tail1", 1, false);
1245 ASSERT_TRUE(success_) << "remove_tail1";
1246 BackendTransaction("remove_tail2", 1, false);
1247 ASSERT_TRUE(success_) << "remove_tail2";
1248 BackendTransaction("remove_tail3", 1, false);
1249 ASSERT_TRUE(success_) << "remove_tail3";
1250
1251 // Removing with one hundred entries on the cache, tiny index.
1252 BackendTransaction("remove_load1", 100, true);
1253 ASSERT_TRUE(success_) << "remove_load1";
1254 BackendTransaction("remove_load2", 100, true);
1255 ASSERT_TRUE(success_) << "remove_load2";
1256 BackendTransaction("remove_load3", 100, true);
1257 ASSERT_TRUE(success_) << "remove_load3";
1258
1259 // This case cannot be reverted.
1260 BackendTransaction("remove_one4", 0, false);
1261 ASSERT_TRUE(success_) << "remove_one4";
1262 BackendTransaction("remove_head4", 1, false);
1263 ASSERT_TRUE(success_) << "remove_head4";
1264 }
1265
TEST_F(DiskCacheBackendTest,RecoverRemove)1266 TEST_F(DiskCacheBackendTest, RecoverRemove) {
1267 BackendRecoverRemove();
1268 }
1269
TEST_F(DiskCacheBackendTest,NewEvictionRecoverRemove)1270 TEST_F(DiskCacheBackendTest, NewEvictionRecoverRemove) {
1271 SetNewEviction();
1272 BackendRecoverRemove();
1273 }
1274
BackendRecoverWithEviction()1275 void DiskCacheBackendTest::BackendRecoverWithEviction() {
1276 success_ = false;
1277 ASSERT_TRUE(CopyTestCache("insert_load1"));
1278 DisableFirstCleanup();
1279
1280 SetMask(0xf);
1281 SetMaxSize(0x1000);
1282
1283 // We should not crash here.
1284 InitCache();
1285 DisableIntegrityCheck();
1286 }
1287
TEST_F(DiskCacheBackendTest,RecoverWithEviction)1288 TEST_F(DiskCacheBackendTest, RecoverWithEviction) {
1289 BackendRecoverWithEviction();
1290 }
1291
TEST_F(DiskCacheBackendTest,NewEvictionRecoverWithEviction)1292 TEST_F(DiskCacheBackendTest, NewEvictionRecoverWithEviction) {
1293 SetNewEviction();
1294 BackendRecoverWithEviction();
1295 }
1296
1297 // Tests dealing with cache files that cannot be recovered.
TEST_F(DiskCacheTest,DeleteOld)1298 TEST_F(DiskCacheTest, DeleteOld) {
1299 ASSERT_TRUE(CopyTestCache("wrong_version"));
1300 FilePath path = GetCacheFilePath();
1301 base::Thread cache_thread("CacheThread");
1302 ASSERT_TRUE(cache_thread.StartWithOptions(
1303 base::Thread::Options(MessageLoop::TYPE_IO, 0)));
1304 TestCompletionCallback cb;
1305
1306 disk_cache::Backend* cache;
1307 int rv = disk_cache::BackendImpl::CreateBackend(
1308 path, true, 0, net::DISK_CACHE, disk_cache::kNoRandom,
1309 cache_thread.message_loop_proxy(), NULL, &cache, &cb);
1310 ASSERT_EQ(net::OK, cb.GetResult(rv));
1311
1312 MessageLoopHelper helper;
1313
1314 ASSERT_TRUE(NULL != cache);
1315 ASSERT_EQ(0, cache->GetEntryCount());
1316
1317 delete cache;
1318 }
1319
1320 // We want to be able to deal with messed up entries on disk.
BackendInvalidEntry2()1321 void DiskCacheBackendTest::BackendInvalidEntry2() {
1322 ASSERT_TRUE(CopyTestCache("bad_entry"));
1323 DisableFirstCleanup();
1324 InitCache();
1325
1326 disk_cache::Entry *entry1, *entry2;
1327 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
1328 EXPECT_NE(net::OK, OpenEntry("some other key", &entry2));
1329 entry1->Close();
1330
1331 // CheckCacheIntegrity will fail at this point.
1332 DisableIntegrityCheck();
1333 }
1334
TEST_F(DiskCacheBackendTest,InvalidEntry2)1335 TEST_F(DiskCacheBackendTest, InvalidEntry2) {
1336 BackendInvalidEntry2();
1337 }
1338
TEST_F(DiskCacheBackendTest,NewEvictionInvalidEntry2)1339 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry2) {
1340 SetNewEviction();
1341 BackendInvalidEntry2();
1342 }
1343
1344 // Tests that we don't crash or hang when enumerating this cache.
BackendInvalidEntry3()1345 void DiskCacheBackendTest::BackendInvalidEntry3() {
1346 SetMask(0x1); // 2-entry table.
1347 SetMaxSize(0x3000); // 12 kB.
1348 DisableFirstCleanup();
1349 InitCache();
1350
1351 disk_cache::Entry* entry;
1352 void* iter = NULL;
1353 while (OpenNextEntry(&iter, &entry) == net::OK) {
1354 entry->Close();
1355 }
1356 }
1357
TEST_F(DiskCacheBackendTest,InvalidEntry3)1358 TEST_F(DiskCacheBackendTest, InvalidEntry3) {
1359 ASSERT_TRUE(CopyTestCache("dirty_entry3"));
1360 BackendInvalidEntry3();
1361 }
1362
TEST_F(DiskCacheBackendTest,NewEvictionInvalidEntry3)1363 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry3) {
1364 ASSERT_TRUE(CopyTestCache("dirty_entry4"));
1365 SetNewEviction();
1366 BackendInvalidEntry3();
1367 DisableIntegrityCheck();
1368 }
1369
1370 // Test that we handle a dirty entry on the LRU list, already replaced with
1371 // the same key, and with hash collisions.
TEST_F(DiskCacheBackendTest,InvalidEntry4)1372 TEST_F(DiskCacheBackendTest, InvalidEntry4) {
1373 ASSERT_TRUE(CopyTestCache("dirty_entry3"));
1374 SetMask(0x1); // 2-entry table.
1375 SetMaxSize(0x3000); // 12 kB.
1376 DisableFirstCleanup();
1377 InitCache();
1378
1379 TrimForTest(false);
1380 }
1381
1382 // Test that we handle a dirty entry on the deleted list, already replaced with
1383 // the same key, and with hash collisions.
TEST_F(DiskCacheBackendTest,InvalidEntry5)1384 TEST_F(DiskCacheBackendTest, InvalidEntry5) {
1385 ASSERT_TRUE(CopyTestCache("dirty_entry4"));
1386 SetNewEviction();
1387 SetMask(0x1); // 2-entry table.
1388 SetMaxSize(0x3000); // 12 kB.
1389 DisableFirstCleanup();
1390 InitCache();
1391
1392 TrimDeletedListForTest(false);
1393 }
1394
TEST_F(DiskCacheBackendTest,InvalidEntry6)1395 TEST_F(DiskCacheBackendTest, InvalidEntry6) {
1396 ASSERT_TRUE(CopyTestCache("dirty_entry5"));
1397 SetMask(0x1); // 2-entry table.
1398 SetMaxSize(0x3000); // 12 kB.
1399 DisableFirstCleanup();
1400 InitCache();
1401
1402 // There is a dirty entry (but marked as clean) at the end, pointing to a
1403 // deleted entry through the hash collision list. We should not re-insert the
1404 // deleted entry into the index table.
1405
1406 TrimForTest(false);
1407 // The cache should be clean (as detected by CheckCacheIntegrity).
1408 }
1409
1410 // Tests that we don't hang when there is a loop on the hash collision list.
1411 // The test cache could be a result of bug 69135.
TEST_F(DiskCacheBackendTest,BadNextEntry1)1412 TEST_F(DiskCacheBackendTest, BadNextEntry1) {
1413 ASSERT_TRUE(CopyTestCache("list_loop2"));
1414 SetMask(0x1); // 2-entry table.
1415 SetMaxSize(0x3000); // 12 kB.
1416 DisableFirstCleanup();
1417 InitCache();
1418
1419 // The second entry points at itselft, and the first entry is not accessible
1420 // though the index, but it is at the head of the LRU.
1421
1422 disk_cache::Entry* entry;
1423 ASSERT_EQ(net::OK, CreateEntry("The first key", &entry));
1424 entry->Close();
1425
1426 TrimForTest(false);
1427 TrimForTest(false);
1428 ASSERT_EQ(net::OK, OpenEntry("The first key", &entry));
1429 entry->Close();
1430 EXPECT_EQ(1, cache_->GetEntryCount());
1431 }
1432
1433 // Tests that we don't hang when there is a loop on the hash collision list.
1434 // The test cache could be a result of bug 69135.
TEST_F(DiskCacheBackendTest,BadNextEntry2)1435 TEST_F(DiskCacheBackendTest, BadNextEntry2) {
1436 ASSERT_TRUE(CopyTestCache("list_loop3"));
1437 SetMask(0x1); // 2-entry table.
1438 SetMaxSize(0x3000); // 12 kB.
1439 DisableFirstCleanup();
1440 InitCache();
1441
1442 // There is a wide loop of 5 entries.
1443
1444 disk_cache::Entry* entry;
1445 ASSERT_NE(net::OK, OpenEntry("Not present key", &entry));
1446 }
1447
TEST_F(DiskCacheBackendTest,NewEvictionInvalidEntry6)1448 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry6) {
1449 ASSERT_TRUE(CopyTestCache("bad_rankings3"));
1450 DisableFirstCleanup();
1451 SetNewEviction();
1452 InitCache();
1453
1454 // The second entry is dirty, but removing it should not corrupt the list.
1455 disk_cache::Entry* entry;
1456 ASSERT_NE(net::OK, OpenEntry("the second key", &entry));
1457 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry));
1458
1459 // This should not delete the cache.
1460 entry->Doom();
1461 FlushQueueForTest();
1462 entry->Close();
1463
1464 ASSERT_EQ(net::OK, OpenEntry("some other key", &entry));
1465 entry->Close();
1466 }
1467
1468 // We want to be able to deal with abnormal dirty entries.
BackendNotMarkedButDirty(const std::string & name)1469 void DiskCacheBackendTest::BackendNotMarkedButDirty(const std::string& name) {
1470 ASSERT_TRUE(CopyTestCache(name));
1471 DisableFirstCleanup();
1472 InitCache();
1473
1474 disk_cache::Entry *entry1, *entry2;
1475 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
1476 EXPECT_NE(net::OK, OpenEntry("some other key", &entry2));
1477 entry1->Close();
1478 }
1479
TEST_F(DiskCacheBackendTest,NotMarkedButDirty)1480 TEST_F(DiskCacheBackendTest, NotMarkedButDirty) {
1481 BackendNotMarkedButDirty("dirty_entry");
1482 }
1483
TEST_F(DiskCacheBackendTest,NewEvictionNotMarkedButDirty)1484 TEST_F(DiskCacheBackendTest, NewEvictionNotMarkedButDirty) {
1485 SetNewEviction();
1486 BackendNotMarkedButDirty("dirty_entry");
1487 }
1488
TEST_F(DiskCacheBackendTest,NotMarkedButDirty2)1489 TEST_F(DiskCacheBackendTest, NotMarkedButDirty2) {
1490 BackendNotMarkedButDirty("dirty_entry2");
1491 }
1492
TEST_F(DiskCacheBackendTest,NewEvictionNotMarkedButDirty2)1493 TEST_F(DiskCacheBackendTest, NewEvictionNotMarkedButDirty2) {
1494 SetNewEviction();
1495 BackendNotMarkedButDirty("dirty_entry2");
1496 }
1497
1498 // We want to be able to deal with messed up entries on disk.
BackendInvalidRankings2()1499 void DiskCacheBackendTest::BackendInvalidRankings2() {
1500 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1501 FilePath path = GetCacheFilePath();
1502 DisableFirstCleanup();
1503 InitCache();
1504
1505 disk_cache::Entry *entry1, *entry2;
1506 EXPECT_NE(net::OK, OpenEntry("the first key", &entry1));
1507 ASSERT_EQ(net::OK, OpenEntry("some other key", &entry2));
1508 entry2->Close();
1509
1510 // CheckCacheIntegrity will fail at this point.
1511 DisableIntegrityCheck();
1512 }
1513
TEST_F(DiskCacheBackendTest,InvalidRankings2)1514 TEST_F(DiskCacheBackendTest, InvalidRankings2) {
1515 BackendInvalidRankings2();
1516 }
1517
TEST_F(DiskCacheBackendTest,NewEvictionInvalidRankings2)1518 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankings2) {
1519 SetNewEviction();
1520 BackendInvalidRankings2();
1521 }
1522
1523 // If the LRU is corrupt, we delete the cache.
BackendInvalidRankings()1524 void DiskCacheBackendTest::BackendInvalidRankings() {
1525 disk_cache::Entry* entry;
1526 void* iter = NULL;
1527 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
1528 entry->Close();
1529 EXPECT_EQ(2, cache_->GetEntryCount());
1530
1531 EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
1532 FlushQueueForTest(); // Allow the restart to finish.
1533 EXPECT_EQ(0, cache_->GetEntryCount());
1534 }
1535
TEST_F(DiskCacheBackendTest,InvalidRankingsSuccess)1536 TEST_F(DiskCacheBackendTest, InvalidRankingsSuccess) {
1537 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1538 DisableFirstCleanup();
1539 SetDirectMode();
1540 InitCache();
1541 BackendInvalidRankings();
1542 }
1543
TEST_F(DiskCacheBackendTest,NewEvictionInvalidRankingsSuccess)1544 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsSuccess) {
1545 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1546 DisableFirstCleanup();
1547 SetDirectMode();
1548 SetNewEviction();
1549 InitCache();
1550 BackendInvalidRankings();
1551 }
1552
TEST_F(DiskCacheBackendTest,InvalidRankingsFailure)1553 TEST_F(DiskCacheBackendTest, InvalidRankingsFailure) {
1554 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1555 DisableFirstCleanup();
1556 SetDirectMode();
1557 InitCache();
1558 SetTestMode(); // Fail cache reinitialization.
1559 BackendInvalidRankings();
1560 }
1561
TEST_F(DiskCacheBackendTest,NewEvictionInvalidRankingsFailure)1562 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsFailure) {
1563 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1564 DisableFirstCleanup();
1565 SetDirectMode();
1566 SetNewEviction();
1567 InitCache();
1568 SetTestMode(); // Fail cache reinitialization.
1569 BackendInvalidRankings();
1570 }
1571
1572 // If the LRU is corrupt and we have open entries, we disable the cache.
BackendDisable()1573 void DiskCacheBackendTest::BackendDisable() {
1574 disk_cache::Entry *entry1, *entry2;
1575 void* iter = NULL;
1576 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
1577
1578 EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2));
1579 EXPECT_EQ(0, cache_->GetEntryCount());
1580 EXPECT_NE(net::OK, CreateEntry("Something new", &entry2));
1581
1582 entry1->Close();
1583 FlushQueueForTest(); // Flushing the Close posts a task to restart the cache.
1584 FlushQueueForTest(); // This one actually allows that task to complete.
1585
1586 EXPECT_EQ(0, cache_->GetEntryCount());
1587 }
1588
TEST_F(DiskCacheBackendTest,DisableSuccess)1589 TEST_F(DiskCacheBackendTest, DisableSuccess) {
1590 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1591 DisableFirstCleanup();
1592 SetDirectMode();
1593 InitCache();
1594 BackendDisable();
1595 }
1596
TEST_F(DiskCacheBackendTest,NewEvictionDisableSuccess)1597 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess) {
1598 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1599 DisableFirstCleanup();
1600 SetDirectMode();
1601 SetNewEviction();
1602 InitCache();
1603 BackendDisable();
1604 }
1605
TEST_F(DiskCacheBackendTest,DisableFailure)1606 TEST_F(DiskCacheBackendTest, DisableFailure) {
1607 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1608 DisableFirstCleanup();
1609 SetDirectMode();
1610 InitCache();
1611 SetTestMode(); // Fail cache reinitialization.
1612 BackendDisable();
1613 }
1614
TEST_F(DiskCacheBackendTest,NewEvictionDisableFailure)1615 TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure) {
1616 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1617 DisableFirstCleanup();
1618 SetDirectMode();
1619 SetNewEviction();
1620 InitCache();
1621 SetTestMode(); // Fail cache reinitialization.
1622 BackendDisable();
1623 }
1624
1625 // This is another type of corruption on the LRU; disable the cache.
BackendDisable2()1626 void DiskCacheBackendTest::BackendDisable2() {
1627 EXPECT_EQ(8, cache_->GetEntryCount());
1628
1629 disk_cache::Entry* entry;
1630 void* iter = NULL;
1631 int count = 0;
1632 while (OpenNextEntry(&iter, &entry) == net::OK) {
1633 ASSERT_TRUE(NULL != entry);
1634 entry->Close();
1635 count++;
1636 ASSERT_LT(count, 9);
1637 };
1638
1639 FlushQueueForTest();
1640 EXPECT_EQ(0, cache_->GetEntryCount());
1641 }
1642
TEST_F(DiskCacheBackendTest,DisableSuccess2)1643 TEST_F(DiskCacheBackendTest, DisableSuccess2) {
1644 ASSERT_TRUE(CopyTestCache("list_loop"));
1645 DisableFirstCleanup();
1646 SetDirectMode();
1647 InitCache();
1648 BackendDisable2();
1649 }
1650
TEST_F(DiskCacheBackendTest,NewEvictionDisableSuccess2)1651 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess2) {
1652 ASSERT_TRUE(CopyTestCache("list_loop"));
1653 DisableFirstCleanup();
1654 SetNewEviction();
1655 SetDirectMode();
1656 InitCache();
1657 BackendDisable2();
1658 }
1659
TEST_F(DiskCacheBackendTest,DisableFailure2)1660 TEST_F(DiskCacheBackendTest, DisableFailure2) {
1661 ASSERT_TRUE(CopyTestCache("list_loop"));
1662 DisableFirstCleanup();
1663 SetDirectMode();
1664 InitCache();
1665 SetTestMode(); // Fail cache reinitialization.
1666 BackendDisable2();
1667 }
1668
TEST_F(DiskCacheBackendTest,NewEvictionDisableFailure2)1669 TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure2) {
1670 ASSERT_TRUE(CopyTestCache("list_loop"));
1671 DisableFirstCleanup();
1672 SetDirectMode();
1673 SetNewEviction();
1674 InitCache();
1675 SetTestMode(); // Fail cache reinitialization.
1676 BackendDisable2();
1677 }
1678
1679 // If the index size changes when we disable the cache, we should not crash.
BackendDisable3()1680 void DiskCacheBackendTest::BackendDisable3() {
1681 disk_cache::Entry *entry1, *entry2;
1682 void* iter = NULL;
1683 EXPECT_EQ(2, cache_->GetEntryCount());
1684 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
1685 entry1->Close();
1686
1687 EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2));
1688 FlushQueueForTest();
1689
1690 ASSERT_EQ(net::OK, CreateEntry("Something new", &entry2));
1691 entry2->Close();
1692
1693 EXPECT_EQ(1, cache_->GetEntryCount());
1694 }
1695
TEST_F(DiskCacheBackendTest,DisableSuccess3)1696 TEST_F(DiskCacheBackendTest, DisableSuccess3) {
1697 ASSERT_TRUE(CopyTestCache("bad_rankings2"));
1698 DisableFirstCleanup();
1699 SetMaxSize(20 * 1024 * 1024);
1700 InitCache();
1701 BackendDisable3();
1702 }
1703
TEST_F(DiskCacheBackendTest,NewEvictionDisableSuccess3)1704 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess3) {
1705 ASSERT_TRUE(CopyTestCache("bad_rankings2"));
1706 DisableFirstCleanup();
1707 SetMaxSize(20 * 1024 * 1024);
1708 SetNewEviction();
1709 InitCache();
1710 BackendDisable3();
1711 }
1712
1713 // If we disable the cache, already open entries should work as far as possible.
BackendDisable4()1714 void DiskCacheBackendTest::BackendDisable4() {
1715 disk_cache::Entry *entry1, *entry2, *entry3, *entry4;
1716 void* iter = NULL;
1717 ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
1718
1719 char key2[2000];
1720 char key3[20000];
1721 CacheTestFillBuffer(key2, sizeof(key2), true);
1722 CacheTestFillBuffer(key3, sizeof(key3), true);
1723 key2[sizeof(key2) - 1] = '\0';
1724 key3[sizeof(key3) - 1] = '\0';
1725 ASSERT_EQ(net::OK, CreateEntry(key2, &entry2));
1726 ASSERT_EQ(net::OK, CreateEntry(key3, &entry3));
1727
1728 const int kBufSize = 20000;
1729 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufSize));
1730 memset(buf->data(), 0, kBufSize);
1731 EXPECT_EQ(100, WriteData(entry2, 0, 0, buf, 100, false));
1732 EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf, kBufSize, false));
1733
1734 // This line should disable the cache but not delete it.
1735 EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry4));
1736 EXPECT_EQ(0, cache_->GetEntryCount());
1737
1738 EXPECT_NE(net::OK, CreateEntry("cache is disabled", &entry4));
1739
1740 EXPECT_EQ(100, ReadData(entry2, 0, 0, buf, 100));
1741 EXPECT_EQ(100, WriteData(entry2, 0, 0, buf, 100, false));
1742 EXPECT_EQ(100, WriteData(entry2, 1, 0, buf, 100, false));
1743
1744 EXPECT_EQ(kBufSize, ReadData(entry3, 0, 0, buf, kBufSize));
1745 EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf, kBufSize, false));
1746 EXPECT_EQ(kBufSize, WriteData(entry3, 1, 0, buf, kBufSize, false));
1747
1748 std::string key = entry2->GetKey();
1749 EXPECT_EQ(sizeof(key2) - 1, key.size());
1750 key = entry3->GetKey();
1751 EXPECT_EQ(sizeof(key3) - 1, key.size());
1752
1753 entry1->Close();
1754 entry2->Close();
1755 entry3->Close();
1756 FlushQueueForTest(); // Flushing the Close posts a task to restart the cache.
1757 FlushQueueForTest(); // This one actually allows that task to complete.
1758
1759 EXPECT_EQ(0, cache_->GetEntryCount());
1760 }
1761
TEST_F(DiskCacheBackendTest,DisableSuccess4)1762 TEST_F(DiskCacheBackendTest, DisableSuccess4) {
1763 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1764 DisableFirstCleanup();
1765 SetDirectMode();
1766 InitCache();
1767 BackendDisable4();
1768 }
1769
TEST_F(DiskCacheBackendTest,NewEvictionDisableSuccess4)1770 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess4) {
1771 ASSERT_TRUE(CopyTestCache("bad_rankings"));
1772 DisableFirstCleanup();
1773 SetDirectMode();
1774 SetNewEviction();
1775 InitCache();
1776 BackendDisable4();
1777 }
1778
TEST_F(DiskCacheTest,Backend_UsageStats)1779 TEST_F(DiskCacheTest, Backend_UsageStats) {
1780 MessageLoopHelper helper;
1781
1782 FilePath path = GetCacheFilePath();
1783 ASSERT_TRUE(DeleteCache(path));
1784 scoped_ptr<disk_cache::BackendImpl> cache;
1785 cache.reset(new disk_cache::BackendImpl(
1786 path, base::MessageLoopProxy::CreateForCurrentThread(),
1787 NULL));
1788 ASSERT_TRUE(NULL != cache.get());
1789 cache->SetUnitTestMode();
1790 ASSERT_EQ(net::OK, cache->SyncInit());
1791
1792 // Wait for a callback that never comes... about 2 secs :). The message loop
1793 // has to run to allow invocation of the usage timer.
1794 helper.WaitUntilCacheIoFinished(1);
1795 }
1796
BackendDoomAll()1797 void DiskCacheBackendTest::BackendDoomAll() {
1798 InitCache();
1799 Time initial = Time::Now();
1800
1801 disk_cache::Entry *entry1, *entry2;
1802 ASSERT_EQ(net::OK, CreateEntry("first", &entry1));
1803 ASSERT_EQ(net::OK, CreateEntry("second", &entry2));
1804 entry1->Close();
1805 entry2->Close();
1806
1807 ASSERT_EQ(net::OK, CreateEntry("third", &entry1));
1808 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2));
1809
1810 ASSERT_EQ(4, cache_->GetEntryCount());
1811 EXPECT_EQ(net::OK, DoomAllEntries());
1812 ASSERT_EQ(0, cache_->GetEntryCount());
1813
1814 // We should stop posting tasks at some point (if we post any).
1815 MessageLoop::current()->RunAllPending();
1816
1817 disk_cache::Entry *entry3, *entry4;
1818 ASSERT_EQ(net::OK, CreateEntry("third", &entry3));
1819 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry4));
1820
1821 EXPECT_EQ(net::OK, DoomAllEntries());
1822 ASSERT_EQ(0, cache_->GetEntryCount());
1823
1824 entry1->Close();
1825 entry2->Close();
1826 entry3->Doom(); // The entry should be already doomed, but this must work.
1827 entry3->Close();
1828 entry4->Close();
1829
1830 // Now try with all references released.
1831 ASSERT_EQ(net::OK, CreateEntry("third", &entry1));
1832 ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2));
1833 entry1->Close();
1834 entry2->Close();
1835
1836 ASSERT_EQ(2, cache_->GetEntryCount());
1837 EXPECT_EQ(net::OK, DoomAllEntries());
1838 ASSERT_EQ(0, cache_->GetEntryCount());
1839 }
1840
TEST_F(DiskCacheBackendTest,DoomAll)1841 TEST_F(DiskCacheBackendTest, DoomAll) {
1842 BackendDoomAll();
1843 }
1844
TEST_F(DiskCacheBackendTest,NewEvictionDoomAll)1845 TEST_F(DiskCacheBackendTest, NewEvictionDoomAll) {
1846 SetNewEviction();
1847 BackendDoomAll();
1848 }
1849
TEST_F(DiskCacheBackendTest,MemoryOnlyDoomAll)1850 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomAll) {
1851 SetMemoryOnlyMode();
1852 BackendDoomAll();
1853 }
1854
TEST_F(DiskCacheBackendTest,AppCacheOnlyDoomAll)1855 TEST_F(DiskCacheBackendTest, AppCacheOnlyDoomAll) {
1856 SetCacheType(net::APP_CACHE);
1857 BackendDoomAll();
1858 }
1859
1860 // If the index size changes when we doom the cache, we should not crash.
BackendDoomAll2()1861 void DiskCacheBackendTest::BackendDoomAll2() {
1862 EXPECT_EQ(2, cache_->GetEntryCount());
1863 EXPECT_EQ(net::OK, DoomAllEntries());
1864
1865 disk_cache::Entry* entry;
1866 ASSERT_EQ(net::OK, CreateEntry("Something new", &entry));
1867 entry->Close();
1868
1869 EXPECT_EQ(1, cache_->GetEntryCount());
1870 }
1871
TEST_F(DiskCacheBackendTest,DoomAll2)1872 TEST_F(DiskCacheBackendTest, DoomAll2) {
1873 ASSERT_TRUE(CopyTestCache("bad_rankings2"));
1874 DisableFirstCleanup();
1875 SetMaxSize(20 * 1024 * 1024);
1876 InitCache();
1877 BackendDoomAll2();
1878 }
1879
TEST_F(DiskCacheBackendTest,NewEvictionDoomAll2)1880 TEST_F(DiskCacheBackendTest, NewEvictionDoomAll2) {
1881 ASSERT_TRUE(CopyTestCache("bad_rankings2"));
1882 DisableFirstCleanup();
1883 SetMaxSize(20 * 1024 * 1024);
1884 SetNewEviction();
1885 InitCache();
1886 BackendDoomAll2();
1887 }
1888
1889 // We should be able to create the same entry on multiple simultaneous instances
1890 // of the cache.
TEST_F(DiskCacheTest,MultipleInstances)1891 TEST_F(DiskCacheTest, MultipleInstances) {
1892 ScopedTestCache store1;
1893 ScopedTestCache store2("cache_test2");
1894 ScopedTestCache store3("cache_test3");
1895 base::Thread cache_thread("CacheThread");
1896 ASSERT_TRUE(cache_thread.StartWithOptions(
1897 base::Thread::Options(MessageLoop::TYPE_IO, 0)));
1898 TestCompletionCallback cb;
1899
1900 const int kNumberOfCaches = 2;
1901 disk_cache::Backend* cache[kNumberOfCaches];
1902
1903 int rv = disk_cache::BackendImpl::CreateBackend(
1904 store1.path(), false, 0, net::DISK_CACHE, disk_cache::kNone,
1905 cache_thread.message_loop_proxy(), NULL, &cache[0], &cb);
1906 ASSERT_EQ(net::OK, cb.GetResult(rv));
1907 rv = disk_cache::BackendImpl::CreateBackend(
1908 store2.path(), false, 0, net::MEDIA_CACHE, disk_cache::kNone,
1909 cache_thread.message_loop_proxy(), NULL, &cache[1], &cb);
1910 ASSERT_EQ(net::OK, cb.GetResult(rv));
1911
1912 ASSERT_TRUE(cache[0] != NULL && cache[1] != NULL);
1913
1914 std::string key("the first key");
1915 disk_cache::Entry* entry;
1916 for (int i = 0; i < kNumberOfCaches; i++) {
1917 rv = cache[i]->CreateEntry(key, &entry, &cb);
1918 ASSERT_EQ(net::OK, cb.GetResult(rv));
1919 entry->Close();
1920 }
1921 delete cache[0];
1922 delete cache[1];
1923 }
1924
1925 // Test the six regions of the curve that determines the max cache size.
TEST_F(DiskCacheTest,AutomaticMaxSize)1926 TEST_F(DiskCacheTest, AutomaticMaxSize) {
1927 const int kDefaultSize = 80 * 1024 * 1024;
1928 int64 large_size = kDefaultSize;
1929 int64 largest_size = kint32max;
1930
1931 // Region 1: expected = available * 0.8
1932 EXPECT_EQ((kDefaultSize - 1) * 8 / 10,
1933 disk_cache::PreferedCacheSize(large_size - 1));
1934 EXPECT_EQ(kDefaultSize * 8 / 10,
1935 disk_cache::PreferedCacheSize(large_size));
1936 EXPECT_EQ(kDefaultSize - 1,
1937 disk_cache::PreferedCacheSize(large_size * 10 / 8 - 1));
1938
1939 // Region 2: expected = default_size
1940 EXPECT_EQ(kDefaultSize,
1941 disk_cache::PreferedCacheSize(large_size * 10 / 8));
1942 EXPECT_EQ(kDefaultSize,
1943 disk_cache::PreferedCacheSize(large_size * 10 - 1));
1944
1945 // Region 3: expected = available * 0.1
1946 EXPECT_EQ(kDefaultSize,
1947 disk_cache::PreferedCacheSize(large_size * 10));
1948 EXPECT_EQ((kDefaultSize * 25 - 1) / 10,
1949 disk_cache::PreferedCacheSize(large_size * 25 - 1));
1950
1951 // Region 4: expected = default_size * 2.5
1952 EXPECT_EQ(kDefaultSize * 25 / 10,
1953 disk_cache::PreferedCacheSize(large_size * 25));
1954 EXPECT_EQ(kDefaultSize * 25 / 10,
1955 disk_cache::PreferedCacheSize(large_size * 100 - 1));
1956 EXPECT_EQ(kDefaultSize * 25 / 10,
1957 disk_cache::PreferedCacheSize(large_size * 100));
1958 EXPECT_EQ(kDefaultSize * 25 / 10,
1959 disk_cache::PreferedCacheSize(large_size * 250 - 1));
1960
1961 // Region 5: expected = available * 0.1
1962 EXPECT_EQ(kDefaultSize * 25 / 10,
1963 disk_cache::PreferedCacheSize(large_size * 250));
1964 EXPECT_EQ(kint32max - 1,
1965 disk_cache::PreferedCacheSize(largest_size * 100 - 1));
1966
1967 // Region 6: expected = kint32max
1968 EXPECT_EQ(kint32max,
1969 disk_cache::PreferedCacheSize(largest_size * 100));
1970 EXPECT_EQ(kint32max,
1971 disk_cache::PreferedCacheSize(largest_size * 10000));
1972 }
1973
1974 // Tests that we can "migrate" a running instance from one experiment group to
1975 // another.
TEST_F(DiskCacheBackendTest,Histograms)1976 TEST_F(DiskCacheBackendTest, Histograms) {
1977 SetDirectMode();
1978 InitCache();
1979 disk_cache::BackendImpl* backend_ = cache_impl_; // Needed be the macro.
1980
1981 for (int i = 1; i < 3; i++) {
1982 CACHE_UMA(HOURS, "FillupTime", i, 28);
1983 }
1984 }
1985
1986 // Make sure that we keep the total memory used by the internal buffers under
1987 // control.
TEST_F(DiskCacheBackendTest,TotalBuffersSize1)1988 TEST_F(DiskCacheBackendTest, TotalBuffersSize1) {
1989 SetDirectMode();
1990 InitCache();
1991 std::string key("the first key");
1992 disk_cache::Entry* entry;
1993 ASSERT_EQ(net::OK, CreateEntry(key, &entry));
1994
1995 const int kSize = 200;
1996 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
1997 CacheTestFillBuffer(buffer->data(), kSize, true);
1998
1999 for (int i = 0; i < 10; i++) {
2000 SCOPED_TRACE(i);
2001 // Allocate 2MB for this entry.
2002 EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, true));
2003 EXPECT_EQ(kSize, WriteData(entry, 1, 0, buffer, kSize, true));
2004 EXPECT_EQ(kSize, WriteData(entry, 0, 1024 * 1024, buffer, kSize, false));
2005 EXPECT_EQ(kSize, WriteData(entry, 1, 1024 * 1024, buffer, kSize, false));
2006
2007 // Delete one of the buffers and truncate the other.
2008 EXPECT_EQ(0, WriteData(entry, 0, 0, buffer, 0, true));
2009 EXPECT_EQ(0, WriteData(entry, 1, 10, buffer, 0, true));
2010
2011 // Delete the second buffer, writing 10 bytes to disk.
2012 entry->Close();
2013 ASSERT_EQ(net::OK, OpenEntry(key, &entry));
2014 }
2015
2016 entry->Close();
2017 EXPECT_EQ(0, cache_impl_->GetTotalBuffersSize());
2018 }
2019
2020 // This test assumes at least 150MB of system memory.
TEST_F(DiskCacheBackendTest,TotalBuffersSize2)2021 TEST_F(DiskCacheBackendTest, TotalBuffersSize2) {
2022 SetDirectMode();
2023 InitCache();
2024
2025 const int kOneMB = 1024 * 1024;
2026 EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB));
2027 EXPECT_EQ(kOneMB, cache_impl_->GetTotalBuffersSize());
2028
2029 EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB));
2030 EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize());
2031
2032 EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB));
2033 EXPECT_EQ(kOneMB * 3, cache_impl_->GetTotalBuffersSize());
2034
2035 cache_impl_->BufferDeleted(kOneMB);
2036 EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize());
2037
2038 // Check the upper limit.
2039 EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, 30 * kOneMB));
2040
2041 for (int i = 0; i < 30; i++)
2042 cache_impl_->IsAllocAllowed(0, kOneMB); // Ignore the result.
2043
2044 EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, kOneMB));
2045 }
2046
2047 // Tests that sharing of external files works and we are able to delete the
2048 // files when we need to.
TEST_F(DiskCacheBackendTest,FileSharing)2049 TEST_F(DiskCacheBackendTest, FileSharing) {
2050 SetDirectMode();
2051 InitCache();
2052
2053 disk_cache::Addr address(0x80000001);
2054 ASSERT_TRUE(cache_impl_->CreateExternalFile(&address));
2055 FilePath name = cache_impl_->GetFileName(address);
2056
2057 scoped_refptr<disk_cache::File> file(new disk_cache::File(false));
2058 file->Init(name);
2059
2060 #if defined(OS_WIN)
2061 DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
2062 DWORD access = GENERIC_READ | GENERIC_WRITE;
2063 base::win::ScopedHandle file2(CreateFile(
2064 name.value().c_str(), access, sharing, NULL, OPEN_EXISTING, 0, NULL));
2065 EXPECT_FALSE(file2.IsValid());
2066
2067 sharing |= FILE_SHARE_DELETE;
2068 file2.Set(CreateFile(name.value().c_str(), access, sharing, NULL,
2069 OPEN_EXISTING, 0, NULL));
2070 EXPECT_TRUE(file2.IsValid());
2071 #endif
2072
2073 EXPECT_TRUE(file_util::Delete(name, false));
2074
2075 // We should be able to use the file.
2076 const int kSize = 200;
2077 char buffer1[kSize];
2078 char buffer2[kSize];
2079 memset(buffer1, 't', kSize);
2080 memset(buffer2, 0, kSize);
2081 EXPECT_TRUE(file->Write(buffer1, kSize, 0));
2082 EXPECT_TRUE(file->Read(buffer2, kSize, 0));
2083 EXPECT_EQ(0, memcmp(buffer1, buffer2, kSize));
2084
2085 EXPECT_TRUE(disk_cache::DeleteCacheFile(name));
2086 }
2087