Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
| 6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
| 7 #include "base/metrics/field_trial.h" | 7 #include "base/metrics/field_trial.h" |
| 8 #include "base/port.h" | 8 #include "base/port.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 | 54 |
| 55 disk_cache::Entry* entry = NULL; | 55 disk_cache::Entry* entry = NULL; |
| 56 rv = cache->CreateEntry(kExistingEntryKey, &entry, cb.callback()); | 56 rv = cache->CreateEntry(kExistingEntryKey, &entry, cb.callback()); |
| 57 if (cb.GetResult(rv) != net::OK) | 57 if (cb.GetResult(rv) != net::OK) |
| 58 return scoped_ptr<disk_cache::BackendImpl>(); | 58 return scoped_ptr<disk_cache::BackendImpl>(); |
| 59 entry->Close(); | 59 entry->Close(); |
| 60 | 60 |
| 61 return cache.Pass(); | 61 return cache.Pass(); |
| 62 } | 62 } |
| 63 | 63 |
| 64 // Perform IO operations on the cache until there is pending IO. | |
| 65 // 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.
| |
| 66 int GeneratePendingIO(disk_cache::Backend* cache, | |
| 67 net::TestCompletionCallback* cb) { | |
| 68 disk_cache::EntryImpl* entry; | |
| 69 int rv = cache->CreateEntry("some key", | |
| 70 reinterpret_cast<disk_cache::Entry**>(&entry), | |
| 71 cb->callback()); | |
| 72 if (cb->GetResult(rv) != net::OK) | |
| 73 return net::ERR_CACHE_CREATE_FAILURE; | |
| 74 | |
| 75 const int kSize = 25000; | |
| 76 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); | |
| 77 CacheTestFillBuffer(buffer->data(), kSize, false); | |
| 78 | |
| 79 for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) { | |
| 80 // We are using the current thread as the cache thread because we want to | |
| 81 // be able to call directly this method to make sure that the OS (instead | |
| 82 // of us switching thread) is returning IO pending. | |
| 83 rv = entry->WriteDataImpl(0, i, buffer.get(), kSize, cb->callback(), false); | |
| 84 if (rv == net::ERR_IO_PENDING) | |
| 85 break; | |
| 86 if (rv != kSize) | |
| 87 rv = net::ERR_FAILED; | |
| 88 } | |
| 89 | |
| 90 // Don't call Close() to avoid going through the queue or we'll deadlock | |
| 91 // waiting for the operation to finish. | |
| 92 entry->Release(); | |
| 93 return rv; | |
| 94 } | |
| 95 | |
| 64 } // namespace | 96 } // namespace |
| 65 | 97 |
| 66 // Tests that can run with different types of caches. | 98 // Tests that can run with different types of caches. |
| 67 class DiskCacheBackendTest : public DiskCacheTestWithCache { | 99 class DiskCacheBackendTest : public DiskCacheTestWithCache { |
| 68 protected: | 100 protected: |
| 69 void BackendBasics(); | 101 void BackendBasics(); |
| 70 void BackendKeying(); | 102 void BackendKeying(); |
| 71 void BackendShutdownWithPendingFileIO(bool fast); | 103 void BackendShutdownWithPendingFileIO(bool fast); |
| 72 void BackendShutdownWithPendingIO(bool fast); | 104 void BackendShutdownWithPendingIO(bool fast); |
| 73 void BackendShutdownWithPendingCreate(bool fast); | 105 void BackendShutdownWithPendingCreate(bool fast); |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 entry->Close(); | 369 entry->Close(); |
| 338 | 370 |
| 339 // And verify that the first file is still there. | 371 // And verify that the first file is still there. |
| 340 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize)); | 372 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize)); |
| 341 ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize)); | 373 ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize)); |
| 342 EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize)); | 374 EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize)); |
| 343 } | 375 } |
| 344 | 376 |
| 345 // Tests that we deal with file-level pending operations at destruction time. | 377 // Tests that we deal with file-level pending operations at destruction time. |
| 346 void DiskCacheBackendTest::BackendShutdownWithPendingFileIO(bool fast) { | 378 void DiskCacheBackendTest::BackendShutdownWithPendingFileIO(bool fast) { |
| 379 ASSERT_TRUE(CleanupCacheDir()); | |
| 380 uint32 flags = disk_cache::kNoBuffering; | |
| 381 if (!fast) | |
| 382 flags |= disk_cache::kNoRandom; | |
| 383 | |
| 384 UseCurrentThread(); | |
| 385 CreateBackend(flags, NULL); | |
| 386 | |
| 347 net::TestCompletionCallback cb; | 387 net::TestCompletionCallback cb; |
| 348 int rv; | 388 int rv = GeneratePendingIO(cache_.get(), &cb); |
| 349 | 389 |
| 350 { | 390 // The cache destructor will see one pending operation here. |
| 351 ASSERT_TRUE(CleanupCacheDir()); | 391 cache_.reset(); |
| 352 base::Thread cache_thread("CacheThread"); | |
| 353 ASSERT_TRUE(cache_thread.StartWithOptions( | |
| 354 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); | |
| 355 | 392 |
| 356 uint32 flags = disk_cache::kNoBuffering; | 393 if (rv == net::ERR_IO_PENDING) { |
| 357 if (!fast) | 394 if (fast) |
| 358 flags |= disk_cache::kNoRandom; | 395 EXPECT_FALSE(cb.have_result()); |
| 359 | 396 else |
| 360 UseCurrentThread(); | 397 EXPECT_TRUE(cb.have_result()); |
| 361 CreateBackend(flags, NULL); | |
| 362 | |
| 363 disk_cache::EntryImpl* entry; | |
| 364 rv = cache_->CreateEntry( | |
| 365 "some key", reinterpret_cast<disk_cache::Entry**>(&entry), | |
| 366 cb.callback()); | |
| 367 ASSERT_EQ(net::OK, cb.GetResult(rv)); | |
| 368 | |
| 369 const int kSize = 25000; | |
| 370 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize)); | |
| 371 CacheTestFillBuffer(buffer->data(), kSize, false); | |
| 372 | |
| 373 for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) { | |
| 374 // We are using the current thread as the cache thread because we want to | |
| 375 // be able to call directly this method to make sure that the OS (instead | |
| 376 // of us switching thread) is returning IO pending. | |
| 377 rv = | |
| 378 entry->WriteDataImpl(0, i, buffer.get(), kSize, cb.callback(), false); | |
| 379 if (rv == net::ERR_IO_PENDING) | |
| 380 break; | |
| 381 EXPECT_EQ(kSize, rv); | |
| 382 } | |
| 383 | |
| 384 // Don't call Close() to avoid going through the queue or we'll deadlock | |
| 385 // waiting for the operation to finish. | |
| 386 entry->Release(); | |
| 387 | |
| 388 // The cache destructor will see one pending operation here. | |
| 389 cache_.reset(); | |
| 390 | |
| 391 if (rv == net::ERR_IO_PENDING) { | |
| 392 if (fast) | |
| 393 EXPECT_FALSE(cb.have_result()); | |
| 394 else | |
| 395 EXPECT_TRUE(cb.have_result()); | |
| 396 } | |
| 397 } | 398 } |
| 398 | 399 |
| 399 base::MessageLoop::current()->RunUntilIdle(); | 400 base::MessageLoop::current()->RunUntilIdle(); |
| 400 | 401 |
| 401 #if defined(OS_WIN) | |
| 402 // Wait for the actual operation to complete, or we'll keep a file handle that | 402 // Wait for the actual operation to complete, or we'll keep a file handle that |
| 403 // may cause issues later. Note that on Posix systems even though this test | 403 // may cause issues later. |
| 404 // uses a single thread, the actual IO is posted to a worker thread and the | |
| 405 // cache destructor breaks the link to reach cb when the operation completes. | |
| 406 rv = cb.GetResult(rv); | 404 rv = cb.GetResult(rv); |
| 407 #endif | |
| 408 } | 405 } |
| 409 | 406 |
| 410 TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO) { | 407 TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO) { |
| 411 BackendShutdownWithPendingFileIO(false); | 408 BackendShutdownWithPendingFileIO(false); |
| 412 } | 409 } |
| 413 | 410 |
| 414 // Here and below, tests that simulate crashes are not compiled in LeakSanitizer | 411 // Here and below, tests that simulate crashes are not compiled in LeakSanitizer |
| 415 // builds because they contain a lot of intentional memory leaks. | 412 // builds because they contain a lot of intentional memory leaks. |
| 416 // The wrapper scripts used to run tests under Valgrind Memcheck and | 413 // The wrapper scripts used to run tests under Valgrind Memcheck and |
| 417 // Heapchecker will also disable these tests under those tools. See: | 414 // Heapchecker will also disable these tests under those tools. See: |
| 418 // tools/valgrind/gtest_exclude/net_unittests.gtest-memcheck.txt | 415 // tools/valgrind/gtest_exclude/net_unittests.gtest-memcheck.txt |
| 419 // tools/heapcheck/net_unittests.gtest-heapcheck.txt | 416 // tools/heapcheck/net_unittests.gtest-heapcheck.txt |
| 420 #if !defined(LEAK_SANITIZER) | 417 #if !defined(LEAK_SANITIZER) |
| 421 // We'll be leaking from this test. | 418 // We'll be leaking from this test. |
| 422 TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO_Fast) { | 419 TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO_Fast) { |
| 423 // The integrity test sets kNoRandom so there's a version mismatch if we don't | 420 // The integrity test sets kNoRandom so there's a version mismatch if we don't |
| 424 // force new eviction. | 421 // force new eviction. |
| 425 SetNewEviction(); | 422 SetNewEviction(); |
| 426 BackendShutdownWithPendingFileIO(true); | 423 BackendShutdownWithPendingFileIO(true); |
| 427 } | 424 } |
| 428 #endif | 425 #endif |
| 429 | 426 |
| 427 // Tests that one cache instance is not affected by another one going away. | |
| 428 TEST_F(DiskCacheBackendTest, MultipleInstancesWithPendingFileIO) { | |
| 429 base::ScopedTempDir store; | |
| 430 ASSERT_TRUE(store.CreateUniqueTempDir()); | |
| 431 | |
| 432 net::TestCompletionCallback cb; | |
| 433 scoped_ptr<disk_cache::Backend> extra_cache; | |
| 434 int rv = disk_cache::CreateCacheBackend( | |
| 435 net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, store.path(), 0, | |
| 436 false, base::MessageLoopProxy::current().get(), NULL, | |
| 437 &extra_cache, cb.callback()); | |
| 438 ASSERT_EQ(net::OK, cb.GetResult(rv)); | |
| 439 ASSERT_TRUE(extra_cache.get() != NULL); | |
| 440 | |
| 441 ASSERT_TRUE(CleanupCacheDir()); | |
| 442 SetNewEviction(); // Match the expected behavior for integrity verification. | |
| 443 UseCurrentThread(); | |
| 444 | |
| 445 CreateBackend(disk_cache::kNoBuffering, NULL); | |
| 446 rv = GeneratePendingIO(cache_.get(), &cb); | |
| 447 | |
| 448 // cache_ has a pending operation, and extra_cache will go away. | |
| 449 extra_cache.reset(); | |
| 450 | |
| 451 if (rv == net::ERR_IO_PENDING) | |
| 452 EXPECT_FALSE(cb.have_result()); | |
| 453 | |
| 454 base::MessageLoop::current()->RunUntilIdle(); | |
| 455 | |
| 456 // Wait for the actual operation to complete, or we'll keep a file handle that | |
| 457 // may cause issues later. | |
| 458 rv = cb.GetResult(rv); | |
| 459 } | |
| 460 | |
| 430 // Tests that we deal with background-thread pending operations. | 461 // Tests that we deal with background-thread pending operations. |
| 431 void DiskCacheBackendTest::BackendShutdownWithPendingIO(bool fast) { | 462 void DiskCacheBackendTest::BackendShutdownWithPendingIO(bool fast) { |
| 432 net::TestCompletionCallback cb; | 463 net::TestCompletionCallback cb; |
| 433 | 464 |
| 434 { | 465 { |
| 435 ASSERT_TRUE(CleanupCacheDir()); | 466 ASSERT_TRUE(CleanupCacheDir()); |
| 436 base::Thread cache_thread("CacheThread"); | 467 base::Thread cache_thread("CacheThread"); |
| 437 ASSERT_TRUE(cache_thread.StartWithOptions( | 468 ASSERT_TRUE(cache_thread.StartWithOptions( |
| 438 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); | 469 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); |
| 439 | 470 |
| (...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1785 ASSERT_TRUE(cache_thread.StartWithOptions( | 1816 ASSERT_TRUE(cache_thread.StartWithOptions( |
| 1786 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); | 1817 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); |
| 1787 | 1818 |
| 1788 scoped_ptr<disk_cache::BackendImpl> cache = | 1819 scoped_ptr<disk_cache::BackendImpl> cache = |
| 1789 CreateExistingEntryCache(cache_thread, cache_path_); | 1820 CreateExistingEntryCache(cache_thread, cache_path_); |
| 1790 ASSERT_TRUE(cache.get()); | 1821 ASSERT_TRUE(cache.get()); |
| 1791 | 1822 |
| 1792 net::TestCompletionCallback cb; | 1823 net::TestCompletionCallback cb; |
| 1793 | 1824 |
| 1794 const int kRestartCount = 5; | 1825 const int kRestartCount = 5; |
| 1795 for (int i=0; i < kRestartCount; ++i) { | 1826 for (int i = 0; i < kRestartCount; ++i) { |
| 1796 cache.reset(new disk_cache::BackendImpl( | 1827 cache.reset(new disk_cache::BackendImpl( |
| 1797 cache_path_, cache_thread.message_loop_proxy(), NULL)); | 1828 cache_path_, cache_thread.message_loop_proxy(), NULL)); |
| 1798 int rv = cache->Init(cb.callback()); | 1829 int rv = cache->Init(cb.callback()); |
| 1799 ASSERT_EQ(net::OK, cb.GetResult(rv)); | 1830 ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| 1800 EXPECT_EQ(1, cache->GetEntryCount()); | 1831 EXPECT_EQ(1, cache->GetEntryCount()); |
| 1801 | 1832 |
| 1802 disk_cache::Entry* entry = NULL; | 1833 disk_cache::Entry* entry = NULL; |
| 1803 rv = cache->OpenEntry(kExistingEntryKey, &entry, cb.callback()); | 1834 rv = cache->OpenEntry(kExistingEntryKey, &entry, cb.callback()); |
| 1804 EXPECT_EQ(net::OK, cb.GetResult(rv)); | 1835 EXPECT_EQ(net::OK, cb.GetResult(rv)); |
| 1805 EXPECT_TRUE(entry); | 1836 EXPECT_TRUE(entry); |
| (...skipping 1600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3406 void* iter = NULL; | 3437 void* iter = NULL; |
| 3407 size_t count = 0; | 3438 size_t count = 0; |
| 3408 ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count)); | 3439 ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count)); |
| 3409 cache_->EndEnumeration(&iter); | 3440 cache_->EndEnumeration(&iter); |
| 3410 | 3441 |
| 3411 EXPECT_EQ(key_pool.size(), count); | 3442 EXPECT_EQ(key_pool.size(), count); |
| 3412 EXPECT_TRUE(keys_to_match.empty()); | 3443 EXPECT_TRUE(keys_to_match.empty()); |
| 3413 } | 3444 } |
| 3414 | 3445 |
| 3415 #endif // !defined(OS_WIN) | 3446 #endif // !defined(OS_WIN) |
| OLD | NEW |