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

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

Issue 13907009: Support optimistic Create and Write operations on the SimpleCache. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: make linker happy Created 7 years, 7 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/bind.h" 6 #include "base/bind.h"
7 #include "base/bind_helpers.h" 7 #include "base/bind_helpers.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/string_util.h"
10 #include "base/stringprintf.h"
9 #include "base/threading/platform_thread.h" 11 #include "base/threading/platform_thread.h"
10 #include "base/timer.h" 12 #include "base/timer.h"
11 #include "base/string_util.h"
12 #include "base/stringprintf.h"
13 #include "net/base/completion_callback.h" 13 #include "net/base/completion_callback.h"
14 #include "net/base/io_buffer.h" 14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
16 #include "net/base/test_completion_callback.h" 16 #include "net/base/test_completion_callback.h"
17 #include "net/disk_cache/backend_impl.h" 17 #include "net/disk_cache/backend_impl.h"
18 #include "net/disk_cache/disk_cache_test_base.h" 18 #include "net/disk_cache/disk_cache_test_base.h"
19 #include "net/disk_cache/disk_cache_test_util.h" 19 #include "net/disk_cache/disk_cache_test_util.h"
20 #include "net/disk_cache/entry_impl.h" 20 #include "net/disk_cache/entry_impl.h"
21 #include "net/disk_cache/mem_entry_impl.h" 21 #include "net/disk_cache/mem_entry_impl.h"
22 #include "net/disk_cache/simple/simple_entry_format.h" 22 #include "net/disk_cache/simple/simple_entry_format.h"
23 #include "net/disk_cache/simple/simple_entry_impl.h"
23 #include "net/disk_cache/simple/simple_util.h" 24 #include "net/disk_cache/simple/simple_util.h"
24 #include "testing/gtest/include/gtest/gtest.h" 25 #include "testing/gtest/include/gtest/gtest.h"
25 26
26 using base::Time; 27 using base::Time;
27 28
28 // Tests that can run with different types of caches. 29 // Tests that can run with different types of caches.
29 class DiskCacheEntryTest : public DiskCacheTestWithCache { 30 class DiskCacheEntryTest : public DiskCacheTestWithCache {
30 public: 31 public:
31 void InternalSyncIOBackground(disk_cache::Entry* entry); 32 void InternalSyncIOBackground(disk_cache::Entry* entry);
32 void ExternalSyncIOBackground(disk_cache::Entry* entry); 33 void ExternalSyncIOBackground(disk_cache::Entry* entry);
(...skipping 2385 matching lines...) Expand 10 before | Expand all | Expand 10 after
2418 const base::FilePath entry_path = cache_path_.AppendASCII( 2419 const base::FilePath entry_path = cache_path_.AppendASCII(
2419 disk_cache::simple_util::GetFilenameFromKeyAndIndex(key, 0)); 2420 disk_cache::simple_util::GetFilenameFromKeyAndIndex(key, 0));
2420 const int64 invalid_size = 2421 const int64 invalid_size =
2421 disk_cache::simple_util::GetFileSizeFromKeyAndDataSize(key, 2422 disk_cache::simple_util::GetFileSizeFromKeyAndDataSize(key,
2422 kTruncationBytes); 2423 kTruncationBytes);
2423 EXPECT_TRUE(TruncatePath(entry_path, invalid_size)); 2424 EXPECT_TRUE(TruncatePath(entry_path, invalid_size));
2424 EXPECT_EQ(net::ERR_FAILED, OpenEntry(key, &entry)); 2425 EXPECT_EQ(net::ERR_FAILED, OpenEntry(key, &entry));
2425 DisableIntegrityCheck(); 2426 DisableIntegrityCheck();
2426 } 2427 }
2427 2428
2429 TEST_F(DiskCacheEntryTest, SimpleCacheOptmisitc) {
gavinp 2013/05/01 13:11:22 speeling
felipeg 2013/05/02 09:49:27 Done.
2430 // Test sequence:
2431 // Create, Write, Read, Write, Read, Close.
2432 SetSimpleCacheMode();
2433 InitCache();
2434 disk_cache::Entry* null = NULL;
2435 const char key[] = "the first key";
2436
2437 MessageLoopHelper helper;
2438 CallbackTest callback1(&helper, false);
2439 CallbackTest callback2(&helper, false);
2440 CallbackTest callback3(&helper, false);
2441 CallbackTest callback4(&helper, false);
2442 CallbackTest callback5(&helper, false);
2443
2444 int expected = 0;
2445 const int kSize1 = 10;
2446 const int kSize2 = 20;
2447 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
2448 scoped_refptr<net::IOBuffer> buffer1_read(new net::IOBuffer(kSize1));
2449 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
2450 scoped_refptr<net::IOBuffer> buffer2_read(new net::IOBuffer(kSize2));
2451 CacheTestFillBuffer(buffer1->data(), kSize1, false);
2452 CacheTestFillBuffer(buffer2->data(), kSize2, false);
2453
2454 disk_cache::Entry* entry = NULL;
2455 // Create is optimistic, must return OK.
2456 EXPECT_EQ(net::OK,
gavinp 2013/05/01 13:11:22 This should be an ASSERT_EQ, so the crash stops wh
felipeg 2013/05/02 09:49:27 Done.
2457 cache_->CreateEntry(key, &entry,
2458 base::Bind(&CallbackTest::Run,
2459 base::Unretained(&callback1))));
2460 EXPECT_NE(null, entry);
2461
2462 // This write may or may not be optimistic (it depends if the previous
2463 // optimistic create already finished by the time we call the write here).
2464 int ret = entry->WriteData(
gavinp 2013/05/01 13:11:22 This seems wise. If we did an optimistic write aft
felipeg 2013/05/02 09:49:27 Done.
2465 0, 0, buffer1, kSize1,
2466 base::Bind(&CallbackTest::Run, base::Unretained(&callback2)), false);
2467 EXPECT_TRUE(kSize1 == ret || net::ERR_IO_PENDING == ret);
2468 if (net::ERR_IO_PENDING == ret)
2469 expected++;
2470
2471 // This Read must not be optimistic, since we don't support that yet.
2472 EXPECT_EQ(net::ERR_IO_PENDING, entry->ReadData(
2473 0, 0, buffer1_read, kSize1,
2474 base::Bind(&CallbackTest::Run, base::Unretained(&callback3))));
2475 expected++;
2476 EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
2477 EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read->data(), kSize1));
2478
2479 // At this point after waiting, the pending operations queue on the entry
2480 // should be empty, so the next Write operation must run as optimistic.
2481 EXPECT_EQ(kSize2,
2482 entry->WriteData(
2483 0, 0, buffer2, kSize2,
2484 base::Bind(&CallbackTest::Run,
2485 base::Unretained(&callback4)), false));
2486
2487 // Lets do another read so we block until both the write and the read
2488 // operation finishes and we can then test for HasOneRef() below.
2489 EXPECT_EQ(net::ERR_IO_PENDING, entry->ReadData(
2490 0, 0, buffer2_read, kSize2,
2491 base::Bind(&CallbackTest::Run, base::Unretained(&callback5))));
2492 expected++;
2493
2494 EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
2495 EXPECT_EQ(0, memcmp(buffer2->data(), buffer2_read->data(), kSize2));
2496
2497 // Check that we are not leaking.
2498 EXPECT_NE(entry, null);
2499 EXPECT_TRUE(
2500 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
2501 entry->Close();
2502 entry = NULL;
2503 }
2504
2505 TEST_F(DiskCacheEntryTest, SimpleCacheOptmisitc2) {
2506 // Test sequence:
2507 // Create, Open, Close, Close.
2508 SetSimpleCacheMode();
2509 InitCache();
2510 disk_cache::Entry* null = NULL;
2511 const char key[] = "the first key";
2512
2513 MessageLoopHelper helper;
2514 CallbackTest callback1(&helper, false);
2515 CallbackTest callback2(&helper, false);
2516
2517 disk_cache::Entry* entry = NULL;
2518 EXPECT_EQ(net::OK,
2519 cache_->CreateEntry(key, &entry,
2520 base::Bind(&CallbackTest::Run,
2521 base::Unretained(&callback1))));
2522 EXPECT_NE(null, entry);
2523
2524 disk_cache::Entry* entry2 = NULL;
2525 EXPECT_EQ(net::ERR_IO_PENDING,
2526 cache_->OpenEntry(key, &entry2,
2527 base::Bind(&CallbackTest::Run,
2528 base::Unretained(&callback2))));
2529 EXPECT_TRUE(helper.WaitUntilCacheIoFinished(1));
2530
2531 EXPECT_NE(null, entry2);
2532 EXPECT_EQ(entry, entry2);
2533
2534 // We have to call close twice, since we called create and open above.
2535 entry->Close();
2536
2537 // Check that we are not leaking.
2538 EXPECT_TRUE(
2539 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
2540 entry->Close();
2541 entry = NULL;
2542 }
2543
2544 TEST_F(DiskCacheEntryTest, SimpleCacheOptmisitc3) {
2545 // Test sequence:
2546 // Create, Close, Open, Close.
2547 SetSimpleCacheMode();
2548 InitCache();
2549 disk_cache::Entry* null = NULL;
2550 const char key[] = "the first key";
2551
2552 disk_cache::Entry* entry = NULL;
2553 EXPECT_EQ(net::OK,
2554 cache_->CreateEntry(key, &entry, net::CompletionCallback()));
2555 EXPECT_NE(null, entry);
2556 entry->Close();
2557
2558 net::TestCompletionCallback cb;
2559 disk_cache::Entry* entry2 = NULL;
2560 EXPECT_EQ(net::ERR_IO_PENDING,
2561 cache_->OpenEntry(key, &entry2, cb.callback()));
2562 EXPECT_EQ(net::OK, cb.GetResult(net::ERR_IO_PENDING));
2563
2564 EXPECT_NE(null, entry2);
2565 EXPECT_EQ(entry, entry2);
2566
2567 // Check that we are not leaking.
2568 EXPECT_TRUE(
2569 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry2)->HasOneRef());
2570 entry2->Close();
2571 }
2572
2573 TEST_F(DiskCacheEntryTest, SimpleCacheOptmisitc4) {
2574 // Test sequence:
2575 // Create, Close, Write, Open, Open, Close, Write, Read, Close.
2576 SetSimpleCacheMode();
2577 InitCache();
2578 disk_cache::Entry* null = NULL;
2579 const char key[] = "the first key";
2580
2581 net::TestCompletionCallback cb;
2582 const int kSize1 = 10;
2583 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
2584 CacheTestFillBuffer(buffer1->data(), kSize1, false);
2585 disk_cache::Entry* entry = NULL;
2586
2587 EXPECT_EQ(net::OK,
2588 cache_->CreateEntry(key, &entry, net::CompletionCallback()));
2589 EXPECT_NE(null, entry);
2590 entry->Close();
2591
2592 // Lets do a Write so we block until both the Close and the Write
2593 // operation finishes. Write must fail since we are writing in a closed entry.
2594 EXPECT_EQ(net::ERR_IO_PENDING, entry->WriteData(
2595 0, 0, buffer1, kSize1, cb.callback(), false));
2596 EXPECT_EQ(net::ERR_FAILED, cb.GetResult(net::ERR_IO_PENDING));
2597
2598 // Finish running the pending tasks so that we fully complete the close
2599 // operation and destroy the entry object.
2600 MessageLoop::current()->RunUntilIdle();
2601
2602 // At this point the |entry| must have been destroyed, and called
2603 // RemoveSelfFromBackend() so we check that the next Open will construct a new
2604 // SimpleEntryImpl object.
2605 disk_cache::Entry* entry2 = NULL;
2606 EXPECT_EQ(net::ERR_IO_PENDING,
2607 cache_->OpenEntry(key, &entry2, cb.callback()));
2608 EXPECT_EQ(net::OK, cb.GetResult(net::ERR_IO_PENDING));
2609 EXPECT_NE(null, entry2);
2610 EXPECT_NE(entry, entry2);
2611
2612 disk_cache::Entry* entry3 = NULL;
2613 EXPECT_EQ(net::ERR_IO_PENDING,
2614 cache_->OpenEntry(key, &entry3, cb.callback()));
2615 EXPECT_EQ(net::OK, cb.GetResult(net::ERR_IO_PENDING));
2616 EXPECT_NE(null, entry3);
2617 EXPECT_EQ(entry2, entry3);
2618 entry3->Close();
2619
2620 // The previous Close doesn't actually closes the entry since we opened it
2621 // twice, so the next Write operation must succeed and it must be able to
2622 // perform it optimistically, since there is no operation running on this
2623 // entry.
2624 EXPECT_EQ(kSize1, entry2->WriteData(
2625 0, 0, buffer1, kSize1, net::CompletionCallback(), false));
2626
2627 // Lets do another read so we block until both the write and the read
2628 // operation finishes and we can then test for HasOneRef() below.
2629 EXPECT_EQ(net::ERR_IO_PENDING, entry2->ReadData(
2630 0, 0, buffer1, kSize1, cb.callback()));
2631 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
2632
2633 // Check that we are not leaking.
2634 EXPECT_TRUE(
2635 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry2)->HasOneRef());
2636 entry2->Close();
2637 }
2638
2639 // This test is flaky because of the race of Create followed by a Doom.
2640 // See test SimpleCacheCreateDoomRace.
2641 TEST_F(DiskCacheEntryTest, DISABLED_SimpleCacheOptmisitc5) {
2642 // Test sequence:
2643 // Create, Doom, Write, Read, Close.
2644 SetSimpleCacheMode();
2645 InitCache();
2646 disk_cache::Entry* null = NULL;
2647 const char key[] = "the first key";
2648
2649 net::TestCompletionCallback cb;
2650 const int kSize1 = 10;
2651 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
2652 CacheTestFillBuffer(buffer1->data(), kSize1, false);
2653 disk_cache::Entry* entry = NULL;
2654
2655 EXPECT_EQ(net::OK,
2656 cache_->CreateEntry(key, &entry, net::CompletionCallback()));
2657 EXPECT_NE(null, entry);
2658 entry->Doom();
2659
2660 EXPECT_EQ(net::ERR_IO_PENDING, entry->WriteData(
2661 0, 0, buffer1, kSize1, cb.callback(), false));
2662 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
2663
2664 EXPECT_EQ(net::ERR_IO_PENDING, entry->ReadData(
2665 0, 0, buffer1, kSize1, cb.callback()));
2666 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
2667
2668 // Check that we are not leaking.
2669 EXPECT_TRUE(
2670 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
2671 entry->Close();
2672 }
2673
2674 TEST_F(DiskCacheEntryTest, SimpleCacheOptmisitc6) {
2675 // Test sequence:
2676 // Create, Write, Doom, Doom, Read, Doom, Close.
2677 SetSimpleCacheMode();
2678 InitCache();
2679 disk_cache::Entry* null = NULL;
2680 const char key[] = "the first key";
2681
2682 net::TestCompletionCallback cb;
2683 const int kSize1 = 10;
2684 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
2685 scoped_refptr<net::IOBuffer> buffer1_read(new net::IOBuffer(kSize1));
2686 CacheTestFillBuffer(buffer1->data(), kSize1, false);
2687 disk_cache::Entry* entry = NULL;
2688
2689 EXPECT_EQ(net::OK,
2690 cache_->CreateEntry(key, &entry, net::CompletionCallback()));
2691 EXPECT_NE(null, entry);
2692
2693 EXPECT_EQ(net::ERR_IO_PENDING, entry->WriteData(
2694 0, 0, buffer1, kSize1, cb.callback(), false));
2695 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
2696
2697 entry->Doom();
2698 entry->Doom();
2699
2700 // This Read must not be optimistic, since we don't support that yet.
2701 EXPECT_EQ(net::ERR_IO_PENDING, entry->ReadData(
2702 0, 0, buffer1_read, kSize1, cb.callback()));
2703 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
2704 EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read->data(), kSize1));
2705
2706 entry->Doom();
2707
2708 // Check that we are not leaking.
2709 EXPECT_TRUE(
2710 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
2711 entry->Close();
2712 }
2713
2714 TEST_F(DiskCacheEntryTest, DISABLED_SimpleCacheCreateDoomRace) {
2715 // Test sequence:
2716 // Create, Doom, Write, Close, Check files are not on disk anymore.
2717 SetSimpleCacheMode();
2718 InitCache();
2719 disk_cache::Entry* null = NULL;
2720 const char key[] = "the first key";
2721
2722 net::TestCompletionCallback cb;
2723 const int kSize1 = 10;
2724 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
2725 CacheTestFillBuffer(buffer1->data(), kSize1, false);
2726 disk_cache::Entry* entry = NULL;
2727
2728 EXPECT_EQ(net::OK,
2729 cache_->CreateEntry(key, &entry, net::CompletionCallback()));
2730 EXPECT_NE(null, entry);
2731
2732 disk_cache::SimpleEntryImpl* simple_entry =
2733 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry);
2734 simple_entry->DoomEntry(cb.callback());
gavinp 2013/05/02 09:49:34 This won't link right. Instead: backend_->DoomE
felipeg 2013/05/02 09:55:06 Done.
2735 EXPECT_EQ(net::OK, cb.GetResult(net::ERR_IO_PENDING));
2736
2737 // Lets do a Write so we block until all operations are done, so we can check
2738 // the HasOneRef() below.
2739 EXPECT_EQ(net::ERR_IO_PENDING, entry->WriteData(
gavinp 2013/05/01 13:11:22 Could we just use something like: EXPECT_EQ(kSi
felipeg 2013/05/02 09:49:27 I would prefer not do that, because I want to make
gavinp 2013/05/02 12:47:39 Good point. Can you call out that this write can't
felipeg 2013/05/02 13:55:58 Done.
2740 0, 0, buffer1, kSize1, cb.callback(), false));
2741 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
2742
2743 // Check that we are not leaking.
2744 EXPECT_TRUE(
2745 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
2746 entry->Close();
2747
2748 // Finish running the pending tasks so that we fully complete the close
2749 // operation and destroy the entry object.
2750 MessageLoop::current()->RunUntilIdle();
2751
2752 for (int i = 0; i < disk_cache::kSimpleEntryFileCount; ++i) {
2753 base::FilePath entry_file_path = cache_path_.AppendASCII(
2754 disk_cache::simple_util::GetFilenameFromKeyAndIndex(key, i));
2755 base::PlatformFileInfo info;
2756 EXPECT_FALSE(file_util::GetFileInfo(entry_file_path, &info));
2757 }
2758 }
2759
2428 // Tests that old entries are evicted while new entries remain in the index. 2760 // Tests that old entries are evicted while new entries remain in the index.
2429 // This test relies on non-mandatory properties of the simple Cache Backend: 2761 // This test relies on non-mandatory properties of the simple Cache Backend:
2430 // LRU eviction, specific values of high-watermark and low-watermark etc. 2762 // LRU eviction, specific values of high-watermark and low-watermark etc.
2431 // When changing the eviction algorithm, the test will have to be re-engineered. 2763 // When changing the eviction algorithm, the test will have to be re-engineered.
2432 TEST_F(DiskCacheEntryTest, SimpleCacheEvictOldEntries) { 2764 TEST_F(DiskCacheEntryTest, SimpleCacheEvictOldEntries) {
2433 const int kMaxSize = 200 * 1024; 2765 const int kMaxSize = 200 * 1024;
2434 const int kWriteSize = kMaxSize / 10; 2766 const int kWriteSize = kMaxSize / 10;
2435 const int kNumExtraEntries = 12; 2767 const int kNumExtraEntries = 12;
2436 SetSimpleCacheMode(); 2768 SetSimpleCacheMode();
2437 SetMaxSize(kMaxSize); 2769 SetMaxSize(kMaxSize);
(...skipping 24 matching lines...) Expand all
2462 // is finished. We are testing the positive case, i.e. when the eviction 2794 // is finished. We are testing the positive case, i.e. when the eviction
2463 // never reaches this entry, should be non-flaky. 2795 // never reaches this entry, should be non-flaky.
2464 ASSERT_EQ(net::OK, OpenEntry(key2 + base::StringPrintf("%d", entry_no), 2796 ASSERT_EQ(net::OK, OpenEntry(key2 + base::StringPrintf("%d", entry_no),
2465 &entry)) 2797 &entry))
2466 << "Should not have evicted fresh entry " << entry_no; 2798 << "Should not have evicted fresh entry " << entry_no;
2467 entry->Close(); 2799 entry->Close();
2468 } 2800 }
2469 } 2801 }
2470 2802
2471 #endif // defined(OS_POSIX) 2803 #endif // defined(OS_POSIX)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698