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

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

Issue 2516713002: [BlobStorage] Implementing disk. (Closed)
Patch Set: windows debugging & victor comments 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());
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 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 std::unique_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); 521 std::unique_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot();
505 EXPECT_EQ(*data, builder); 522 EXPECT_EQ(*data, builder);
506 EXPECT_FALSE(data_handle->HasOneRef()) 523 EXPECT_FALSE(data_handle->HasOneRef())
507 << "Data handle was destructed while context and builder still exist."; 524 << "Data handle was destructed while context and builder still exist.";
508 } 525 }
509 EXPECT_TRUE(data_handle->HasOneRef()) 526 EXPECT_TRUE(data_handle->HasOneRef())
510 << "Data handle was not destructed along with blob storage context."; 527 << "Data handle was not destructed along with blob storage context.";
511 base::RunLoop().RunUntilIdle(); 528 base::RunLoop().RunUntilIdle();
512 } 529 }
513 530
531 TEST_F(BlobStorageContextTest, BuildFutureFileOnlyBlob) {
532 const std::string kId1("id1");
533 context_ =
534 base::MakeUnique<BlobStorageContext>(temp_dir_.GetPath(), file_runner_);
535
536 BlobDataBuilder builder(kId1);
537 builder.set_content_type("text/plain");
538 builder.AppendFutureFile(0, 10, 0);
539
540 BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
541 std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob(
542 builder, base::Bind(&SaveBlobStatusAndFiles, &status, &files_));
543
544 size_t blobs_finished = 0;
545 EXPECT_EQ(BlobStatus::PENDING_QUOTA, handle->GetBlobStatus());
546 EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, status);
547 handle->RunOnConstructionComplete(
548 base::Bind(&IncrementNumber, &blobs_finished));
549 EXPECT_EQ(0u, blobs_finished);
550
551 EXPECT_TRUE(file_runner_->HasPendingTask());
552 file_runner_->RunPendingTasks();
553 EXPECT_EQ(0u, blobs_finished);
554 EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, status);
555 EXPECT_EQ(BlobStatus::PENDING_QUOTA, handle->GetBlobStatus());
556 base::RunLoop().RunUntilIdle();
557
558 EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, status);
559 EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, handle->GetBlobStatus());
560 EXPECT_EQ(0u, blobs_finished);
561
562 ASSERT_EQ(1u, files_.size());
563
564 builder.PopulateFutureFile(0, files_[0].file_reference, base::Time::Max());
565 context_->NotifyTransportComplete(kId1);
566
567 EXPECT_EQ(BlobStatus::DONE, handle->GetBlobStatus());
568 EXPECT_EQ(0u, blobs_finished);
569 base::RunLoop().RunUntilIdle();
570 EXPECT_EQ(1u, blobs_finished);
571 }
572
514 TEST_F(BlobStorageContextTest, CompoundBlobs) { 573 TEST_F(BlobStorageContextTest, CompoundBlobs) {
515 const std::string kId1("id1"); 574 const std::string kId1("id1");
516 const std::string kId2("id2"); 575 const std::string kId2("id2");
517 const std::string kId3("id3"); 576 const std::string kId3("id3");
518 577
519 // Setup a set of blob data for testing. 578 // Setup a set of blob data for testing.
520 base::Time time1, time2; 579 base::Time time1, time2;
521 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); 580 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1);
522 base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2); 581 base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2);
523 582
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 builder3.AppendData("data"); 707 builder3.AppendData("data");
649 builder3.AppendBlob(kBuildingId); 708 builder3.AppendBlob(kBuildingId);
650 handle = context_->AddFinishedBlob(builder3); 709 handle = context_->AddFinishedBlob(builder3);
651 EXPECT_TRUE(handle->IsBroken()); 710 EXPECT_TRUE(handle->IsBroken());
652 EXPECT_TRUE(context_->registry().HasEntry(kReferencingId)); 711 EXPECT_TRUE(context_->registry().HasEntry(kReferencingId));
653 handle.reset(); 712 handle.reset();
654 base::RunLoop().RunUntilIdle(); 713 base::RunLoop().RunUntilIdle();
655 EXPECT_FALSE(context_->registry().HasEntry(kReferencingId)); 714 EXPECT_FALSE(context_->registry().HasEntry(kReferencingId));
656 } 715 }
657 716
658 // TODO(michaeln): tests for the depcrecated url stuff 717 namespace {
718 constexpr size_t kTotalRawBlobs = 200;
719 constexpr size_t kTotalSlicedBlobs = 100;
720 constexpr char kTestDiskCacheData[] = "Test Blob Data";
659 721
660 } // namespace content 722 // Appends data and data types that depend on the index. This is designed to
723 // exercise all types of combinations of data, future data, files, future files,
724 // and disk cache entries.
725 size_t AppendDataInBuilder(BlobDataBuilder* builder,
726 size_t index,
727 disk_cache::Entry* cache_entry) {
728 size_t size = 0;
729 // We can't have both future data and future files, so split those up.
730 if (index % 2 != 0) {
731 builder->AppendFutureData(5u);
732 size += 5u;
733 if (index % 3 == 1) {
734 builder->AppendData("abcdefghij", 4u);
735 size += 4u;
736 }
737 if (index % 3 == 0) {
738 builder->AppendFutureData(1u);
739 size += 1u;
740 }
741 } else if (index % 3 == 0) {
742 builder->AppendFutureFile(0lu, 3lu, 0);
743 size += 3u;
744 }
745 if (index % 5 != 0) {
746 builder->AppendFile(
747 base::FilePath::FromUTF8Unsafe(base::SizeTToString(index)), 0ul, 20ul,
748 base::Time::Max());
749 size += 20u;
750 }
751 if (index % 3 != 0) {
752 scoped_refptr<BlobDataBuilder::DataHandle> disk_cache_data_handle =
753 new EmptyDataHandle();
754 builder->AppendDiskCacheEntry(disk_cache_data_handle, cache_entry,
755 kTestDiskCacheStreamIndex);
756 size += strlen(kTestDiskCacheData);
757 }
758 return size;
759 }
760
761 bool DoesBuilderHaveFutureData(size_t index) {
762 return (index % 2 != 0 || index % 3 == 0);
763 }
764
765 void PopulateDataInBuilder(BlobDataBuilder* builder,
766 size_t index,
767 base::TaskRunner* file_runner) {
768 if (index % 2 != 0) {
769 builder->PopulateFutureData(0, "abcde", 0, 5);
770 if (index % 3 == 0) {
771 builder->PopulateFutureData(1, "z", 0, 1);
772 }
773 } else if (index % 3 == 0) {
774 scoped_refptr<ShareableFileReference> file_ref =
775 ShareableFileReference::GetOrCreate(
776 base::FilePath::FromUTF8Unsafe(
777 base::SizeTToString(index + kTotalRawBlobs)),
778 ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE, file_runner);
779 builder->PopulateFutureFile(0, file_ref, base::Time::Max());
780 }
781 }
782 } // namespace
783
784 TEST_F(BlobStorageContextTest, BuildBlobCombinations) {
785 const std::string kId("id");
786
787 context_ =
788 base::MakeUnique<BlobStorageContext>(temp_dir_.GetPath(), file_runner_);
789
790 SetTestMemoryLimits();
791 std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
792 ASSERT_TRUE(cache);
793 disk_cache::ScopedEntryPtr entry =
794 CreateDiskCacheEntry(cache.get(), "test entry", kTestDiskCacheData);
795
796 // This tests mixed blob content with both synchronous and asynchronous
797 // construction. Blobs should also be paged to disk during execution.
798 std::vector<std::unique_ptr<BlobDataBuilder>> builders;
799 std::vector<size_t> sizes;
800 for (size_t i = 0; i < kTotalRawBlobs; i++) {
801 builders.emplace_back(new BlobDataBuilder(base::SizeTToString(i)));
802 auto& builder = *builders.back();
803 size_t size = AppendDataInBuilder(&builder, i, entry.get());
804 EXPECT_NE(0u, size);
805 sizes.push_back(size);
806 }
807
808 for (size_t i = 0; i < kTotalSlicedBlobs; i++) {
809 builders.emplace_back(
810 new BlobDataBuilder(base::SizeTToString(i + kTotalRawBlobs)));
811 size_t source_size = sizes[i];
812 size_t offset = source_size == 1 ? 0 : i % (source_size - 1);
813 size_t size = (i % (source_size - offset)) + 1;
814 builders.back()->AppendBlob(base::SizeTToString(i), offset, size);
815 }
816
817 size_t total_finished_blobs = 0;
818 std::vector<std::unique_ptr<BlobDataHandle>> handles;
819 std::vector<BlobStatus> statuses;
820 std::vector<bool> populated;
821 statuses.resize(kTotalRawBlobs,
822 BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS);
823 populated.resize(kTotalRawBlobs, false);
824 for (size_t i = 0; i < builders.size(); i++) {
825 BlobDataBuilder& builder = *builders[i];
826 builder.set_content_type("text/plain");
827 bool has_pending_memory = i < kTotalRawBlobs && (i % 2 != 0 || i % 3 == 0);
kinuko 2016/12/02 08:52:32 && DoesBuilderHaveFutureData(i)
dmurph 2016/12/02 21:53:07 Done.
828 std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob(
829 builder,
830 has_pending_memory
831 ? base::Bind(&SaveBlobStatusAndFiles, &statuses[0] + i, &files_)
832 : BlobStorageContext::TransportAllowedCallback());
833 handle->RunOnConstructionComplete(
834 base::Bind(&IncrementNumber, &total_finished_blobs));
835 handles.push_back(std::move(handle));
836 }
837 base::RunLoop().RunUntilIdle();
838
839 // We should be needing to send a page or two to disk.
840 EXPECT_TRUE(file_runner_->HasPendingTask());
841 do {
842 file_runner_->RunPendingTasks();
843 base::RunLoop().RunUntilIdle();
844 // Continue populating data for items that can fit.
845 for (size_t i = 0; i < kTotalRawBlobs; i++) {
846 BlobDataBuilder* builder = builders[i].get();
847 bool has_pending_memory = DoesBuilderHaveFutureData(i);
848 if (has_pending_memory && !populated[i] &&
kinuko 2016/12/02 08:52:32 nit: can just write like 'if (DoesBuilderHaveFutur
dmurph 2016/12/02 21:53:07 Done.
849 statuses[i] == BlobStatus::PENDING_TRANSPORT) {
850 PopulateDataInBuilder(builder, i, file_runner_.get());
851 context_->NotifyTransportComplete(base::SizeTToString(i));
852 populated[i] = true;
853 }
854 }
855 base::RunLoop().RunUntilIdle();
856 } while (file_runner_->HasPendingTask());
857
858 // Check all builders with future items were signalled and populated.
859 for (size_t i = 0; i < populated.size(); i++) {
860 bool has_pending_memory = DoesBuilderHaveFutureData(i);
861 if (has_pending_memory) {
kinuko 2016/12/02 08:52:32 nit: can just write like 'if (DoesBuilderHaveFutur
dmurph 2016/12/02 21:53:07 Done.
862 EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, statuses[i]) << i;
863 EXPECT_TRUE(populated[i]) << i;
864 }
865 }
866 base::RunLoop().RunUntilIdle();
867
868 // We should be completely built now.
869 EXPECT_EQ(kTotalRawBlobs + kTotalSlicedBlobs, total_finished_blobs);
870 for (std::unique_ptr<BlobDataHandle>& handle : handles) {
871 EXPECT_EQ(BlobStatus::DONE, handle->GetBlobStatus());
872 }
873 handles.clear();
874 base::RunLoop().RunUntilIdle();
875 files_.clear();
876 // We should have file cleanup tasks.
877 EXPECT_TRUE(file_runner_->HasPendingTask());
878 file_runner_->RunPendingTasks();
879 base::RunLoop().RunUntilIdle();
880 EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
881 EXPECT_EQ(0lu, context_->memory_controller().disk_usage());
882 }
883
884 // TODO(michaeln): tests for the deprecated url stuff
885
886 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698