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/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 Loading... | |
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, SimpleCacheOptimistic) { | |
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 ASSERT_EQ(net::OK, | |
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( | |
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()); | |
gavinp
2013/05/02 12:47:39
This isn't a safe use of reinterpret_cast; static_
felipeg
2013/05/02 13:55:58
Done.
| |
2501 entry->Close(); | |
2502 entry = NULL; | |
2503 } | |
2504 | |
2505 TEST_F(DiskCacheEntryTest, SimpleCacheOptimistic2) { | |
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 ASSERT_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, SimpleCacheOptimistic3) { | |
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 ASSERT_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, SimpleCacheOptimistic4) { | |
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 ASSERT_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(). | |
2604 disk_cache::Entry* entry2 = NULL; | |
2605 EXPECT_EQ(net::ERR_IO_PENDING, | |
2606 cache_->OpenEntry(key, &entry2, cb.callback())); | |
2607 EXPECT_EQ(net::OK, cb.GetResult(net::ERR_IO_PENDING)); | |
2608 EXPECT_NE(null, entry2); | |
2609 | |
2610 disk_cache::Entry* entry3 = NULL; | |
2611 EXPECT_EQ(net::ERR_IO_PENDING, | |
2612 cache_->OpenEntry(key, &entry3, cb.callback())); | |
2613 EXPECT_EQ(net::OK, cb.GetResult(net::ERR_IO_PENDING)); | |
2614 EXPECT_NE(null, entry3); | |
2615 EXPECT_EQ(entry2, entry3); | |
2616 entry3->Close(); | |
2617 | |
2618 // The previous Close doesn't actually closes the entry since we opened it | |
2619 // twice, so the next Write operation must succeed and it must be able to | |
2620 // perform it optimistically, since there is no operation running on this | |
2621 // entry. | |
2622 EXPECT_EQ(kSize1, entry2->WriteData( | |
2623 0, 0, buffer1, kSize1, net::CompletionCallback(), false)); | |
2624 | |
2625 // Lets do another read so we block until both the write and the read | |
2626 // operation finishes and we can then test for HasOneRef() below. | |
2627 EXPECT_EQ(net::ERR_IO_PENDING, entry2->ReadData( | |
2628 0, 0, buffer1, kSize1, cb.callback())); | |
2629 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING)); | |
2630 | |
2631 // Check that we are not leaking. | |
2632 EXPECT_TRUE( | |
2633 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry2)->HasOneRef()); | |
2634 entry2->Close(); | |
2635 } | |
2636 | |
2637 // This test is flaky because of the race of Create followed by a Doom. | |
2638 // See test SimpleCacheCreateDoomRace. | |
2639 TEST_F(DiskCacheEntryTest, DISABLED_SimpleCacheOptimistic5) { | |
2640 // Test sequence: | |
2641 // Create, Doom, Write, Read, Close. | |
2642 SetSimpleCacheMode(); | |
2643 InitCache(); | |
2644 disk_cache::Entry* null = NULL; | |
2645 const char key[] = "the first key"; | |
2646 | |
2647 net::TestCompletionCallback cb; | |
2648 const int kSize1 = 10; | |
2649 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1)); | |
2650 CacheTestFillBuffer(buffer1->data(), kSize1, false); | |
2651 disk_cache::Entry* entry = NULL; | |
2652 | |
2653 ASSERT_EQ(net::OK, | |
2654 cache_->CreateEntry(key, &entry, net::CompletionCallback())); | |
2655 EXPECT_NE(null, entry); | |
2656 entry->Doom(); | |
2657 | |
2658 EXPECT_EQ(net::ERR_IO_PENDING, entry->WriteData( | |
2659 0, 0, buffer1, kSize1, cb.callback(), false)); | |
2660 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING)); | |
2661 | |
2662 EXPECT_EQ(net::ERR_IO_PENDING, entry->ReadData( | |
2663 0, 0, buffer1, kSize1, cb.callback())); | |
2664 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING)); | |
2665 | |
2666 // Check that we are not leaking. | |
2667 EXPECT_TRUE( | |
2668 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef()); | |
2669 entry->Close(); | |
2670 } | |
2671 | |
2672 TEST_F(DiskCacheEntryTest, SimpleCacheOptimistic6) { | |
2673 // Test sequence: | |
2674 // Create, Write, Doom, Doom, Read, Doom, Close. | |
2675 SetSimpleCacheMode(); | |
2676 InitCache(); | |
2677 disk_cache::Entry* null = NULL; | |
2678 const char key[] = "the first key"; | |
2679 | |
2680 net::TestCompletionCallback cb; | |
2681 const int kSize1 = 10; | |
2682 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1)); | |
2683 scoped_refptr<net::IOBuffer> buffer1_read(new net::IOBuffer(kSize1)); | |
2684 CacheTestFillBuffer(buffer1->data(), kSize1, false); | |
2685 disk_cache::Entry* entry = NULL; | |
2686 | |
2687 ASSERT_EQ(net::OK, | |
2688 cache_->CreateEntry(key, &entry, net::CompletionCallback())); | |
2689 EXPECT_NE(null, entry); | |
2690 | |
2691 EXPECT_EQ(net::ERR_IO_PENDING, entry->WriteData( | |
2692 0, 0, buffer1, kSize1, cb.callback(), false)); | |
2693 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING)); | |
2694 | |
2695 entry->Doom(); | |
2696 entry->Doom(); | |
2697 | |
2698 // This Read must not be optimistic, since we don't support that yet. | |
2699 EXPECT_EQ(net::ERR_IO_PENDING, entry->ReadData( | |
2700 0, 0, buffer1_read, kSize1, cb.callback())); | |
2701 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING)); | |
2702 EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read->data(), kSize1)); | |
2703 | |
2704 entry->Doom(); | |
2705 | |
2706 // Check that we are not leaking. | |
2707 EXPECT_TRUE( | |
2708 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef()); | |
2709 entry->Close(); | |
2710 } | |
2711 | |
2712 TEST_F(DiskCacheEntryTest, DISABLED_SimpleCacheCreateDoomRace) { | |
2713 // Test sequence: | |
2714 // Create, Doom, Write, Close, Check files are not on disk anymore. | |
2715 SetSimpleCacheMode(); | |
2716 InitCache(); | |
2717 disk_cache::Entry* null = NULL; | |
2718 const char key[] = "the first key"; | |
2719 | |
2720 net::TestCompletionCallback cb; | |
2721 const int kSize1 = 10; | |
2722 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1)); | |
2723 CacheTestFillBuffer(buffer1->data(), kSize1, false); | |
2724 disk_cache::Entry* entry = NULL; | |
2725 | |
2726 ASSERT_EQ(net::OK, | |
2727 cache_->CreateEntry(key, &entry, net::CompletionCallback())); | |
2728 EXPECT_NE(null, entry); | |
2729 | |
2730 cache_->DoomEntry(key, cb.callback()); | |
2731 EXPECT_EQ(net::OK, cb.GetResult(net::ERR_IO_PENDING)); | |
2732 | |
2733 // Lets do a Write so we block until all operations are done, so we can check | |
2734 // the HasOneRef() below. | |
2735 EXPECT_EQ(net::ERR_IO_PENDING, entry->WriteData( | |
2736 0, 0, buffer1, kSize1, cb.callback(), false)); | |
2737 EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING)); | |
2738 | |
2739 // Check that we are not leaking. | |
2740 EXPECT_TRUE( | |
2741 reinterpret_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef()); | |
2742 entry->Close(); | |
2743 | |
2744 // Finish running the pending tasks so that we fully complete the close | |
2745 // operation and destroy the entry object. | |
2746 MessageLoop::current()->RunUntilIdle(); | |
2747 | |
2748 for (int i = 0; i < disk_cache::kSimpleEntryFileCount; ++i) { | |
2749 base::FilePath entry_file_path = cache_path_.AppendASCII( | |
2750 disk_cache::simple_util::GetFilenameFromKeyAndIndex(key, i)); | |
2751 base::PlatformFileInfo info; | |
2752 EXPECT_FALSE(file_util::GetFileInfo(entry_file_path, &info)); | |
2753 } | |
2754 } | |
2755 | |
2428 // Tests that old entries are evicted while new entries remain in the index. | 2756 // 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: | 2757 // This test relies on non-mandatory properties of the simple Cache Backend: |
2430 // LRU eviction, specific values of high-watermark and low-watermark etc. | 2758 // 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. | 2759 // When changing the eviction algorithm, the test will have to be re-engineered. |
2432 TEST_F(DiskCacheEntryTest, SimpleCacheEvictOldEntries) { | 2760 TEST_F(DiskCacheEntryTest, SimpleCacheEvictOldEntries) { |
2433 const int kMaxSize = 200 * 1024; | 2761 const int kMaxSize = 200 * 1024; |
2434 const int kWriteSize = kMaxSize / 10; | 2762 const int kWriteSize = kMaxSize / 10; |
2435 const int kNumExtraEntries = 12; | 2763 const int kNumExtraEntries = 12; |
2436 SetSimpleCacheMode(); | 2764 SetSimpleCacheMode(); |
2437 SetMaxSize(kMaxSize); | 2765 SetMaxSize(kMaxSize); |
(...skipping 24 matching lines...) Expand all Loading... | |
2462 // is finished. We are testing the positive case, i.e. when the eviction | 2790 // is finished. We are testing the positive case, i.e. when the eviction |
2463 // never reaches this entry, should be non-flaky. | 2791 // never reaches this entry, should be non-flaky. |
2464 ASSERT_EQ(net::OK, OpenEntry(key2 + base::StringPrintf("%d", entry_no), | 2792 ASSERT_EQ(net::OK, OpenEntry(key2 + base::StringPrintf("%d", entry_no), |
2465 &entry)) | 2793 &entry)) |
2466 << "Should not have evicted fresh entry " << entry_no; | 2794 << "Should not have evicted fresh entry " << entry_no; |
2467 entry->Close(); | 2795 entry->Close(); |
2468 } | 2796 } |
2469 } | 2797 } |
2470 | 2798 |
2471 #endif // defined(OS_POSIX) | 2799 #endif // defined(OS_POSIX) |
OLD | NEW |