| Index: net/disk_cache/entry_unittest.cc
|
| diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc
|
| index 2166ac16a25337029b51cf08dd9a13b57d7b41c6..851f0a97c1b25dce15d9f9869ef13c2a74f0a7ee 100644
|
| --- a/net/disk_cache/entry_unittest.cc
|
| +++ b/net/disk_cache/entry_unittest.cc
|
| @@ -3937,6 +3937,70 @@ TEST_F(DiskCacheEntryTest, SimpleCacheDoomOptimisticWritesRace) {
|
| }
|
| }
|
|
|
| +// Tests for a regression in crbug.com/317138 , in which deleting an already
|
| +// doomed entry was removing the active entry from the index.
|
| +TEST_F(DiskCacheEntryTest, SimpleCachePreserveActiveEntries) {
|
| + SetSimpleCacheMode();
|
| + InitCache();
|
| +
|
| + disk_cache::Entry* null = NULL;
|
| +
|
| + const char key[] = "this is a key";
|
| +
|
| + disk_cache::Entry* entry1 = NULL;
|
| + ASSERT_EQ(net::OK, CreateEntry(key, &entry1));
|
| + ScopedEntryPtr entry1_closer(entry1);
|
| + EXPECT_NE(null, entry1);
|
| + entry1->Doom();
|
| +
|
| + disk_cache::Entry* entry2 = NULL;
|
| + ASSERT_EQ(net::OK, CreateEntry(key, &entry2));
|
| + ScopedEntryPtr entry2_closer(entry2);
|
| + EXPECT_NE(null, entry2);
|
| + entry2_closer.reset();
|
| +
|
| + // Closing then reopening entry2 insures that entry2 is serialized, and so
|
| + // it can be opened from files without error.
|
| + entry2 = NULL;
|
| + ASSERT_EQ(net::OK, OpenEntry(key, &entry2));
|
| + EXPECT_NE(null, entry2);
|
| + entry2_closer.reset(entry2);
|
| +
|
| + scoped_refptr<disk_cache::SimpleEntryImpl>
|
| + entry1_refptr = static_cast<disk_cache::SimpleEntryImpl*>(entry1);
|
| +
|
| + // If crbug.com/317138 has regressed, this will remove |entry2| from
|
| + // the backend's |active_entries_| while |entry2| is still alive and its
|
| + // files are still on disk.
|
| + entry1_closer.reset();
|
| + entry1 = NULL;
|
| +
|
| + // Close does not have a callback. However, we need to be sure the close is
|
| + // finished before we continue the test. We can take advantage of how the ref
|
| + // counting of a SimpleEntryImpl works to fake out a callback: When the
|
| + // last Close() call is made to an entry, an IO operation is sent to the
|
| + // synchronous entry to close the platform files. This IO operation holds a
|
| + // ref pointer to the entry, which expires when the operation is done. So,
|
| + // we take a refpointer, and watch the SimpleEntry object until it has only
|
| + // one ref; this indicates the IO operation is complete.
|
| + while (!entry1_refptr->HasOneRef()) {
|
| + base::PlatformThread::YieldCurrentThread();
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + }
|
| + entry1_refptr = NULL;
|
| +
|
| + // In the bug case, this new entry ends up being a duplicate object pointing
|
| + // at the same underlying files.
|
| + disk_cache::Entry* entry3 = NULL;
|
| + EXPECT_EQ(net::OK, OpenEntry(key, &entry3));
|
| + ScopedEntryPtr entry3_closer(entry3);
|
| + EXPECT_NE(null, entry3);
|
| +
|
| + // The test passes if these two dooms do not crash.
|
| + entry2->Doom();
|
| + entry3->Doom();
|
| +}
|
| +
|
| TEST_F(DiskCacheEntryTest, SimpleCacheBasicSparseIO) {
|
| SetSimpleCacheMode();
|
| InitCache();
|
|
|