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

Unified Diff: content/browser/blob_storage/blob_memory_controller_unittest.cc

Issue 2552153002: [BlobStorage] Enabling disk paging and direct storage. (Closed)
Patch Set: Added an early-exit clause so files don't get created unnecessarily 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/blob_storage/blob_memory_controller_unittest.cc
diff --git a/content/browser/blob_storage/blob_memory_controller_unittest.cc b/content/browser/blob_storage/blob_memory_controller_unittest.cc
index ae0e796c5e34ea4fb555ab52b32889cf6f736503..0876d5817f56c35ead019ac77d5fdeebdba344e1 100644
--- a/content/browser/blob_storage/blob_memory_controller_unittest.cc
+++ b/content/browser/blob_storage/blob_memory_controller_unittest.cc
@@ -34,6 +34,8 @@ const uint64_t kTestBlobStorageMaxDiskSpace = 1000;
const uint64_t kTestBlobStorageMinFileSizeBytes = 10;
const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
+const uint64_t kTestSmallBlobStorageMaxDiskSpace = 100;
+
class BlobMemoryControllerTest : public testing::Test {
protected:
BlobMemoryControllerTest() {}
@@ -74,6 +76,17 @@ class BlobMemoryControllerTest : public testing::Test {
controller->set_limits_for_testing(limits);
}
+ void SetSmallDiskTestMemoryLimits(BlobMemoryController* controller) {
+ BlobStorageLimits limits;
+ limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
+ limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
+ limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
+ limits.max_blob_disk_space = kTestSmallBlobStorageMaxDiskSpace;
+ limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
+ limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
+ controller->set_limits_for_testing(limits);
+ }
+
void SaveFileCreationInfo(std::vector<FileCreationInfo> info, bool success) {
file_quota_result_ = success;
if (success) {
@@ -81,6 +94,10 @@ class BlobMemoryControllerTest : public testing::Test {
}
}
+ void SaveMemoryRequestToOutput(bool* output, bool success) {
+ ASSERT_TRUE(output);
+ *output = success;
+ }
void SaveMemoryRequest(bool success) { memory_quota_result_ = success; }
BlobMemoryController::FileQuotaRequestCallback GetFileCreationCallback() {
@@ -93,6 +110,12 @@ class BlobMemoryControllerTest : public testing::Test {
base::Unretained(this));
}
+ BlobMemoryController::MemoryQuotaRequestCallback
+ GetMemoryRequestCallbackToOutput(bool* output) {
+ return base::Bind(&BlobMemoryControllerTest::SaveMemoryRequestToOutput,
+ base::Unretained(this), output);
+ }
+
void RunFileThreadTasks() {
base::ThreadRestrictions::SetIOAllowed(true);
file_runner_->RunPendingTasks();
@@ -159,6 +182,16 @@ TEST_F(BlobMemoryControllerTest, Strategy) {
EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(
0, kTestBlobStorageMaxDiskSpace + 1));
}
+ {
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetSmallDiskTestMemoryLimits(&controller);
+
+ EXPECT_TRUE(controller.CanReserveQuota(kTestBlobStorageMaxBlobMemorySize));
+ // Since our disk is too small, this should be sent with shared memory.
+ EXPECT_EQ(
+ Strategy::SHARED_MEMORY,
+ controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize));
+ }
}
TEST_F(BlobMemoryControllerTest, GrantMemory) {
@@ -281,7 +314,6 @@ TEST_F(BlobMemoryControllerTest, PageToDisk) {
}
TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) {
- const std::string kId = "id";
BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
SetTestMemoryLimits(&controller);
@@ -291,7 +323,6 @@ TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) {
}
TEST_F(BlobMemoryControllerTest, TooLargeForDisk) {
- const std::string kId = "id";
BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
SetTestMemoryLimits(&controller);
@@ -594,6 +625,135 @@ TEST_F(BlobMemoryControllerTest, FullEviction) {
EXPECT_TRUE(memory_quota_result_);
}
+TEST_F(BlobMemoryControllerTest, PagingStopsWhenFull) {
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+ const size_t kTotalBlobStorageSize =
+ kTestBlobStorageMaxDiskSpace + kTestBlobStorageMaxBlobMemorySize;
+
+ const size_t kDataSize = 10u;
+ const size_t kBlobsThatCanFit = kTotalBlobStorageSize / kDataSize;
+ const size_t kNumFastBlobs = kTestBlobStorageMaxBlobMemorySize / kDataSize;
+ char kData[10];
+ memset(kData, 'e', kDataSize);
+
+ // Create all of our blobs.
+ std::vector<scoped_refptr<ShareableBlobDataItem>> all_items;
+ std::vector<base::WeakPtr<QuotaAllocationTask>> memory_tasks;
+ bool memory_requested[kBlobsThatCanFit] = {};
+ for (size_t i = 0; i < kBlobsThatCanFit; i++) {
+ BlobDataBuilder builder("fake");
+ builder.AppendData(kData, kDataSize);
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+ EXPECT_TRUE(controller.CanReserveQuota(kDataSize));
+ EXPECT_EQ((i < kNumFastBlobs) ? Strategy::NONE_NEEDED : Strategy::IPC,
+ controller.DetermineStrategy(kDataSize, kDataSize))
+ << i;
+ base::WeakPtr<QuotaAllocationTask> memory_task =
+ controller.ReserveMemoryQuota(
+ items, GetMemoryRequestCallbackToOutput(memory_requested + i));
+ if (memory_task) {
+ memory_tasks.push_back(std::move(memory_task));
+ }
+ all_items.insert(all_items.end(), items.begin(), items.end());
+ }
+ // We should have stored all of our memory quota, and no disk yet.
+ EXPECT_EQ(500u, controller.memory_usage());
+ EXPECT_EQ(0ull, controller.disk_usage());
+
+ EXPECT_FALSE(controller.CanReserveQuota(1u));
+ EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(1u, 1ull));
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+
+ for (size_t i = 0; i < kBlobsThatCanFit; i++) {
+ // Note: this can fail if the bot's disk is almost full.
+ EXPECT_EQ(i < kBlobsThatCanFit / 3, memory_requested[i]) << i;
+ if (memory_requested[i] &&
+ all_items[i]->state() != ItemState::POPULATED_WITH_QUOTA) {
+ EXPECT_TRUE(memory_requested[i]);
+ all_items[i]->set_state(ItemState::POPULATED_WITH_QUOTA);
+ std::vector<scoped_refptr<ShareableBlobDataItem>> temp_vector;
+ temp_vector.push_back(all_items[i]);
+ controller.NotifyMemoryItemsUsed(temp_vector);
+ }
+ }
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+
+ // This will schedule one task. Paging starts as soon as there is enough
+ // memory to page, and multiple pagings can't happen at the same time.
+ EXPECT_EQ(10ull, controller.disk_usage());
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ // The rest of the tasks should be scheduled.
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ // Everything in memory should be on disk, and next batch of memory items
+ // should be granted.
+ EXPECT_EQ(500u, controller.memory_usage());
+ EXPECT_EQ(500ull, controller.disk_usage());
+
+ // Still can't add anything.
+ EXPECT_FALSE(controller.CanReserveQuota(1u));
+ EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(1u, 1ull));
+
+ // Flag next batch for saving to disk.
+ for (size_t i = 0; i < kBlobsThatCanFit; i++) {
+ // Note: this can fail if the bot's disk is almost full.
+ EXPECT_EQ(i < kBlobsThatCanFit * 2 / 3, memory_requested[i]) << i;
+ if (memory_requested[i] &&
+ all_items[i]->state() != ItemState::POPULATED_WITH_QUOTA) {
+ all_items[i]->set_state(ItemState::POPULATED_WITH_QUOTA);
+ std::vector<scoped_refptr<ShareableBlobDataItem>> temp_vector;
+ temp_vector.push_back(all_items[i]);
+ controller.NotifyMemoryItemsUsed(temp_vector);
+ }
+ }
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+
+ // Same as before. One page task is scheduled, so run them twice.
+ EXPECT_EQ(510ull, controller.disk_usage());
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ // We page one time first, as it blocks paging once it starts.
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+
+ // All quota should be allocated.
+ EXPECT_EQ(500u, controller.memory_usage());
+ EXPECT_EQ(1000ull, controller.disk_usage());
+
+ // Still can't add anything.
+ EXPECT_FALSE(controller.CanReserveQuota(1u));
+ EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(1u, 1ull));
+
+ // Flag last batch as populated.
+ for (size_t i = 0; i < kBlobsThatCanFit; i++) {
+ // Note: this can fail if the bot's disk is almost full.
+ EXPECT_TRUE(memory_requested[i]);
+ if (memory_requested[i] &&
+ all_items[i]->state() != ItemState::POPULATED_WITH_QUOTA) {
+ all_items[i]->set_state(ItemState::POPULATED_WITH_QUOTA);
+ std::vector<scoped_refptr<ShareableBlobDataItem>> temp_vector;
+ temp_vector.push_back(all_items[i]);
+ controller.NotifyMemoryItemsUsed(temp_vector);
+ }
+ }
+
+ // There should be no more paging to disk, as we've reached the end.
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+
+ // All quota should be allocated still.
+ EXPECT_EQ(500u, controller.memory_usage());
+ EXPECT_EQ(1000ull, controller.disk_usage());
+
+ // Still can't add anything.
+ EXPECT_FALSE(controller.CanReserveQuota(1u));
+ EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(1u, 1ull));
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+}
+
TEST_F(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) {
const std::string kFirstMemoryId = "id";
const uint64_t kFirstMemorySize = kTestBlobStorageMaxBlobMemorySize;

Powered by Google App Engine
This is Rietveld 408576698