- add sources.
[platform/framework/web/crosswalk.git] / src / net / disk_cache / backend_unittest.cc
1 // Copyright (c) 2012 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/metrics/field_trial.h"
8 #include "base/port.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
12 #include "base/threading/platform_thread.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "net/base/cache_type.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/disk_cache/backend_impl.h"
19 #include "net/disk_cache/cache_util.h"
20 #include "net/disk_cache/disk_cache_test_base.h"
21 #include "net/disk_cache/disk_cache_test_util.h"
22 #include "net/disk_cache/entry_impl.h"
23 #include "net/disk_cache/experiments.h"
24 #include "net/disk_cache/histogram_macros.h"
25 #include "net/disk_cache/mapped_file.h"
26 #include "net/disk_cache/mem_backend_impl.h"
27 #include "net/disk_cache/simple/simple_backend_impl.h"
28 #include "net/disk_cache/simple/simple_entry_format.h"
29 #include "net/disk_cache/simple/simple_test_util.h"
30 #include "net/disk_cache/simple/simple_util.h"
31 #include "net/disk_cache/tracing_cache_backend.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33
34 #if defined(OS_WIN)
35 #include "base/win/scoped_handle.h"
36 #endif
37
38 using base::Time;
39
40 namespace {
41
42 const char kExistingEntryKey[] = "existing entry key";
43
44 scoped_ptr<disk_cache::BackendImpl> CreateExistingEntryCache(
45     const base::Thread& cache_thread,
46     base::FilePath& cache_path) {
47   net::TestCompletionCallback cb;
48
49   scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
50       cache_path, cache_thread.message_loop_proxy(), NULL));
51   int rv = cache->Init(cb.callback());
52   if (cb.GetResult(rv) != net::OK)
53     return scoped_ptr<disk_cache::BackendImpl>();
54
55   disk_cache::Entry* entry = NULL;
56   rv = cache->CreateEntry(kExistingEntryKey, &entry, cb.callback());
57   if (cb.GetResult(rv) != net::OK)
58     return scoped_ptr<disk_cache::BackendImpl>();
59   entry->Close();
60
61   return cache.Pass();
62 }
63
64 }  // namespace
65
66 // Tests that can run with different types of caches.
67 class DiskCacheBackendTest : public DiskCacheTestWithCache {
68  protected:
69   // Some utility methods:
70
71   // Perform IO operations on the cache until there is pending IO.
72   int GeneratePendingIO(net::TestCompletionCallback* cb);
73
74   // Adds 5 sparse entries. |doomed_start| and |doomed_end| if not NULL,
75   // will be filled with times, used by DoomEntriesSince and DoomEntriesBetween.
76   // There are 4 entries after doomed_start and 2 after doomed_end.
77   void InitSparseCache(base::Time* doomed_start, base::Time* doomed_end);
78
79   bool CreateSetOfRandomEntries(std::set<std::string>* key_pool);
80   bool EnumerateAndMatchKeys(int max_to_open,
81                              void** iter,
82                              std::set<std::string>* keys_to_match,
83                              size_t* count);
84
85   // Actual tests:
86   void BackendBasics();
87   void BackendKeying();
88   void BackendShutdownWithPendingFileIO(bool fast);
89   void BackendShutdownWithPendingIO(bool fast);
90   void BackendShutdownWithPendingCreate(bool fast);
91   void BackendSetSize();
92   void BackendLoad();
93   void BackendChain();
94   void BackendValidEntry();
95   void BackendInvalidEntry();
96   void BackendInvalidEntryRead();
97   void BackendInvalidEntryWithLoad();
98   void BackendTrimInvalidEntry();
99   void BackendTrimInvalidEntry2();
100   void BackendEnumerations();
101   void BackendEnumerations2();
102   void BackendInvalidEntryEnumeration();
103   void BackendFixEnumerators();
104   void BackendDoomRecent();
105   void BackendDoomBetween();
106   void BackendTransaction(const std::string& name, int num_entries, bool load);
107   void BackendRecoverInsert();
108   void BackendRecoverRemove();
109   void BackendRecoverWithEviction();
110   void BackendInvalidEntry2();
111   void BackendInvalidEntry3();
112   void BackendInvalidEntry7();
113   void BackendInvalidEntry8();
114   void BackendInvalidEntry9(bool eviction);
115   void BackendInvalidEntry10(bool eviction);
116   void BackendInvalidEntry11(bool eviction);
117   void BackendTrimInvalidEntry12();
118   void BackendDoomAll();
119   void BackendDoomAll2();
120   void BackendInvalidRankings();
121   void BackendInvalidRankings2();
122   void BackendDisable();
123   void BackendDisable2();
124   void BackendDisable3();
125   void BackendDisable4();
126   void TracingBackendBasics();
127 };
128
129 int DiskCacheBackendTest::GeneratePendingIO(net::TestCompletionCallback* cb) {
130   if (!use_current_thread_) {
131     ADD_FAILURE();
132     return net::ERR_FAILED;
133   }
134
135   disk_cache::Entry* entry;
136   int rv = cache_->CreateEntry("some key", &entry, cb->callback());
137   if (cb->GetResult(rv) != net::OK)
138     return net::ERR_CACHE_CREATE_FAILURE;
139
140   const int kSize = 25000;
141   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
142   CacheTestFillBuffer(buffer->data(), kSize, false);
143
144   for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) {
145     // We are using the current thread as the cache thread because we want to
146     // be able to call directly this method to make sure that the OS (instead
147     // of us switching thread) is returning IO pending.
148     if (!simple_cache_mode_) {
149       rv = static_cast<disk_cache::EntryImpl*>(entry)->WriteDataImpl(
150           0, i, buffer.get(), kSize, cb->callback(), false);
151     } else {
152       rv = entry->WriteData(0, i, buffer.get(), kSize, cb->callback(), false);
153     }
154
155     if (rv == net::ERR_IO_PENDING)
156       break;
157     if (rv != kSize)
158       rv = net::ERR_FAILED;
159   }
160
161   // Don't call Close() to avoid going through the queue or we'll deadlock
162   // waiting for the operation to finish.
163   if (!simple_cache_mode_)
164     static_cast<disk_cache::EntryImpl*>(entry)->Release();
165   else
166     entry->Close();
167
168   return rv;
169 }
170
171 void DiskCacheBackendTest::InitSparseCache(base::Time* doomed_start,
172                                            base::Time* doomed_end) {
173   InitCache();
174
175   const int kSize = 50;
176   // This must be greater then MemEntryImpl::kMaxSparseEntrySize.
177   const int kOffset = 10 + 1024 * 1024;
178
179   disk_cache::Entry* entry0 = NULL;
180   disk_cache::Entry* entry1 = NULL;
181   disk_cache::Entry* entry2 = NULL;
182
183   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
184   CacheTestFillBuffer(buffer->data(), kSize, false);
185
186   ASSERT_EQ(net::OK, CreateEntry("zeroth", &entry0));
187   ASSERT_EQ(kSize, WriteSparseData(entry0, 0, buffer.get(), kSize));
188   ASSERT_EQ(kSize,
189             WriteSparseData(entry0, kOffset + kSize, buffer.get(), kSize));
190   entry0->Close();
191
192   FlushQueueForTest();
193   AddDelay();
194   if (doomed_start)
195     *doomed_start = base::Time::Now();
196
197   // Order in rankings list:
198   // first_part1, first_part2, second_part1, second_part2
199   ASSERT_EQ(net::OK, CreateEntry("first", &entry1));
200   ASSERT_EQ(kSize, WriteSparseData(entry1, 0, buffer.get(), kSize));
201   ASSERT_EQ(kSize,
202             WriteSparseData(entry1, kOffset + kSize, buffer.get(), kSize));
203   entry1->Close();
204
205   ASSERT_EQ(net::OK, CreateEntry("second", &entry2));
206   ASSERT_EQ(kSize, WriteSparseData(entry2, 0, buffer.get(), kSize));
207   ASSERT_EQ(kSize,
208             WriteSparseData(entry2, kOffset + kSize, buffer.get(), kSize));
209   entry2->Close();
210
211   FlushQueueForTest();
212   AddDelay();
213   if (doomed_end)
214     *doomed_end = base::Time::Now();
215
216   // Order in rankings list:
217   // third_part1, fourth_part1, third_part2, fourth_part2
218   disk_cache::Entry* entry3 = NULL;
219   disk_cache::Entry* entry4 = NULL;
220   ASSERT_EQ(net::OK, CreateEntry("third", &entry3));
221   ASSERT_EQ(kSize, WriteSparseData(entry3, 0, buffer.get(), kSize));
222   ASSERT_EQ(net::OK, CreateEntry("fourth", &entry4));
223   ASSERT_EQ(kSize, WriteSparseData(entry4, 0, buffer.get(), kSize));
224   ASSERT_EQ(kSize,
225             WriteSparseData(entry3, kOffset + kSize, buffer.get(), kSize));
226   ASSERT_EQ(kSize,
227             WriteSparseData(entry4, kOffset + kSize, buffer.get(), kSize));
228   entry3->Close();
229   entry4->Close();
230
231   FlushQueueForTest();
232   AddDelay();
233 }
234
235 // Creates entries based on random keys. Stores these keys in |key_pool|.
236 bool DiskCacheBackendTest::CreateSetOfRandomEntries(
237     std::set<std::string>* key_pool) {
238   const int kNumEntries = 10;
239
240   for (int i = 0; i < kNumEntries; ++i) {
241     std::string key = GenerateKey(true);
242     disk_cache::Entry* entry;
243     if (CreateEntry(key, &entry) != net::OK)
244       return false;
245     key_pool->insert(key);
246     entry->Close();
247   }
248   return key_pool->size() == implicit_cast<size_t>(cache_->GetEntryCount());
249 }
250
251 // Performs iteration over the backend and checks that the keys of entries
252 // opened are in |keys_to_match|, then erases them. Up to |max_to_open| entries
253 // will be opened, if it is positive. Otherwise, iteration will continue until
254 // OpenNextEntry stops returning net::OK.
255 bool DiskCacheBackendTest::EnumerateAndMatchKeys(
256     int max_to_open,
257     void** iter,
258     std::set<std::string>* keys_to_match,
259     size_t* count) {
260   disk_cache::Entry* entry;
261
262   while (OpenNextEntry(iter, &entry) == net::OK) {
263     if (!entry)
264       return false;
265     EXPECT_EQ(1U, keys_to_match->erase(entry->GetKey()));
266     entry->Close();
267     ++(*count);
268     if (max_to_open >= 0 && implicit_cast<int>(*count) >= max_to_open)
269       break;
270   };
271
272   return true;
273 }
274
275 void DiskCacheBackendTest::BackendBasics() {
276   InitCache();
277   disk_cache::Entry *entry1 = NULL, *entry2 = NULL;
278   EXPECT_NE(net::OK, OpenEntry("the first key", &entry1));
279   ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1));
280   ASSERT_TRUE(NULL != entry1);
281   entry1->Close();
282   entry1 = NULL;
283
284   ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
285   ASSERT_TRUE(NULL != entry1);
286   entry1->Close();
287   entry1 = NULL;
288
289   EXPECT_NE(net::OK, CreateEntry("the first key", &entry1));
290   ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
291   EXPECT_NE(net::OK, OpenEntry("some other key", &entry2));
292   ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2));
293   ASSERT_TRUE(NULL != entry1);
294   ASSERT_TRUE(NULL != entry2);
295   EXPECT_EQ(2, cache_->GetEntryCount());
296
297   disk_cache::Entry* entry3 = NULL;
298   ASSERT_EQ(net::OK, OpenEntry("some other key", &entry3));
299   ASSERT_TRUE(NULL != entry3);
300   EXPECT_TRUE(entry2 == entry3);
301   EXPECT_EQ(2, cache_->GetEntryCount());
302
303   EXPECT_EQ(net::OK, DoomEntry("some other key"));
304   EXPECT_EQ(1, cache_->GetEntryCount());
305   entry1->Close();
306   entry2->Close();
307   entry3->Close();
308
309   EXPECT_EQ(net::OK, DoomEntry("the first key"));
310   EXPECT_EQ(0, cache_->GetEntryCount());
311
312   ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1));
313   ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2));
314   entry1->Doom();
315   entry1->Close();
316   EXPECT_EQ(net::OK, DoomEntry("some other key"));
317   EXPECT_EQ(0, cache_->GetEntryCount());
318   entry2->Close();
319 }
320
321 TEST_F(DiskCacheBackendTest, Basics) {
322   BackendBasics();
323 }
324
325 TEST_F(DiskCacheBackendTest, NewEvictionBasics) {
326   SetNewEviction();
327   BackendBasics();
328 }
329
330 TEST_F(DiskCacheBackendTest, MemoryOnlyBasics) {
331   SetMemoryOnlyMode();
332   BackendBasics();
333 }
334
335 TEST_F(DiskCacheBackendTest, AppCacheBasics) {
336   SetCacheType(net::APP_CACHE);
337   BackendBasics();
338 }
339
340 TEST_F(DiskCacheBackendTest, ShaderCacheBasics) {
341   SetCacheType(net::SHADER_CACHE);
342   BackendBasics();
343 }
344
345 void DiskCacheBackendTest::BackendKeying() {
346   InitCache();
347   const char* kName1 = "the first key";
348   const char* kName2 = "the first Key";
349   disk_cache::Entry *entry1, *entry2;
350   ASSERT_EQ(net::OK, CreateEntry(kName1, &entry1));
351
352   ASSERT_EQ(net::OK, CreateEntry(kName2, &entry2));
353   EXPECT_TRUE(entry1 != entry2) << "Case sensitive";
354   entry2->Close();
355
356   char buffer[30];
357   base::strlcpy(buffer, kName1, arraysize(buffer));
358   ASSERT_EQ(net::OK, OpenEntry(buffer, &entry2));
359   EXPECT_TRUE(entry1 == entry2);
360   entry2->Close();
361
362   base::strlcpy(buffer + 1, kName1, arraysize(buffer) - 1);
363   ASSERT_EQ(net::OK, OpenEntry(buffer + 1, &entry2));
364   EXPECT_TRUE(entry1 == entry2);
365   entry2->Close();
366
367   base::strlcpy(buffer + 3,  kName1, arraysize(buffer) - 3);
368   ASSERT_EQ(net::OK, OpenEntry(buffer + 3, &entry2));
369   EXPECT_TRUE(entry1 == entry2);
370   entry2->Close();
371
372   // Now verify long keys.
373   char buffer2[20000];
374   memset(buffer2, 's', sizeof(buffer2));
375   buffer2[1023] = '\0';
376   ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on block file";
377   entry2->Close();
378
379   buffer2[1023] = 'g';
380   buffer2[19999] = '\0';
381   ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on external file";
382   entry2->Close();
383   entry1->Close();
384 }
385
386 TEST_F(DiskCacheBackendTest, Keying) {
387   BackendKeying();
388 }
389
390 TEST_F(DiskCacheBackendTest, NewEvictionKeying) {
391   SetNewEviction();
392   BackendKeying();
393 }
394
395 TEST_F(DiskCacheBackendTest, MemoryOnlyKeying) {
396   SetMemoryOnlyMode();
397   BackendKeying();
398 }
399
400 TEST_F(DiskCacheBackendTest, AppCacheKeying) {
401   SetCacheType(net::APP_CACHE);
402   BackendKeying();
403 }
404
405 TEST_F(DiskCacheBackendTest, ShaderCacheKeying) {
406   SetCacheType(net::SHADER_CACHE);
407   BackendKeying();
408 }
409
410 TEST_F(DiskCacheTest, CreateBackend) {
411   net::TestCompletionCallback cb;
412
413   {
414     ASSERT_TRUE(CleanupCacheDir());
415     base::Thread cache_thread("CacheThread");
416     ASSERT_TRUE(cache_thread.StartWithOptions(
417         base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
418
419     // Test the private factory method(s).
420     scoped_ptr<disk_cache::Backend> cache;
421     cache = disk_cache::MemBackendImpl::CreateBackend(0, NULL);
422     ASSERT_TRUE(cache.get());
423     cache.reset();
424
425     // Now test the public API.
426     int rv =
427         disk_cache::CreateCacheBackend(net::DISK_CACHE,
428                                        net::CACHE_BACKEND_DEFAULT,
429                                        cache_path_,
430                                        0,
431                                        false,
432                                        cache_thread.message_loop_proxy().get(),
433                                        NULL,
434                                        &cache,
435                                        cb.callback());
436     ASSERT_EQ(net::OK, cb.GetResult(rv));
437     ASSERT_TRUE(cache.get());
438     cache.reset();
439
440     rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE,
441                                         net::CACHE_BACKEND_DEFAULT,
442                                         base::FilePath(), 0,
443                                         false, NULL, NULL, &cache,
444                                         cb.callback());
445     ASSERT_EQ(net::OK, cb.GetResult(rv));
446     ASSERT_TRUE(cache.get());
447     cache.reset();
448   }
449
450   base::MessageLoop::current()->RunUntilIdle();
451 }
452
453 // Tests that |BackendImpl| fails to initialize with a missing file.
454 TEST_F(DiskCacheBackendTest, CreateBackend_MissingFile) {
455   ASSERT_TRUE(CopyTestCache("bad_entry"));
456   base::FilePath filename = cache_path_.AppendASCII("data_1");
457   base::DeleteFile(filename, false);
458   base::Thread cache_thread("CacheThread");
459   ASSERT_TRUE(cache_thread.StartWithOptions(
460       base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
461   net::TestCompletionCallback cb;
462
463   bool prev = base::ThreadRestrictions::SetIOAllowed(false);
464   scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
465       cache_path_, cache_thread.message_loop_proxy().get(), NULL));
466   int rv = cache->Init(cb.callback());
467   EXPECT_EQ(net::ERR_FAILED, cb.GetResult(rv));
468   base::ThreadRestrictions::SetIOAllowed(prev);
469
470   cache.reset();
471   DisableIntegrityCheck();
472 }
473
474 TEST_F(DiskCacheBackendTest, ExternalFiles) {
475   InitCache();
476   // First, let's create a file on the folder.
477   base::FilePath filename = cache_path_.AppendASCII("f_000001");
478
479   const int kSize = 50;
480   scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
481   CacheTestFillBuffer(buffer1->data(), kSize, false);
482   ASSERT_EQ(kSize, file_util::WriteFile(filename, buffer1->data(), kSize));
483
484   // Now let's create a file with the cache.
485   disk_cache::Entry* entry;
486   ASSERT_EQ(net::OK, CreateEntry("key", &entry));
487   ASSERT_EQ(0, WriteData(entry, 0, 20000, buffer1.get(), 0, false));
488   entry->Close();
489
490   // And verify that the first file is still there.
491   scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
492   ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize));
493   EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize));
494 }
495
496 // Tests that we deal with file-level pending operations at destruction time.
497 void DiskCacheBackendTest::BackendShutdownWithPendingFileIO(bool fast) {
498   ASSERT_TRUE(CleanupCacheDir());
499   uint32 flags = disk_cache::kNoBuffering;
500   if (!fast)
501     flags |= disk_cache::kNoRandom;
502
503   UseCurrentThread();
504   CreateBackend(flags, NULL);
505
506   net::TestCompletionCallback cb;
507   int rv = GeneratePendingIO(&cb);
508
509   // The cache destructor will see one pending operation here.
510   cache_.reset();
511
512   if (rv == net::ERR_IO_PENDING) {
513     if (fast || simple_cache_mode_)
514       EXPECT_FALSE(cb.have_result());
515     else
516       EXPECT_TRUE(cb.have_result());
517   }
518
519   base::MessageLoop::current()->RunUntilIdle();
520
521   // Wait for the actual operation to complete, or we'll keep a file handle that
522   // may cause issues later.
523   rv = cb.GetResult(rv);
524 }
525
526 TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO) {
527   BackendShutdownWithPendingFileIO(false);
528 }
529
530 // Here and below, tests that simulate crashes are not compiled in LeakSanitizer
531 // builds because they contain a lot of intentional memory leaks.
532 // The wrapper scripts used to run tests under Valgrind Memcheck and
533 // Heapchecker will also disable these tests under those tools. See:
534 // tools/valgrind/gtest_exclude/net_unittests.gtest-memcheck.txt
535 // tools/heapcheck/net_unittests.gtest-heapcheck.txt
536 #if !defined(LEAK_SANITIZER)
537 // We'll be leaking from this test.
538 TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO_Fast) {
539   // The integrity test sets kNoRandom so there's a version mismatch if we don't
540   // force new eviction.
541   SetNewEviction();
542   BackendShutdownWithPendingFileIO(true);
543 }
544 #endif
545
546 // Tests that one cache instance is not affected by another one going away.
547 TEST_F(DiskCacheBackendTest, MultipleInstancesWithPendingFileIO) {
548   base::ScopedTempDir store;
549   ASSERT_TRUE(store.CreateUniqueTempDir());
550
551   net::TestCompletionCallback cb;
552   scoped_ptr<disk_cache::Backend> extra_cache;
553   int rv = disk_cache::CreateCacheBackend(
554                net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, store.path(), 0,
555                false, base::MessageLoopProxy::current().get(), NULL,
556                &extra_cache, cb.callback());
557   ASSERT_EQ(net::OK, cb.GetResult(rv));
558   ASSERT_TRUE(extra_cache.get() != NULL);
559
560   ASSERT_TRUE(CleanupCacheDir());
561   SetNewEviction();  // Match the expected behavior for integrity verification.
562   UseCurrentThread();
563
564   CreateBackend(disk_cache::kNoBuffering, NULL);
565   rv = GeneratePendingIO(&cb);
566
567   // cache_ has a pending operation, and extra_cache will go away.
568   extra_cache.reset();
569
570   if (rv == net::ERR_IO_PENDING)
571     EXPECT_FALSE(cb.have_result());
572
573   base::MessageLoop::current()->RunUntilIdle();
574
575   // Wait for the actual operation to complete, or we'll keep a file handle that
576   // may cause issues later.
577   rv = cb.GetResult(rv);
578 }
579
580 // Tests that we deal with background-thread pending operations.
581 void DiskCacheBackendTest::BackendShutdownWithPendingIO(bool fast) {
582   net::TestCompletionCallback cb;
583
584   {
585     ASSERT_TRUE(CleanupCacheDir());
586     base::Thread cache_thread("CacheThread");
587     ASSERT_TRUE(cache_thread.StartWithOptions(
588         base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
589
590     uint32 flags = disk_cache::kNoBuffering;
591     if (!fast)
592       flags |= disk_cache::kNoRandom;
593
594     CreateBackend(flags, &cache_thread);
595
596     disk_cache::Entry* entry;
597     int rv = cache_->CreateEntry("some key", &entry, cb.callback());
598     ASSERT_EQ(net::OK, cb.GetResult(rv));
599
600     entry->Close();
601
602     // The cache destructor will see one pending operation here.
603     cache_.reset();
604   }
605
606   base::MessageLoop::current()->RunUntilIdle();
607 }
608
609 TEST_F(DiskCacheBackendTest, ShutdownWithPendingIO) {
610   BackendShutdownWithPendingIO(false);
611 }
612
613 #if !defined(LEAK_SANITIZER)
614 // We'll be leaking from this test.
615 TEST_F(DiskCacheBackendTest, ShutdownWithPendingIO_Fast) {
616   // The integrity test sets kNoRandom so there's a version mismatch if we don't
617   // force new eviction.
618   SetNewEviction();
619   BackendShutdownWithPendingIO(true);
620 }
621 #endif
622
623 // Tests that we deal with create-type pending operations.
624 void DiskCacheBackendTest::BackendShutdownWithPendingCreate(bool fast) {
625   net::TestCompletionCallback cb;
626
627   {
628     ASSERT_TRUE(CleanupCacheDir());
629     base::Thread cache_thread("CacheThread");
630     ASSERT_TRUE(cache_thread.StartWithOptions(
631         base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
632
633     disk_cache::BackendFlags flags =
634       fast ? disk_cache::kNone : disk_cache::kNoRandom;
635     CreateBackend(flags, &cache_thread);
636
637     disk_cache::Entry* entry;
638     int rv = cache_->CreateEntry("some key", &entry, cb.callback());
639     ASSERT_EQ(net::ERR_IO_PENDING, rv);
640
641     cache_.reset();
642     EXPECT_FALSE(cb.have_result());
643   }
644
645   base::MessageLoop::current()->RunUntilIdle();
646 }
647
648 TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate) {
649   BackendShutdownWithPendingCreate(false);
650 }
651
652 #if !defined(LEAK_SANITIZER)
653 // We'll be leaking an entry from this test.
654 TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate_Fast) {
655   // The integrity test sets kNoRandom so there's a version mismatch if we don't
656   // force new eviction.
657   SetNewEviction();
658   BackendShutdownWithPendingCreate(true);
659 }
660 #endif
661
662 TEST_F(DiskCacheTest, TruncatedIndex) {
663   ASSERT_TRUE(CleanupCacheDir());
664   base::FilePath index = cache_path_.AppendASCII("index");
665   ASSERT_EQ(5, file_util::WriteFile(index, "hello", 5));
666
667   base::Thread cache_thread("CacheThread");
668   ASSERT_TRUE(cache_thread.StartWithOptions(
669       base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
670   net::TestCompletionCallback cb;
671
672   scoped_ptr<disk_cache::Backend> backend;
673   int rv =
674       disk_cache::CreateCacheBackend(net::DISK_CACHE,
675                                      net::CACHE_BACKEND_BLOCKFILE,
676                                      cache_path_,
677                                      0,
678                                      false,
679                                      cache_thread.message_loop_proxy().get(),
680                                      NULL,
681                                      &backend,
682                                      cb.callback());
683   ASSERT_NE(net::OK, cb.GetResult(rv));
684
685   ASSERT_FALSE(backend);
686 }
687
688 void DiskCacheBackendTest::BackendSetSize() {
689   const int cache_size = 0x10000;  // 64 kB
690   SetMaxSize(cache_size);
691   InitCache();
692
693   std::string first("some key");
694   std::string second("something else");
695   disk_cache::Entry* entry;
696   ASSERT_EQ(net::OK, CreateEntry(first, &entry));
697
698   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(cache_size));
699   memset(buffer->data(), 0, cache_size);
700   EXPECT_EQ(cache_size / 10,
701             WriteData(entry, 0, 0, buffer.get(), cache_size / 10, false))
702       << "normal file";
703
704   EXPECT_EQ(net::ERR_FAILED,
705             WriteData(entry, 1, 0, buffer.get(), cache_size / 5, false))
706       << "file size above the limit";
707
708   // By doubling the total size, we make this file cacheable.
709   SetMaxSize(cache_size * 2);
710   EXPECT_EQ(cache_size / 5,
711             WriteData(entry, 1, 0, buffer.get(), cache_size / 5, false));
712
713   // Let's fill up the cache!.
714   SetMaxSize(cache_size * 10);
715   EXPECT_EQ(cache_size * 3 / 4,
716             WriteData(entry, 0, 0, buffer.get(), cache_size * 3 / 4, false));
717   entry->Close();
718   FlushQueueForTest();
719
720   SetMaxSize(cache_size);
721
722   // The cache is 95% full.
723
724   ASSERT_EQ(net::OK, CreateEntry(second, &entry));
725   EXPECT_EQ(cache_size / 10,
726             WriteData(entry, 0, 0, buffer.get(), cache_size / 10, false));
727
728   disk_cache::Entry* entry2;
729   ASSERT_EQ(net::OK, CreateEntry("an extra key", &entry2));
730   EXPECT_EQ(cache_size / 10,
731             WriteData(entry2, 0, 0, buffer.get(), cache_size / 10, false));
732   entry2->Close();  // This will trigger the cache trim.
733
734   EXPECT_NE(net::OK, OpenEntry(first, &entry2));
735
736   FlushQueueForTest();  // Make sure that we are done trimming the cache.
737   FlushQueueForTest();  // We may have posted two tasks to evict stuff.
738
739   entry->Close();
740   ASSERT_EQ(net::OK, OpenEntry(second, &entry));
741   EXPECT_EQ(cache_size / 10, entry->GetDataSize(0));
742   entry->Close();
743 }
744
745 TEST_F(DiskCacheBackendTest, SetSize) {
746   BackendSetSize();
747 }
748
749 TEST_F(DiskCacheBackendTest, NewEvictionSetSize) {
750   SetNewEviction();
751   BackendSetSize();
752 }
753
754 TEST_F(DiskCacheBackendTest, MemoryOnlySetSize) {
755   SetMemoryOnlyMode();
756   BackendSetSize();
757 }
758
759 void DiskCacheBackendTest::BackendLoad() {
760   InitCache();
761   int seed = static_cast<int>(Time::Now().ToInternalValue());
762   srand(seed);
763
764   disk_cache::Entry* entries[100];
765   for (int i = 0; i < 100; i++) {
766     std::string key = GenerateKey(true);
767     ASSERT_EQ(net::OK, CreateEntry(key, &entries[i]));
768   }
769   EXPECT_EQ(100, cache_->GetEntryCount());
770
771   for (int i = 0; i < 100; i++) {
772     int source1 = rand() % 100;
773     int source2 = rand() % 100;
774     disk_cache::Entry* temp = entries[source1];
775     entries[source1] = entries[source2];
776     entries[source2] = temp;
777   }
778
779   for (int i = 0; i < 100; i++) {
780     disk_cache::Entry* entry;
781     ASSERT_EQ(net::OK, OpenEntry(entries[i]->GetKey(), &entry));
782     EXPECT_TRUE(entry == entries[i]);
783     entry->Close();
784     entries[i]->Doom();
785     entries[i]->Close();
786   }
787   FlushQueueForTest();
788   EXPECT_EQ(0, cache_->GetEntryCount());
789 }
790
791 TEST_F(DiskCacheBackendTest, Load) {
792   // Work with a tiny index table (16 entries)
793   SetMask(0xf);
794   SetMaxSize(0x100000);
795   BackendLoad();
796 }
797
798 TEST_F(DiskCacheBackendTest, NewEvictionLoad) {
799   SetNewEviction();
800   // Work with a tiny index table (16 entries)
801   SetMask(0xf);
802   SetMaxSize(0x100000);
803   BackendLoad();
804 }
805
806 TEST_F(DiskCacheBackendTest, MemoryOnlyLoad) {
807   SetMaxSize(0x100000);
808   SetMemoryOnlyMode();
809   BackendLoad();
810 }
811
812 TEST_F(DiskCacheBackendTest, AppCacheLoad) {
813   SetCacheType(net::APP_CACHE);
814   // Work with a tiny index table (16 entries)
815   SetMask(0xf);
816   SetMaxSize(0x100000);
817   BackendLoad();
818 }
819
820 TEST_F(DiskCacheBackendTest, ShaderCacheLoad) {
821   SetCacheType(net::SHADER_CACHE);
822   // Work with a tiny index table (16 entries)
823   SetMask(0xf);
824   SetMaxSize(0x100000);
825   BackendLoad();
826 }
827
828 // Tests the chaining of an entry to the current head.
829 void DiskCacheBackendTest::BackendChain() {
830   SetMask(0x1);  // 2-entry table.
831   SetMaxSize(0x3000);  // 12 kB.
832   InitCache();
833
834   disk_cache::Entry* entry;
835   ASSERT_EQ(net::OK, CreateEntry("The first key", &entry));
836   entry->Close();
837   ASSERT_EQ(net::OK, CreateEntry("The Second key", &entry));
838   entry->Close();
839 }
840
841 TEST_F(DiskCacheBackendTest, Chain) {
842   BackendChain();
843 }
844
845 TEST_F(DiskCacheBackendTest, NewEvictionChain) {
846   SetNewEviction();
847   BackendChain();
848 }
849
850 TEST_F(DiskCacheBackendTest, AppCacheChain) {
851   SetCacheType(net::APP_CACHE);
852   BackendChain();
853 }
854
855 TEST_F(DiskCacheBackendTest, ShaderCacheChain) {
856   SetCacheType(net::SHADER_CACHE);
857   BackendChain();
858 }
859
860 TEST_F(DiskCacheBackendTest, NewEvictionTrim) {
861   SetNewEviction();
862   InitCache();
863
864   disk_cache::Entry* entry;
865   for (int i = 0; i < 100; i++) {
866     std::string name(base::StringPrintf("Key %d", i));
867     ASSERT_EQ(net::OK, CreateEntry(name, &entry));
868     entry->Close();
869     if (i < 90) {
870       // Entries 0 to 89 are in list 1; 90 to 99 are in list 0.
871       ASSERT_EQ(net::OK, OpenEntry(name, &entry));
872       entry->Close();
873     }
874   }
875
876   // The first eviction must come from list 1 (10% limit), the second must come
877   // from list 0.
878   TrimForTest(false);
879   EXPECT_NE(net::OK, OpenEntry("Key 0", &entry));
880   TrimForTest(false);
881   EXPECT_NE(net::OK, OpenEntry("Key 90", &entry));
882
883   // Double check that we still have the list tails.
884   ASSERT_EQ(net::OK, OpenEntry("Key 1", &entry));
885   entry->Close();
886   ASSERT_EQ(net::OK, OpenEntry("Key 91", &entry));
887   entry->Close();
888 }
889
890 // Before looking for invalid entries, let's check a valid entry.
891 void DiskCacheBackendTest::BackendValidEntry() {
892   InitCache();
893
894   std::string key("Some key");
895   disk_cache::Entry* entry;
896   ASSERT_EQ(net::OK, CreateEntry(key, &entry));
897
898   const int kSize = 50;
899   scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
900   memset(buffer1->data(), 0, kSize);
901   base::strlcpy(buffer1->data(), "And the data to save", kSize);
902   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer1.get(), kSize, false));
903   entry->Close();
904   SimulateCrash();
905
906   ASSERT_EQ(net::OK, OpenEntry(key, &entry));
907
908   scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
909   memset(buffer2->data(), 0, kSize);
910   EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer2.get(), kSize));
911   entry->Close();
912   EXPECT_STREQ(buffer1->data(), buffer2->data());
913 }
914
915 TEST_F(DiskCacheBackendTest, ValidEntry) {
916   BackendValidEntry();
917 }
918
919 TEST_F(DiskCacheBackendTest, NewEvictionValidEntry) {
920   SetNewEviction();
921   BackendValidEntry();
922 }
923
924 // The same logic of the previous test (ValidEntry), but this time force the
925 // entry to be invalid, simulating a crash in the middle.
926 // We'll be leaking memory from this test.
927 void DiskCacheBackendTest::BackendInvalidEntry() {
928   InitCache();
929
930   std::string key("Some key");
931   disk_cache::Entry* entry;
932   ASSERT_EQ(net::OK, CreateEntry(key, &entry));
933
934   const int kSize = 50;
935   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
936   memset(buffer->data(), 0, kSize);
937   base::strlcpy(buffer->data(), "And the data to save", kSize);
938   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
939   SimulateCrash();
940
941   EXPECT_NE(net::OK, OpenEntry(key, &entry));
942   EXPECT_EQ(0, cache_->GetEntryCount());
943 }
944
945 #if !defined(LEAK_SANITIZER)
946 // We'll be leaking memory from this test.
947 TEST_F(DiskCacheBackendTest, InvalidEntry) {
948   BackendInvalidEntry();
949 }
950
951 // We'll be leaking memory from this test.
952 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry) {
953   SetNewEviction();
954   BackendInvalidEntry();
955 }
956
957 // We'll be leaking memory from this test.
958 TEST_F(DiskCacheBackendTest, AppCacheInvalidEntry) {
959   SetCacheType(net::APP_CACHE);
960   BackendInvalidEntry();
961 }
962
963 // We'll be leaking memory from this test.
964 TEST_F(DiskCacheBackendTest, ShaderCacheInvalidEntry) {
965   SetCacheType(net::SHADER_CACHE);
966   BackendInvalidEntry();
967 }
968
969 // Almost the same test, but this time crash the cache after reading an entry.
970 // We'll be leaking memory from this test.
971 void DiskCacheBackendTest::BackendInvalidEntryRead() {
972   InitCache();
973
974   std::string key("Some key");
975   disk_cache::Entry* entry;
976   ASSERT_EQ(net::OK, CreateEntry(key, &entry));
977
978   const int kSize = 50;
979   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
980   memset(buffer->data(), 0, kSize);
981   base::strlcpy(buffer->data(), "And the data to save", kSize);
982   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
983   entry->Close();
984   ASSERT_EQ(net::OK, OpenEntry(key, &entry));
985   EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer.get(), kSize));
986
987   SimulateCrash();
988
989   if (type_ == net::APP_CACHE) {
990     // Reading an entry and crashing should not make it dirty.
991     ASSERT_EQ(net::OK, OpenEntry(key, &entry));
992     EXPECT_EQ(1, cache_->GetEntryCount());
993     entry->Close();
994   } else {
995     EXPECT_NE(net::OK, OpenEntry(key, &entry));
996     EXPECT_EQ(0, cache_->GetEntryCount());
997   }
998 }
999
1000 // We'll be leaking memory from this test.
1001 TEST_F(DiskCacheBackendTest, InvalidEntryRead) {
1002   BackendInvalidEntryRead();
1003 }
1004
1005 // We'll be leaking memory from this test.
1006 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryRead) {
1007   SetNewEviction();
1008   BackendInvalidEntryRead();
1009 }
1010
1011 // We'll be leaking memory from this test.
1012 TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryRead) {
1013   SetCacheType(net::APP_CACHE);
1014   BackendInvalidEntryRead();
1015 }
1016
1017 // We'll be leaking memory from this test.
1018 TEST_F(DiskCacheBackendTest, ShaderCacheInvalidEntryRead) {
1019   SetCacheType(net::SHADER_CACHE);
1020   BackendInvalidEntryRead();
1021 }
1022
1023 // We'll be leaking memory from this test.
1024 void DiskCacheBackendTest::BackendInvalidEntryWithLoad() {
1025   // Work with a tiny index table (16 entries)
1026   SetMask(0xf);
1027   SetMaxSize(0x100000);
1028   InitCache();
1029
1030   int seed = static_cast<int>(Time::Now().ToInternalValue());
1031   srand(seed);
1032
1033   const int kNumEntries = 100;
1034   disk_cache::Entry* entries[kNumEntries];
1035   for (int i = 0; i < kNumEntries; i++) {
1036     std::string key = GenerateKey(true);
1037     ASSERT_EQ(net::OK, CreateEntry(key, &entries[i]));
1038   }
1039   EXPECT_EQ(kNumEntries, cache_->GetEntryCount());
1040
1041   for (int i = 0; i < kNumEntries; i++) {
1042     int source1 = rand() % kNumEntries;
1043     int source2 = rand() % kNumEntries;
1044     disk_cache::Entry* temp = entries[source1];
1045     entries[source1] = entries[source2];
1046     entries[source2] = temp;
1047   }
1048
1049   std::string keys[kNumEntries];
1050   for (int i = 0; i < kNumEntries; i++) {
1051     keys[i] = entries[i]->GetKey();
1052     if (i < kNumEntries / 2)
1053       entries[i]->Close();
1054   }
1055
1056   SimulateCrash();
1057
1058   for (int i = kNumEntries / 2; i < kNumEntries; i++) {
1059     disk_cache::Entry* entry;
1060     EXPECT_NE(net::OK, OpenEntry(keys[i], &entry));
1061   }
1062
1063   for (int i = 0; i < kNumEntries / 2; i++) {
1064     disk_cache::Entry* entry;
1065     ASSERT_EQ(net::OK, OpenEntry(keys[i], &entry));
1066     entry->Close();
1067   }
1068
1069   EXPECT_EQ(kNumEntries / 2, cache_->GetEntryCount());
1070 }
1071
1072 // We'll be leaking memory from this test.
1073 TEST_F(DiskCacheBackendTest, InvalidEntryWithLoad) {
1074   BackendInvalidEntryWithLoad();
1075 }
1076
1077 // We'll be leaking memory from this test.
1078 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryWithLoad) {
1079   SetNewEviction();
1080   BackendInvalidEntryWithLoad();
1081 }
1082
1083 // We'll be leaking memory from this test.
1084 TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryWithLoad) {
1085   SetCacheType(net::APP_CACHE);
1086   BackendInvalidEntryWithLoad();
1087 }
1088
1089 // We'll be leaking memory from this test.
1090 TEST_F(DiskCacheBackendTest, ShaderCacheInvalidEntryWithLoad) {
1091   SetCacheType(net::SHADER_CACHE);
1092   BackendInvalidEntryWithLoad();
1093 }
1094
1095 // We'll be leaking memory from this test.
1096 void DiskCacheBackendTest::BackendTrimInvalidEntry() {
1097   const int kSize = 0x3000;  // 12 kB
1098   SetMaxSize(kSize * 10);
1099   InitCache();
1100
1101   std::string first("some key");
1102   std::string second("something else");
1103   disk_cache::Entry* entry;
1104   ASSERT_EQ(net::OK, CreateEntry(first, &entry));
1105
1106   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
1107   memset(buffer->data(), 0, kSize);
1108   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
1109
1110   // Simulate a crash.
1111   SimulateCrash();
1112
1113   ASSERT_EQ(net::OK, CreateEntry(second, &entry));
1114   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
1115
1116   EXPECT_EQ(2, cache_->GetEntryCount());
1117   SetMaxSize(kSize);
1118   entry->Close();  // Trim the cache.
1119   FlushQueueForTest();
1120
1121   // If we evicted the entry in less than 20mS, we have one entry in the cache;
1122   // if it took more than that, we posted a task and we'll delete the second
1123   // entry too.
1124   base::MessageLoop::current()->RunUntilIdle();
1125
1126   // This may be not thread-safe in general, but for now it's OK so add some
1127   // ThreadSanitizer annotations to ignore data races on cache_.
1128   // See http://crbug.com/55970
1129   ANNOTATE_IGNORE_READS_BEGIN();
1130   EXPECT_GE(1, cache_->GetEntryCount());
1131   ANNOTATE_IGNORE_READS_END();
1132
1133   EXPECT_NE(net::OK, OpenEntry(first, &entry));
1134 }
1135
1136 // We'll be leaking memory from this test.
1137 TEST_F(DiskCacheBackendTest, TrimInvalidEntry) {
1138   BackendTrimInvalidEntry();
1139 }
1140
1141 // We'll be leaking memory from this test.
1142 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry) {
1143   SetNewEviction();
1144   BackendTrimInvalidEntry();
1145 }
1146
1147 // We'll be leaking memory from this test.
1148 void DiskCacheBackendTest::BackendTrimInvalidEntry2() {
1149   SetMask(0xf);  // 16-entry table.
1150
1151   const int kSize = 0x3000;  // 12 kB
1152   SetMaxSize(kSize * 40);
1153   InitCache();
1154
1155   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
1156   memset(buffer->data(), 0, kSize);
1157   disk_cache::Entry* entry;
1158
1159   // Writing 32 entries to this cache chains most of them.
1160   for (int i = 0; i < 32; i++) {
1161     std::string key(base::StringPrintf("some key %d", i));
1162     ASSERT_EQ(net::OK, CreateEntry(key, &entry));
1163     EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
1164     entry->Close();
1165     ASSERT_EQ(net::OK, OpenEntry(key, &entry));
1166     // Note that we are not closing the entries.
1167   }
1168
1169   // Simulate a crash.
1170   SimulateCrash();
1171
1172   ASSERT_EQ(net::OK, CreateEntry("Something else", &entry));
1173   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
1174
1175   FlushQueueForTest();
1176   EXPECT_EQ(33, cache_->GetEntryCount());
1177   SetMaxSize(kSize);
1178
1179   // For the new eviction code, all corrupt entries are on the second list so
1180   // they are not going away that easy.
1181   if (new_eviction_) {
1182     EXPECT_EQ(net::OK, DoomAllEntries());
1183   }
1184
1185   entry->Close();  // Trim the cache.
1186   FlushQueueForTest();
1187
1188   // We may abort the eviction before cleaning up everything.
1189   base::MessageLoop::current()->RunUntilIdle();
1190   FlushQueueForTest();
1191   // If it's not clear enough: we may still have eviction tasks running at this
1192   // time, so the number of entries is changing while we read it.
1193   ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
1194   EXPECT_GE(30, cache_->GetEntryCount());
1195   ANNOTATE_IGNORE_READS_AND_WRITES_END();
1196 }
1197
1198 // We'll be leaking memory from this test.
1199 TEST_F(DiskCacheBackendTest, TrimInvalidEntry2) {
1200   BackendTrimInvalidEntry2();
1201 }
1202
1203 // We'll be leaking memory from this test.
1204 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry2) {
1205   SetNewEviction();
1206   BackendTrimInvalidEntry2();
1207 }
1208 #endif  // !defined(LEAK_SANITIZER)
1209
1210 void DiskCacheBackendTest::BackendEnumerations() {
1211   InitCache();
1212   Time initial = Time::Now();
1213
1214   const int kNumEntries = 100;
1215   for (int i = 0; i < kNumEntries; i++) {
1216     std::string key = GenerateKey(true);
1217     disk_cache::Entry* entry;
1218     ASSERT_EQ(net::OK, CreateEntry(key, &entry));
1219     entry->Close();
1220   }
1221   EXPECT_EQ(kNumEntries, cache_->GetEntryCount());
1222   Time final = Time::Now();
1223
1224   disk_cache::Entry* entry;
1225   void* iter = NULL;
1226   int count = 0;
1227   Time last_modified[kNumEntries];
1228   Time last_used[kNumEntries];
1229   while (OpenNextEntry(&iter, &entry) == net::OK) {
1230     ASSERT_TRUE(NULL != entry);
1231     if (count < kNumEntries) {
1232       last_modified[count] = entry->GetLastModified();
1233       last_used[count] = entry->GetLastUsed();
1234       EXPECT_TRUE(initial <= last_modified[count]);
1235       EXPECT_TRUE(final >= last_modified[count]);
1236     }
1237
1238     entry->Close();
1239     count++;
1240   };
1241   EXPECT_EQ(kNumEntries, count);
1242
1243   iter = NULL;
1244   count = 0;
1245   // The previous enumeration should not have changed the timestamps.
1246   while (OpenNextEntry(&iter, &entry) == net::OK) {
1247     ASSERT_TRUE(NULL != entry);
1248     if (count < kNumEntries) {
1249       EXPECT_TRUE(last_modified[count] == entry->GetLastModified());
1250       EXPECT_TRUE(last_used[count] == entry->GetLastUsed());
1251     }
1252     entry->Close();
1253     count++;
1254   };
1255   EXPECT_EQ(kNumEntries, count);
1256 }
1257
1258 TEST_F(DiskCacheBackendTest, Enumerations) {
1259   BackendEnumerations();
1260 }
1261
1262 TEST_F(DiskCacheBackendTest, NewEvictionEnumerations) {
1263   SetNewEviction();
1264   BackendEnumerations();
1265 }
1266
1267 TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations) {
1268   SetMemoryOnlyMode();
1269   BackendEnumerations();
1270 }
1271
1272 TEST_F(DiskCacheBackendTest, ShaderCacheEnumerations) {
1273   SetCacheType(net::SHADER_CACHE);
1274   BackendEnumerations();
1275 }
1276
1277 TEST_F(DiskCacheBackendTest, AppCacheEnumerations) {
1278   SetCacheType(net::APP_CACHE);
1279   BackendEnumerations();
1280 }
1281
1282 // Verifies enumerations while entries are open.
1283 void DiskCacheBackendTest::BackendEnumerations2() {
1284   InitCache();
1285   const std::string first("first");
1286   const std::string second("second");
1287   disk_cache::Entry *entry1, *entry2;
1288   ASSERT_EQ(net::OK, CreateEntry(first, &entry1));
1289   entry1->Close();
1290   ASSERT_EQ(net::OK, CreateEntry(second, &entry2));
1291   entry2->Close();
1292   FlushQueueForTest();
1293
1294   // Make sure that the timestamp is not the same.
1295   AddDelay();
1296   ASSERT_EQ(net::OK, OpenEntry(second, &entry1));
1297   void* iter = NULL;
1298   ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
1299   EXPECT_EQ(entry2->GetKey(), second);
1300
1301   // Two entries and the iterator pointing at "first".
1302   entry1->Close();
1303   entry2->Close();
1304
1305   // The iterator should still be valid, so we should not crash.
1306   ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
1307   EXPECT_EQ(entry2->GetKey(), first);
1308   entry2->Close();
1309   cache_->EndEnumeration(&iter);
1310
1311   // Modify the oldest entry and get the newest element.
1312   ASSERT_EQ(net::OK, OpenEntry(first, &entry1));
1313   EXPECT_EQ(0, WriteData(entry1, 0, 200, NULL, 0, false));
1314   ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
1315   if (type_ == net::APP_CACHE) {
1316     // The list is not updated.
1317     EXPECT_EQ(entry2->GetKey(), second);
1318   } else {
1319     EXPECT_EQ(entry2->GetKey(), first);
1320   }
1321
1322   entry1->Close();
1323   entry2->Close();
1324   cache_->EndEnumeration(&iter);
1325 }
1326
1327 TEST_F(DiskCacheBackendTest, Enumerations2) {
1328   BackendEnumerations2();
1329 }
1330
1331 TEST_F(DiskCacheBackendTest, NewEvictionEnumerations2) {
1332   SetNewEviction();
1333   BackendEnumerations2();
1334 }
1335
1336 TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations2) {
1337   SetMemoryOnlyMode();
1338   BackendEnumerations2();
1339 }
1340
1341 TEST_F(DiskCacheBackendTest, AppCacheEnumerations2) {
1342   SetCacheType(net::APP_CACHE);
1343   BackendEnumerations2();
1344 }
1345
1346 TEST_F(DiskCacheBackendTest, ShaderCacheEnumerations2) {
1347   SetCacheType(net::SHADER_CACHE);
1348   BackendEnumerations2();
1349 }
1350
1351 // Verify that ReadData calls do not update the LRU cache
1352 // when using the SHADER_CACHE type.
1353 TEST_F(DiskCacheBackendTest, ShaderCacheEnumerationReadData) {
1354   SetCacheType(net::SHADER_CACHE);
1355   InitCache();
1356   const std::string first("first");
1357   const std::string second("second");
1358   disk_cache::Entry *entry1, *entry2;
1359   const int kSize = 50;
1360   scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
1361
1362   ASSERT_EQ(net::OK, CreateEntry(first, &entry1));
1363   memset(buffer1->data(), 0, kSize);
1364   base::strlcpy(buffer1->data(), "And the data to save", kSize);
1365   EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1.get(), kSize, false));
1366
1367   ASSERT_EQ(net::OK, CreateEntry(second, &entry2));
1368   entry2->Close();
1369
1370   FlushQueueForTest();
1371
1372   // Make sure that the timestamp is not the same.
1373   AddDelay();
1374
1375   // Read from the last item in the LRU.
1376   EXPECT_EQ(kSize, ReadData(entry1, 0, 0, buffer1.get(), kSize));
1377   entry1->Close();
1378
1379   void* iter = NULL;
1380   ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
1381   EXPECT_EQ(entry2->GetKey(), second);
1382   entry2->Close();
1383   cache_->EndEnumeration(&iter);
1384 }
1385
1386 #if !defined(LEAK_SANITIZER)
1387 // Verify handling of invalid entries while doing enumerations.
1388 // We'll be leaking memory from this test.
1389 void DiskCacheBackendTest::BackendInvalidEntryEnumeration() {
1390   InitCache();
1391
1392   std::string key("Some key");
1393   disk_cache::Entry *entry, *entry1, *entry2;
1394   ASSERT_EQ(net::OK, CreateEntry(key, &entry1));
1395
1396   const int kSize = 50;
1397   scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
1398   memset(buffer1->data(), 0, kSize);
1399   base::strlcpy(buffer1->data(), "And the data to save", kSize);
1400   EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1.get(), kSize, false));
1401   entry1->Close();
1402   ASSERT_EQ(net::OK, OpenEntry(key, &entry1));
1403   EXPECT_EQ(kSize, ReadData(entry1, 0, 0, buffer1.get(), kSize));
1404
1405   std::string key2("Another key");
1406   ASSERT_EQ(net::OK, CreateEntry(key2, &entry2));
1407   entry2->Close();
1408   ASSERT_EQ(2, cache_->GetEntryCount());
1409
1410   SimulateCrash();
1411
1412   void* iter = NULL;
1413   int count = 0;
1414   while (OpenNextEntry(&iter, &entry) == net::OK) {
1415     ASSERT_TRUE(NULL != entry);
1416     EXPECT_EQ(key2, entry->GetKey());
1417     entry->Close();
1418     count++;
1419   };
1420   EXPECT_EQ(1, count);
1421   EXPECT_EQ(1, cache_->GetEntryCount());
1422 }
1423
1424 // We'll be leaking memory from this test.
1425 TEST_F(DiskCacheBackendTest, InvalidEntryEnumeration) {
1426   BackendInvalidEntryEnumeration();
1427 }
1428
1429 // We'll be leaking memory from this test.
1430 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryEnumeration) {
1431   SetNewEviction();
1432   BackendInvalidEntryEnumeration();
1433 }
1434 #endif  // !defined(LEAK_SANITIZER)
1435
1436 // Tests that if for some reason entries are modified close to existing cache
1437 // iterators, we don't generate fatal errors or reset the cache.
1438 void DiskCacheBackendTest::BackendFixEnumerators() {
1439   InitCache();
1440
1441   int seed = static_cast<int>(Time::Now().ToInternalValue());
1442   srand(seed);
1443
1444   const int kNumEntries = 10;
1445   for (int i = 0; i < kNumEntries; i++) {
1446     std::string key = GenerateKey(true);
1447     disk_cache::Entry* entry;
1448     ASSERT_EQ(net::OK, CreateEntry(key, &entry));
1449     entry->Close();
1450   }
1451   EXPECT_EQ(kNumEntries, cache_->GetEntryCount());
1452
1453   disk_cache::Entry *entry1, *entry2;
1454   void* iter1 = NULL;
1455   void* iter2 = NULL;
1456   ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1));
1457   ASSERT_TRUE(NULL != entry1);
1458   entry1->Close();
1459   entry1 = NULL;
1460
1461   // Let's go to the middle of the list.
1462   for (int i = 0; i < kNumEntries / 2; i++) {
1463     if (entry1)
1464       entry1->Close();
1465     ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1));
1466     ASSERT_TRUE(NULL != entry1);
1467
1468     ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2));
1469     ASSERT_TRUE(NULL != entry2);
1470     entry2->Close();
1471   }
1472
1473   // Messing up with entry1 will modify entry2->next.
1474   entry1->Doom();
1475   ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2));
1476   ASSERT_TRUE(NULL != entry2);
1477
1478   // The link entry2->entry1 should be broken.
1479   EXPECT_NE(entry2->GetKey(), entry1->GetKey());
1480   entry1->Close();
1481   entry2->Close();
1482
1483   // And the second iterator should keep working.
1484   ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2));
1485   ASSERT_TRUE(NULL != entry2);
1486   entry2->Close();
1487
1488   cache_->EndEnumeration(&iter1);
1489   cache_->EndEnumeration(&iter2);
1490 }
1491
1492 TEST_F(DiskCacheBackendTest, FixEnumerators) {
1493   BackendFixEnumerators();
1494 }
1495
1496 TEST_F(DiskCacheBackendTest, NewEvictionFixEnumerators) {
1497   SetNewEviction();
1498   BackendFixEnumerators();
1499 }
1500
1501 void DiskCacheBackendTest::BackendDoomRecent() {
1502   InitCache();
1503
1504   disk_cache::Entry *entry;
1505   ASSERT_EQ(net::OK, CreateEntry("first", &entry));
1506   entry->Close();
1507   ASSERT_EQ(net::OK, CreateEntry("second", &entry));
1508   entry->Close();
1509   FlushQueueForTest();
1510
1511   AddDelay();
1512   Time middle = Time::Now();
1513
1514   ASSERT_EQ(net::OK, CreateEntry("third", &entry));
1515   entry->Close();
1516   ASSERT_EQ(net::OK, CreateEntry("fourth", &entry));
1517   entry->Close();
1518   FlushQueueForTest();
1519
1520   AddDelay();
1521   Time final = Time::Now();
1522
1523   ASSERT_EQ(4, cache_->GetEntryCount());
1524   EXPECT_EQ(net::OK, DoomEntriesSince(final));
1525   ASSERT_EQ(4, cache_->GetEntryCount());
1526
1527   EXPECT_EQ(net::OK, DoomEntriesSince(middle));
1528   ASSERT_EQ(2, cache_->GetEntryCount());
1529
1530   ASSERT_EQ(net::OK, OpenEntry("second", &entry));
1531   entry->Close();
1532 }
1533
1534 TEST_F(DiskCacheBackendTest, DoomRecent) {
1535   BackendDoomRecent();
1536 }
1537
1538 TEST_F(DiskCacheBackendTest, NewEvictionDoomRecent) {
1539   SetNewEviction();
1540   BackendDoomRecent();
1541 }
1542
1543 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomRecent) {
1544   SetMemoryOnlyMode();
1545   BackendDoomRecent();
1546 }
1547
1548 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomEntriesSinceSparse) {
1549   SetMemoryOnlyMode();
1550   base::Time start;
1551   InitSparseCache(&start, NULL);
1552   DoomEntriesSince(start);
1553   EXPECT_EQ(1, cache_->GetEntryCount());
1554 }
1555
1556 TEST_F(DiskCacheBackendTest, DoomEntriesSinceSparse) {
1557   base::Time start;
1558   InitSparseCache(&start, NULL);
1559   DoomEntriesSince(start);
1560   // NOTE: BackendImpl counts child entries in its GetEntryCount(), while
1561   // MemBackendImpl does not. Thats why expected value differs here from
1562   // MemoryOnlyDoomEntriesSinceSparse.
1563   EXPECT_EQ(3, cache_->GetEntryCount());
1564 }
1565
1566 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomAllSparse) {
1567   SetMemoryOnlyMode();
1568   InitSparseCache(NULL, NULL);
1569   EXPECT_EQ(net::OK, DoomAllEntries());
1570   EXPECT_EQ(0, cache_->GetEntryCount());
1571 }
1572
1573 TEST_F(DiskCacheBackendTest, DoomAllSparse) {
1574   InitSparseCache(NULL, NULL);
1575   EXPECT_EQ(net::OK, DoomAllEntries());
1576   EXPECT_EQ(0, cache_->GetEntryCount());
1577 }
1578
1579 void DiskCacheBackendTest::BackendDoomBetween() {
1580   InitCache();
1581
1582   disk_cache::Entry *entry;
1583   ASSERT_EQ(net::OK, CreateEntry("first", &entry));
1584   entry->Close();
1585   FlushQueueForTest();
1586
1587   AddDelay();
1588   Time middle_start = Time::Now();
1589
1590   ASSERT_EQ(net::OK, CreateEntry("second", &entry));
1591   entry->Close();
1592   ASSERT_EQ(net::OK, CreateEntry("third", &entry));
1593   entry->Close();
1594   FlushQueueForTest();
1595
1596   AddDelay();
1597   Time middle_end = Time::Now();
1598   AddDelay();
1599
1600   ASSERT_EQ(net::OK, CreateEntry("fourth", &entry));
1601   entry->Close();
1602   ASSERT_EQ(net::OK, OpenEntry("fourth", &entry));
1603   entry->Close();
1604   FlushQueueForTest();
1605
1606   AddDelay();
1607   Time final = Time::Now();
1608
1609   ASSERT_EQ(4, cache_->GetEntryCount());
1610   EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, middle_end));
1611   ASSERT_EQ(2, cache_->GetEntryCount());
1612
1613   ASSERT_EQ(net::OK, OpenEntry("fourth", &entry));
1614   entry->Close();
1615
1616   EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, final));
1617   ASSERT_EQ(1, cache_->GetEntryCount());
1618
1619   ASSERT_EQ(net::OK, OpenEntry("first", &entry));
1620   entry->Close();
1621 }
1622
1623 TEST_F(DiskCacheBackendTest, DoomBetween) {
1624   BackendDoomBetween();
1625 }
1626
1627 TEST_F(DiskCacheBackendTest, NewEvictionDoomBetween) {
1628   SetNewEviction();
1629   BackendDoomBetween();
1630 }
1631
1632 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomBetween) {
1633   SetMemoryOnlyMode();
1634   BackendDoomBetween();
1635 }
1636
1637 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomEntriesBetweenSparse) {
1638   SetMemoryOnlyMode();
1639   base::Time start, end;
1640   InitSparseCache(&start, &end);
1641   DoomEntriesBetween(start, end);
1642   EXPECT_EQ(3, cache_->GetEntryCount());
1643
1644   start = end;
1645   end = base::Time::Now();
1646   DoomEntriesBetween(start, end);
1647   EXPECT_EQ(1, cache_->GetEntryCount());
1648 }
1649
1650 TEST_F(DiskCacheBackendTest, DoomEntriesBetweenSparse) {
1651   base::Time start, end;
1652   InitSparseCache(&start, &end);
1653   DoomEntriesBetween(start, end);
1654   EXPECT_EQ(9, cache_->GetEntryCount());
1655
1656   start = end;
1657   end = base::Time::Now();
1658   DoomEntriesBetween(start, end);
1659   EXPECT_EQ(3, cache_->GetEntryCount());
1660 }
1661
1662 void DiskCacheBackendTest::BackendTransaction(const std::string& name,
1663                                               int num_entries, bool load) {
1664   success_ = false;
1665   ASSERT_TRUE(CopyTestCache(name));
1666   DisableFirstCleanup();
1667
1668   uint32 mask;
1669   if (load) {
1670     mask = 0xf;
1671     SetMaxSize(0x100000);
1672   } else {
1673     // Clear the settings from the previous run.
1674     mask = 0;
1675     SetMaxSize(0);
1676   }
1677   SetMask(mask);
1678
1679   InitCache();
1680   ASSERT_EQ(num_entries + 1, cache_->GetEntryCount());
1681
1682   std::string key("the first key");
1683   disk_cache::Entry* entry1;
1684   ASSERT_NE(net::OK, OpenEntry(key, &entry1));
1685
1686   int actual = cache_->GetEntryCount();
1687   if (num_entries != actual) {
1688     ASSERT_TRUE(load);
1689     // If there is a heavy load, inserting an entry will make another entry
1690     // dirty (on the hash bucket) so two entries are removed.
1691     ASSERT_EQ(num_entries - 1, actual);
1692   }
1693
1694   cache_.reset();
1695   cache_impl_ = NULL;
1696
1697   ASSERT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, mask));
1698   success_ = true;
1699 }
1700
1701 void DiskCacheBackendTest::BackendRecoverInsert() {
1702   // Tests with an empty cache.
1703   BackendTransaction("insert_empty1", 0, false);
1704   ASSERT_TRUE(success_) << "insert_empty1";
1705   BackendTransaction("insert_empty2", 0, false);
1706   ASSERT_TRUE(success_) << "insert_empty2";
1707   BackendTransaction("insert_empty3", 0, false);
1708   ASSERT_TRUE(success_) << "insert_empty3";
1709
1710   // Tests with one entry on the cache.
1711   BackendTransaction("insert_one1", 1, false);
1712   ASSERT_TRUE(success_) << "insert_one1";
1713   BackendTransaction("insert_one2", 1, false);
1714   ASSERT_TRUE(success_) << "insert_one2";
1715   BackendTransaction("insert_one3", 1, false);
1716   ASSERT_TRUE(success_) << "insert_one3";
1717
1718   // Tests with one hundred entries on the cache, tiny index.
1719   BackendTransaction("insert_load1", 100, true);
1720   ASSERT_TRUE(success_) << "insert_load1";
1721   BackendTransaction("insert_load2", 100, true);
1722   ASSERT_TRUE(success_) << "insert_load2";
1723 }
1724
1725 TEST_F(DiskCacheBackendTest, RecoverInsert) {
1726   BackendRecoverInsert();
1727 }
1728
1729 TEST_F(DiskCacheBackendTest, NewEvictionRecoverInsert) {
1730   SetNewEviction();
1731   BackendRecoverInsert();
1732 }
1733
1734 void DiskCacheBackendTest::BackendRecoverRemove() {
1735   // Removing the only element.
1736   BackendTransaction("remove_one1", 0, false);
1737   ASSERT_TRUE(success_) << "remove_one1";
1738   BackendTransaction("remove_one2", 0, false);
1739   ASSERT_TRUE(success_) << "remove_one2";
1740   BackendTransaction("remove_one3", 0, false);
1741   ASSERT_TRUE(success_) << "remove_one3";
1742
1743   // Removing the head.
1744   BackendTransaction("remove_head1", 1, false);
1745   ASSERT_TRUE(success_) << "remove_head1";
1746   BackendTransaction("remove_head2", 1, false);
1747   ASSERT_TRUE(success_) << "remove_head2";
1748   BackendTransaction("remove_head3", 1, false);
1749   ASSERT_TRUE(success_) << "remove_head3";
1750
1751   // Removing the tail.
1752   BackendTransaction("remove_tail1", 1, false);
1753   ASSERT_TRUE(success_) << "remove_tail1";
1754   BackendTransaction("remove_tail2", 1, false);
1755   ASSERT_TRUE(success_) << "remove_tail2";
1756   BackendTransaction("remove_tail3", 1, false);
1757   ASSERT_TRUE(success_) << "remove_tail3";
1758
1759   // Removing with one hundred entries on the cache, tiny index.
1760   BackendTransaction("remove_load1", 100, true);
1761   ASSERT_TRUE(success_) << "remove_load1";
1762   BackendTransaction("remove_load2", 100, true);
1763   ASSERT_TRUE(success_) << "remove_load2";
1764   BackendTransaction("remove_load3", 100, true);
1765   ASSERT_TRUE(success_) << "remove_load3";
1766
1767   // This case cannot be reverted.
1768   BackendTransaction("remove_one4", 0, false);
1769   ASSERT_TRUE(success_) << "remove_one4";
1770   BackendTransaction("remove_head4", 1, false);
1771   ASSERT_TRUE(success_) << "remove_head4";
1772 }
1773
1774 TEST_F(DiskCacheBackendTest, RecoverRemove) {
1775   BackendRecoverRemove();
1776 }
1777
1778 TEST_F(DiskCacheBackendTest, NewEvictionRecoverRemove) {
1779   SetNewEviction();
1780   BackendRecoverRemove();
1781 }
1782
1783 void DiskCacheBackendTest::BackendRecoverWithEviction() {
1784   success_ = false;
1785   ASSERT_TRUE(CopyTestCache("insert_load1"));
1786   DisableFirstCleanup();
1787
1788   SetMask(0xf);
1789   SetMaxSize(0x1000);
1790
1791   // We should not crash here.
1792   InitCache();
1793   DisableIntegrityCheck();
1794 }
1795
1796 TEST_F(DiskCacheBackendTest, RecoverWithEviction) {
1797   BackendRecoverWithEviction();
1798 }
1799
1800 TEST_F(DiskCacheBackendTest, NewEvictionRecoverWithEviction) {
1801   SetNewEviction();
1802   BackendRecoverWithEviction();
1803 }
1804
1805 // Tests that the |BackendImpl| fails to start with the wrong cache version.
1806 TEST_F(DiskCacheTest, WrongVersion) {
1807   ASSERT_TRUE(CopyTestCache("wrong_version"));
1808   base::Thread cache_thread("CacheThread");
1809   ASSERT_TRUE(cache_thread.StartWithOptions(
1810       base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
1811   net::TestCompletionCallback cb;
1812
1813   scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
1814       cache_path_, cache_thread.message_loop_proxy().get(), NULL));
1815   int rv = cache->Init(cb.callback());
1816   ASSERT_EQ(net::ERR_FAILED, cb.GetResult(rv));
1817 }
1818
1819 class BadEntropyProvider : public base::FieldTrial::EntropyProvider {
1820  public:
1821   virtual ~BadEntropyProvider() {}
1822
1823   virtual double GetEntropyForTrial(const std::string& trial_name,
1824                                     uint32 randomization_seed) const OVERRIDE {
1825     return 0.5;
1826   }
1827 };
1828
1829 // Tests that the disk cache successfully joins the control group, dropping the
1830 // existing cache in favour of a new empty cache.
1831 TEST_F(DiskCacheTest, SimpleCacheControlJoin) {
1832   base::Thread cache_thread("CacheThread");
1833   ASSERT_TRUE(cache_thread.StartWithOptions(
1834                   base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
1835
1836   scoped_ptr<disk_cache::BackendImpl> cache =
1837       CreateExistingEntryCache(cache_thread, cache_path_);
1838   ASSERT_TRUE(cache.get());
1839   cache.reset();
1840
1841   // Instantiate the SimpleCacheTrial, forcing this run into the
1842   // ExperimentControl group.
1843   base::FieldTrialList field_trial_list(new BadEntropyProvider());
1844   base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial",
1845                                          "ExperimentControl");
1846   net::TestCompletionCallback cb;
1847   scoped_ptr<disk_cache::Backend> base_cache;
1848   int rv =
1849       disk_cache::CreateCacheBackend(net::DISK_CACHE,
1850                                      net::CACHE_BACKEND_BLOCKFILE,
1851                                      cache_path_,
1852                                      0,
1853                                      true,
1854                                      cache_thread.message_loop_proxy().get(),
1855                                      NULL,
1856                                      &base_cache,
1857                                      cb.callback());
1858   ASSERT_EQ(net::OK, cb.GetResult(rv));
1859   EXPECT_EQ(0, base_cache->GetEntryCount());
1860 }
1861
1862 // Tests that the disk cache can restart in the control group preserving
1863 // existing entries.
1864 TEST_F(DiskCacheTest, SimpleCacheControlRestart) {
1865   // Instantiate the SimpleCacheTrial, forcing this run into the
1866   // ExperimentControl group.
1867   base::FieldTrialList field_trial_list(new BadEntropyProvider());
1868   base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial",
1869                                          "ExperimentControl");
1870
1871   base::Thread cache_thread("CacheThread");
1872   ASSERT_TRUE(cache_thread.StartWithOptions(
1873                   base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
1874
1875   scoped_ptr<disk_cache::BackendImpl> cache =
1876       CreateExistingEntryCache(cache_thread, cache_path_);
1877   ASSERT_TRUE(cache.get());
1878
1879   net::TestCompletionCallback cb;
1880
1881   const int kRestartCount = 5;
1882   for (int i = 0; i < kRestartCount; ++i) {
1883     cache.reset(new disk_cache::BackendImpl(
1884         cache_path_, cache_thread.message_loop_proxy(), NULL));
1885     int rv = cache->Init(cb.callback());
1886     ASSERT_EQ(net::OK, cb.GetResult(rv));
1887     EXPECT_EQ(1, cache->GetEntryCount());
1888
1889     disk_cache::Entry* entry = NULL;
1890     rv = cache->OpenEntry(kExistingEntryKey, &entry, cb.callback());
1891     EXPECT_EQ(net::OK, cb.GetResult(rv));
1892     EXPECT_TRUE(entry);
1893     entry->Close();
1894   }
1895 }
1896
1897 // Tests that the disk cache can leave the control group preserving existing
1898 // entries.
1899 TEST_F(DiskCacheTest, SimpleCacheControlLeave) {
1900   base::Thread cache_thread("CacheThread");
1901   ASSERT_TRUE(cache_thread.StartWithOptions(
1902       base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
1903
1904   {
1905     // Instantiate the SimpleCacheTrial, forcing this run into the
1906     // ExperimentControl group.
1907     base::FieldTrialList field_trial_list(new BadEntropyProvider());
1908     base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial",
1909                                            "ExperimentControl");
1910
1911     scoped_ptr<disk_cache::BackendImpl> cache =
1912         CreateExistingEntryCache(cache_thread, cache_path_);
1913     ASSERT_TRUE(cache.get());
1914   }
1915
1916   // Instantiate the SimpleCacheTrial, forcing this run into the
1917   // ExperimentNo group.
1918   base::FieldTrialList field_trial_list(new BadEntropyProvider());
1919   base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial", "ExperimentNo");
1920   net::TestCompletionCallback cb;
1921
1922   const int kRestartCount = 5;
1923   for (int i = 0; i < kRestartCount; ++i) {
1924     scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
1925         cache_path_, cache_thread.message_loop_proxy(), NULL));
1926     int rv = cache->Init(cb.callback());
1927     ASSERT_EQ(net::OK, cb.GetResult(rv));
1928     EXPECT_EQ(1, cache->GetEntryCount());
1929
1930     disk_cache::Entry* entry = NULL;
1931     rv = cache->OpenEntry(kExistingEntryKey, &entry, cb.callback());
1932     EXPECT_EQ(net::OK, cb.GetResult(rv));
1933     EXPECT_TRUE(entry);
1934     entry->Close();
1935   }
1936 }
1937
1938 // Tests that the cache is properly restarted on recovery error.
1939 TEST_F(DiskCacheBackendTest, DeleteOld) {
1940   ASSERT_TRUE(CopyTestCache("wrong_version"));
1941   SetNewEviction();
1942   base::Thread cache_thread("CacheThread");
1943   ASSERT_TRUE(cache_thread.StartWithOptions(
1944       base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
1945
1946   net::TestCompletionCallback cb;
1947   bool prev = base::ThreadRestrictions::SetIOAllowed(false);
1948   base::FilePath path(cache_path_);
1949   int rv =
1950       disk_cache::CreateCacheBackend(net::DISK_CACHE,
1951                                      net::CACHE_BACKEND_BLOCKFILE,
1952                                      path,
1953                                      0,
1954                                      true,
1955                                      cache_thread.message_loop_proxy().get(),
1956                                      NULL,
1957                                      &cache_,
1958                                      cb.callback());
1959   path.clear();  // Make sure path was captured by the previous call.
1960   ASSERT_EQ(net::OK, cb.GetResult(rv));
1961   base::ThreadRestrictions::SetIOAllowed(prev);
1962   cache_.reset();
1963   EXPECT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, mask_));
1964 }
1965
1966 // We want to be able to deal with messed up entries on disk.
1967 void DiskCacheBackendTest::BackendInvalidEntry2() {
1968   ASSERT_TRUE(CopyTestCache("bad_entry"));
1969   DisableFirstCleanup();
1970   InitCache();
1971
1972   disk_cache::Entry *entry1, *entry2;
1973   ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
1974   EXPECT_NE(net::OK, OpenEntry("some other key", &entry2));
1975   entry1->Close();
1976
1977   // CheckCacheIntegrity will fail at this point.
1978   DisableIntegrityCheck();
1979 }
1980
1981 TEST_F(DiskCacheBackendTest, InvalidEntry2) {
1982   BackendInvalidEntry2();
1983 }
1984
1985 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry2) {
1986   SetNewEviction();
1987   BackendInvalidEntry2();
1988 }
1989
1990 // Tests that we don't crash or hang when enumerating this cache.
1991 void DiskCacheBackendTest::BackendInvalidEntry3() {
1992   SetMask(0x1);  // 2-entry table.
1993   SetMaxSize(0x3000);  // 12 kB.
1994   DisableFirstCleanup();
1995   InitCache();
1996
1997   disk_cache::Entry* entry;
1998   void* iter = NULL;
1999   while (OpenNextEntry(&iter, &entry) == net::OK) {
2000     entry->Close();
2001   }
2002 }
2003
2004 TEST_F(DiskCacheBackendTest, InvalidEntry3) {
2005   ASSERT_TRUE(CopyTestCache("dirty_entry3"));
2006   BackendInvalidEntry3();
2007 }
2008
2009 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry3) {
2010   ASSERT_TRUE(CopyTestCache("dirty_entry4"));
2011   SetNewEviction();
2012   BackendInvalidEntry3();
2013   DisableIntegrityCheck();
2014 }
2015
2016 // Test that we handle a dirty entry on the LRU list, already replaced with
2017 // the same key, and with hash collisions.
2018 TEST_F(DiskCacheBackendTest, InvalidEntry4) {
2019   ASSERT_TRUE(CopyTestCache("dirty_entry3"));
2020   SetMask(0x1);  // 2-entry table.
2021   SetMaxSize(0x3000);  // 12 kB.
2022   DisableFirstCleanup();
2023   InitCache();
2024
2025   TrimForTest(false);
2026 }
2027
2028 // Test that we handle a dirty entry on the deleted list, already replaced with
2029 // the same key, and with hash collisions.
2030 TEST_F(DiskCacheBackendTest, InvalidEntry5) {
2031   ASSERT_TRUE(CopyTestCache("dirty_entry4"));
2032   SetNewEviction();
2033   SetMask(0x1);  // 2-entry table.
2034   SetMaxSize(0x3000);  // 12 kB.
2035   DisableFirstCleanup();
2036   InitCache();
2037
2038   TrimDeletedListForTest(false);
2039 }
2040
2041 TEST_F(DiskCacheBackendTest, InvalidEntry6) {
2042   ASSERT_TRUE(CopyTestCache("dirty_entry5"));
2043   SetMask(0x1);  // 2-entry table.
2044   SetMaxSize(0x3000);  // 12 kB.
2045   DisableFirstCleanup();
2046   InitCache();
2047
2048   // There is a dirty entry (but marked as clean) at the end, pointing to a
2049   // deleted entry through the hash collision list. We should not re-insert the
2050   // deleted entry into the index table.
2051
2052   TrimForTest(false);
2053   // The cache should be clean (as detected by CheckCacheIntegrity).
2054 }
2055
2056 // Tests that we don't hang when there is a loop on the hash collision list.
2057 // The test cache could be a result of bug 69135.
2058 TEST_F(DiskCacheBackendTest, BadNextEntry1) {
2059   ASSERT_TRUE(CopyTestCache("list_loop2"));
2060   SetMask(0x1);  // 2-entry table.
2061   SetMaxSize(0x3000);  // 12 kB.
2062   DisableFirstCleanup();
2063   InitCache();
2064
2065   // The second entry points at itselft, and the first entry is not accessible
2066   // though the index, but it is at the head of the LRU.
2067
2068   disk_cache::Entry* entry;
2069   ASSERT_EQ(net::OK, CreateEntry("The first key", &entry));
2070   entry->Close();
2071
2072   TrimForTest(false);
2073   TrimForTest(false);
2074   ASSERT_EQ(net::OK, OpenEntry("The first key", &entry));
2075   entry->Close();
2076   EXPECT_EQ(1, cache_->GetEntryCount());
2077 }
2078
2079 // Tests that we don't hang when there is a loop on the hash collision list.
2080 // The test cache could be a result of bug 69135.
2081 TEST_F(DiskCacheBackendTest, BadNextEntry2) {
2082   ASSERT_TRUE(CopyTestCache("list_loop3"));
2083   SetMask(0x1);  // 2-entry table.
2084   SetMaxSize(0x3000);  // 12 kB.
2085   DisableFirstCleanup();
2086   InitCache();
2087
2088   // There is a wide loop of 5 entries.
2089
2090   disk_cache::Entry* entry;
2091   ASSERT_NE(net::OK, OpenEntry("Not present key", &entry));
2092 }
2093
2094 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry6) {
2095   ASSERT_TRUE(CopyTestCache("bad_rankings3"));
2096   DisableFirstCleanup();
2097   SetNewEviction();
2098   InitCache();
2099
2100   // The second entry is dirty, but removing it should not corrupt the list.
2101   disk_cache::Entry* entry;
2102   ASSERT_NE(net::OK, OpenEntry("the second key", &entry));
2103   ASSERT_EQ(net::OK, OpenEntry("the first key", &entry));
2104
2105   // This should not delete the cache.
2106   entry->Doom();
2107   FlushQueueForTest();
2108   entry->Close();
2109
2110   ASSERT_EQ(net::OK, OpenEntry("some other key", &entry));
2111   entry->Close();
2112 }
2113
2114 // Tests handling of corrupt entries by keeping the rankings node around, with
2115 // a fatal failure.
2116 void DiskCacheBackendTest::BackendInvalidEntry7() {
2117   const int kSize = 0x3000;  // 12 kB.
2118   SetMaxSize(kSize * 10);
2119   InitCache();
2120
2121   std::string first("some key");
2122   std::string second("something else");
2123   disk_cache::Entry* entry;
2124   ASSERT_EQ(net::OK, CreateEntry(first, &entry));
2125   entry->Close();
2126   ASSERT_EQ(net::OK, CreateEntry(second, &entry));
2127
2128   // Corrupt this entry.
2129   disk_cache::EntryImpl* entry_impl =
2130       static_cast<disk_cache::EntryImpl*>(entry);
2131
2132   entry_impl->rankings()->Data()->next = 0;
2133   entry_impl->rankings()->Store();
2134   entry->Close();
2135   FlushQueueForTest();
2136   EXPECT_EQ(2, cache_->GetEntryCount());
2137
2138   // This should detect the bad entry.
2139   EXPECT_NE(net::OK, OpenEntry(second, &entry));
2140   EXPECT_EQ(1, cache_->GetEntryCount());
2141
2142   // We should delete the cache. The list still has a corrupt node.
2143   void* iter = NULL;
2144   EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
2145   FlushQueueForTest();
2146   EXPECT_EQ(0, cache_->GetEntryCount());
2147 }
2148
2149 TEST_F(DiskCacheBackendTest, InvalidEntry7) {
2150   BackendInvalidEntry7();
2151 }
2152
2153 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry7) {
2154   SetNewEviction();
2155   BackendInvalidEntry7();
2156 }
2157
2158 // Tests handling of corrupt entries by keeping the rankings node around, with
2159 // a non fatal failure.
2160 void DiskCacheBackendTest::BackendInvalidEntry8() {
2161   const int kSize = 0x3000;  // 12 kB
2162   SetMaxSize(kSize * 10);
2163   InitCache();
2164
2165   std::string first("some key");
2166   std::string second("something else");
2167   disk_cache::Entry* entry;
2168   ASSERT_EQ(net::OK, CreateEntry(first, &entry));
2169   entry->Close();
2170   ASSERT_EQ(net::OK, CreateEntry(second, &entry));
2171
2172   // Corrupt this entry.
2173   disk_cache::EntryImpl* entry_impl =
2174       static_cast<disk_cache::EntryImpl*>(entry);
2175
2176   entry_impl->rankings()->Data()->contents = 0;
2177   entry_impl->rankings()->Store();
2178   entry->Close();
2179   FlushQueueForTest();
2180   EXPECT_EQ(2, cache_->GetEntryCount());
2181
2182   // This should detect the bad entry.
2183   EXPECT_NE(net::OK, OpenEntry(second, &entry));
2184   EXPECT_EQ(1, cache_->GetEntryCount());
2185
2186   // We should not delete the cache.
2187   void* iter = NULL;
2188   ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
2189   entry->Close();
2190   EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
2191   EXPECT_EQ(1, cache_->GetEntryCount());
2192 }
2193
2194 TEST_F(DiskCacheBackendTest, InvalidEntry8) {
2195   BackendInvalidEntry8();
2196 }
2197
2198 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry8) {
2199   SetNewEviction();
2200   BackendInvalidEntry8();
2201 }
2202
2203 // Tests handling of corrupt entries detected by enumerations. Note that these
2204 // tests (xx9 to xx11) are basically just going though slightly different
2205 // codepaths so they are tighlty coupled with the code, but that is better than
2206 // not testing error handling code.
2207 void DiskCacheBackendTest::BackendInvalidEntry9(bool eviction) {
2208   const int kSize = 0x3000;  // 12 kB.
2209   SetMaxSize(kSize * 10);
2210   InitCache();
2211
2212   std::string first("some key");
2213   std::string second("something else");
2214   disk_cache::Entry* entry;
2215   ASSERT_EQ(net::OK, CreateEntry(first, &entry));
2216   entry->Close();
2217   ASSERT_EQ(net::OK, CreateEntry(second, &entry));
2218
2219   // Corrupt this entry.
2220   disk_cache::EntryImpl* entry_impl =
2221       static_cast<disk_cache::EntryImpl*>(entry);
2222
2223   entry_impl->entry()->Data()->state = 0xbad;
2224   entry_impl->entry()->Store();
2225   entry->Close();
2226   FlushQueueForTest();
2227   EXPECT_EQ(2, cache_->GetEntryCount());
2228
2229   if (eviction) {
2230     TrimForTest(false);
2231     EXPECT_EQ(1, cache_->GetEntryCount());
2232     TrimForTest(false);
2233     EXPECT_EQ(1, cache_->GetEntryCount());
2234   } else {
2235     // We should detect the problem through the list, but we should not delete
2236     // the entry, just fail the iteration.
2237     void* iter = NULL;
2238     EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
2239
2240     // Now a full iteration will work, and return one entry.
2241     ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
2242     entry->Close();
2243     EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
2244
2245     // This should detect what's left of the bad entry.
2246     EXPECT_NE(net::OK, OpenEntry(second, &entry));
2247     EXPECT_EQ(2, cache_->GetEntryCount());
2248   }
2249   DisableIntegrityCheck();
2250 }
2251
2252 TEST_F(DiskCacheBackendTest, InvalidEntry9) {
2253   BackendInvalidEntry9(false);
2254 }
2255
2256 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry9) {
2257   SetNewEviction();
2258   BackendInvalidEntry9(false);
2259 }
2260
2261 TEST_F(DiskCacheBackendTest, TrimInvalidEntry9) {
2262   BackendInvalidEntry9(true);
2263 }
2264
2265 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry9) {
2266   SetNewEviction();
2267   BackendInvalidEntry9(true);
2268 }
2269
2270 // Tests handling of corrupt entries detected by enumerations.
2271 void DiskCacheBackendTest::BackendInvalidEntry10(bool eviction) {
2272   const int kSize = 0x3000;  // 12 kB.
2273   SetMaxSize(kSize * 10);
2274   SetNewEviction();
2275   InitCache();
2276
2277   std::string first("some key");
2278   std::string second("something else");
2279   disk_cache::Entry* entry;
2280   ASSERT_EQ(net::OK, CreateEntry(first, &entry));
2281   entry->Close();
2282   ASSERT_EQ(net::OK, OpenEntry(first, &entry));
2283   EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false));
2284   entry->Close();
2285   ASSERT_EQ(net::OK, CreateEntry(second, &entry));
2286
2287   // Corrupt this entry.
2288   disk_cache::EntryImpl* entry_impl =
2289       static_cast<disk_cache::EntryImpl*>(entry);
2290
2291   entry_impl->entry()->Data()->state = 0xbad;
2292   entry_impl->entry()->Store();
2293   entry->Close();
2294   ASSERT_EQ(net::OK, CreateEntry("third", &entry));
2295   entry->Close();
2296   EXPECT_EQ(3, cache_->GetEntryCount());
2297
2298   // We have:
2299   // List 0: third -> second (bad).
2300   // List 1: first.
2301
2302   if (eviction) {
2303     // Detection order: second -> first -> third.
2304     TrimForTest(false);
2305     EXPECT_EQ(3, cache_->GetEntryCount());
2306     TrimForTest(false);
2307     EXPECT_EQ(2, cache_->GetEntryCount());
2308     TrimForTest(false);
2309     EXPECT_EQ(1, cache_->GetEntryCount());
2310   } else {
2311     // Detection order: third -> second -> first.
2312     // We should detect the problem through the list, but we should not delete
2313     // the entry.
2314     void* iter = NULL;
2315     ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
2316     entry->Close();
2317     ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
2318     EXPECT_EQ(first, entry->GetKey());
2319     entry->Close();
2320     EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
2321   }
2322   DisableIntegrityCheck();
2323 }
2324
2325 TEST_F(DiskCacheBackendTest, InvalidEntry10) {
2326   BackendInvalidEntry10(false);
2327 }
2328
2329 TEST_F(DiskCacheBackendTest, TrimInvalidEntry10) {
2330   BackendInvalidEntry10(true);
2331 }
2332
2333 // Tests handling of corrupt entries detected by enumerations.
2334 void DiskCacheBackendTest::BackendInvalidEntry11(bool eviction) {
2335   const int kSize = 0x3000;  // 12 kB.
2336   SetMaxSize(kSize * 10);
2337   SetNewEviction();
2338   InitCache();
2339
2340   std::string first("some key");
2341   std::string second("something else");
2342   disk_cache::Entry* entry;
2343   ASSERT_EQ(net::OK, CreateEntry(first, &entry));
2344   entry->Close();
2345   ASSERT_EQ(net::OK, OpenEntry(first, &entry));
2346   EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false));
2347   entry->Close();
2348   ASSERT_EQ(net::OK, CreateEntry(second, &entry));
2349   entry->Close();
2350   ASSERT_EQ(net::OK, OpenEntry(second, &entry));
2351   EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false));
2352
2353   // Corrupt this entry.
2354   disk_cache::EntryImpl* entry_impl =
2355       static_cast<disk_cache::EntryImpl*>(entry);
2356
2357   entry_impl->entry()->Data()->state = 0xbad;
2358   entry_impl->entry()->Store();
2359   entry->Close();
2360   ASSERT_EQ(net::OK, CreateEntry("third", &entry));
2361   entry->Close();
2362   FlushQueueForTest();
2363   EXPECT_EQ(3, cache_->GetEntryCount());
2364
2365   // We have:
2366   // List 0: third.
2367   // List 1: second (bad) -> first.
2368
2369   if (eviction) {
2370     // Detection order: third -> first -> second.
2371     TrimForTest(false);
2372     EXPECT_EQ(2, cache_->GetEntryCount());
2373     TrimForTest(false);
2374     EXPECT_EQ(1, cache_->GetEntryCount());
2375     TrimForTest(false);
2376     EXPECT_EQ(1, cache_->GetEntryCount());
2377   } else {
2378     // Detection order: third -> second.
2379     // We should detect the problem through the list, but we should not delete
2380     // the entry, just fail the iteration.
2381     void* iter = NULL;
2382     ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
2383     entry->Close();
2384     EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
2385
2386     // Now a full iteration will work, and return two entries.
2387     ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
2388     entry->Close();
2389     ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
2390     entry->Close();
2391     EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
2392   }
2393   DisableIntegrityCheck();
2394 }
2395
2396 TEST_F(DiskCacheBackendTest, InvalidEntry11) {
2397   BackendInvalidEntry11(false);
2398 }
2399
2400 TEST_F(DiskCacheBackendTest, TrimInvalidEntry11) {
2401   BackendInvalidEntry11(true);
2402 }
2403
2404 // Tests handling of corrupt entries in the middle of a long eviction run.
2405 void DiskCacheBackendTest::BackendTrimInvalidEntry12() {
2406   const int kSize = 0x3000;  // 12 kB
2407   SetMaxSize(kSize * 10);
2408   InitCache();
2409
2410   std::string first("some key");
2411   std::string second("something else");
2412   disk_cache::Entry* entry;
2413   ASSERT_EQ(net::OK, CreateEntry(first, &entry));
2414   entry->Close();
2415   ASSERT_EQ(net::OK, CreateEntry(second, &entry));
2416
2417   // Corrupt this entry.
2418   disk_cache::EntryImpl* entry_impl =
2419       static_cast<disk_cache::EntryImpl*>(entry);
2420
2421   entry_impl->entry()->Data()->state = 0xbad;
2422   entry_impl->entry()->Store();
2423   entry->Close();
2424   ASSERT_EQ(net::OK, CreateEntry("third", &entry));
2425   entry->Close();
2426   ASSERT_EQ(net::OK, CreateEntry("fourth", &entry));
2427   TrimForTest(true);
2428   EXPECT_EQ(1, cache_->GetEntryCount());
2429   entry->Close();
2430   DisableIntegrityCheck();
2431 }
2432
2433 TEST_F(DiskCacheBackendTest, TrimInvalidEntry12) {
2434   BackendTrimInvalidEntry12();
2435 }
2436
2437 TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry12) {
2438   SetNewEviction();
2439   BackendTrimInvalidEntry12();
2440 }
2441
2442 // We want to be able to deal with messed up entries on disk.
2443 void DiskCacheBackendTest::BackendInvalidRankings2() {
2444   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2445   DisableFirstCleanup();
2446   InitCache();
2447
2448   disk_cache::Entry *entry1, *entry2;
2449   EXPECT_NE(net::OK, OpenEntry("the first key", &entry1));
2450   ASSERT_EQ(net::OK, OpenEntry("some other key", &entry2));
2451   entry2->Close();
2452
2453   // CheckCacheIntegrity will fail at this point.
2454   DisableIntegrityCheck();
2455 }
2456
2457 TEST_F(DiskCacheBackendTest, InvalidRankings2) {
2458   BackendInvalidRankings2();
2459 }
2460
2461 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankings2) {
2462   SetNewEviction();
2463   BackendInvalidRankings2();
2464 }
2465
2466 // If the LRU is corrupt, we delete the cache.
2467 void DiskCacheBackendTest::BackendInvalidRankings() {
2468   disk_cache::Entry* entry;
2469   void* iter = NULL;
2470   ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
2471   entry->Close();
2472   EXPECT_EQ(2, cache_->GetEntryCount());
2473
2474   EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
2475   FlushQueueForTest();  // Allow the restart to finish.
2476   EXPECT_EQ(0, cache_->GetEntryCount());
2477 }
2478
2479 TEST_F(DiskCacheBackendTest, InvalidRankingsSuccess) {
2480   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2481   DisableFirstCleanup();
2482   InitCache();
2483   BackendInvalidRankings();
2484 }
2485
2486 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsSuccess) {
2487   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2488   DisableFirstCleanup();
2489   SetNewEviction();
2490   InitCache();
2491   BackendInvalidRankings();
2492 }
2493
2494 TEST_F(DiskCacheBackendTest, InvalidRankingsFailure) {
2495   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2496   DisableFirstCleanup();
2497   InitCache();
2498   SetTestMode();  // Fail cache reinitialization.
2499   BackendInvalidRankings();
2500 }
2501
2502 TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsFailure) {
2503   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2504   DisableFirstCleanup();
2505   SetNewEviction();
2506   InitCache();
2507   SetTestMode();  // Fail cache reinitialization.
2508   BackendInvalidRankings();
2509 }
2510
2511 // If the LRU is corrupt and we have open entries, we disable the cache.
2512 void DiskCacheBackendTest::BackendDisable() {
2513   disk_cache::Entry *entry1, *entry2;
2514   void* iter = NULL;
2515   ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
2516
2517   EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2));
2518   EXPECT_EQ(0, cache_->GetEntryCount());
2519   EXPECT_NE(net::OK, CreateEntry("Something new", &entry2));
2520
2521   entry1->Close();
2522   FlushQueueForTest();  // Flushing the Close posts a task to restart the cache.
2523   FlushQueueForTest();  // This one actually allows that task to complete.
2524
2525   EXPECT_EQ(0, cache_->GetEntryCount());
2526 }
2527
2528 TEST_F(DiskCacheBackendTest, DisableSuccess) {
2529   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2530   DisableFirstCleanup();
2531   InitCache();
2532   BackendDisable();
2533 }
2534
2535 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess) {
2536   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2537   DisableFirstCleanup();
2538   SetNewEviction();
2539   InitCache();
2540   BackendDisable();
2541 }
2542
2543 TEST_F(DiskCacheBackendTest, DisableFailure) {
2544   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2545   DisableFirstCleanup();
2546   InitCache();
2547   SetTestMode();  // Fail cache reinitialization.
2548   BackendDisable();
2549 }
2550
2551 TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure) {
2552   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2553   DisableFirstCleanup();
2554   SetNewEviction();
2555   InitCache();
2556   SetTestMode();  // Fail cache reinitialization.
2557   BackendDisable();
2558 }
2559
2560 // This is another type of corruption on the LRU; disable the cache.
2561 void DiskCacheBackendTest::BackendDisable2() {
2562   EXPECT_EQ(8, cache_->GetEntryCount());
2563
2564   disk_cache::Entry* entry;
2565   void* iter = NULL;
2566   int count = 0;
2567   while (OpenNextEntry(&iter, &entry) == net::OK) {
2568     ASSERT_TRUE(NULL != entry);
2569     entry->Close();
2570     count++;
2571     ASSERT_LT(count, 9);
2572   };
2573
2574   FlushQueueForTest();
2575   EXPECT_EQ(0, cache_->GetEntryCount());
2576 }
2577
2578 TEST_F(DiskCacheBackendTest, DisableSuccess2) {
2579   ASSERT_TRUE(CopyTestCache("list_loop"));
2580   DisableFirstCleanup();
2581   InitCache();
2582   BackendDisable2();
2583 }
2584
2585 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess2) {
2586   ASSERT_TRUE(CopyTestCache("list_loop"));
2587   DisableFirstCleanup();
2588   SetNewEviction();
2589   InitCache();
2590   BackendDisable2();
2591 }
2592
2593 TEST_F(DiskCacheBackendTest, DisableFailure2) {
2594   ASSERT_TRUE(CopyTestCache("list_loop"));
2595   DisableFirstCleanup();
2596   InitCache();
2597   SetTestMode();  // Fail cache reinitialization.
2598   BackendDisable2();
2599 }
2600
2601 TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure2) {
2602   ASSERT_TRUE(CopyTestCache("list_loop"));
2603   DisableFirstCleanup();
2604   SetNewEviction();
2605   InitCache();
2606   SetTestMode();  // Fail cache reinitialization.
2607   BackendDisable2();
2608 }
2609
2610 // If the index size changes when we disable the cache, we should not crash.
2611 void DiskCacheBackendTest::BackendDisable3() {
2612   disk_cache::Entry *entry1, *entry2;
2613   void* iter = NULL;
2614   EXPECT_EQ(2, cache_->GetEntryCount());
2615   ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
2616   entry1->Close();
2617
2618   EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2));
2619   FlushQueueForTest();
2620
2621   ASSERT_EQ(net::OK, CreateEntry("Something new", &entry2));
2622   entry2->Close();
2623
2624   EXPECT_EQ(1, cache_->GetEntryCount());
2625 }
2626
2627 TEST_F(DiskCacheBackendTest, DisableSuccess3) {
2628   ASSERT_TRUE(CopyTestCache("bad_rankings2"));
2629   DisableFirstCleanup();
2630   SetMaxSize(20 * 1024 * 1024);
2631   InitCache();
2632   BackendDisable3();
2633 }
2634
2635 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess3) {
2636   ASSERT_TRUE(CopyTestCache("bad_rankings2"));
2637   DisableFirstCleanup();
2638   SetMaxSize(20 * 1024 * 1024);
2639   SetNewEviction();
2640   InitCache();
2641   BackendDisable3();
2642 }
2643
2644 // If we disable the cache, already open entries should work as far as possible.
2645 void DiskCacheBackendTest::BackendDisable4() {
2646   disk_cache::Entry *entry1, *entry2, *entry3, *entry4;
2647   void* iter = NULL;
2648   ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
2649
2650   char key2[2000];
2651   char key3[20000];
2652   CacheTestFillBuffer(key2, sizeof(key2), true);
2653   CacheTestFillBuffer(key3, sizeof(key3), true);
2654   key2[sizeof(key2) - 1] = '\0';
2655   key3[sizeof(key3) - 1] = '\0';
2656   ASSERT_EQ(net::OK, CreateEntry(key2, &entry2));
2657   ASSERT_EQ(net::OK, CreateEntry(key3, &entry3));
2658
2659   const int kBufSize = 20000;
2660   scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufSize));
2661   memset(buf->data(), 0, kBufSize);
2662   EXPECT_EQ(100, WriteData(entry2, 0, 0, buf.get(), 100, false));
2663   EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf.get(), kBufSize, false));
2664
2665   // This line should disable the cache but not delete it.
2666   EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry4));
2667   EXPECT_EQ(0, cache_->GetEntryCount());
2668
2669   EXPECT_NE(net::OK, CreateEntry("cache is disabled", &entry4));
2670
2671   EXPECT_EQ(100, ReadData(entry2, 0, 0, buf.get(), 100));
2672   EXPECT_EQ(100, WriteData(entry2, 0, 0, buf.get(), 100, false));
2673   EXPECT_EQ(100, WriteData(entry2, 1, 0, buf.get(), 100, false));
2674
2675   EXPECT_EQ(kBufSize, ReadData(entry3, 0, 0, buf.get(), kBufSize));
2676   EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf.get(), kBufSize, false));
2677   EXPECT_EQ(kBufSize, WriteData(entry3, 1, 0, buf.get(), kBufSize, false));
2678
2679   std::string key = entry2->GetKey();
2680   EXPECT_EQ(sizeof(key2) - 1, key.size());
2681   key = entry3->GetKey();
2682   EXPECT_EQ(sizeof(key3) - 1, key.size());
2683
2684   entry1->Close();
2685   entry2->Close();
2686   entry3->Close();
2687   FlushQueueForTest();  // Flushing the Close posts a task to restart the cache.
2688   FlushQueueForTest();  // This one actually allows that task to complete.
2689
2690   EXPECT_EQ(0, cache_->GetEntryCount());
2691 }
2692
2693 TEST_F(DiskCacheBackendTest, DisableSuccess4) {
2694   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2695   DisableFirstCleanup();
2696   InitCache();
2697   BackendDisable4();
2698 }
2699
2700 TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess4) {
2701   ASSERT_TRUE(CopyTestCache("bad_rankings"));
2702   DisableFirstCleanup();
2703   SetNewEviction();
2704   InitCache();
2705   BackendDisable4();
2706 }
2707
2708 TEST_F(DiskCacheTest, Backend_UsageStatsTimer) {
2709   MessageLoopHelper helper;
2710
2711   ASSERT_TRUE(CleanupCacheDir());
2712   scoped_ptr<disk_cache::BackendImpl> cache;
2713   cache.reset(new disk_cache::BackendImpl(
2714       cache_path_, base::MessageLoopProxy::current().get(), NULL));
2715   ASSERT_TRUE(NULL != cache.get());
2716   cache->SetUnitTestMode();
2717   ASSERT_EQ(net::OK, cache->SyncInit());
2718
2719   // Wait for a callback that never comes... about 2 secs :). The message loop
2720   // has to run to allow invocation of the usage timer.
2721   helper.WaitUntilCacheIoFinished(1);
2722 }
2723
2724 TEST_F(DiskCacheBackendTest, Backend_UsageStats) {
2725   InitCache();
2726   disk_cache::Entry* entry;
2727   ASSERT_EQ(net::OK, CreateEntry("key", &entry));
2728   entry->Close();
2729   FlushQueueForTest();
2730
2731   disk_cache::StatsItems stats;
2732   cache_->GetStats(&stats);
2733   EXPECT_FALSE(stats.empty());
2734
2735   disk_cache::StatsItems::value_type hits("Create hit", "0x1");
2736   EXPECT_EQ(1, std::count(stats.begin(), stats.end(), hits));
2737
2738   cache_.reset();
2739
2740   // Now open the cache and verify that the stats are still there.
2741   DisableFirstCleanup();
2742   InitCache();
2743   EXPECT_EQ(1, cache_->GetEntryCount());
2744
2745   stats.clear();
2746   cache_->GetStats(&stats);
2747   EXPECT_FALSE(stats.empty());
2748
2749   EXPECT_EQ(1, std::count(stats.begin(), stats.end(), hits));
2750 }
2751
2752 void DiskCacheBackendTest::BackendDoomAll() {
2753   InitCache();
2754
2755   disk_cache::Entry *entry1, *entry2;
2756   ASSERT_EQ(net::OK, CreateEntry("first", &entry1));
2757   ASSERT_EQ(net::OK, CreateEntry("second", &entry2));
2758   entry1->Close();
2759   entry2->Close();
2760
2761   ASSERT_EQ(net::OK, CreateEntry("third", &entry1));
2762   ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2));
2763
2764   ASSERT_EQ(4, cache_->GetEntryCount());
2765   EXPECT_EQ(net::OK, DoomAllEntries());
2766   ASSERT_EQ(0, cache_->GetEntryCount());
2767
2768   // We should stop posting tasks at some point (if we post any).
2769   base::MessageLoop::current()->RunUntilIdle();
2770
2771   disk_cache::Entry *entry3, *entry4;
2772   EXPECT_NE(net::OK, OpenEntry("third", &entry3));
2773   ASSERT_EQ(net::OK, CreateEntry("third", &entry3));
2774   ASSERT_EQ(net::OK, CreateEntry("fourth", &entry4));
2775
2776   EXPECT_EQ(net::OK, DoomAllEntries());
2777   ASSERT_EQ(0, cache_->GetEntryCount());
2778
2779   entry1->Close();
2780   entry2->Close();
2781   entry3->Doom();  // The entry should be already doomed, but this must work.
2782   entry3->Close();
2783   entry4->Close();
2784
2785   // Now try with all references released.
2786   ASSERT_EQ(net::OK, CreateEntry("third", &entry1));
2787   ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2));
2788   entry1->Close();
2789   entry2->Close();
2790
2791   ASSERT_EQ(2, cache_->GetEntryCount());
2792   EXPECT_EQ(net::OK, DoomAllEntries());
2793   ASSERT_EQ(0, cache_->GetEntryCount());
2794
2795   EXPECT_EQ(net::OK, DoomAllEntries());
2796 }
2797
2798 TEST_F(DiskCacheBackendTest, DoomAll) {
2799   BackendDoomAll();
2800 }
2801
2802 TEST_F(DiskCacheBackendTest, NewEvictionDoomAll) {
2803   SetNewEviction();
2804   BackendDoomAll();
2805 }
2806
2807 TEST_F(DiskCacheBackendTest, MemoryOnlyDoomAll) {
2808   SetMemoryOnlyMode();
2809   BackendDoomAll();
2810 }
2811
2812 TEST_F(DiskCacheBackendTest, AppCacheOnlyDoomAll) {
2813   SetCacheType(net::APP_CACHE);
2814   BackendDoomAll();
2815 }
2816
2817 TEST_F(DiskCacheBackendTest, ShaderCacheOnlyDoomAll) {
2818   SetCacheType(net::SHADER_CACHE);
2819   BackendDoomAll();
2820 }
2821
2822 // If the index size changes when we doom the cache, we should not crash.
2823 void DiskCacheBackendTest::BackendDoomAll2() {
2824   EXPECT_EQ(2, cache_->GetEntryCount());
2825   EXPECT_EQ(net::OK, DoomAllEntries());
2826
2827   disk_cache::Entry* entry;
2828   ASSERT_EQ(net::OK, CreateEntry("Something new", &entry));
2829   entry->Close();
2830
2831   EXPECT_EQ(1, cache_->GetEntryCount());
2832 }
2833
2834 TEST_F(DiskCacheBackendTest, DoomAll2) {
2835   ASSERT_TRUE(CopyTestCache("bad_rankings2"));
2836   DisableFirstCleanup();
2837   SetMaxSize(20 * 1024 * 1024);
2838   InitCache();
2839   BackendDoomAll2();
2840 }
2841
2842 TEST_F(DiskCacheBackendTest, NewEvictionDoomAll2) {
2843   ASSERT_TRUE(CopyTestCache("bad_rankings2"));
2844   DisableFirstCleanup();
2845   SetMaxSize(20 * 1024 * 1024);
2846   SetNewEviction();
2847   InitCache();
2848   BackendDoomAll2();
2849 }
2850
2851 // We should be able to create the same entry on multiple simultaneous instances
2852 // of the cache.
2853 TEST_F(DiskCacheTest, MultipleInstances) {
2854   base::ScopedTempDir store1, store2;
2855   ASSERT_TRUE(store1.CreateUniqueTempDir());
2856   ASSERT_TRUE(store2.CreateUniqueTempDir());
2857
2858   base::Thread cache_thread("CacheThread");
2859   ASSERT_TRUE(cache_thread.StartWithOptions(
2860       base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
2861   net::TestCompletionCallback cb;
2862
2863   const int kNumberOfCaches = 2;
2864   scoped_ptr<disk_cache::Backend> cache[kNumberOfCaches];
2865
2866   int rv =
2867       disk_cache::CreateCacheBackend(net::DISK_CACHE,
2868                                      net::CACHE_BACKEND_DEFAULT,
2869                                      store1.path(),
2870                                      0,
2871                                      false,
2872                                      cache_thread.message_loop_proxy().get(),
2873                                      NULL,
2874                                      &cache[0],
2875                                      cb.callback());
2876   ASSERT_EQ(net::OK, cb.GetResult(rv));
2877   rv = disk_cache::CreateCacheBackend(net::MEDIA_CACHE,
2878                                       net::CACHE_BACKEND_DEFAULT,
2879                                       store2.path(),
2880                                       0,
2881                                       false,
2882                                       cache_thread.message_loop_proxy().get(),
2883                                       NULL,
2884                                       &cache[1],
2885                                       cb.callback());
2886   ASSERT_EQ(net::OK, cb.GetResult(rv));
2887
2888   ASSERT_TRUE(cache[0].get() != NULL && cache[1].get() != NULL);
2889
2890   std::string key("the first key");
2891   disk_cache::Entry* entry;
2892   for (int i = 0; i < kNumberOfCaches; i++) {
2893     rv = cache[i]->CreateEntry(key, &entry, cb.callback());
2894     ASSERT_EQ(net::OK, cb.GetResult(rv));
2895     entry->Close();
2896   }
2897 }
2898
2899 // Test the six regions of the curve that determines the max cache size.
2900 TEST_F(DiskCacheTest, AutomaticMaxSize) {
2901   const int kDefaultSize = 80 * 1024 * 1024;
2902   int64 large_size = kDefaultSize;
2903   int64 largest_size = kint32max;
2904
2905   // Region 1: expected = available * 0.8
2906   EXPECT_EQ((kDefaultSize - 1) * 8 / 10,
2907             disk_cache::PreferedCacheSize(large_size - 1));
2908   EXPECT_EQ(kDefaultSize * 8 / 10,
2909             disk_cache::PreferedCacheSize(large_size));
2910   EXPECT_EQ(kDefaultSize - 1,
2911             disk_cache::PreferedCacheSize(large_size * 10 / 8 - 1));
2912
2913   // Region 2: expected = default_size
2914   EXPECT_EQ(kDefaultSize,
2915             disk_cache::PreferedCacheSize(large_size * 10 / 8));
2916   EXPECT_EQ(kDefaultSize,
2917             disk_cache::PreferedCacheSize(large_size * 10 - 1));
2918
2919   // Region 3: expected = available * 0.1
2920   EXPECT_EQ(kDefaultSize,
2921             disk_cache::PreferedCacheSize(large_size * 10));
2922   EXPECT_EQ((kDefaultSize * 25 - 1) / 10,
2923             disk_cache::PreferedCacheSize(large_size * 25 - 1));
2924
2925   // Region 4: expected = default_size * 2.5
2926   EXPECT_EQ(kDefaultSize * 25 / 10,
2927             disk_cache::PreferedCacheSize(large_size * 25));
2928   EXPECT_EQ(kDefaultSize * 25 / 10,
2929             disk_cache::PreferedCacheSize(large_size * 100 - 1));
2930   EXPECT_EQ(kDefaultSize * 25 / 10,
2931             disk_cache::PreferedCacheSize(large_size * 100));
2932   EXPECT_EQ(kDefaultSize * 25 / 10,
2933             disk_cache::PreferedCacheSize(large_size * 250 - 1));
2934
2935   // Region 5: expected = available * 0.1
2936   EXPECT_EQ(kDefaultSize * 25 / 10,
2937             disk_cache::PreferedCacheSize(large_size * 250));
2938   EXPECT_EQ(kint32max - 1,
2939             disk_cache::PreferedCacheSize(largest_size * 100 - 1));
2940
2941   // Region 6: expected = kint32max
2942   EXPECT_EQ(kint32max,
2943             disk_cache::PreferedCacheSize(largest_size * 100));
2944   EXPECT_EQ(kint32max,
2945             disk_cache::PreferedCacheSize(largest_size * 10000));
2946 }
2947
2948 // Tests that we can "migrate" a running instance from one experiment group to
2949 // another.
2950 TEST_F(DiskCacheBackendTest, Histograms) {
2951   InitCache();
2952   disk_cache::BackendImpl* backend_ = cache_impl_;  // Needed be the macro.
2953
2954   for (int i = 1; i < 3; i++) {
2955     CACHE_UMA(HOURS, "FillupTime", i, 28);
2956   }
2957 }
2958
2959 // Make sure that we keep the total memory used by the internal buffers under
2960 // control.
2961 TEST_F(DiskCacheBackendTest, TotalBuffersSize1) {
2962   InitCache();
2963   std::string key("the first key");
2964   disk_cache::Entry* entry;
2965   ASSERT_EQ(net::OK, CreateEntry(key, &entry));
2966
2967   const int kSize = 200;
2968   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
2969   CacheTestFillBuffer(buffer->data(), kSize, true);
2970
2971   for (int i = 0; i < 10; i++) {
2972     SCOPED_TRACE(i);
2973     // Allocate 2MB for this entry.
2974     EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, true));
2975     EXPECT_EQ(kSize, WriteData(entry, 1, 0, buffer.get(), kSize, true));
2976     EXPECT_EQ(kSize,
2977               WriteData(entry, 0, 1024 * 1024, buffer.get(), kSize, false));
2978     EXPECT_EQ(kSize,
2979               WriteData(entry, 1, 1024 * 1024, buffer.get(), kSize, false));
2980
2981     // Delete one of the buffers and truncate the other.
2982     EXPECT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, true));
2983     EXPECT_EQ(0, WriteData(entry, 1, 10, buffer.get(), 0, true));
2984
2985     // Delete the second buffer, writing 10 bytes to disk.
2986     entry->Close();
2987     ASSERT_EQ(net::OK, OpenEntry(key, &entry));
2988   }
2989
2990   entry->Close();
2991   EXPECT_EQ(0, cache_impl_->GetTotalBuffersSize());
2992 }
2993
2994 // This test assumes at least 150MB of system memory.
2995 TEST_F(DiskCacheBackendTest, TotalBuffersSize2) {
2996   InitCache();
2997
2998   const int kOneMB = 1024 * 1024;
2999   EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB));
3000   EXPECT_EQ(kOneMB, cache_impl_->GetTotalBuffersSize());
3001
3002   EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB));
3003   EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize());
3004
3005   EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB));
3006   EXPECT_EQ(kOneMB * 3, cache_impl_->GetTotalBuffersSize());
3007
3008   cache_impl_->BufferDeleted(kOneMB);
3009   EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize());
3010
3011   // Check the upper limit.
3012   EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, 30 * kOneMB));
3013
3014   for (int i = 0; i < 30; i++)
3015     cache_impl_->IsAllocAllowed(0, kOneMB);  // Ignore the result.
3016
3017   EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, kOneMB));
3018 }
3019
3020 // Tests that sharing of external files works and we are able to delete the
3021 // files when we need to.
3022 TEST_F(DiskCacheBackendTest, FileSharing) {
3023   InitCache();
3024
3025   disk_cache::Addr address(0x80000001);
3026   ASSERT_TRUE(cache_impl_->CreateExternalFile(&address));
3027   base::FilePath name = cache_impl_->GetFileName(address);
3028
3029   scoped_refptr<disk_cache::File> file(new disk_cache::File(false));
3030   file->Init(name);
3031
3032 #if defined(OS_WIN)
3033   DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
3034   DWORD access = GENERIC_READ | GENERIC_WRITE;
3035   base::win::ScopedHandle file2(CreateFile(
3036       name.value().c_str(), access, sharing, NULL, OPEN_EXISTING, 0, NULL));
3037   EXPECT_FALSE(file2.IsValid());
3038
3039   sharing |= FILE_SHARE_DELETE;
3040   file2.Set(CreateFile(name.value().c_str(), access, sharing, NULL,
3041                        OPEN_EXISTING, 0, NULL));
3042   EXPECT_TRUE(file2.IsValid());
3043 #endif
3044
3045   EXPECT_TRUE(base::DeleteFile(name, false));
3046
3047   // We should be able to use the file.
3048   const int kSize = 200;
3049   char buffer1[kSize];
3050   char buffer2[kSize];
3051   memset(buffer1, 't', kSize);
3052   memset(buffer2, 0, kSize);
3053   EXPECT_TRUE(file->Write(buffer1, kSize, 0));
3054   EXPECT_TRUE(file->Read(buffer2, kSize, 0));
3055   EXPECT_EQ(0, memcmp(buffer1, buffer2, kSize));
3056
3057   EXPECT_TRUE(disk_cache::DeleteCacheFile(name));
3058 }
3059
3060 TEST_F(DiskCacheBackendTest, UpdateRankForExternalCacheHit) {
3061   InitCache();
3062
3063   disk_cache::Entry* entry;
3064
3065   for (int i = 0; i < 2; ++i) {
3066     std::string key = base::StringPrintf("key%d", i);
3067     ASSERT_EQ(net::OK, CreateEntry(key, &entry));
3068     entry->Close();
3069   }
3070
3071   // Ping the oldest entry.
3072   cache_->OnExternalCacheHit("key0");
3073
3074   TrimForTest(false);
3075
3076   // Make sure the older key remains.
3077   EXPECT_EQ(1, cache_->GetEntryCount());
3078   ASSERT_EQ(net::OK, OpenEntry("key0", &entry));
3079   entry->Close();
3080 }
3081
3082 TEST_F(DiskCacheBackendTest, ShaderCacheUpdateRankForExternalCacheHit) {
3083   SetCacheType(net::SHADER_CACHE);
3084   InitCache();
3085
3086   disk_cache::Entry* entry;
3087
3088   for (int i = 0; i < 2; ++i) {
3089     std::string key = base::StringPrintf("key%d", i);
3090     ASSERT_EQ(net::OK, CreateEntry(key, &entry));
3091     entry->Close();
3092   }
3093
3094   // Ping the oldest entry.
3095   cache_->OnExternalCacheHit("key0");
3096
3097   TrimForTest(false);
3098
3099   // Make sure the older key remains.
3100   EXPECT_EQ(1, cache_->GetEntryCount());
3101   ASSERT_EQ(net::OK, OpenEntry("key0", &entry));
3102   entry->Close();
3103 }
3104
3105 void DiskCacheBackendTest::TracingBackendBasics() {
3106   InitCache();
3107   cache_.reset(new disk_cache::TracingCacheBackend(cache_.Pass()));
3108   cache_impl_ = NULL;
3109   EXPECT_EQ(net::DISK_CACHE, cache_->GetCacheType());
3110   if (!simple_cache_mode_) {
3111     EXPECT_EQ(0, cache_->GetEntryCount());
3112   }
3113
3114   net::TestCompletionCallback cb;
3115   disk_cache::Entry* entry = NULL;
3116   EXPECT_NE(net::OK, OpenEntry("key", &entry));
3117   EXPECT_TRUE(NULL == entry);
3118
3119   ASSERT_EQ(net::OK, CreateEntry("key", &entry));
3120   EXPECT_TRUE(NULL != entry);
3121
3122   disk_cache::Entry* same_entry = NULL;
3123   ASSERT_EQ(net::OK, OpenEntry("key", &same_entry));
3124   EXPECT_TRUE(NULL != same_entry);
3125
3126   if (!simple_cache_mode_) {
3127     EXPECT_EQ(1, cache_->GetEntryCount());
3128   }
3129   entry->Close();
3130   entry = NULL;
3131   same_entry->Close();
3132   same_entry = NULL;
3133 }
3134
3135 TEST_F(DiskCacheBackendTest, TracingBackendBasics) {
3136   TracingBackendBasics();
3137 }
3138
3139 // The Simple Cache backend requires a few guarantees from the filesystem like
3140 // atomic renaming of recently open files. Those guarantees are not provided in
3141 // general on Windows.
3142 #if defined(OS_POSIX)
3143
3144 TEST_F(DiskCacheBackendTest, SimpleCacheShutdownWithPendingCreate) {
3145   SetCacheType(net::APP_CACHE);
3146   SetSimpleCacheMode();
3147   BackendShutdownWithPendingCreate(false);
3148 }
3149
3150 TEST_F(DiskCacheBackendTest, SimpleCacheShutdownWithPendingFileIO) {
3151   SetCacheType(net::APP_CACHE);
3152   SetSimpleCacheMode();
3153   BackendShutdownWithPendingFileIO(false);
3154 }
3155
3156 TEST_F(DiskCacheBackendTest, SimpleCacheBasics) {
3157   SetSimpleCacheMode();
3158   BackendBasics();
3159 }
3160
3161 TEST_F(DiskCacheBackendTest, SimpleCacheAppCacheBasics) {
3162   SetCacheType(net::APP_CACHE);
3163   SetSimpleCacheMode();
3164   BackendBasics();
3165 }
3166
3167 TEST_F(DiskCacheBackendTest, SimpleCacheKeying) {
3168   SetSimpleCacheMode();
3169   BackendKeying();
3170 }
3171
3172 TEST_F(DiskCacheBackendTest, SimpleCacheAppCacheKeying) {
3173   SetSimpleCacheMode();
3174   SetCacheType(net::APP_CACHE);
3175   BackendKeying();
3176 }
3177
3178 TEST_F(DiskCacheBackendTest, DISABLED_SimpleCacheSetSize) {
3179   SetSimpleCacheMode();
3180   BackendSetSize();
3181 }
3182
3183 // MacOS has a default open file limit of 256 files, which is incompatible with
3184 // this simple cache test.
3185 #if defined(OS_MACOSX)
3186 #define SIMPLE_MAYBE_MACOS(TestName) DISABLED_ ## TestName
3187 #else
3188 #define SIMPLE_MAYBE_MACOS(TestName) TestName
3189 #endif
3190
3191 TEST_F(DiskCacheBackendTest, SIMPLE_MAYBE_MACOS(SimpleCacheLoad)) {
3192   SetMaxSize(0x100000);
3193   SetSimpleCacheMode();
3194   BackendLoad();
3195 }
3196
3197 TEST_F(DiskCacheBackendTest, SIMPLE_MAYBE_MACOS(SimpleCacheAppCacheLoad)) {
3198   SetCacheType(net::APP_CACHE);
3199   SetSimpleCacheMode();
3200   SetMaxSize(0x100000);
3201   BackendLoad();
3202 }
3203
3204 TEST_F(DiskCacheBackendTest, SimpleDoomRecent) {
3205   SetSimpleCacheMode();
3206   BackendDoomRecent();
3207 }
3208
3209 TEST_F(DiskCacheBackendTest, SimpleDoomBetween) {
3210   SetSimpleCacheMode();
3211   BackendDoomBetween();
3212 }
3213
3214 TEST_F(DiskCacheBackendTest, SimpleCacheDoomAll) {
3215   SetSimpleCacheMode();
3216   BackendDoomAll();
3217 }
3218
3219 TEST_F(DiskCacheBackendTest, SimpleCacheAppCacheOnlyDoomAll) {
3220   SetCacheType(net::APP_CACHE);
3221   SetSimpleCacheMode();
3222   BackendDoomAll();
3223 }
3224
3225 TEST_F(DiskCacheBackendTest, SimpleCacheTracingBackendBasics) {
3226   SetSimpleCacheMode();
3227   TracingBackendBasics();
3228   // TODO(pasko): implement integrity checking on the Simple Backend.
3229   DisableIntegrityCheck();
3230 }
3231
3232 TEST_F(DiskCacheBackendTest, SimpleCacheOpenMissingFile) {
3233   SetSimpleCacheMode();
3234   InitCache();
3235
3236   const char* key = "the first key";
3237   disk_cache::Entry* entry = NULL;
3238
3239   ASSERT_EQ(net::OK, CreateEntry(key, &entry));
3240   ASSERT_TRUE(entry != NULL);
3241   entry->Close();
3242   entry = NULL;
3243
3244   // To make sure the file creation completed we need to call open again so that
3245   // we block until it actually created the files.
3246   ASSERT_EQ(net::OK, OpenEntry(key, &entry));
3247   ASSERT_TRUE(entry != NULL);
3248   entry->Close();
3249   entry = NULL;
3250
3251   // Delete one of the files in the entry.
3252   base::FilePath to_delete_file = cache_path_.AppendASCII(
3253       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
3254   EXPECT_TRUE(base::PathExists(to_delete_file));
3255   EXPECT_TRUE(disk_cache::DeleteCacheFile(to_delete_file));
3256
3257   // Failing to open the entry should delete the rest of these files.
3258   ASSERT_EQ(net::ERR_FAILED, OpenEntry(key, &entry));
3259
3260   // Confirm the rest of the files are gone.
3261   for (int i = 1; i < disk_cache::kSimpleEntryFileCount; ++i) {
3262     base::FilePath should_be_gone_file(cache_path_.AppendASCII(
3263         disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, i)));
3264     EXPECT_FALSE(base::PathExists(should_be_gone_file));
3265   }
3266 }
3267
3268 TEST_F(DiskCacheBackendTest, SimpleCacheOpenBadFile) {
3269   SetSimpleCacheMode();
3270   InitCache();
3271
3272   const char* key = "the first key";
3273   disk_cache::Entry* entry = NULL;
3274
3275   ASSERT_EQ(net::OK, CreateEntry(key, &entry));
3276   disk_cache::Entry* null = NULL;
3277   ASSERT_NE(null, entry);
3278   entry->Close();
3279   entry = NULL;
3280
3281   // To make sure the file creation completed we need to call open again so that
3282   // we block until it actually created the files.
3283   ASSERT_EQ(net::OK, OpenEntry(key, &entry));
3284   ASSERT_NE(null, entry);
3285   entry->Close();
3286   entry = NULL;
3287
3288   // Write an invalid header for stream 0 and stream 1.
3289   base::FilePath entry_file1_path = cache_path_.AppendASCII(
3290       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
3291
3292   disk_cache::SimpleFileHeader header;
3293   header.initial_magic_number = GG_UINT64_C(0xbadf00d);
3294   EXPECT_EQ(
3295       implicit_cast<int>(sizeof(header)),
3296       file_util::WriteFile(entry_file1_path, reinterpret_cast<char*>(&header),
3297                            sizeof(header)));
3298   ASSERT_EQ(net::ERR_FAILED, OpenEntry(key, &entry));
3299 }
3300
3301 // Tests that the Simple Cache Backend fails to initialize with non-matching
3302 // file structure on disk.
3303 TEST_F(DiskCacheBackendTest, SimpleCacheOverBlockfileCache) {
3304   // Create a cache structure with the |BackendImpl|.
3305   InitCache();
3306   disk_cache::Entry* entry;
3307   const int kSize = 50;
3308   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
3309   CacheTestFillBuffer(buffer->data(), kSize, false);
3310   ASSERT_EQ(net::OK, CreateEntry("key", &entry));
3311   ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false));
3312   entry->Close();
3313   cache_.reset();
3314
3315   // Check that the |SimpleBackendImpl| does not favor this structure.
3316   base::Thread cache_thread("CacheThread");
3317   ASSERT_TRUE(cache_thread.StartWithOptions(
3318       base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
3319   disk_cache::SimpleBackendImpl* simple_cache =
3320       new disk_cache::SimpleBackendImpl(cache_path_,
3321                                         0,
3322                                         net::DISK_CACHE,
3323                                         cache_thread.message_loop_proxy().get(),
3324                                         NULL);
3325   net::TestCompletionCallback cb;
3326   int rv = simple_cache->Init(cb.callback());
3327   EXPECT_NE(net::OK, cb.GetResult(rv));
3328   delete simple_cache;
3329   DisableIntegrityCheck();
3330 }
3331
3332 // Tests that the |BackendImpl| refuses to initialize on top of the files
3333 // generated by the Simple Cache Backend.
3334 TEST_F(DiskCacheBackendTest, BlockfileCacheOverSimpleCache) {
3335   // Create a cache structure with the |SimpleBackendImpl|.
3336   SetSimpleCacheMode();
3337   InitCache();
3338   disk_cache::Entry* entry;
3339   const int kSize = 50;
3340   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
3341   CacheTestFillBuffer(buffer->data(), kSize, false);
3342   ASSERT_EQ(net::OK, CreateEntry("key", &entry));
3343   ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false));
3344   entry->Close();
3345   cache_.reset();
3346
3347   // Check that the |BackendImpl| does not favor this structure.
3348   base::Thread cache_thread("CacheThread");
3349   ASSERT_TRUE(cache_thread.StartWithOptions(
3350       base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
3351   disk_cache::BackendImpl* cache = new disk_cache::BackendImpl(
3352       cache_path_, base::MessageLoopProxy::current().get(), NULL);
3353   cache->SetUnitTestMode();
3354   net::TestCompletionCallback cb;
3355   int rv = cache->Init(cb.callback());
3356   EXPECT_NE(net::OK, cb.GetResult(rv));
3357   delete cache;
3358   DisableIntegrityCheck();
3359 }
3360
3361 TEST_F(DiskCacheBackendTest, SimpleCacheFixEnumerators) {
3362   SetSimpleCacheMode();
3363   BackendFixEnumerators();
3364 }
3365
3366 // Tests basic functionality of the SimpleBackend implementation of the
3367 // enumeration API.
3368 TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationBasics) {
3369   SetSimpleCacheMode();
3370   InitCache();
3371   std::set<std::string> key_pool;
3372   ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool));
3373
3374   // Check that enumeration returns all entries.
3375   std::set<std::string> keys_to_match(key_pool);
3376   void* iter = NULL;
3377   size_t count = 0;
3378   ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count));
3379   cache_->EndEnumeration(&iter);
3380   EXPECT_EQ(key_pool.size(), count);
3381   EXPECT_TRUE(keys_to_match.empty());
3382
3383   // Check that opening entries does not affect enumeration.
3384   keys_to_match = key_pool;
3385   iter = NULL;
3386   count = 0;
3387   disk_cache::Entry* entry_opened_before;
3388   ASSERT_EQ(net::OK, OpenEntry(*(key_pool.begin()), &entry_opened_before));
3389   ASSERT_TRUE(EnumerateAndMatchKeys(key_pool.size()/2,
3390                                     &iter,
3391                                     &keys_to_match,
3392                                     &count));
3393
3394   disk_cache::Entry* entry_opened_middle;
3395   ASSERT_EQ(net::OK,
3396             OpenEntry(*(keys_to_match.begin()), &entry_opened_middle));
3397   ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count));
3398   cache_->EndEnumeration(&iter);
3399   entry_opened_before->Close();
3400   entry_opened_middle->Close();
3401
3402   EXPECT_EQ(key_pool.size(), count);
3403   EXPECT_TRUE(keys_to_match.empty());
3404 }
3405
3406 // Tests that the enumerations are not affected by dooming an entry in the
3407 // middle.
3408 TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationWhileDoomed) {
3409   SetSimpleCacheMode();
3410   InitCache();
3411   std::set<std::string> key_pool;
3412   ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool));
3413
3414   // Check that enumeration returns all entries but the doomed one.
3415   std::set<std::string> keys_to_match(key_pool);
3416   void* iter = NULL;
3417   size_t count = 0;
3418   ASSERT_TRUE(EnumerateAndMatchKeys(key_pool.size()/2,
3419                                     &iter,
3420                                     &keys_to_match,
3421                                     &count));
3422
3423   std::string key_to_delete = *(keys_to_match.begin());
3424   DoomEntry(key_to_delete);
3425   keys_to_match.erase(key_to_delete);
3426   key_pool.erase(key_to_delete);
3427   ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count));
3428   cache_->EndEnumeration(&iter);
3429
3430   EXPECT_EQ(key_pool.size(), count);
3431   EXPECT_TRUE(keys_to_match.empty());
3432 }
3433
3434 // Tests that enumerations are not affected by corrupt files.
3435 TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationCorruption) {
3436   SetSimpleCacheMode();
3437   InitCache();
3438   std::set<std::string> key_pool;
3439   ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool));
3440
3441   // Create a corrupt entry. The write/read sequence ensures that the entry will
3442   // have been created before corrupting the platform files, in the case of
3443   // optimistic operations.
3444   const std::string key = "the key";
3445   disk_cache::Entry* corrupted_entry;
3446
3447   ASSERT_EQ(net::OK, CreateEntry(key, &corrupted_entry));
3448   ASSERT_TRUE(corrupted_entry);
3449   const int kSize = 50;
3450   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
3451   CacheTestFillBuffer(buffer->data(), kSize, false);
3452   ASSERT_EQ(kSize,
3453             WriteData(corrupted_entry, 0, 0, buffer.get(), kSize, false));
3454   ASSERT_EQ(kSize, ReadData(corrupted_entry, 0, 0, buffer.get(), kSize));
3455   corrupted_entry->Close();
3456
3457   EXPECT_TRUE(disk_cache::simple_util::CreateCorruptFileForTests(
3458       key, cache_path_));
3459   EXPECT_EQ(key_pool.size() + 1,
3460             implicit_cast<size_t>(cache_->GetEntryCount()));
3461
3462   // Check that enumeration returns all entries but the corrupt one.
3463   std::set<std::string> keys_to_match(key_pool);
3464   void* iter = NULL;
3465   size_t count = 0;
3466   ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count));
3467   cache_->EndEnumeration(&iter);
3468
3469   EXPECT_EQ(key_pool.size(), count);
3470   EXPECT_TRUE(keys_to_match.empty());
3471 }
3472
3473 #endif  // defined(OS_POSIX)