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