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

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

Issue 2339933004: [BlobStorage] BlobMemoryController & tests (Closed)
Patch Set: Fixed windows bug! Created 4 years, 2 months 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
« no previous file with comments | « content/browser/blob_storage/blob_data_builder_unittest.cc ('k') | content/test/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "storage/browser/blob/blob_memory_controller.h"
6
7 #include "base/bind.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/test/test_simple_task_runner.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "storage/browser/blob/blob_data_builder.h"
16 #include "storage/browser/blob/blob_data_item.h"
17 #include "storage/browser/blob/shareable_blob_data_item.h"
18 #include "storage/common/data_element.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace storage {
22
23 using Strategy = BlobMemoryController::Strategy;
24 using FileCreationInfo = BlobMemoryController::FileCreationInfo;
25 using base::TestSimpleTaskRunner;
26 using ItemState = ShareableBlobDataItem::State;
27 using QuotaAllocationTask = BlobMemoryController::QuotaAllocationTask;
28
29 const std::string kBlobStorageDirectory = "blob_storage";
30 const size_t kTestBlobStorageIPCThresholdBytes = 20;
31 const size_t kTestBlobStorageMaxSharedMemoryBytes = 50;
32 const size_t kTestBlobStorageMaxBlobMemorySize = 500;
33 const uint64_t kTestBlobStorageMaxDiskSpace = 1000;
34 const uint64_t kTestBlobStorageMinFileSizeBytes = 10;
35 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
36
37 class BlobMemoryControllerTest : public testing::Test {
38 protected:
39 BlobMemoryControllerTest() {}
40
41 void SetUp() override {
42 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
43 base::ThreadRestrictions::SetIOAllowed(false);
44 };
45
46 void TearDown() override {
47 files_created_.clear();
48 // Make sure we clean up the files.
49 base::RunLoop().RunUntilIdle();
50 RunFileThreadTasks();
51 base::RunLoop().RunUntilIdle();
52 base::ThreadRestrictions::SetIOAllowed(true);
53 ASSERT_TRUE(temp_dir_.Delete());
54 }
55
56 std::vector<scoped_refptr<ShareableBlobDataItem>> CreateSharedDataItems(
57 const BlobDataBuilder& builder) {
58 std::vector<scoped_refptr<ShareableBlobDataItem>> result;
59 for (size_t i = 0; i < builder.items_.size(); ++i) {
60 result.push_back(make_scoped_refptr(
61 new ShareableBlobDataItem(builder.uuid(), builder.items_[i],
62 ShareableBlobDataItem::QUOTA_NEEDED)));
63 }
64 return result;
65 }
66
67 void SetTestMemoryLimits(BlobMemoryController* controller) {
68 BlobStorageLimits limits;
69 limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
70 limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
71 limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
72 limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace;
73 limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
74 limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
75 controller->set_limits_for_testing(limits);
76 }
77
78 void SaveFileCreationInfo(bool success, std::vector<FileCreationInfo> info) {
79 file_quota_result_ = success;
80 if (success) {
81 files_created_.swap(info);
82 }
83 }
84
85 void SaveMemoryRequest(bool success) { memory_quota_result_ = success; }
86
87 BlobMemoryController::FileQuotaRequestCallback GetFileCreationCallback() {
88 return base::Bind(&BlobMemoryControllerTest::SaveFileCreationInfo,
89 base::Unretained(this));
90 }
91
92 BlobMemoryController::MemoryQuotaRequestCallback GetMemoryRequestCallback() {
93 return base::Bind(&BlobMemoryControllerTest::SaveMemoryRequest,
94 base::Unretained(this));
95 }
96
97 void RunFileThreadTasks() {
98 base::ThreadRestrictions::SetIOAllowed(true);
99 file_runner_->RunPendingTasks();
100 base::ThreadRestrictions::SetIOAllowed(false);
101 }
102
103 bool HasMemoryAllocation(ShareableBlobDataItem* item) {
104 return static_cast<bool>(item->memory_allocation_);
105 }
106
107 bool file_quota_result_ = false;
108 base::ScopedTempDir temp_dir_;
109 std::vector<FileCreationInfo> files_created_;
110 bool memory_quota_result_ = false;
111
112 scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner();
113
114 base::MessageLoop fake_io_message_loop_;
115 };
116
117 TEST_F(BlobMemoryControllerTest, Strategy) {
118 {
119 BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
120 SetTestMemoryLimits(&controller);
121
122 // No transportation needed.
123 EXPECT_EQ(Strategy::NONE_NEEDED, controller.DetermineStrategy(0, 0));
124
125 // IPC.
126 EXPECT_EQ(Strategy::IPC, controller.DetermineStrategy(
127 0, kTestBlobStorageIPCThresholdBytes));
128
129 // Shared Memory.
130 EXPECT_EQ(
131 Strategy::SHARED_MEMORY,
132 controller.DetermineStrategy(kTestBlobStorageIPCThresholdBytes,
133 kTestBlobStorageMaxSharedMemoryBytes));
134 EXPECT_EQ(
135 Strategy::SHARED_MEMORY,
136 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize));
137
138 // Too large.
139 EXPECT_EQ(
140 Strategy::TOO_LARGE,
141 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize + 1));
142 }
143 {
144 // Enable disk, and check file strategies.
145 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
146 SetTestMemoryLimits(&controller);
147
148 EXPECT_EQ(
149 Strategy::SHARED_MEMORY,
150 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize -
151 kTestBlobStorageMinFileSizeBytes));
152 EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
153 0, kTestBlobStorageMaxBlobMemorySize -
154 kTestBlobStorageMinFileSizeBytes + 1));
155
156 EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
157 0, kTestBlobStorageMaxBlobMemorySize));
158
159 // Too large for disk.
160 EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(
161 0, kTestBlobStorageMaxDiskSpace + 1));
162 }
163 }
164
165 TEST_F(BlobMemoryControllerTest, GrantMemory) {
166 const std::string kId = "id";
167 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
168 SetTestMemoryLimits(&controller);
169
170 BlobDataBuilder builder(kId);
171 builder.AppendFutureData(10);
172 builder.AppendFutureData(20);
173 builder.AppendFutureData(30);
174
175 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
176 CreateSharedDataItems(builder);
177
178 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
179 EXPECT_TRUE(memory_quota_result_);
180 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
181 EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
182 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[1]->state());
183 EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
184 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[2]->state());
185 EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
186 }
187
188 TEST_F(BlobMemoryControllerTest, SimpleMemoryRequest) {
189 const std::string kId = "id";
190 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
191 SetTestMemoryLimits(&controller);
192
193 // Add memory item that is the memory quota.
194 BlobDataBuilder builder(kId);
195 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
196
197 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
198 CreateSharedDataItems(builder);
199
200 base::WeakPtr<QuotaAllocationTask> task =
201 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
202 EXPECT_EQ(nullptr, task);
203 EXPECT_TRUE(memory_quota_result_);
204 memory_quota_result_ = false;
205 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
206 EXPECT_FALSE(file_runner_->HasPendingTask());
207 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
208 EXPECT_EQ(0u, controller.disk_usage());
209
210 items.clear();
211 EXPECT_EQ(0u, controller.memory_usage());
212 }
213
214 TEST_F(BlobMemoryControllerTest, PageToDisk) {
215 const std::string kId = "id";
216 const std::string kId2 = "id2";
217 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
218 SetTestMemoryLimits(&controller);
219
220 char kData[kTestBlobStorageMaxBlobMemorySize];
221 std::memset(kData, kTestBlobStorageMaxBlobMemorySize, 'e');
222
223 // Add memory item that is the memory quota.
224 BlobDataBuilder builder(kId);
225 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
226
227 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
228 CreateSharedDataItems(builder);
229
230 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
231 EXPECT_TRUE(memory_quota_result_);
232 memory_quota_result_ = false;
233 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
234 EXPECT_FALSE(file_runner_->HasPendingTask());
235 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
236 EXPECT_EQ(0u, controller.disk_usage());
237
238 // Create an item that is just a little too big.
239 BlobDataBuilder builder2(kId2);
240 builder2.AppendFutureData(kTestBlobStorageMinFileSizeBytes + 1);
241
242 // Reserve memory, which should request successfuly but we can't fit it yet
243 // (no callback).
244 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
245 CreateSharedDataItems(builder2);
246 base::WeakPtr<QuotaAllocationTask> task =
247 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
248 EXPECT_NE(nullptr, task);
249 // We don't count the usage yet.
250 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
251 EXPECT_EQ(0u, controller.disk_usage());
252
253 EXPECT_FALSE(memory_quota_result_);
254 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
255 EXPECT_FALSE(file_runner_->HasPendingTask());
256
257 // Add our original item as populated so it's paged to disk.
258 items[0]->item()->data_element_ptr()->SetToBytes(
259 kData, kTestBlobStorageMaxBlobMemorySize);
260 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
261 controller.NotifyMemoryItemsUsed(items);
262
263 EXPECT_TRUE(file_runner_->HasPendingTask());
264 RunFileThreadTasks();
265 base::RunLoop().RunUntilIdle();
266 // items2 are successfuly allocated.
267 EXPECT_EQ(nullptr, task);
268 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
269 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
270 EXPECT_EQ(kTestBlobStorageMinFileSizeBytes + 1, controller.memory_usage());
271 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
272
273 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
274
275 items2.clear();
276 EXPECT_EQ(0u, controller.memory_usage());
277 items.clear();
278 EXPECT_TRUE(file_runner_->HasPendingTask());
279 RunFileThreadTasks();
280 base::RunLoop().RunUntilIdle();
281 EXPECT_EQ(0u, controller.disk_usage());
282 }
283
284 TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) {
285 const std::string kId = "id";
286 BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
287 SetTestMemoryLimits(&controller);
288
289 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxBlobMemorySize +
290 kTestBlobStorageMinFileSizeBytes +
291 1));
292 }
293
294 TEST_F(BlobMemoryControllerTest, TooLargeForDisk) {
295 const std::string kId = "id";
296 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
297 SetTestMemoryLimits(&controller);
298
299 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace + 1));
300 }
301
302 TEST_F(BlobMemoryControllerTest, CancelMemoryRequest) {
303 const std::string kId = "id";
304 const std::string kId2 = "id2";
305 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
306 SetTestMemoryLimits(&controller);
307
308 char kData[kTestBlobStorageMaxBlobMemorySize];
309 std::memset(kData, kTestBlobStorageMaxBlobMemorySize, 'e');
310
311 // Add memory item that is the memory quota.
312 BlobDataBuilder builder(kId);
313 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
314
315 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
316 CreateSharedDataItems(builder);
317
318 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
319
320 // Create an item that is just a little too big.
321 BlobDataBuilder builder2(kId2);
322 builder2.AppendFutureData(kTestBlobStorageMinFileSizeBytes + 1);
323
324 // Reserve memory, which should request successfuly but we can't fit it yet
325 // (no callback).
326 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
327 CreateSharedDataItems(builder2);
328 base::WeakPtr<QuotaAllocationTask> task =
329 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
330 // We don't count the usage yet.
331 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
332 EXPECT_EQ(0u, controller.disk_usage());
333
334 // Add our original item as populated so we start paging to disk.
335 items[0]->item()->data_element_ptr()->SetToBytes(
336 kData, kTestBlobStorageMaxBlobMemorySize);
337 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
338 controller.NotifyMemoryItemsUsed(items);
339
340 EXPECT_TRUE(file_runner_->HasPendingTask());
341 EXPECT_TRUE(task);
342
343 task->Cancel();
344 EXPECT_FALSE(task);
345 RunFileThreadTasks();
346 base::RunLoop().RunUntilIdle();
347 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
348 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
349 EXPECT_EQ(0u, controller.memory_usage());
350 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
351
352 items.clear();
353 // Run cleanup tasks from the ShareableFileReferences.
354 base::RunLoop().RunUntilIdle();
355 RunFileThreadTasks();
356 base::RunLoop().RunUntilIdle();
357
358 EXPECT_EQ(0u, controller.disk_usage());
359 }
360
361 TEST_F(BlobMemoryControllerTest, FileRequest) {
362 const std::string kId = "id";
363 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
364
365 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
366 SetTestMemoryLimits(&controller);
367
368 char kData[kBlobSize];
369 std::memset(kData, kBlobSize, 'e');
370
371 // Add item that is the file quota.
372 BlobDataBuilder builder(kId);
373 builder.AppendFutureFile(0, kBlobSize, 0);
374
375 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
376 CreateSharedDataItems(builder);
377
378 file_quota_result_ = false;
379 base::WeakPtr<QuotaAllocationTask> task =
380 controller.ReserveFileQuota(items, GetFileCreationCallback());
381 EXPECT_TRUE(task);
382 EXPECT_FALSE(file_quota_result_);
383 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
384 EXPECT_TRUE(file_runner_->HasPendingTask());
385 EXPECT_EQ(0u, controller.memory_usage());
386 EXPECT_EQ(kBlobSize, controller.disk_usage());
387
388 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
389
390 RunFileThreadTasks();
391 base::RunLoop().RunUntilIdle();
392 EXPECT_TRUE(file_quota_result_);
393 EXPECT_FALSE(file_runner_->HasPendingTask());
394 EXPECT_FALSE(task);
395
396 // Do the work to populate the file.
397 EXPECT_EQ(1u, files_created_.size());
398 EXPECT_TRUE(
399 builder.PopulateFutureFile(0, std::move(files_created_[0].file_reference),
400 files_created_[0].last_modified));
401 base::ThreadRestrictions::SetIOAllowed(true);
402 files_created_.clear();
403 base::ThreadRestrictions::SetIOAllowed(false);
404 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
405 EXPECT_FALSE(
406 BlobDataBuilder::IsFutureFileItem(items[0]->item()->data_element()));
407
408 builder.Clear();
409 items.clear();
410 // Run cleanup tasks from the ShareableFileReferences.
411 base::RunLoop().RunUntilIdle();
412 RunFileThreadTasks();
413 base::RunLoop().RunUntilIdle();
414
415 EXPECT_EQ(0u, controller.disk_usage());
416 }
417
418 TEST_F(BlobMemoryControllerTest, CancelFileRequest) {
419 const std::string kId = "id";
420 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
421
422 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
423 SetTestMemoryLimits(&controller);
424
425 char kData[kBlobSize];
426 std::memset(kData, kBlobSize, 'e');
427
428 // Add memory item that is the memory quota.
429 BlobDataBuilder builder(kId);
430 builder.AppendFutureFile(0, kBlobSize, 0);
431
432 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
433 CreateSharedDataItems(builder);
434
435 base::WeakPtr<QuotaAllocationTask> task =
436 controller.ReserveFileQuota(items, GetFileCreationCallback());
437 EXPECT_TRUE(task);
438 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
439 EXPECT_TRUE(file_runner_->HasPendingTask());
440 EXPECT_EQ(0u, controller.memory_usage());
441 EXPECT_EQ(kBlobSize, controller.disk_usage());
442
443 task->Cancel();
444 EXPECT_FALSE(task);
445 EXPECT_EQ(kBlobSize, controller.disk_usage());
446 EXPECT_TRUE(file_runner_->HasPendingTask());
447 RunFileThreadTasks();
448 base::RunLoop().RunUntilIdle();
449 EXPECT_EQ(0u, controller.disk_usage());
450 }
451
452 TEST_F(BlobMemoryControllerTest, MultipleFilesPaged) {
453 const std::string kId1 = "id";
454 const size_t kSize1 = kTestBlobStorageMaxFileSizeBytes;
455 char kData1[kSize1];
456 std::memset(kData1, 'e', kSize1);
457
458 const std::string kId2 = "id2";
459 const size_t kSize2 = kTestBlobStorageMaxFileSizeBytes;
460 char kData2[kSize2];
461 std::memset(kData2, 'f', kSize2);
462
463 const std::string kId3 = "id3";
464 const size_t kSize3 = kTestBlobStorageMaxBlobMemorySize - 1;
465
466 // Assert we shouldn't trigger paging preemptively.
467 ASSERT_LE(kSize1 + kSize2, kTestBlobStorageMaxBlobMemorySize);
468
469 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
470 SetTestMemoryLimits(&controller);
471
472 // We add two items that should be their own files when we page to disk, and
473 // then add the last item to trigger the paging.
474
475 BlobDataBuilder builder1(kId1);
476 builder1.AppendFutureData(kSize1);
477 BlobDataBuilder builder2(kId2);
478 builder2.AppendFutureData(kSize2);
479
480 std::vector<scoped_refptr<ShareableBlobDataItem>> items1 =
481 CreateSharedDataItems(builder1);
482 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
483 CreateSharedDataItems(builder2);
484
485 memory_quota_result_ = false;
486 controller.ReserveMemoryQuota(items1, GetMemoryRequestCallback());
487 EXPECT_TRUE(memory_quota_result_);
488 memory_quota_result_ = false;
489 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
490 EXPECT_TRUE(memory_quota_result_);
491 EXPECT_EQ(ItemState::QUOTA_GRANTED, items1[0]->state());
492 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
493 EXPECT_FALSE(file_runner_->HasPendingTask());
494 EXPECT_EQ(kSize1 + kSize2, controller.memory_usage());
495 EXPECT_EQ(0u, controller.disk_usage());
496
497 // Create an item that is too big.
498 BlobDataBuilder builder3(kId3);
499 builder3.AppendFutureData(kSize3);
500
501 std::vector<scoped_refptr<ShareableBlobDataItem>> items3 =
502 CreateSharedDataItems(builder3);
503 memory_quota_result_ = false;
504 controller.ReserveMemoryQuota(items3, GetMemoryRequestCallback());
505 EXPECT_FALSE(memory_quota_result_);
506
507 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items3[0]->state());
508 EXPECT_FALSE(file_runner_->HasPendingTask());
509
510 // Add our original item as populated so it's paged to disk.
511 items1[0]->item()->data_element_ptr()->SetToBytes(kData1, kSize1);
512 items1[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
513 items2[0]->item()->data_element_ptr()->SetToBytes(kData2, kSize2);
514 items2[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
515
516 std::vector<scoped_refptr<ShareableBlobDataItem>> both_items = {items1[0],
517 items2[0]};
518 controller.NotifyMemoryItemsUsed(both_items);
519 both_items.clear();
520
521 EXPECT_TRUE(file_runner_->HasPendingTask());
522 RunFileThreadTasks();
523 base::RunLoop().RunUntilIdle();
524 EXPECT_TRUE(memory_quota_result_);
525 EXPECT_EQ(ItemState::QUOTA_GRANTED, items3[0]->state());
526 EXPECT_EQ(DataElement::TYPE_FILE, items1[0]->item()->type());
527 EXPECT_EQ(DataElement::TYPE_FILE, items2[0]->item()->type());
528 EXPECT_NE(items1[0]->item()->path(), items2[0]->item()->path());
529 EXPECT_EQ(kSize3, controller.memory_usage());
530 EXPECT_EQ(kSize1 + kSize2, controller.disk_usage());
531
532 items1.clear();
533 items2.clear();
534 items3.clear();
535
536 EXPECT_EQ(0u, controller.memory_usage());
537 base::RunLoop().RunUntilIdle();
538 EXPECT_TRUE(file_runner_->HasPendingTask());
539 RunFileThreadTasks();
540 base::RunLoop().RunUntilIdle();
541 EXPECT_EQ(0u, controller.disk_usage());
542 }
543
544 TEST_F(BlobMemoryControllerTest, FullEviction) {
545 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
546 SetTestMemoryLimits(&controller);
547
548 char kData[1];
549 kData[0] = 'e';
550
551 // Create a bunch of small stuff.
552 std::vector<scoped_refptr<ShareableBlobDataItem>> small_items;
553 for (size_t i = 0;
554 i < kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes;
555 i++) {
556 BlobDataBuilder builder("fake");
557 builder.AppendData(kData, 1);
558 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
559 CreateSharedDataItems(builder);
560 base::WeakPtr<QuotaAllocationTask> memory_task =
561 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
562 EXPECT_FALSE(memory_task);
563 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
564 small_items.insert(small_items.end(), items.begin(), items.end());
565 }
566 controller.NotifyMemoryItemsUsed(small_items);
567 EXPECT_FALSE(file_runner_->HasPendingTask());
568 EXPECT_EQ(
569 kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes,
570 controller.memory_usage());
571
572 // Create maximum size blob to evict ALL small stuff.
573 BlobDataBuilder builder("fake");
574 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize -
575 kTestBlobStorageMinFileSizeBytes);
576 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
577 CreateSharedDataItems(builder);
578
579 memory_quota_result_ = false;
580 base::WeakPtr<QuotaAllocationTask> memory_task =
581 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
582 EXPECT_TRUE(memory_task);
583 EXPECT_TRUE(file_runner_->HasPendingTask());
584
585 RunFileThreadTasks();
586 base::RunLoop().RunUntilIdle();
587
588 EXPECT_EQ(
589 kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes,
590 controller.memory_usage());
591 EXPECT_EQ(
592 kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes,
593 controller.disk_usage());
594
595 EXPECT_TRUE(memory_quota_result_);
596 }
597
598 TEST_F(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) {
599 const std::string kFirstMemoryId = "id";
600 const uint64_t kFirstMemorySize = kTestBlobStorageMaxBlobMemorySize;
601 const std::string kSecondMemoryId = "id2";
602 const uint64_t kSecondMemorySize = 1;
603 const std::string kFileId = "id2";
604 const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
605
606 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
607 SetTestMemoryLimits(&controller);
608
609 char kDataMemoryData[kFirstMemorySize];
610 std::memset(kDataMemoryData, kFirstMemorySize, 'e');
611
612 // Add first memory item to fill up some memory quota.
613 BlobDataBuilder builder(kFirstMemoryId);
614 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
615
616 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
617 CreateSharedDataItems(builder);
618
619 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
620
621 // Create a second memory item that is just a little too big.
622 BlobDataBuilder builder2(kSecondMemoryId);
623 builder2.AppendFutureData(kSecondMemorySize);
624
625 // Reserve memory, which should request successfuly but we can't fit it yet.
626 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
627 CreateSharedDataItems(builder2);
628 base::WeakPtr<QuotaAllocationTask> memory_task =
629 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
630 // We don't count the usage yet.
631 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
632 EXPECT_EQ(0u, controller.disk_usage());
633
634 // Add our original item as populated so we start paging it to disk.
635 items[0]->item()->data_element_ptr()->SetToBytes(kDataMemoryData,
636 kFirstMemorySize);
637 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
638 controller.NotifyMemoryItemsUsed(items);
639
640 EXPECT_TRUE(file_runner_->HasPendingTask());
641 EXPECT_TRUE(memory_task);
642 EXPECT_EQ(kFirstMemorySize, controller.disk_usage());
643
644 // Add our file item now.
645 BlobDataBuilder file_builder(kFileId);
646 file_builder.AppendFutureFile(0, kFileBlobSize, 0);
647
648 std::vector<scoped_refptr<ShareableBlobDataItem>> file_items =
649 CreateSharedDataItems(file_builder);
650
651 base::WeakPtr<QuotaAllocationTask> file_task =
652 controller.ReserveFileQuota(file_items, GetFileCreationCallback());
653 EXPECT_TRUE(file_task);
654 EXPECT_TRUE(file_runner_->HasPendingTask());
655
656 // We should have both memory paging tasks and file paging tasks.
657 EXPECT_EQ(kFirstMemorySize, controller.memory_usage());
658 EXPECT_EQ(kFirstMemorySize + kFileBlobSize, controller.disk_usage());
659 file_quota_result_ = true;
660 memory_quota_result_ = true;
661
662 files_created_.clear();
663
664 // Disable paging! This should cancel all file-related tasks and leave us with
665 // only the first memory item.
666 controller.DisableFilePaging(base::File::FILE_ERROR_FAILED);
667 EXPECT_FALSE(file_quota_result_);
668 EXPECT_FALSE(memory_quota_result_);
669 EXPECT_FALSE(file_task);
670 EXPECT_FALSE(memory_task);
671
672 file_items.clear();
673 items.clear();
674
675 RunFileThreadTasks();
676 base::RunLoop().RunUntilIdle();
677
678 EXPECT_EQ(0ull, controller.disk_usage());
679 EXPECT_EQ(0ull, controller.memory_usage());
680 }
681 } // namespace storage
OLDNEW
« no previous file with comments | « content/browser/blob_storage/blob_data_builder_unittest.cc ('k') | content/test/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698