Index: net/disk_cache/backend_unittest.cc |
=================================================================== |
--- net/disk_cache/backend_unittest.cc (revision 51874) |
+++ net/disk_cache/backend_unittest.cc (working copy) |
@@ -7,7 +7,6 @@ |
#include "base/path_service.h" |
#include "base/platform_thread.h" |
#include "base/string_util.h" |
-#include "base/thread.h" |
#include "net/base/io_buffer.h" |
#include "net/base/net_errors.h" |
#include "net/base/test_completion_callback.h" |
@@ -254,8 +253,9 @@ |
EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize)); |
} |
+// Tests that we deal with file-level pending operations at destruction time. |
TEST_F(DiskCacheTest, ShutdownWithPendingIO) { |
- TestCompletionCallback callback; |
+ TestCompletionCallback cb; |
{ |
FilePath path = GetCacheFilePath(); |
@@ -267,33 +267,80 @@ |
disk_cache::Backend* cache; |
int rv = disk_cache::BackendImpl::CreateBackend( |
path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom, |
- cache_thread.message_loop_proxy(), &cache, &callback); |
- ASSERT_EQ(net::OK, callback.GetResult(rv)); |
+ base::MessageLoopProxy::CreateForCurrentThread(), &cache, &cb); |
+ ASSERT_EQ(net::OK, cb.GetResult(rv)); |
- disk_cache::Entry* entry; |
- rv = cache->CreateEntry("some key", &entry, &callback); |
- ASSERT_EQ(net::OK, callback.GetResult(rv)); |
+ disk_cache::EntryImpl* entry; |
+ rv = cache->CreateEntry("some key", |
+ reinterpret_cast<disk_cache::Entry**>(&entry), &cb); |
+ ASSERT_EQ(net::OK, cb.GetResult(rv)); |
const int kSize = 25000; |
scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); |
CacheTestFillBuffer(buffer->data(), kSize, false); |
for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) { |
- int rv = entry->WriteData(0, i, buffer, kSize, &callback, false); |
+ // We are using the current thread as the cache thread because we want to |
+ // be able to call directly this method to make sure that the OS (instead |
+ // of us switching thread) is returning IO pending. |
+ rv = entry->WriteDataImpl(0, i, buffer, kSize, &cb, false); |
if (rv == net::ERR_IO_PENDING) |
break; |
EXPECT_EQ(kSize, rv); |
} |
- entry->Close(); |
+ // Don't call Close() to avoid going through the queue or we'll deadlock |
+ // waiting for the operation to finish. |
+ entry->Release(); |
// The cache destructor will see one pending operation here. |
delete cache; |
+ |
+ if (rv == net::ERR_IO_PENDING) { |
+ EXPECT_TRUE(cb.have_result()); |
+ } |
} |
MessageLoop::current()->RunAllPending(); |
} |
+// Tests that we deal with background-thread pending operations. |
+TEST_F(DiskCacheTest, ShutdownWithPendingIO2) { |
+ TestCompletionCallback cb; |
+ |
+ { |
+ FilePath path = GetCacheFilePath(); |
+ ASSERT_TRUE(DeleteCache(path)); |
+ base::Thread cache_thread("CacheThread"); |
+ ASSERT_TRUE(cache_thread.StartWithOptions( |
+ base::Thread::Options(MessageLoop::TYPE_IO, 0))); |
+ |
+ disk_cache::Backend* cache; |
+ int rv = disk_cache::BackendImpl::CreateBackend( |
+ path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom, |
+ cache_thread.message_loop_proxy(), &cache, &cb); |
+ ASSERT_EQ(net::OK, cb.GetResult(rv)); |
+ |
+ disk_cache::Entry* entry; |
+ rv = cache->CreateEntry("some key", &entry, &cb); |
+ ASSERT_EQ(net::OK, cb.GetResult(rv)); |
+ |
+ const int kSize = 25000; |
+ scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); |
+ CacheTestFillBuffer(buffer->data(), kSize, false); |
+ |
+ rv = entry->WriteData(0, 0, buffer, kSize, &cb, false); |
+ EXPECT_EQ(net::ERR_IO_PENDING, rv); |
+ |
+ entry->Close(); |
+ |
+ // The cache destructor will see two pending operations here. |
+ delete cache; |
+ } |
+ |
+ MessageLoop::current()->RunAllPending(); |
+} |
+ |
TEST_F(DiskCacheTest, TruncatedIndex) { |
FilePath path = GetCacheFilePath(); |
ASSERT_TRUE(DeleteCache(path)); |
@@ -344,6 +391,7 @@ |
EXPECT_EQ(cache_size * 3 / 4, entry->WriteData(0, 0, buffer, |
cache_size * 3 / 4, NULL, false)); |
entry->Close(); |
+ FlushQueueForTest(); |
SetMaxSize(cache_size); |
@@ -351,10 +399,20 @@ |
ASSERT_EQ(net::OK, CreateEntry(second, &entry)); |
EXPECT_EQ(cache_size / 10, entry->WriteData(0, 0, buffer, cache_size / 10, |
- NULL, false)) << "trim the cache"; |
+ NULL, false)); |
+ |
+ disk_cache::Entry* entry2; |
+ ASSERT_EQ(net::OK, CreateEntry("an extra key", &entry2)); |
+ EXPECT_EQ(cache_size / 10, entry2->WriteData(0, 0, buffer, cache_size / 10, |
+ NULL, false)); |
+ entry2->Close(); // This will trigger the cache trim. |
+ |
+ EXPECT_NE(net::OK, OpenEntry(first, &entry2)); |
+ |
+ FlushQueueForTest(); // Make sure that we are done trimming the cache. |
+ FlushQueueForTest(); // We may have posted two tasks to evict stuff. |
+ |
entry->Close(); |
- |
- EXPECT_NE(net::OK, OpenEntry(first, &entry)); |
ASSERT_EQ(net::OK, OpenEntry(second, &entry)); |
EXPECT_EQ(cache_size / 10, entry->GetDataSize(0)); |
entry->Close(); |
@@ -402,6 +460,7 @@ |
entries[i]->Doom(); |
entries[i]->Close(); |
} |
+ FlushQueueForTest(); |
EXPECT_EQ(0, cache_->GetEntryCount()); |
} |
@@ -625,6 +684,7 @@ |
EXPECT_EQ(2, cache_->GetEntryCount()); |
SetMaxSize(kSize); |
entry->Close(); // Trim the cache. |
+ FlushQueueForTest(); |
// If we evicted the entry in less than 20mS, we have one entry in the cache; |
// if it took more than that, we posted a task and we'll delete the second |
@@ -685,6 +745,7 @@ |
} |
entry->Close(); // Trim the cache. |
+ FlushQueueForTest(); |
// We may abort the eviction before cleaning up everything. |
MessageLoop::current()->RunAllPending(); |
@@ -1259,7 +1320,7 @@ |
EXPECT_EQ(2, cache_->GetEntryCount()); |
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); |
- MessageLoop::current()->RunAllPending(); |
+ FlushQueueForTest(); // Allow the restart to finish. |
EXPECT_EQ(0, cache_->GetEntryCount()); |
} |
@@ -1310,7 +1371,8 @@ |
EXPECT_NE(net::OK, CreateEntry("Something new", &entry2)); |
entry1->Close(); |
- MessageLoop::current()->RunAllPending(); |
+ FlushQueueForTest(); // Flushing the Close posts a task to restart the cache. |
+ FlushQueueForTest(); // This one actually allows that task to complete. |
EXPECT_EQ(0, cache_->GetEntryCount()); |
} |
@@ -1365,7 +1427,7 @@ |
ASSERT_LT(count, 9); |
}; |
- MessageLoop::current()->RunAllPending(); |
+ FlushQueueForTest(); |
EXPECT_EQ(0, cache_->GetEntryCount()); |
} |
@@ -1414,7 +1476,7 @@ |
entry1->Close(); |
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2)); |
- MessageLoop::current()->RunAllPending(); |
+ FlushQueueForTest(); |
ASSERT_EQ(net::OK, CreateEntry("Something new", &entry2)); |
entry2->Close(); |
@@ -1482,7 +1544,8 @@ |
entry1->Close(); |
entry2->Close(); |
entry3->Close(); |
- MessageLoop::current()->RunAllPending(); |
+ FlushQueueForTest(); // Flushing the Close posts a task to restart the cache. |
+ FlushQueueForTest(); // This one actually allows that task to complete. |
EXPECT_EQ(0, cache_->GetEntryCount()); |
} |