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