Chromium Code Reviews| Index: net/disk_cache/backend_unittest.cc |
| diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc |
| index 7eeeee1fd83200c90b0dc1a2775f4654fd903a2f..d408f3bf607b5ecc5d08f5eb6acf27971ff6ea3e 100644 |
| --- a/net/disk_cache/backend_unittest.cc |
| +++ b/net/disk_cache/backend_unittest.cc |
| @@ -61,6 +61,38 @@ scoped_ptr<disk_cache::BackendImpl> CreateExistingEntryCache( |
| return cache.Pass(); |
| } |
| +// Perform IO operations on the cache until there is pending IO. |
| +// This function requires the use of a single thread for the cache. |
|
gavinp
2013/09/09 21:18:16
I think grammar is confusing me a bit here. Does t
rvargas (doing something else)
2013/09/09 22:26:57
Done.
|
| +int GeneratePendingIO(disk_cache::Backend* cache, |
| + net::TestCompletionCallback* cb) { |
| + disk_cache::EntryImpl* entry; |
| + int rv = cache->CreateEntry("some key", |
| + reinterpret_cast<disk_cache::Entry**>(&entry), |
| + cb->callback()); |
| + if (cb->GetResult(rv) != net::OK) |
| + return net::ERR_CACHE_CREATE_FAILURE; |
| + |
| + 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) { |
| + // 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.get(), kSize, cb->callback(), false); |
| + if (rv == net::ERR_IO_PENDING) |
| + break; |
| + if (rv != kSize) |
| + rv = net::ERR_FAILED; |
| + } |
| + |
| + // Don't call Close() to avoid going through the queue or we'll deadlock |
| + // waiting for the operation to finish. |
| + entry->Release(); |
| + return rv; |
| +} |
| + |
| } // namespace |
| // Tests that can run with different types of caches. |
| @@ -344,67 +376,32 @@ TEST_F(DiskCacheBackendTest, ExternalFiles) { |
| // Tests that we deal with file-level pending operations at destruction time. |
| void DiskCacheBackendTest::BackendShutdownWithPendingFileIO(bool fast) { |
| - net::TestCompletionCallback cb; |
| - int rv; |
| - |
| - { |
| - ASSERT_TRUE(CleanupCacheDir()); |
| - base::Thread cache_thread("CacheThread"); |
| - ASSERT_TRUE(cache_thread.StartWithOptions( |
| - base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); |
| - |
| - uint32 flags = disk_cache::kNoBuffering; |
| - if (!fast) |
| - flags |= disk_cache::kNoRandom; |
| - |
| - UseCurrentThread(); |
| - CreateBackend(flags, NULL); |
| - |
| - disk_cache::EntryImpl* entry; |
| - rv = cache_->CreateEntry( |
| - "some key", reinterpret_cast<disk_cache::Entry**>(&entry), |
| - cb.callback()); |
| - ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| + ASSERT_TRUE(CleanupCacheDir()); |
| + uint32 flags = disk_cache::kNoBuffering; |
| + if (!fast) |
| + flags |= disk_cache::kNoRandom; |
| - 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) { |
| - // 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.get(), kSize, cb.callback(), false); |
| - if (rv == net::ERR_IO_PENDING) |
| - break; |
| - EXPECT_EQ(kSize, rv); |
| - } |
| + UseCurrentThread(); |
| + CreateBackend(flags, NULL); |
| - // Don't call Close() to avoid going through the queue or we'll deadlock |
| - // waiting for the operation to finish. |
| - entry->Release(); |
| + net::TestCompletionCallback cb; |
| + int rv = GeneratePendingIO(cache_.get(), &cb); |
| - // The cache destructor will see one pending operation here. |
| - cache_.reset(); |
| + // The cache destructor will see one pending operation here. |
| + cache_.reset(); |
| - if (rv == net::ERR_IO_PENDING) { |
| - if (fast) |
| - EXPECT_FALSE(cb.have_result()); |
| - else |
| - EXPECT_TRUE(cb.have_result()); |
| - } |
| + if (rv == net::ERR_IO_PENDING) { |
| + if (fast) |
| + EXPECT_FALSE(cb.have_result()); |
| + else |
| + EXPECT_TRUE(cb.have_result()); |
| } |
| base::MessageLoop::current()->RunUntilIdle(); |
| -#if defined(OS_WIN) |
| // Wait for the actual operation to complete, or we'll keep a file handle that |
| - // may cause issues later. Note that on Posix systems even though this test |
| - // uses a single thread, the actual IO is posted to a worker thread and the |
| - // cache destructor breaks the link to reach cb when the operation completes. |
| + // may cause issues later. |
| rv = cb.GetResult(rv); |
| -#endif |
| } |
| TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO) { |
| @@ -427,6 +424,40 @@ TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO_Fast) { |
| } |
| #endif |
| +// Tests that one cache instance is not affected by another one going away. |
| +TEST_F(DiskCacheBackendTest, MultipleInstancesWithPendingFileIO) { |
| + base::ScopedTempDir store; |
| + ASSERT_TRUE(store.CreateUniqueTempDir()); |
| + |
| + net::TestCompletionCallback cb; |
| + scoped_ptr<disk_cache::Backend> extra_cache; |
| + int rv = disk_cache::CreateCacheBackend( |
| + net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, store.path(), 0, |
| + false, base::MessageLoopProxy::current().get(), NULL, |
| + &extra_cache, cb.callback()); |
| + ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| + ASSERT_TRUE(extra_cache.get() != NULL); |
| + |
| + ASSERT_TRUE(CleanupCacheDir()); |
| + SetNewEviction(); // Match the expected behavior for integrity verification. |
| + UseCurrentThread(); |
| + |
| + CreateBackend(disk_cache::kNoBuffering, NULL); |
| + rv = GeneratePendingIO(cache_.get(), &cb); |
| + |
| + // cache_ has a pending operation, and extra_cache will go away. |
| + extra_cache.reset(); |
| + |
| + if (rv == net::ERR_IO_PENDING) |
| + EXPECT_FALSE(cb.have_result()); |
| + |
| + base::MessageLoop::current()->RunUntilIdle(); |
| + |
| + // Wait for the actual operation to complete, or we'll keep a file handle that |
| + // may cause issues later. |
| + rv = cb.GetResult(rv); |
| +} |
| + |
| // Tests that we deal with background-thread pending operations. |
| void DiskCacheBackendTest::BackendShutdownWithPendingIO(bool fast) { |
| net::TestCompletionCallback cb; |
| @@ -1792,7 +1823,7 @@ TEST_F(DiskCacheTest, SimpleCacheControlRestart) { |
| net::TestCompletionCallback cb; |
| const int kRestartCount = 5; |
| - for (int i=0; i < kRestartCount; ++i) { |
| + for (int i = 0; i < kRestartCount; ++i) { |
| cache.reset(new disk_cache::BackendImpl( |
| cache_path_, cache_thread.message_loop_proxy(), NULL)); |
| int rv = cache->Init(cb.callback()); |