summaryrefslogtreecommitdiffstats
path: root/net/disk_cache/backend_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/disk_cache/backend_unittest.cc')
-rw-r--r--net/disk_cache/backend_unittest.cc340
1 files changed, 340 insertions, 0 deletions
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index e764a15..5b101c9 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -15,6 +15,7 @@
#include "net/disk_cache/cache_util.h"
#include "net/disk_cache/disk_cache_test_base.h"
#include "net/disk_cache/disk_cache_test_util.h"
+#include "net/disk_cache/entry_impl.h"
#include "net/disk_cache/histogram_macros.h"
#include "net/disk_cache/mapped_file.h"
#include "net/disk_cache/mem_backend_impl.h"
@@ -51,6 +52,12 @@ class DiskCacheBackendTest : public DiskCacheTestWithCache {
void BackendRecoverWithEviction();
void BackendInvalidEntry2();
void BackendInvalidEntry3();
+ void BackendInvalidEntry7();
+ void BackendInvalidEntry8();
+ void BackendInvalidEntry9(bool eviction);
+ void BackendInvalidEntry10(bool eviction);
+ void BackendInvalidEntry11(bool eviction);
+ void BackendTrimInvalidEntry12();
void BackendNotMarkedButDirty(const std::string& name);
void BackendDoomAll();
void BackendDoomAll2();
@@ -1499,6 +1506,339 @@ TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry6) {
entry->Close();
}
+// Tests handling of corrupt entries by keeping the rankings node around, with
+// a fatal failure.
+void DiskCacheBackendTest::BackendInvalidEntry7() {
+ SetDirectMode();
+ const int kSize = 0x3000; // 12 kB.
+ SetMaxSize(kSize * 10);
+ InitCache();
+
+ std::string first("some key");
+ std::string second("something else");
+ disk_cache::Entry* entry;
+ ASSERT_EQ(net::OK, CreateEntry(first, &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry(second, &entry));
+
+ // Corrupt this entry.
+ disk_cache::EntryImpl* entry_impl =
+ static_cast<disk_cache::EntryImpl*>(entry);
+
+ entry_impl->rankings()->Data()->next = 0;
+ entry_impl->rankings()->Store();
+ entry->Close();
+ FlushQueueForTest();
+ EXPECT_EQ(2, cache_->GetEntryCount());
+
+ // This should detect the bad entry.
+ EXPECT_NE(net::OK, OpenEntry(second, &entry));
+ EXPECT_EQ(1, cache_->GetEntryCount());
+
+ // We should delete the cache. The list still has a corrupt node.
+ void* iter = NULL;
+ EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
+ EXPECT_EQ(0, cache_->GetEntryCount());
+}
+
+TEST_F(DiskCacheBackendTest, InvalidEntry7) {
+ BackendInvalidEntry7();
+}
+
+TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry7) {
+ SetNewEviction();
+ BackendInvalidEntry7();
+}
+
+// Tests handling of corrupt entries by keeping the rankings node around, with
+// a non fatal failure.
+void DiskCacheBackendTest::BackendInvalidEntry8() {
+ SetDirectMode();
+ const int kSize = 0x3000; // 12 kB
+ SetMaxSize(kSize * 10);
+ InitCache();
+
+ std::string first("some key");
+ std::string second("something else");
+ disk_cache::Entry* entry;
+ ASSERT_EQ(net::OK, CreateEntry(first, &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry(second, &entry));
+
+ // Corrupt this entry.
+ disk_cache::EntryImpl* entry_impl =
+ static_cast<disk_cache::EntryImpl*>(entry);
+
+ entry_impl->rankings()->Data()->contents = 0;
+ entry_impl->rankings()->Store();
+ entry->Close();
+ FlushQueueForTest();
+ EXPECT_EQ(2, cache_->GetEntryCount());
+
+ // This should detect the bad entry.
+ EXPECT_NE(net::OK, OpenEntry(second, &entry));
+ EXPECT_EQ(1, cache_->GetEntryCount());
+
+ // We should not delete the cache.
+ void* iter = NULL;
+ ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
+ entry->Close();
+ EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
+ EXPECT_EQ(1, cache_->GetEntryCount());
+}
+
+TEST_F(DiskCacheBackendTest, InvalidEntry8) {
+ BackendInvalidEntry8();
+}
+
+TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry8) {
+ SetNewEviction();
+ BackendInvalidEntry8();
+}
+
+// Tests handling of corrupt entries detected by enumerations. Note that these
+// tests (xx9 to xx11) are basically just going though slightly different
+// codepaths so they are tighlty coupled with the code, but that is better than
+// not testing error handling code.
+void DiskCacheBackendTest::BackendInvalidEntry9(bool eviction) {
+ SetDirectMode();
+ const int kSize = 0x3000; // 12 kB.
+ SetMaxSize(kSize * 10);
+ InitCache();
+
+ std::string first("some key");
+ std::string second("something else");
+ disk_cache::Entry* entry;
+ ASSERT_EQ(net::OK, CreateEntry(first, &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry(second, &entry));
+
+ // Corrupt this entry.
+ disk_cache::EntryImpl* entry_impl =
+ static_cast<disk_cache::EntryImpl*>(entry);
+
+ entry_impl->entry()->Data()->state = 0xbad;
+ entry_impl->entry()->Store();
+ entry->Close();
+ FlushQueueForTest();
+ EXPECT_EQ(2, cache_->GetEntryCount());
+
+ if (eviction) {
+ TrimForTest(false);
+ EXPECT_EQ(1, cache_->GetEntryCount());
+ TrimForTest(false);
+ EXPECT_EQ(1, cache_->GetEntryCount());
+ } else {
+ // We should detect the problem through the list, but we should not delete
+ // the entry, just fail the iteration.
+ void* iter = NULL;
+ EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
+
+ // Now a full iteration will work, and return one entry.
+ ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
+ entry->Close();
+ EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
+
+ // This should detect what's left of the bad entry.
+ EXPECT_NE(net::OK, OpenEntry(second, &entry));
+ EXPECT_EQ(2, cache_->GetEntryCount());
+ }
+ DisableIntegrityCheck();
+}
+
+TEST_F(DiskCacheBackendTest, InvalidEntry9) {
+ BackendInvalidEntry9(false);
+}
+
+TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry9) {
+ SetNewEviction();
+ BackendInvalidEntry9(false);
+}
+
+TEST_F(DiskCacheBackendTest, TrimInvalidEntry9) {
+ BackendInvalidEntry9(true);
+}
+
+TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry9) {
+ SetNewEviction();
+ BackendInvalidEntry9(true);
+}
+
+// Tests handling of corrupt entries detected by enumerations.
+void DiskCacheBackendTest::BackendInvalidEntry10(bool eviction) {
+ SetDirectMode();
+ const int kSize = 0x3000; // 12 kB.
+ SetMaxSize(kSize * 10);
+ SetNewEviction();
+ InitCache();
+
+ std::string first("some key");
+ std::string second("something else");
+ disk_cache::Entry* entry;
+ ASSERT_EQ(net::OK, CreateEntry(first, &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, OpenEntry(first, &entry));
+ EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false));
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry(second, &entry));
+
+ // Corrupt this entry.
+ disk_cache::EntryImpl* entry_impl =
+ static_cast<disk_cache::EntryImpl*>(entry);
+
+ entry_impl->entry()->Data()->state = 0xbad;
+ entry_impl->entry()->Store();
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry("third", &entry));
+ entry->Close();
+ EXPECT_EQ(3, cache_->GetEntryCount());
+
+ // We have:
+ // List 0: third -> second (bad).
+ // List 1: first.
+
+ if (eviction) {
+ // Detection order: second -> first -> third.
+ TrimForTest(false);
+ EXPECT_EQ(3, cache_->GetEntryCount());
+ TrimForTest(false);
+ EXPECT_EQ(2, cache_->GetEntryCount());
+ TrimForTest(false);
+ EXPECT_EQ(1, cache_->GetEntryCount());
+ } else {
+ // Detection order: third -> second -> first.
+ // We should detect the problem through the list, but we should not delete
+ // the entry.
+ void* iter = NULL;
+ ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
+ EXPECT_EQ(first, entry->GetKey());
+ entry->Close();
+ EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
+ }
+ DisableIntegrityCheck();
+}
+
+TEST_F(DiskCacheBackendTest, InvalidEntry10) {
+ BackendInvalidEntry10(false);
+}
+
+TEST_F(DiskCacheBackendTest, TrimInvalidEntry10) {
+ BackendInvalidEntry10(true);
+}
+
+// Tests handling of corrupt entries detected by enumerations.
+void DiskCacheBackendTest::BackendInvalidEntry11(bool eviction) {
+ SetDirectMode();
+ const int kSize = 0x3000; // 12 kB.
+ SetMaxSize(kSize * 10);
+ SetNewEviction();
+ InitCache();
+
+ std::string first("some key");
+ std::string second("something else");
+ disk_cache::Entry* entry;
+ ASSERT_EQ(net::OK, CreateEntry(first, &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, OpenEntry(first, &entry));
+ EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false));
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry(second, &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, OpenEntry(second, &entry));
+ EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false));
+
+ // Corrupt this entry.
+ disk_cache::EntryImpl* entry_impl =
+ static_cast<disk_cache::EntryImpl*>(entry);
+
+ entry_impl->entry()->Data()->state = 0xbad;
+ entry_impl->entry()->Store();
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry("third", &entry));
+ entry->Close();
+ FlushQueueForTest();
+ EXPECT_EQ(3, cache_->GetEntryCount());
+
+ // We have:
+ // List 0: third.
+ // List 1: second (bad) -> first.
+
+ if (eviction) {
+ // Detection order: third -> first -> second.
+ TrimForTest(false);
+ EXPECT_EQ(2, cache_->GetEntryCount());
+ TrimForTest(false);
+ EXPECT_EQ(1, cache_->GetEntryCount());
+ TrimForTest(false);
+ EXPECT_EQ(1, cache_->GetEntryCount());
+ } else {
+ // Detection order: third -> second.
+ // We should detect the problem through the list, but we should not delete
+ // the entry, just fail the iteration.
+ void* iter = NULL;
+ ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
+ entry->Close();
+ EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
+
+ // Now a full iteration will work, and return two entries.
+ ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
+ entry->Close();
+ EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
+ }
+ DisableIntegrityCheck();
+}
+
+TEST_F(DiskCacheBackendTest, InvalidEntry11) {
+ BackendInvalidEntry11(false);
+}
+
+TEST_F(DiskCacheBackendTest, TrimInvalidEntry11) {
+ BackendInvalidEntry11(true);
+}
+
+// Tests handling of corrupt entries in the middle of a long eviction run.
+void DiskCacheBackendTest::BackendTrimInvalidEntry12() {
+ SetDirectMode();
+ const int kSize = 0x3000; // 12 kB
+ SetMaxSize(kSize * 10);
+ InitCache();
+
+ std::string first("some key");
+ std::string second("something else");
+ disk_cache::Entry* entry;
+ ASSERT_EQ(net::OK, CreateEntry(first, &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry(second, &entry));
+
+ // Corrupt this entry.
+ disk_cache::EntryImpl* entry_impl =
+ static_cast<disk_cache::EntryImpl*>(entry);
+
+ entry_impl->entry()->Data()->state = 0xbad;
+ entry_impl->entry()->Store();
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry("third", &entry));
+ entry->Close();
+ ASSERT_EQ(net::OK, CreateEntry("fourth", &entry));
+ TrimForTest(true);
+ EXPECT_EQ(1, cache_->GetEntryCount());
+ entry->Close();
+ DisableIntegrityCheck();
+}
+
+TEST_F(DiskCacheBackendTest, TrimInvalidEntry12) {
+ BackendTrimInvalidEntry12();
+}
+
+TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry12) {
+ SetNewEviction();
+ BackendTrimInvalidEntry12();
+}
+
// We want to be able to deal with abnormal dirty entries.
void DiskCacheBackendTest::BackendNotMarkedButDirty(const std::string& name) {
ASSERT_TRUE(CopyTestCache(name));