Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: net/disk_cache/backend_unittest.cc

Issue 23752005: Disk Cache: Replace the worker pool with a sequenced worker pool (posix). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698