summaryrefslogtreecommitdiffstats
path: root/net/disk_cache/entry_unittest.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 22:42:52 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 22:42:52 +0000
commit586acc5fe142f498261f52c66862fa417c3d52d2 (patch)
treec98b3417a883f2477029c8cd5888f4078681e24e /net/disk_cache/entry_unittest.cc
parenta814a8d55429605fe6d7045045cd25b6bf624580 (diff)
downloadchromium_src-586acc5fe142f498261f52c66862fa417c3d52d2.zip
chromium_src-586acc5fe142f498261f52c66862fa417c3d52d2.tar.gz
chromium_src-586acc5fe142f498261f52c66862fa417c3d52d2.tar.bz2
Add net to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/disk_cache/entry_unittest.cc')
-rw-r--r--net/disk_cache/entry_unittest.cc713
1 files changed, 713 insertions, 0 deletions
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc
new file mode 100644
index 0000000..d2eea79
--- /dev/null
+++ b/net/disk_cache/entry_unittest.cc
@@ -0,0 +1,713 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "base/timer.h"
+#include "net/base/net_errors.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 "testing/gtest/include/gtest/gtest.h"
+
+extern int g_cache_tests_max_id;
+extern volatile int g_cache_tests_received;
+extern volatile bool g_cache_tests_error;
+
+// Tests that can run with different types of caches.
+class DiskCacheEntryTest : public DiskCacheTestBase {
+ protected:
+ void InternalSyncIO();
+ void InternalAsyncIO();
+ void ExternalSyncIO();
+ void ExternalAsyncIO();
+ void GetKey();
+ void GrowData();
+ void TruncateData();
+ void InvalidData();
+ void DoomEntry();
+ void DoomedEntry();
+};
+
+void DiskCacheEntryTest::InternalSyncIO() {
+ disk_cache::Entry *entry1 = NULL;
+ ASSERT_TRUE(cache_->CreateEntry("the first key", &entry1));
+ ASSERT_TRUE(NULL != entry1);
+
+ char buffer1[10];
+ CacheTestFillBuffer(buffer1, sizeof(buffer1), false);
+ EXPECT_EQ(0, entry1->ReadData(0, 0, buffer1, sizeof(buffer1), NULL));
+ strcpy_s(buffer1, "the data");
+ EXPECT_EQ(10, entry1->WriteData(0, 0, buffer1, sizeof(buffer1), NULL, false));
+ memset(buffer1, 0, sizeof(buffer1));
+ EXPECT_EQ(10, entry1->ReadData(0, 0, buffer1, sizeof(buffer1), NULL));
+ EXPECT_STREQ("the data", buffer1);
+
+ char buffer2[5000];
+ char buffer3[10000] = {0};
+ CacheTestFillBuffer(buffer2, sizeof(buffer2), false);
+ strcpy_s(buffer2, "The really big data goes here");
+ EXPECT_EQ(5000, entry1->WriteData(1, 1500, buffer2, sizeof(buffer2), NULL,
+ false));
+ memset(buffer2, 0, sizeof(buffer2));
+ EXPECT_EQ(4989, entry1->ReadData(1, 1511, buffer2, sizeof(buffer2), NULL));
+ EXPECT_STREQ("big data goes here", buffer2);
+ EXPECT_EQ(5000, entry1->ReadData(1, 0, buffer2, sizeof(buffer2), NULL));
+ EXPECT_EQ(0, memcmp(buffer2, buffer3, 1500));
+ EXPECT_EQ(1500, entry1->ReadData(1, 5000, buffer2, sizeof(buffer2), NULL));
+
+ EXPECT_EQ(0, entry1->ReadData(1, 6500, buffer2, sizeof(buffer2), NULL));
+ EXPECT_EQ(6500, entry1->ReadData(1, 0, buffer3, sizeof(buffer3), NULL));
+ EXPECT_EQ(8192, entry1->WriteData(1, 0, buffer3, 8192, NULL, false));
+ EXPECT_EQ(8192, entry1->ReadData(1, 0, buffer3, sizeof(buffer3), NULL));
+ EXPECT_EQ(8192, entry1->GetDataSize(1));
+
+ entry1->Doom();
+ entry1->Close();
+ EXPECT_EQ(0, cache_->GetEntryCount());
+}
+
+TEST_F(DiskCacheEntryTest, InternalSyncIO) {
+ InitCache();
+ InternalSyncIO();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyInternalSyncIO) {
+ SetMemoryOnlyMode();
+ InitCache();
+ InternalSyncIO();
+}
+
+void DiskCacheEntryTest::InternalAsyncIO() {
+ disk_cache::Entry *entry1 = NULL;
+ ASSERT_TRUE(cache_->CreateEntry("the first key", &entry1));
+ ASSERT_TRUE(NULL != entry1);
+
+ // Let's verify that each IO goes to the right callback object.
+ CallbackTest callback1(1, false);
+ CallbackTest callback2(2, false);
+ CallbackTest callback3(3, false);
+ CallbackTest callback4(4, false);
+ CallbackTest callback5(5, false);
+ CallbackTest callback6(6, false);
+ CallbackTest callback7(7, false);
+ CallbackTest callback8(8, false);
+ CallbackTest callback9(9, false);
+ CallbackTest callback10(10, false);
+ CallbackTest callback11(11, false);
+ CallbackTest callback12(12, false);
+ CallbackTest callback13(13, false);
+
+ g_cache_tests_error = false;
+ g_cache_tests_max_id = 0;
+ g_cache_tests_received = 0;
+
+ MessageLoopHelper helper;
+
+ char buffer1[10];
+ char buffer2[5000];
+ char buffer3[10000];
+ CacheTestFillBuffer(buffer1, sizeof(buffer1), false);
+ CacheTestFillBuffer(buffer2, sizeof(buffer2), false);
+ CacheTestFillBuffer(buffer3, sizeof(buffer3), false);
+
+ EXPECT_EQ(0, entry1->ReadData(0, 0, buffer1, sizeof(buffer1), &callback1));
+ strcpy_s(buffer1, "the data");
+ int expected = 0;
+ int ret = entry1->WriteData(0, 0, buffer1, sizeof(buffer1), &callback2,
+ false);
+ EXPECT_TRUE(10 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ memset(buffer2, 0, sizeof(buffer1));
+ ret = entry1->ReadData(0, 0, buffer2, sizeof(buffer1), &callback3);
+ EXPECT_TRUE(10 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ g_cache_tests_max_id = 3;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+ EXPECT_STREQ("the data", buffer2);
+
+ strcpy_s(buffer2, sizeof(buffer2), "The really big data goes here");
+ ret = entry1->WriteData(1, 1500, buffer2, sizeof(buffer2), &callback4, false);
+ EXPECT_TRUE(5000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ memset(buffer3, 0, sizeof(buffer2));
+ ret = entry1->ReadData(1, 1511, buffer3, sizeof(buffer2), &callback5);
+ EXPECT_TRUE(4989 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ g_cache_tests_max_id = 5;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+ EXPECT_STREQ("big data goes here", buffer3);
+ ret = entry1->ReadData(1, 0, buffer2, sizeof(buffer2), &callback6);
+ EXPECT_TRUE(5000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ memset(buffer3, 0, sizeof(buffer3));
+
+ g_cache_tests_max_id = 6;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+ EXPECT_EQ(0, memcmp(buffer2, buffer3, 1500));
+ ret = entry1->ReadData(1, 5000, buffer2, sizeof(buffer2), &callback7);
+ EXPECT_TRUE(1500 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ EXPECT_EQ(0, entry1->ReadData(1, 6500, buffer2, sizeof(buffer2), &callback8));
+ ret = entry1->ReadData(1, 0, buffer3, sizeof(buffer3), &callback9);
+ EXPECT_TRUE(6500 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ ret = entry1->WriteData(1, 0, buffer3, 8192, &callback10, false);
+ EXPECT_TRUE(8192 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ ret = entry1->ReadData(1, 0, buffer3, sizeof(buffer3), &callback11);
+ EXPECT_TRUE(8192 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ EXPECT_EQ(8192, entry1->GetDataSize(1));
+
+ ret = entry1->ReadData(0, 0, buffer1, sizeof(buffer1), &callback12);
+ EXPECT_TRUE(10 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ ret = entry1->ReadData(1, 0, buffer2, sizeof(buffer2), &callback13);
+ EXPECT_TRUE(5000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ g_cache_tests_max_id = 13;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+
+ EXPECT_FALSE(g_cache_tests_error);
+ EXPECT_EQ(expected, g_cache_tests_received);
+
+ entry1->Doom();
+ entry1->Close();
+ EXPECT_EQ(0, cache_->GetEntryCount());
+}
+
+TEST_F(DiskCacheEntryTest, InternalAsyncIO) {
+ InitCache();
+ InternalAsyncIO();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyInternalAsyncIO) {
+ SetMemoryOnlyMode();
+ InitCache();
+ InternalAsyncIO();
+}
+
+void DiskCacheEntryTest::ExternalSyncIO() {
+ disk_cache::Entry *entry1;
+ ASSERT_TRUE(cache_->CreateEntry("the first key", &entry1));
+
+ char buffer1[17000], buffer2[25000];
+ CacheTestFillBuffer(buffer1, sizeof(buffer1), false);
+ CacheTestFillBuffer(buffer2, sizeof(buffer2), false);
+ strcpy_s(buffer1, "the data");
+ EXPECT_EQ(17000, entry1->WriteData(0, 0, buffer1, sizeof(buffer1), NULL,
+ false));
+ memset(buffer1, 0, sizeof(buffer1));
+ EXPECT_EQ(17000, entry1->ReadData(0, 0, buffer1, sizeof(buffer1), NULL));
+ EXPECT_STREQ("the data", buffer1);
+
+ strcpy_s(buffer2, "The really big data goes here");
+ EXPECT_EQ(25000, entry1->WriteData(1, 10000, buffer2, sizeof(buffer2), NULL,
+ false));
+ memset(buffer2, 0, sizeof(buffer2));
+ EXPECT_EQ(24989, entry1->ReadData(1, 10011, buffer2, sizeof(buffer2), NULL));
+ EXPECT_STREQ("big data goes here", buffer2);
+ EXPECT_EQ(25000, entry1->ReadData(1, 0, buffer2, sizeof(buffer2), NULL));
+ EXPECT_EQ(0, memcmp(buffer2, buffer2, 10000));
+ EXPECT_EQ(5000, entry1->ReadData(1, 30000, buffer2, sizeof(buffer2), NULL));
+
+ EXPECT_EQ(0, entry1->ReadData(1, 35000, buffer2, sizeof(buffer2), NULL));
+ EXPECT_EQ(17000, entry1->ReadData(1, 0, buffer1, sizeof(buffer1), NULL));
+ EXPECT_EQ(17000, entry1->WriteData(1, 20000, buffer1, sizeof(buffer1), NULL,
+ false));
+ EXPECT_EQ(37000, entry1->GetDataSize(1));
+
+ entry1->Doom();
+ entry1->Close();
+ EXPECT_EQ(0, cache_->GetEntryCount());
+}
+
+TEST_F(DiskCacheEntryTest, ExternalSyncIO) {
+ InitCache();
+ ExternalSyncIO();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyExternalSyncIO) {
+ SetMemoryOnlyMode();
+ InitCache();
+ ExternalSyncIO();
+}
+
+void DiskCacheEntryTest::ExternalAsyncIO() {
+ disk_cache::Entry *entry1;
+ ASSERT_TRUE(cache_->CreateEntry("the first key", &entry1));
+
+ // Let's verify that each IO goes to the right callback object.
+ CallbackTest callback1(1, false);
+ CallbackTest callback2(2, false);
+ CallbackTest callback3(3, false);
+ CallbackTest callback4(4, false);
+ CallbackTest callback5(5, false);
+ CallbackTest callback6(6, false);
+ CallbackTest callback7(7, false);
+ CallbackTest callback8(8, false);
+ CallbackTest callback9(9, false);
+
+ g_cache_tests_error = false;
+ g_cache_tests_max_id = 0;
+ g_cache_tests_received = 0;
+ int expected = 0;
+
+ MessageLoopHelper helper;
+
+ char buffer1[17000], buffer2[25000], buffer3[25000];
+ CacheTestFillBuffer(buffer1, sizeof(buffer1), false);
+ CacheTestFillBuffer(buffer2, sizeof(buffer2), false);
+ CacheTestFillBuffer(buffer3, sizeof(buffer3), false);
+ strcpy_s(buffer1, "the data");
+ int ret = entry1->WriteData(0, 0, buffer1, sizeof(buffer1), &callback1,
+ false);
+ EXPECT_TRUE(17000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ g_cache_tests_max_id = 1;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+
+ memset(buffer2, 0, sizeof(buffer1));
+ ret = entry1->ReadData(0, 0, buffer2, sizeof(buffer1), &callback2);
+ EXPECT_TRUE(17000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ g_cache_tests_max_id = 2;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+ EXPECT_STREQ("the data", buffer1);
+
+ strcpy_s(buffer2, "The really big data goes here");
+ ret = entry1->WriteData(1, 10000, buffer2, sizeof(buffer2), &callback3,
+ false);
+ EXPECT_TRUE(25000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ g_cache_tests_max_id = 3;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+
+ memset(buffer3, 0, sizeof(buffer3));
+ ret = entry1->ReadData(1, 10011, buffer3, sizeof(buffer3), &callback4);
+ EXPECT_TRUE(24989 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ g_cache_tests_max_id = 4;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+ EXPECT_STREQ("big data goes here", buffer3);
+ ret = entry1->ReadData(1, 0, buffer2, sizeof(buffer2), &callback5);
+ EXPECT_TRUE(25000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ g_cache_tests_max_id = 5;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+ EXPECT_EQ(0, memcmp(buffer2, buffer2, 10000));
+ ret = entry1->ReadData(1, 30000, buffer2, sizeof(buffer2), &callback6);
+ EXPECT_TRUE(5000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+
+ EXPECT_EQ(0, entry1->ReadData(1, 35000, buffer2, sizeof(buffer2),
+ &callback7));
+ ret = entry1->ReadData(1, 0, buffer1, sizeof(buffer1), &callback8);
+ EXPECT_TRUE(17000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+ ret = entry1->WriteData(1, 20000, buffer1, sizeof(buffer1), &callback9,
+ false);
+ EXPECT_TRUE(17000 == ret || net::ERR_IO_PENDING == ret);
+ if (net::ERR_IO_PENDING == ret)
+ expected++;
+ EXPECT_EQ(37000, entry1->GetDataSize(1));
+
+ g_cache_tests_max_id = 9;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+
+ EXPECT_FALSE(g_cache_tests_error);
+ EXPECT_EQ(expected, g_cache_tests_received);
+
+ entry1->Doom();
+ entry1->Close();
+ EXPECT_EQ(0, cache_->GetEntryCount());
+}
+
+TEST_F(DiskCacheEntryTest, ExternalAsyncIO) {
+ InitCache();
+ ExternalAsyncIO();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyExternalAsyncIO) {
+ SetMemoryOnlyMode();
+ InitCache();
+ ExternalAsyncIO();
+}
+
+void DiskCacheEntryTest::GetKey() {
+ std::string key1("the first key");
+ disk_cache::Entry *entry1;
+ ASSERT_TRUE(cache_->CreateEntry(key1, &entry1));
+ EXPECT_EQ(key1, entry1->GetKey()) << "short key";
+ entry1->Close();
+
+ int seed = static_cast<int>(Time::Now().ToInternalValue());
+ srand(seed);
+ char key_buffer[20000];
+
+ CacheTestFillBuffer(key_buffer, 3000, true);
+ key_buffer[1000] = '\0';
+
+ key1 = key_buffer;
+ ASSERT_TRUE(cache_->CreateEntry(key1, &entry1));
+ EXPECT_TRUE(key1 == entry1->GetKey()) << "1000 bytes key";
+ entry1->Close();
+
+ key_buffer[1000] = 'p';
+ key_buffer[3000] = '\0';
+ key1 = key_buffer;
+ ASSERT_TRUE(cache_->CreateEntry(key1, &entry1));
+ EXPECT_TRUE(key1 == entry1->GetKey()) << "medium size key";
+ entry1->Close();
+
+ CacheTestFillBuffer(key_buffer, sizeof(key_buffer), true);
+ key_buffer[19999] = '\0';
+
+ key1 = key_buffer;
+ ASSERT_TRUE(cache_->CreateEntry(key1, &entry1));
+ EXPECT_TRUE(key1 == entry1->GetKey()) << "long key";
+ entry1->Close();
+}
+
+TEST_F(DiskCacheEntryTest, GetKey) {
+ InitCache();
+ GetKey();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyGetKey) {
+ SetMemoryOnlyMode();
+ InitCache();
+ GetKey();
+}
+
+void DiskCacheEntryTest::GrowData() {
+ std::string key1("the first key");
+ disk_cache::Entry *entry1, *entry2;
+ ASSERT_TRUE(cache_->CreateEntry(key1, &entry1));
+
+ char buffer1[20000];
+ char buffer2[20000];
+ CacheTestFillBuffer(buffer1, sizeof(buffer1), false);
+ memset(buffer2, 0, sizeof(buffer2));
+
+ strcpy_s(buffer1, "the data");
+ EXPECT_EQ(10, entry1->WriteData(0, 0, buffer1, 10, NULL, false));
+ EXPECT_EQ(10, entry1->ReadData(0, 0, buffer2, 10, NULL));
+ EXPECT_STREQ("the data", buffer2);
+ EXPECT_EQ(10, entry1->GetDataSize(0));
+
+ EXPECT_EQ(2000, entry1->WriteData(0, 0, buffer1, 2000, NULL, false));
+ EXPECT_EQ(2000, entry1->GetDataSize(0));
+ EXPECT_EQ(2000, entry1->ReadData(0, 0, buffer2, 2000, NULL));
+ EXPECT_TRUE(!memcmp(buffer1, buffer2, 2000));
+
+ EXPECT_EQ(20000, entry1->WriteData(0, 0, buffer1, sizeof(buffer1), NULL,
+ false));
+ EXPECT_EQ(20000, entry1->GetDataSize(0));
+ EXPECT_EQ(20000, entry1->ReadData(0, 0, buffer2, sizeof(buffer2), NULL));
+ EXPECT_TRUE(!memcmp(buffer1, buffer2, sizeof(buffer1)));
+ entry1->Close();
+
+ memset(buffer2, 0, sizeof(buffer2));
+ ASSERT_TRUE(cache_->CreateEntry("Second key", &entry2));
+ EXPECT_EQ(10, entry2->WriteData(0, 0, buffer1, 10, NULL, false));
+ EXPECT_EQ(10, entry2->GetDataSize(0));
+ entry2->Close();
+
+ // Go from an internal address to a bigger block size.
+ ASSERT_TRUE(cache_->OpenEntry("Second key", &entry2));
+ EXPECT_EQ(2000, entry2->WriteData(0, 0, buffer1, 2000, NULL, false));
+ EXPECT_EQ(2000, entry2->GetDataSize(0));
+ EXPECT_EQ(2000, entry2->ReadData(0, 0, buffer2, 2000, NULL));
+ EXPECT_TRUE(!memcmp(buffer1, buffer2, 2000));
+ entry2->Close();
+ memset(buffer2, 0, sizeof(buffer2));
+
+ // Go from an internal address to an external one.
+ ASSERT_TRUE(cache_->OpenEntry("Second key", &entry2));
+ EXPECT_EQ(20000, entry2->WriteData(0, 0, buffer1, sizeof(buffer1), NULL,
+ false));
+ EXPECT_EQ(20000, entry2->GetDataSize(0));
+ EXPECT_EQ(20000, entry2->ReadData(0, 0, buffer2, sizeof(buffer2), NULL));
+ EXPECT_TRUE(!memcmp(buffer1, buffer2, sizeof(buffer1)));
+ entry2->Close();
+}
+
+TEST_F(DiskCacheEntryTest, GrowData) {
+ InitCache();
+ GrowData();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyGrowData) {
+ SetMemoryOnlyMode();
+ InitCache();
+ GrowData();
+}
+
+void DiskCacheEntryTest::TruncateData() {
+ std::string key1("the first key");
+ disk_cache::Entry *entry1;
+ ASSERT_TRUE(cache_->CreateEntry(key1, &entry1));
+
+ char buffer1[20000];
+ char buffer2[20000];
+
+ CacheTestFillBuffer(buffer1, sizeof(buffer1), false);
+ memset(buffer2, 0, sizeof(buffer2));
+
+ // Simple truncation:
+ EXPECT_EQ(200, entry1->WriteData(0, 0, buffer1, 200, NULL, false));
+ EXPECT_EQ(200, entry1->GetDataSize(0));
+ EXPECT_EQ(100, entry1->WriteData(0, 0, buffer1, 100, NULL, false));
+ EXPECT_EQ(200, entry1->GetDataSize(0));
+ EXPECT_EQ(100, entry1->WriteData(0, 0, buffer1, 100, NULL, true));
+ EXPECT_EQ(100, entry1->GetDataSize(0));
+ EXPECT_EQ(0, entry1->WriteData(0, 50, buffer1, 0, NULL, true));
+ EXPECT_EQ(50, entry1->GetDataSize(0));
+ EXPECT_EQ(0, entry1->WriteData(0, 0, buffer1, 0, NULL, true));
+ EXPECT_EQ(0, entry1->GetDataSize(0));
+ entry1->Close();
+ ASSERT_TRUE(cache_->OpenEntry(key1, &entry1));
+
+ // Go to an external file.
+ EXPECT_EQ(20000, entry1->WriteData(0, 0, buffer1, 20000, NULL, true));
+ EXPECT_EQ(20000, entry1->GetDataSize(0));
+ EXPECT_EQ(20000, entry1->ReadData(0, 0, buffer2, 20000, NULL));
+ EXPECT_TRUE(!memcmp(buffer1, buffer2, 20000));
+ memset(buffer2, 0, sizeof(buffer2));
+
+ // External file truncation
+ EXPECT_EQ(18000, entry1->WriteData(0, 0, buffer1, 18000, NULL, false));
+ EXPECT_EQ(20000, entry1->GetDataSize(0));
+ EXPECT_EQ(18000, entry1->WriteData(0, 0, buffer1, 18000, NULL, true));
+ EXPECT_EQ(18000, entry1->GetDataSize(0));
+ EXPECT_EQ(0, entry1->WriteData(0, 17500, buffer1, 0, NULL, true));
+ EXPECT_EQ(17500, entry1->GetDataSize(0));
+
+ // And back to an internal block.
+ EXPECT_EQ(600, entry1->WriteData(0, 1000, buffer1, 600, NULL, true));
+ EXPECT_EQ(1600, entry1->GetDataSize(0));
+ EXPECT_EQ(600, entry1->ReadData(0, 1000, buffer2, 600, NULL));
+ EXPECT_TRUE(!memcmp(buffer1, buffer2, 600));
+ EXPECT_EQ(1000, entry1->ReadData(0, 0, buffer2, 1000, NULL));
+ EXPECT_TRUE(!memcmp(buffer1, buffer2, 1000)) << "Preserves previous data";
+
+ // Go from external file to zero length.
+ EXPECT_EQ(20000, entry1->WriteData(0, 0, buffer1, 20000, NULL, true));
+ EXPECT_EQ(20000, entry1->GetDataSize(0));
+ EXPECT_EQ(0, entry1->WriteData(0, 0, buffer1, 0, NULL, true));
+ EXPECT_EQ(0, entry1->GetDataSize(0));
+
+ entry1->Close();
+}
+
+TEST_F(DiskCacheEntryTest, TruncateData) {
+ InitCache();
+ TruncateData();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyTruncateData) {
+ SetMemoryOnlyMode();
+ InitCache();
+ TruncateData();
+}
+
+// Reading somewhere that was not written should return zeros.
+void DiskCacheEntryTest::InvalidData() {
+ std::string key1("the first key");
+ disk_cache::Entry *entry1;
+ ASSERT_TRUE(cache_->CreateEntry(key1, &entry1));
+
+ char buffer1[20000];
+ char buffer2[20000];
+ char buffer3[20000];
+
+ CacheTestFillBuffer(buffer1, sizeof(buffer1), false);
+ memset(buffer2, 0, sizeof(buffer2));
+
+ // Simple data grow:
+ EXPECT_EQ(200, entry1->WriteData(0, 400, buffer1, 200, NULL, false));
+ EXPECT_EQ(600, entry1->GetDataSize(0));
+ EXPECT_EQ(100, entry1->ReadData(0, 300, buffer3, 100, NULL));
+ EXPECT_TRUE(!memcmp(buffer3, buffer2, 100));
+ entry1->Close();
+ ASSERT_TRUE(cache_->OpenEntry(key1, &entry1));
+
+ // The entry is now on disk. Load it and extend it.
+ EXPECT_EQ(200, entry1->WriteData(0, 800, buffer1, 200, NULL, false));
+ EXPECT_EQ(1000, entry1->GetDataSize(0));
+ EXPECT_EQ(100, entry1->ReadData(0, 700, buffer3, 100, NULL));
+ EXPECT_TRUE(!memcmp(buffer3, buffer2, 100));
+ entry1->Close();
+ ASSERT_TRUE(cache_->OpenEntry(key1, &entry1));
+
+ // This time using truncate.
+ EXPECT_EQ(200, entry1->WriteData(0, 1800, buffer1, 200, NULL, true));
+ EXPECT_EQ(2000, entry1->GetDataSize(0));
+ EXPECT_EQ(100, entry1->ReadData(0, 1500, buffer3, 100, NULL));
+ EXPECT_TRUE(!memcmp(buffer3, buffer2, 100));
+
+ // Go to an external file.
+ EXPECT_EQ(200, entry1->WriteData(0, 19800, buffer1, 200, NULL, false));
+ EXPECT_EQ(20000, entry1->GetDataSize(0));
+ EXPECT_EQ(4000, entry1->ReadData(0, 14000, buffer3, 4000, NULL));
+ EXPECT_TRUE(!memcmp(buffer3, buffer2, 4000));
+
+ // And back to an internal block.
+ EXPECT_EQ(600, entry1->WriteData(0, 1000, buffer1, 600, NULL, true));
+ EXPECT_EQ(1600, entry1->GetDataSize(0));
+ EXPECT_EQ(600, entry1->ReadData(0, 1000, buffer3, 600, NULL));
+ EXPECT_TRUE(!memcmp(buffer3, buffer1, 600));
+
+ // Extend it again.
+ EXPECT_EQ(600, entry1->WriteData(0, 2000, buffer1, 600, NULL, false));
+ EXPECT_EQ(2600, entry1->GetDataSize(0));
+ EXPECT_EQ(200, entry1->ReadData(0, 1800, buffer3, 200, NULL));
+ EXPECT_TRUE(!memcmp(buffer3, buffer2, 200));
+
+ // And again (with truncation flag).
+ EXPECT_EQ(600, entry1->WriteData(0, 3000, buffer1, 600, NULL, true));
+ EXPECT_EQ(3600, entry1->GetDataSize(0));
+ EXPECT_EQ(200, entry1->ReadData(0, 2800, buffer3, 200, NULL));
+ EXPECT_TRUE(!memcmp(buffer3, buffer2, 200));
+
+ entry1->Close();
+}
+
+TEST_F(DiskCacheEntryTest, InvalidData) {
+ InitCache();
+ InvalidData();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyInvalidData) {
+ SetMemoryOnlyMode();
+ InitCache();
+ InvalidData();
+}
+
+void DiskCacheEntryTest::DoomEntry() {
+ std::string key1("the first key");
+ disk_cache::Entry *entry1;
+ ASSERT_TRUE(cache_->CreateEntry(key1, &entry1));
+ entry1->Doom();
+ entry1->Close();
+
+ char key_buffer[20000];
+ CacheTestFillBuffer(key_buffer, sizeof(key_buffer), true);
+ key_buffer[19999] = '\0';
+
+ key1 = key_buffer;
+ ASSERT_TRUE(cache_->CreateEntry(key1, &entry1));
+ EXPECT_EQ(20000, entry1->WriteData(0, 0, key_buffer, 20000, NULL, false));
+ EXPECT_EQ(20000, entry1->WriteData(1, 0, key_buffer, 20000, NULL, false));
+ entry1->Doom();
+ entry1->Close();
+
+ EXPECT_EQ(0, cache_->GetEntryCount());
+}
+
+TEST_F(DiskCacheEntryTest, DoomEntry) {
+ InitCache();
+ DoomEntry();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyDoomEntry) {
+ SetMemoryOnlyMode();
+ InitCache();
+ DoomEntry();
+}
+
+// Verify that basic operations work as expected with doomed entries.
+void DiskCacheEntryTest::DoomedEntry() {
+ std::string key("the first key");
+ disk_cache::Entry *entry;
+ ASSERT_TRUE(cache_->CreateEntry(key, &entry));
+ entry->Doom();
+
+ EXPECT_EQ(0, cache_->GetEntryCount());
+ Time initial = Time::Now();
+ Sleep(20);
+
+ char buffer1[2000];
+ char buffer2[2000];
+ CacheTestFillBuffer(buffer1, sizeof(buffer1), false);
+ memset(buffer2, 0, sizeof(buffer2));
+
+ EXPECT_EQ(2000, entry->WriteData(0, 0, buffer1, 2000, NULL, false));
+ EXPECT_EQ(2000, entry->ReadData(0, 0, buffer2, 2000, NULL));
+ EXPECT_EQ(0, memcmp(buffer1, buffer2, sizeof(buffer1)));
+ EXPECT_TRUE(initial < entry->GetLastModified());
+ EXPECT_TRUE(initial < entry->GetLastUsed());
+
+ entry->Close();
+}
+
+TEST_F(DiskCacheEntryTest, DoomedEntry) {
+ InitCache();
+ DoomEntry();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyDoomedEntry) {
+ SetMemoryOnlyMode();
+ InitCache();
+ DoomEntry();
+}