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

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

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

Powered by Google App Engine
This is Rietveld 408576698