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

Side by Side Diff: content/browser/blob_storage/blob_storage_context_unittest.cc

Issue 2516713002: [BlobStorage] Implementing disk. (Closed)
Patch Set: test & windows fix Created 4 years 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "storage/browser/blob/blob_storage_context.h" 5 #include "storage/browser/blob/blob_storage_context.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <limits> 9 #include <limits>
10 #include <memory> 10 #include <memory>
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 } 92 }
93 93
94 void SaveBlobStatus(BlobStatus* status_ptr, BlobStatus status) { 94 void SaveBlobStatus(BlobStatus* status_ptr, BlobStatus status) {
95 *status_ptr = status; 95 *status_ptr = status;
96 } 96 }
97 97
98 void SaveBlobStatusAndFiles(BlobStatus* status_ptr, 98 void SaveBlobStatusAndFiles(BlobStatus* status_ptr,
99 std::vector<FileCreationInfo>* files_ptr, 99 std::vector<FileCreationInfo>* files_ptr,
100 BlobStatus status, 100 BlobStatus status,
101 std::vector<FileCreationInfo> files) { 101 std::vector<FileCreationInfo> files) {
102 EXPECT_FALSE(BlobStatusIsError(status));
102 *status_ptr = status; 103 *status_ptr = status;
103 for (FileCreationInfo& info : files) { 104 for (FileCreationInfo& info : files) {
104 files_ptr->push_back(std::move(info)); 105 files_ptr->push_back(std::move(info));
105 } 106 }
106 } 107 }
107 108
109 void IncrementPointer(size_t* number, BlobStatus status) {
110 EXPECT_EQ(BlobStatus::DONE, status);
111 *number = *number + 1;
112 }
113
108 } // namespace 114 } // namespace
109 115
110 class BlobStorageContextTest : public testing::Test { 116 class BlobStorageContextTest : public testing::Test {
111 protected: 117 protected:
112 BlobStorageContextTest() {} 118 BlobStorageContextTest() {}
113 ~BlobStorageContextTest() override {} 119 ~BlobStorageContextTest() override {}
114 120
115 void SetUp() override { context_ = base::MakeUnique<BlobStorageContext>(); } 121 void SetUp() override {
122 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
123 context_ = base::MakeUnique<BlobStorageContext>();
124 }
125
126 void TearDown() override {
127 base::RunLoop().RunUntilIdle();
128 file_runner_->RunPendingTasks();
129 ASSERT_TRUE(temp_dir_.Delete());
130 }
116 131
117 std::unique_ptr<BlobDataHandle> SetupBasicBlob(const std::string& id) { 132 std::unique_ptr<BlobDataHandle> SetupBasicBlob(const std::string& id) {
118 BlobDataBuilder builder(id); 133 BlobDataBuilder builder(id);
119 builder.AppendData("1", 1); 134 builder.AppendData("1", 1);
120 builder.set_content_type("text/plain"); 135 builder.set_content_type("text/plain");
121 return context_->AddFinishedBlob(builder); 136 return context_->AddFinishedBlob(builder);
122 } 137 }
123 138
124 void SetTestMemoryLimits() { 139 void SetTestMemoryLimits() {
125 BlobStorageLimits limits; 140 BlobStorageLimits limits;
126 limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes; 141 limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
127 limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes; 142 limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
128 limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize; 143 limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
129 limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace; 144 limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace;
130 limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes; 145 limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
131 limits.max_file_size = kTestBlobStorageMaxFileSizeBytes; 146 limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
132 context_->mutable_memory_controller()->set_limits_for_testing(limits); 147 context_->mutable_memory_controller()->set_limits_for_testing(limits);
133 } 148 }
134 149
135 void IncrementRefCount(const std::string& uuid) { 150 void IncrementRefCount(const std::string& uuid) {
136 context_->IncrementBlobRefCount(uuid); 151 context_->IncrementBlobRefCount(uuid);
137 } 152 }
138 153
139 void DecrementRefCount(const std::string& uuid) { 154 void DecrementRefCount(const std::string& uuid) {
140 context_->DecrementBlobRefCount(uuid); 155 context_->DecrementBlobRefCount(uuid);
141 } 156 }
142 157
143 std::vector<FileCreationInfo> files_; 158 std::vector<FileCreationInfo> files_;
159 base::ScopedTempDir temp_dir_;
160 scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner();
144 161
145 base::MessageLoop fake_io_message_loop_; 162 base::MessageLoop fake_io_message_loop_;
146 std::unique_ptr<BlobStorageContext> context_; 163 std::unique_ptr<BlobStorageContext> context_;
147 }; 164 };
148 165
149 TEST_F(BlobStorageContextTest, BuildBlobAsync) { 166 TEST_F(BlobStorageContextTest, BuildBlobAsync) {
150 const std::string kId("id"); 167 const std::string kId("id");
151 const size_t kSize = 10u; 168 const size_t kSize = 10u;
152 BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; 169 BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
153 170
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 builder3.AppendData("data"); 665 builder3.AppendData("data");
649 builder3.AppendBlob(kBuildingId); 666 builder3.AppendBlob(kBuildingId);
650 handle = context_->AddFinishedBlob(builder3); 667 handle = context_->AddFinishedBlob(builder3);
651 EXPECT_TRUE(handle->IsBroken()); 668 EXPECT_TRUE(handle->IsBroken());
652 EXPECT_TRUE(context_->registry().HasEntry(kReferencingId)); 669 EXPECT_TRUE(context_->registry().HasEntry(kReferencingId));
653 handle.reset(); 670 handle.reset();
654 base::RunLoop().RunUntilIdle(); 671 base::RunLoop().RunUntilIdle();
655 EXPECT_FALSE(context_->registry().HasEntry(kReferencingId)); 672 EXPECT_FALSE(context_->registry().HasEntry(kReferencingId));
656 } 673 }
657 674
675 TEST_F(BlobStorageContextTest, BuildBlobFuzzer) {
kinuko 2016/11/27 14:45:22 Fuzzer sounds like it's using fuzzer. Should we r
dmurph 2016/11/28 19:20:36 I wanted to have every combination of blob that is
676 const std::string kTestBlobData = "Test Blob Data";
677 const std::string kId("id");
678 const size_t kTotalRawBlobs = 200;
679 const size_t kTotalSlicedBlobs = 100;
680 scoped_refptr<BlobDataBuilder::DataHandle> disk_cache_data_handle =
681 new EmptyDataHandle();
682
683 context_ =
684 base::MakeUnique<BlobStorageContext>(temp_dir_.GetPath(), file_runner_);
685
686 SetTestMemoryLimits();
687 std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
688 ASSERT_TRUE(cache);
689 disk_cache::ScopedEntryPtr entry =
690 CreateDiskCacheEntry(cache.get(), "test entry", kTestBlobData);
691
692 // This tests mixed blob content with both synchronous and asynchronous
693 // construction. Blobs should also be paged to disk during execution.
694 std::vector<std::unique_ptr<BlobDataBuilder>> builders;
695 std::vector<size_t> sizes;
696 for (size_t i = 0; i < kTotalRawBlobs; i++) {
697 builders.emplace_back(new BlobDataBuilder(base::SizeTToString(i)));
698 auto& builder = *builders.back();
699 size_t size = 0;
700 if (i % 2 != 0) {
701 builder.AppendFutureData(5u);
702 size += 5u;
703 if (i % 3 == 1) {
704 builder.AppendData("abcdefghij", 4u);
705 size += 4u;
706 }
707 if (i % 3 == 0) {
708 builder.AppendFutureData(1u);
709 size += 1u;
710 }
711 } else if (i % 3 == 0) {
712 builder.AppendFutureFile(0lu, 3lu, 0);
713 size += 3u;
714 }
715 if (i % 5 != 0) {
716 builder.AppendFile(base::FilePath::FromUTF8Unsafe(base::SizeTToString(i)),
717 0ul, 20ul, base::Time::Max());
718 size += 20u;
719 }
720 builder.AppendDiskCacheEntry(disk_cache_data_handle, entry.get(),
721 kTestDiskCacheStreamIndex);
722 size += 14;
723 EXPECT_NE(0u, size);
724 sizes.push_back(size);
725 }
726
727 for (size_t i = 0; i < kTotalSlicedBlobs; i++) {
728 builders.emplace_back(
729 new BlobDataBuilder(base::SizeTToString(i + kTotalRawBlobs)));
730 size_t source_size = sizes[i];
731 size_t offset = sizes[i] == 1 ? 0 : i % (source_size - 1);
732 size_t size = (i % (source_size - offset)) + 1;
733 builders.back()->AppendBlob(base::SizeTToString(i), offset, size);
734 sizes.push_back(size);
735 }
736
737 size_t total_finished_blobs = 0;
738 std::vector<std::unique_ptr<BlobDataHandle>> handles;
739 std::vector<BlobStatus> statuses;
740 std::vector<bool> populated;
741 statuses.resize(kTotalRawBlobs,
742 BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS);
743 populated.resize(kTotalRawBlobs, false);
744 for (size_t i = 0; i < builders.size(); i++) {
745 BlobDataBuilder& builder = *builders[i];
746 builder.set_content_type("text/plain");
747 bool has_pending_memory = i < kTotalRawBlobs && (i % 2 != 0 || i % 3 == 0);
748 std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob(
749 builder,
750 has_pending_memory
751 ? base::Bind(&SaveBlobStatusAndFiles, &statuses[0] + i, &files_)
752 : BlobStorageContext::TransportAllowedCallback());
753 handle->RunOnConstructionComplete(
754 base::Bind(&IncrementPointer, &total_finished_blobs));
755 handles.push_back(std::move(handle));
756 }
757 base::RunLoop().RunUntilIdle();
758
759 // We should be needing to send a page or two to disk.
760 EXPECT_TRUE(file_runner_->HasPendingTask());
761 do {
762 file_runner_->RunPendingTasks();
763 base::RunLoop().RunUntilIdle();
764 // Continue populating data for items that can fit.
765 for (size_t i = 0; i < kTotalRawBlobs; i++) {
766 auto& builder = *builders[i];
767 bool has_pending_memory = (i % 2 != 0 || i % 3 == 0);
768 if (has_pending_memory && !populated[i] &&
769 statuses[i] == BlobStatus::PENDING_TRANSPORT) {
770 if (i % 2 != 0) {
771 builder.PopulateFutureData(0, "abcde", 0, 5);
772 if (i % 3 == 0) {
773 builder.PopulateFutureData(1, "z", 0, 1);
774 }
775 } else if (i % 3 == 0) {
776 scoped_refptr<ShareableFileReference> file_ref =
777 ShareableFileReference::GetOrCreate(
778 base::FilePath::FromUTF8Unsafe(
779 base::SizeTToString(i + kTotalRawBlobs)),
780 ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
781 file_runner_.get());
782 builder.PopulateFutureFile(0, file_ref, base::Time::Max());
783 }
784 context_->NotifyTransportComplete(base::SizeTToString(i));
785 populated[i] = true;
786 }
787 }
788 base::RunLoop().RunUntilIdle();
789 } while (file_runner_->HasPendingTask());
790
791 for (size_t i = 0; i < populated.size(); i++) {
792 bool has_pending_memory = (i % 2 != 0 || i % 3 == 0);
793 if (has_pending_memory)
794 EXPECT_TRUE(populated[i]) << i;
795 }
796 base::RunLoop().RunUntilIdle();
797
798 // We should be completely built now.
799 EXPECT_EQ(kTotalRawBlobs + kTotalSlicedBlobs, total_finished_blobs);
800 for (std::unique_ptr<BlobDataHandle>& handle : handles) {
801 EXPECT_EQ(BlobStatus::DONE, handle->GetBlobStatus());
802 }
803 handles.clear();
804 base::RunLoop().RunUntilIdle();
805 files_.clear();
806 // We should have file cleanup tasks.
807 EXPECT_TRUE(file_runner_->HasPendingTask());
808 file_runner_->RunPendingTasks();
809 base::RunLoop().RunUntilIdle();
810 for (size_t i = 0; i < kTotalRawBlobs; i++) {
811 bool has_pending_memory = (i % 2 != 0 || i % 3 == 0);
812 if (has_pending_memory)
813 EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, statuses[i]) << i;
814 }
815 EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
816 EXPECT_EQ(0lu, context_->memory_controller().disk_usage());
817 }
818
658 // TODO(michaeln): tests for the depcrecated url stuff 819 // TODO(michaeln): tests for the depcrecated url stuff
659 820
660 } // namespace content 821 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698