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

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

Issue 2516713002: [BlobStorage] Implementing disk. (Closed)
Patch Set: file flushing, stack track on reader error 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 IncrementNumber(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());
michaeln 2016/12/02 20:41:07 Possibly the test is failing because a file handle
dmurph 2016/12/02 21:53:06 Yeah, that's it. Thanks! The windows browsertest f
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
658 // TODO(michaeln): tests for the depcrecated url stuff 675 namespace {
676 constexpr size_t kTotalRawBlobs = 200;
677 constexpr size_t kTotalSlicedBlobs = 100;
678 constexpr char kTestDiskCacheData[] = "Test Blob Data";
659 679
660 } // namespace content 680 // Appends data and data types that depend on the index. This is designed to
681 // exercise all types of combinations of data, future data, files, future files,
682 // and disk cache entries.
683 size_t AppendDataInBuilder(BlobDataBuilder* builder,
684 size_t index,
685 disk_cache::Entry* cache_entry) {
686 size_t size = 0;
687 // We can't have both future data and future files, so split those up.
688 if (index % 2 != 0) {
689 builder->AppendFutureData(5u);
690 size += 5u;
691 if (index % 3 == 1) {
692 builder->AppendData("abcdefghij", 4u);
693 size += 4u;
694 }
695 if (index % 3 == 0) {
696 builder->AppendFutureData(1u);
697 size += 1u;
698 }
699 } else if (index % 3 == 0) {
700 builder->AppendFutureFile(0lu, 3lu, 0);
701 size += 3u;
702 }
703 if (index % 5 != 0) {
704 builder->AppendFile(
705 base::FilePath::FromUTF8Unsafe(base::SizeTToString(index)), 0ul, 20ul,
706 base::Time::Max());
707 size += 20u;
708 }
709 if (index % 3 != 0) {
710 scoped_refptr<BlobDataBuilder::DataHandle> disk_cache_data_handle =
711 new EmptyDataHandle();
712 builder->AppendDiskCacheEntry(disk_cache_data_handle, cache_entry,
713 kTestDiskCacheStreamIndex);
714 size += strlen(kTestDiskCacheData);
715 }
716 return size;
717 }
718
719 bool DoesBuilderHaveFutureData(size_t index) {
720 return (index % 2 != 0 || index % 3 == 0);
721 }
722
723 void PopulateDataInBuilder(BlobDataBuilder* builder,
724 size_t index,
725 base::TaskRunner* file_runner) {
726 if (index % 2 != 0) {
727 builder->PopulateFutureData(0, "abcde", 0, 5);
728 if (index % 3 == 0) {
729 builder->PopulateFutureData(1, "z", 0, 1);
730 }
731 } else if (index % 3 == 0) {
732 scoped_refptr<ShareableFileReference> file_ref =
733 ShareableFileReference::GetOrCreate(
734 base::FilePath::FromUTF8Unsafe(
735 base::SizeTToString(index + kTotalRawBlobs)),
736 ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE, file_runner);
737 builder->PopulateFutureFile(0, file_ref, base::Time::Max());
738 }
739 }
740 } // namespace
741
742 TEST_F(BlobStorageContextTest, BuildBlobCombinations) {
743 const std::string kId("id");
744
745 context_ =
746 base::MakeUnique<BlobStorageContext>(temp_dir_.GetPath(), file_runner_);
747
748 SetTestMemoryLimits();
749 std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
750 ASSERT_TRUE(cache);
751 disk_cache::ScopedEntryPtr entry =
752 CreateDiskCacheEntry(cache.get(), "test entry", kTestDiskCacheData);
753
754 // This tests mixed blob content with both synchronous and asynchronous
755 // construction. Blobs should also be paged to disk during execution.
756 std::vector<std::unique_ptr<BlobDataBuilder>> builders;
757 std::vector<size_t> sizes;
758 for (size_t i = 0; i < kTotalRawBlobs; i++) {
759 builders.emplace_back(new BlobDataBuilder(base::SizeTToString(i)));
760 auto& builder = *builders.back();
761 size_t size = AppendDataInBuilder(&builder, i, entry.get());
762 EXPECT_NE(0u, size);
763 sizes.push_back(size);
764 }
765
766 for (size_t i = 0; i < kTotalSlicedBlobs; i++) {
767 builders.emplace_back(
768 new BlobDataBuilder(base::SizeTToString(i + kTotalRawBlobs)));
769 size_t source_size = sizes[i];
770 size_t offset = source_size == 1 ? 0 : i % (source_size - 1);
771 size_t size = (i % (source_size - offset)) + 1;
772 builders.back()->AppendBlob(base::SizeTToString(i), offset, size);
773 }
774
775 size_t total_finished_blobs = 0;
776 std::vector<std::unique_ptr<BlobDataHandle>> handles;
777 std::vector<BlobStatus> statuses;
778 std::vector<bool> populated;
779 statuses.resize(kTotalRawBlobs,
780 BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS);
781 populated.resize(kTotalRawBlobs, false);
782 for (size_t i = 0; i < builders.size(); i++) {
783 BlobDataBuilder& builder = *builders[i];
784 builder.set_content_type("text/plain");
785 bool has_pending_memory = i < kTotalRawBlobs && (i % 2 != 0 || i % 3 == 0);
786 std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob(
787 builder,
788 has_pending_memory
789 ? base::Bind(&SaveBlobStatusAndFiles, &statuses[0] + i, &files_)
790 : BlobStorageContext::TransportAllowedCallback());
791 handle->RunOnConstructionComplete(
792 base::Bind(&IncrementNumber, &total_finished_blobs));
793 handles.push_back(std::move(handle));
794 }
795 base::RunLoop().RunUntilIdle();
796
797 // We should be needing to send a page or two to disk.
798 EXPECT_TRUE(file_runner_->HasPendingTask());
799 do {
800 file_runner_->RunPendingTasks();
801 base::RunLoop().RunUntilIdle();
802 // Continue populating data for items that can fit.
803 for (size_t i = 0; i < kTotalRawBlobs; i++) {
804 BlobDataBuilder* builder = builders[i].get();
805 bool has_pending_memory = DoesBuilderHaveFutureData(i);
806 if (has_pending_memory && !populated[i] &&
807 statuses[i] == BlobStatus::PENDING_TRANSPORT) {
808 PopulateDataInBuilder(builder, i, file_runner_.get());
809 context_->NotifyTransportComplete(base::SizeTToString(i));
810 populated[i] = true;
811 }
812 }
813 base::RunLoop().RunUntilIdle();
814 } while (file_runner_->HasPendingTask());
815
816 // Check all builders with future items were signalled and populated.
817 for (size_t i = 0; i < populated.size(); i++) {
818 bool has_pending_memory = DoesBuilderHaveFutureData(i);
819 if (has_pending_memory) {
820 EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, statuses[i]) << i;
821 EXPECT_TRUE(populated[i]) << i;
822 }
823 }
824 base::RunLoop().RunUntilIdle();
825
826 // We should be completely built now.
827 EXPECT_EQ(kTotalRawBlobs + kTotalSlicedBlobs, total_finished_blobs);
828 for (std::unique_ptr<BlobDataHandle>& handle : handles) {
829 EXPECT_EQ(BlobStatus::DONE, handle->GetBlobStatus());
830 }
831 handles.clear();
832 base::RunLoop().RunUntilIdle();
833 files_.clear();
834 // We should have file cleanup tasks.
835 EXPECT_TRUE(file_runner_->HasPendingTask());
836 file_runner_->RunPendingTasks();
837 base::RunLoop().RunUntilIdle();
838 EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
839 EXPECT_EQ(0lu, context_->memory_controller().disk_usage());
840 }
841
842 // TODO(michaeln): tests for the deprecated url stuff
843
844 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698