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

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

Issue 2774413002: Move some blob tests next to the files they cover. (Closed)
Patch Set: Created 3 years, 8 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
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/sys_info.h"
13 #include "base/test/test_simple_task_runner.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "base/threading/thread_task_runner_handle.h"
16 #include "storage/browser/blob/blob_data_builder.h"
17 #include "storage/browser/blob/blob_data_item.h"
18 #include "storage/browser/blob/shareable_blob_data_item.h"
19 #include "storage/common/data_element.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace storage {
23
24 using Strategy = BlobMemoryController::Strategy;
25 using FileCreationInfo = BlobMemoryController::FileCreationInfo;
26 using base::TestSimpleTaskRunner;
27 using ItemState = ShareableBlobDataItem::State;
28 using QuotaAllocationTask = BlobMemoryController::QuotaAllocationTask;
29
30 const std::string kBlobStorageDirectory = "blob_storage";
31 const size_t kTestBlobStorageIPCThresholdBytes = 20;
32 const size_t kTestBlobStorageMaxSharedMemoryBytes = 50;
33 const size_t kTestBlobStorageMaxBlobMemorySize = 500;
34 const uint64_t kTestBlobStorageMaxDiskSpace = 1000;
35 const uint64_t kTestBlobStorageMinFileSizeBytes = 10;
36 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
37
38 const uint64_t kTestSmallBlobStorageMaxDiskSpace = 100;
39
40 static int64_t sFakeDiskSpace = 0;
41 static bool sFakeDiskSpaceCalled = true;
42
43 int64_t FakeDiskSpaceMethod(const base::FilePath& path) {
44 EXPECT_FALSE(sFakeDiskSpaceCalled);
45 sFakeDiskSpaceCalled = true;
46 return sFakeDiskSpace;
47 }
48
49 class BlobMemoryControllerTest : public testing::Test {
50 protected:
51 BlobMemoryControllerTest() {}
52
53 void SetUp() override {
54 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
55 base::ThreadRestrictions::SetIOAllowed(false);
56 };
57
58 void TearDown() override {
59 files_created_.clear();
60 // Make sure we clean up the files.
61 base::RunLoop().RunUntilIdle();
62 RunFileThreadTasks();
63 base::RunLoop().RunUntilIdle();
64 base::ThreadRestrictions::SetIOAllowed(true);
65 ASSERT_TRUE(temp_dir_.Delete());
66 }
67
68 void AssertEnoughDiskSpace() {
69 base::ThreadRestrictions::SetIOAllowed(true);
70 ASSERT_GT(base::SysInfo::AmountOfFreeDiskSpace(temp_dir_.GetPath()),
71 static_cast<int64_t>(kTestBlobStorageMaxDiskSpace))
72 << "Bot doesn't have enough disk space to run these tests.";
73 base::ThreadRestrictions::SetIOAllowed(false);
74 }
75
76 std::vector<scoped_refptr<ShareableBlobDataItem>> CreateSharedDataItems(
77 const BlobDataBuilder& builder) {
78 std::vector<scoped_refptr<ShareableBlobDataItem>> result;
79 for (size_t i = 0; i < builder.items_.size(); ++i) {
80 result.push_back(make_scoped_refptr(new ShareableBlobDataItem(
81 builder.items_[i], ShareableBlobDataItem::QUOTA_NEEDED)));
82 }
83 return result;
84 }
85
86 void SetTestMemoryLimits(BlobMemoryController* controller) {
87 BlobStorageLimits limits;
88 limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
89 limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
90 limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
91 limits.desired_max_disk_space = kTestBlobStorageMaxDiskSpace;
92 limits.effective_max_disk_space = kTestBlobStorageMaxDiskSpace;
93 limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
94 limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
95 controller->set_limits_for_testing(limits);
96 }
97
98 void SetSmallDiskTestMemoryLimits(BlobMemoryController* controller) {
99 BlobStorageLimits limits;
100 limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
101 limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
102 limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
103 limits.desired_max_disk_space = kTestSmallBlobStorageMaxDiskSpace;
104 limits.effective_max_disk_space = kTestSmallBlobStorageMaxDiskSpace;
105 limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
106 limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
107 controller->set_limits_for_testing(limits);
108 }
109
110 void SaveFileCreationInfo(std::vector<FileCreationInfo> info, bool success) {
111 file_quota_result_ = success;
112 if (success) {
113 files_created_.swap(info);
114 }
115 }
116
117 void SaveMemoryRequestToOutput(bool* output, bool success) {
118 ASSERT_TRUE(output);
119 *output = success;
120 }
121 void SaveMemoryRequest(bool success) { memory_quota_result_ = success; }
122
123 BlobMemoryController::FileQuotaRequestCallback GetFileCreationCallback() {
124 return base::Bind(&BlobMemoryControllerTest::SaveFileCreationInfo,
125 base::Unretained(this));
126 }
127
128 BlobMemoryController::MemoryQuotaRequestCallback GetMemoryRequestCallback() {
129 return base::Bind(&BlobMemoryControllerTest::SaveMemoryRequest,
130 base::Unretained(this));
131 }
132
133 BlobMemoryController::MemoryQuotaRequestCallback
134 GetMemoryRequestCallbackToOutput(bool* output) {
135 return base::Bind(&BlobMemoryControllerTest::SaveMemoryRequestToOutput,
136 base::Unretained(this), output);
137 }
138
139 void RunFileThreadTasks() {
140 base::ThreadRestrictions::SetIOAllowed(true);
141 file_runner_->RunPendingTasks();
142 base::ThreadRestrictions::SetIOAllowed(false);
143 }
144
145 bool HasMemoryAllocation(ShareableBlobDataItem* item) {
146 return static_cast<bool>(item->memory_allocation_);
147 }
148
149 void set_disk_space(int64_t space) {
150 sFakeDiskSpaceCalled = false;
151 sFakeDiskSpace = space;
152 }
153
154 void ExpectDiskSpaceCalled() { EXPECT_TRUE(sFakeDiskSpaceCalled); }
155
156 bool file_quota_result_ = false;
157 base::ScopedTempDir temp_dir_;
158 std::vector<FileCreationInfo> files_created_;
159 bool memory_quota_result_ = false;
160
161 scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner();
162
163 base::MessageLoop fake_io_message_loop_;
164 };
165
166 TEST_F(BlobMemoryControllerTest, Strategy) {
167 {
168 BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
169 SetTestMemoryLimits(&controller);
170
171 // No transportation needed.
172 EXPECT_EQ(Strategy::NONE_NEEDED, controller.DetermineStrategy(0, 0));
173
174 // IPC.
175 EXPECT_EQ(Strategy::IPC, controller.DetermineStrategy(
176 0, kTestBlobStorageIPCThresholdBytes));
177
178 // Shared Memory.
179 EXPECT_EQ(
180 Strategy::SHARED_MEMORY,
181 controller.DetermineStrategy(kTestBlobStorageIPCThresholdBytes,
182 kTestBlobStorageMaxSharedMemoryBytes));
183 EXPECT_EQ(
184 Strategy::SHARED_MEMORY,
185 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize));
186
187 // Too large.
188 EXPECT_EQ(
189 Strategy::TOO_LARGE,
190 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize + 1));
191 }
192 {
193 // Enable disk, and check file strategies.
194 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
195 SetTestMemoryLimits(&controller);
196
197 EXPECT_EQ(
198 Strategy::SHARED_MEMORY,
199 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize -
200 kTestBlobStorageMinFileSizeBytes));
201 EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
202 0, kTestBlobStorageMaxBlobMemorySize -
203 kTestBlobStorageMinFileSizeBytes + 1));
204
205 EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
206 0, kTestBlobStorageMaxBlobMemorySize));
207
208 // Too large for disk.
209 EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(
210 0, kTestBlobStorageMaxDiskSpace + 1));
211 }
212 {
213 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
214 SetSmallDiskTestMemoryLimits(&controller);
215
216 EXPECT_TRUE(controller.CanReserveQuota(kTestBlobStorageMaxBlobMemorySize));
217 // Since our disk is too small, this should be sent with shared memory.
218 EXPECT_EQ(
219 Strategy::SHARED_MEMORY,
220 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize));
221 }
222 }
223
224 TEST_F(BlobMemoryControllerTest, GrantMemory) {
225 const std::string kId = "id";
226 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
227 SetTestMemoryLimits(&controller);
228
229 BlobDataBuilder builder(kId);
230 builder.AppendFutureData(10);
231 builder.AppendFutureData(20);
232 builder.AppendFutureData(30);
233
234 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
235 CreateSharedDataItems(builder);
236
237 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
238 EXPECT_TRUE(memory_quota_result_);
239 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
240 EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
241 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[1]->state());
242 EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
243 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[2]->state());
244 EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
245 }
246
247 TEST_F(BlobMemoryControllerTest, SimpleMemoryRequest) {
248 const std::string kId = "id";
249 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
250 SetTestMemoryLimits(&controller);
251
252 // Add memory item that is the memory quota.
253 BlobDataBuilder builder(kId);
254 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
255
256 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
257 CreateSharedDataItems(builder);
258
259 base::WeakPtr<QuotaAllocationTask> task =
260 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
261 EXPECT_EQ(nullptr, task);
262 EXPECT_TRUE(memory_quota_result_);
263 memory_quota_result_ = false;
264 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
265 EXPECT_FALSE(file_runner_->HasPendingTask());
266 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
267 EXPECT_EQ(0u, controller.disk_usage());
268
269 items.clear();
270 EXPECT_EQ(0u, controller.memory_usage());
271 }
272
273 TEST_F(BlobMemoryControllerTest, PageToDisk) {
274 const std::string kId = "id";
275 const std::string kId2 = "id2";
276 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
277 SetTestMemoryLimits(&controller);
278 AssertEnoughDiskSpace();
279
280 char kData[kTestBlobStorageMaxBlobMemorySize];
281 std::memset(kData, 'e', kTestBlobStorageMaxBlobMemorySize);
282
283 // Add memory item that is the memory quota.
284 BlobDataBuilder builder(kId);
285 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
286
287 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
288 CreateSharedDataItems(builder);
289
290 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
291 EXPECT_TRUE(memory_quota_result_);
292 memory_quota_result_ = false;
293 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
294 EXPECT_FALSE(file_runner_->HasPendingTask());
295 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
296 EXPECT_EQ(0u, controller.disk_usage());
297
298 // Create an item that is just a little too big.
299 BlobDataBuilder builder2(kId2);
300 builder2.AppendFutureData(kTestBlobStorageMinFileSizeBytes + 1);
301
302 // Reserve memory, which should request successfuly but we can't fit it yet
303 // (no callback).
304 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
305 CreateSharedDataItems(builder2);
306 base::WeakPtr<QuotaAllocationTask> task =
307 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
308 EXPECT_NE(nullptr, task);
309 // We don't count the usage yet.
310 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
311 EXPECT_EQ(0u, controller.disk_usage());
312
313 EXPECT_FALSE(memory_quota_result_);
314 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
315 EXPECT_FALSE(file_runner_->HasPendingTask());
316
317 // Add our original item as populated so it's paged to disk.
318 items[0]->item()->data_element_ptr()->SetToBytes(
319 kData, kTestBlobStorageMaxBlobMemorySize);
320 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
321 controller.NotifyMemoryItemsUsed(items);
322
323 EXPECT_TRUE(file_runner_->HasPendingTask());
324 RunFileThreadTasks();
325 base::RunLoop().RunUntilIdle();
326 // items2 are successfuly allocated.
327 EXPECT_EQ(nullptr, task);
328 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
329 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
330 EXPECT_EQ(kTestBlobStorageMinFileSizeBytes + 1, controller.memory_usage());
331 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
332
333 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
334
335 items2.clear();
336 EXPECT_EQ(0u, controller.memory_usage());
337 items.clear();
338 EXPECT_TRUE(file_runner_->HasPendingTask());
339 RunFileThreadTasks();
340 base::RunLoop().RunUntilIdle();
341 EXPECT_EQ(0u, controller.disk_usage());
342 }
343
344 TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) {
345 BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
346 SetTestMemoryLimits(&controller);
347
348 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxBlobMemorySize +
349 kTestBlobStorageMinFileSizeBytes +
350 1));
351 }
352
353 TEST_F(BlobMemoryControllerTest, TooLargeForDisk) {
354 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
355 SetTestMemoryLimits(&controller);
356
357 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace + 1));
358 }
359
360 TEST_F(BlobMemoryControllerTest, CancelMemoryRequest) {
361 const std::string kId = "id";
362 const std::string kId2 = "id2";
363 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
364 SetTestMemoryLimits(&controller);
365
366 char kData[kTestBlobStorageMaxBlobMemorySize];
367 std::memset(kData, 'e', kTestBlobStorageMaxBlobMemorySize);
368
369 // Add memory item that is the memory quota.
370 BlobDataBuilder builder(kId);
371 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
372
373 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
374 CreateSharedDataItems(builder);
375
376 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
377
378 // Create an item that is just a little too big.
379 BlobDataBuilder builder2(kId2);
380 builder2.AppendFutureData(kTestBlobStorageMinFileSizeBytes + 1);
381
382 // Reserve memory, which should request successfuly but we can't fit it yet
383 // (no callback).
384 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
385 CreateSharedDataItems(builder2);
386 base::WeakPtr<QuotaAllocationTask> task =
387 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
388 // We don't count the usage yet.
389 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
390 EXPECT_EQ(0u, controller.disk_usage());
391
392 // Add our original item as populated so we start paging to disk.
393 items[0]->item()->data_element_ptr()->SetToBytes(
394 kData, kTestBlobStorageMaxBlobMemorySize);
395 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
396 controller.NotifyMemoryItemsUsed(items);
397
398 EXPECT_TRUE(file_runner_->HasPendingTask());
399 EXPECT_TRUE(task);
400
401 task->Cancel();
402 EXPECT_FALSE(task);
403 RunFileThreadTasks();
404 base::RunLoop().RunUntilIdle();
405 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
406 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
407 EXPECT_EQ(0u, controller.memory_usage());
408 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
409
410 items.clear();
411 // Run cleanup tasks from the ShareableFileReferences.
412 base::RunLoop().RunUntilIdle();
413 RunFileThreadTasks();
414 base::RunLoop().RunUntilIdle();
415
416 EXPECT_EQ(0u, controller.disk_usage());
417 }
418
419 TEST_F(BlobMemoryControllerTest, FileRequest) {
420 const std::string kId = "id";
421 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
422
423 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
424 SetTestMemoryLimits(&controller);
425
426 char kData[kBlobSize];
427 std::memset(kData, 'e', kBlobSize);
428
429 // Add item that is the file quota.
430 BlobDataBuilder builder(kId);
431 builder.AppendFutureFile(0, kBlobSize, 0);
432
433 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
434 CreateSharedDataItems(builder);
435
436 file_quota_result_ = false;
437 base::WeakPtr<QuotaAllocationTask> task =
438 controller.ReserveFileQuota(items, GetFileCreationCallback());
439 EXPECT_TRUE(task);
440 EXPECT_FALSE(file_quota_result_);
441 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
442 EXPECT_TRUE(file_runner_->HasPendingTask());
443 EXPECT_EQ(0u, controller.memory_usage());
444 EXPECT_EQ(kBlobSize, controller.disk_usage());
445
446 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
447
448 RunFileThreadTasks();
449 base::RunLoop().RunUntilIdle();
450 EXPECT_TRUE(file_quota_result_);
451 EXPECT_FALSE(file_runner_->HasPendingTask());
452 EXPECT_FALSE(task);
453
454 // Do the work to populate the file.
455 EXPECT_EQ(1u, files_created_.size());
456 EXPECT_TRUE(
457 builder.PopulateFutureFile(0, std::move(files_created_[0].file_reference),
458 files_created_[0].last_modified));
459 base::ThreadRestrictions::SetIOAllowed(true);
460 files_created_.clear();
461 base::ThreadRestrictions::SetIOAllowed(false);
462 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
463 EXPECT_FALSE(
464 BlobDataBuilder::IsFutureFileItem(items[0]->item()->data_element()));
465
466 builder.Clear();
467 items.clear();
468 // Run cleanup tasks from the ShareableFileReferences.
469 base::RunLoop().RunUntilIdle();
470 RunFileThreadTasks();
471 base::RunLoop().RunUntilIdle();
472
473 EXPECT_EQ(0u, controller.disk_usage());
474 }
475
476 TEST_F(BlobMemoryControllerTest, CancelFileRequest) {
477 const std::string kId = "id";
478 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
479
480 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
481 SetTestMemoryLimits(&controller);
482
483 char kData[kBlobSize];
484 std::memset(kData, 'e', kBlobSize);
485
486 // Add memory item that is the memory quota.
487 BlobDataBuilder builder(kId);
488 builder.AppendFutureFile(0, kBlobSize, 0);
489
490 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
491 CreateSharedDataItems(builder);
492
493 base::WeakPtr<QuotaAllocationTask> task =
494 controller.ReserveFileQuota(items, GetFileCreationCallback());
495 EXPECT_TRUE(task);
496 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
497 EXPECT_TRUE(file_runner_->HasPendingTask());
498 EXPECT_EQ(0u, controller.memory_usage());
499 EXPECT_EQ(kBlobSize, controller.disk_usage());
500
501 task->Cancel();
502 EXPECT_FALSE(task);
503 EXPECT_EQ(0ull, controller.disk_usage());
504
505 RunFileThreadTasks();
506 base::RunLoop().RunUntilIdle();
507 }
508
509 TEST_F(BlobMemoryControllerTest, MultipleFilesPaged) {
510 const std::string kId1 = "id";
511 const size_t kSize1 = kTestBlobStorageMaxFileSizeBytes;
512 char kData1[kSize1];
513 std::memset(kData1, 'e', kSize1);
514
515 const std::string kId2 = "id2";
516 const size_t kSize2 = kTestBlobStorageMaxFileSizeBytes;
517 char kData2[kSize2];
518 std::memset(kData2, 'f', kSize2);
519
520 const std::string kId3 = "id3";
521 const size_t kSize3 = kTestBlobStorageMaxBlobMemorySize - 1;
522
523 // Assert we shouldn't trigger paging preemptively.
524 ASSERT_LE(kSize1 + kSize2, kTestBlobStorageMaxBlobMemorySize);
525
526 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
527 SetTestMemoryLimits(&controller);
528 AssertEnoughDiskSpace();
529
530 // We add two items that should be their own files when we page to disk, and
531 // then add the last item to trigger the paging.
532
533 BlobDataBuilder builder1(kId1);
534 builder1.AppendFutureData(kSize1);
535 BlobDataBuilder builder2(kId2);
536 builder2.AppendFutureData(kSize2);
537
538 std::vector<scoped_refptr<ShareableBlobDataItem>> items1 =
539 CreateSharedDataItems(builder1);
540 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
541 CreateSharedDataItems(builder2);
542
543 memory_quota_result_ = false;
544 controller.ReserveMemoryQuota(items1, GetMemoryRequestCallback());
545 EXPECT_TRUE(memory_quota_result_);
546 memory_quota_result_ = false;
547 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
548 EXPECT_TRUE(memory_quota_result_);
549 EXPECT_EQ(ItemState::QUOTA_GRANTED, items1[0]->state());
550 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
551 EXPECT_FALSE(file_runner_->HasPendingTask());
552 EXPECT_EQ(kSize1 + kSize2, controller.memory_usage());
553 EXPECT_EQ(0u, controller.disk_usage());
554
555 // Create an item that is too big.
556 BlobDataBuilder builder3(kId3);
557 builder3.AppendFutureData(kSize3);
558
559 std::vector<scoped_refptr<ShareableBlobDataItem>> items3 =
560 CreateSharedDataItems(builder3);
561 memory_quota_result_ = false;
562 controller.ReserveMemoryQuota(items3, GetMemoryRequestCallback());
563 EXPECT_FALSE(memory_quota_result_);
564
565 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items3[0]->state());
566 EXPECT_FALSE(file_runner_->HasPendingTask());
567
568 // Add our original item as populated so it's paged to disk.
569 items1[0]->item()->data_element_ptr()->SetToBytes(kData1, kSize1);
570 items1[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
571 items2[0]->item()->data_element_ptr()->SetToBytes(kData2, kSize2);
572 items2[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
573
574 std::vector<scoped_refptr<ShareableBlobDataItem>> both_items = {items1[0],
575 items2[0]};
576 controller.NotifyMemoryItemsUsed(both_items);
577 both_items.clear();
578
579 EXPECT_TRUE(file_runner_->HasPendingTask());
580 RunFileThreadTasks();
581 base::RunLoop().RunUntilIdle();
582 EXPECT_TRUE(memory_quota_result_);
583 EXPECT_EQ(ItemState::QUOTA_GRANTED, items3[0]->state());
584 EXPECT_EQ(DataElement::TYPE_FILE, items1[0]->item()->type());
585 EXPECT_EQ(DataElement::TYPE_FILE, items2[0]->item()->type());
586 EXPECT_NE(items1[0]->item()->path(), items2[0]->item()->path());
587 EXPECT_EQ(kSize3, controller.memory_usage());
588 EXPECT_EQ(kSize1 + kSize2, controller.disk_usage());
589
590 items1.clear();
591 items2.clear();
592 items3.clear();
593
594 EXPECT_EQ(0u, controller.memory_usage());
595 base::RunLoop().RunUntilIdle();
596 EXPECT_TRUE(file_runner_->HasPendingTask());
597 RunFileThreadTasks();
598 base::RunLoop().RunUntilIdle();
599 EXPECT_EQ(0u, controller.disk_usage());
600 }
601
602 TEST_F(BlobMemoryControllerTest, FullEviction) {
603 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
604 SetTestMemoryLimits(&controller);
605 AssertEnoughDiskSpace();
606
607 char kData[1];
608 kData[0] = 'e';
609
610 // Create a bunch of small stuff.
611 std::vector<scoped_refptr<ShareableBlobDataItem>> small_items;
612 for (size_t i = 0;
613 i < kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes;
614 i++) {
615 BlobDataBuilder builder("fake");
616 builder.AppendData(kData, 1);
617 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
618 CreateSharedDataItems(builder);
619 base::WeakPtr<QuotaAllocationTask> memory_task =
620 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
621 EXPECT_FALSE(memory_task);
622 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
623 small_items.insert(small_items.end(), items.begin(), items.end());
624 }
625 controller.NotifyMemoryItemsUsed(small_items);
626 EXPECT_FALSE(file_runner_->HasPendingTask());
627 EXPECT_EQ(
628 kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes,
629 controller.memory_usage());
630
631 // Create maximum size blob to evict ALL small stuff.
632 BlobDataBuilder builder("fake");
633 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize -
634 kTestBlobStorageMinFileSizeBytes);
635 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
636 CreateSharedDataItems(builder);
637
638 memory_quota_result_ = false;
639 base::WeakPtr<QuotaAllocationTask> memory_task =
640 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
641 EXPECT_TRUE(memory_task);
642 EXPECT_TRUE(file_runner_->HasPendingTask());
643
644 RunFileThreadTasks();
645 base::RunLoop().RunUntilIdle();
646
647 EXPECT_EQ(
648 kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes,
649 controller.memory_usage());
650 EXPECT_EQ(
651 kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes,
652 controller.disk_usage());
653
654 EXPECT_TRUE(memory_quota_result_);
655 }
656
657 TEST_F(BlobMemoryControllerTest, PagingStopsWhenFull) {
658 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
659 SetTestMemoryLimits(&controller);
660 AssertEnoughDiskSpace();
661 const size_t kTotalBlobStorageSize =
662 kTestBlobStorageMaxDiskSpace + kTestBlobStorageMaxBlobMemorySize;
663
664 const size_t kDataSize = 10u;
665 const size_t kBlobsThatCanFit = kTotalBlobStorageSize / kDataSize;
666 const size_t kNumFastBlobs = kTestBlobStorageMaxBlobMemorySize / kDataSize;
667 char kData[10];
668 memset(kData, 'e', kDataSize);
669
670 // Create all of our blobs.
671 std::vector<scoped_refptr<ShareableBlobDataItem>> all_items;
672 std::vector<base::WeakPtr<QuotaAllocationTask>> memory_tasks;
673 bool memory_requested[kBlobsThatCanFit] = {};
674 for (size_t i = 0; i < kBlobsThatCanFit; i++) {
675 BlobDataBuilder builder("fake");
676 builder.AppendData(kData, kDataSize);
677 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
678 CreateSharedDataItems(builder);
679 EXPECT_TRUE(controller.CanReserveQuota(kDataSize));
680 EXPECT_EQ((i < kNumFastBlobs) ? Strategy::NONE_NEEDED : Strategy::IPC,
681 controller.DetermineStrategy(kDataSize, kDataSize))
682 << i;
683 base::WeakPtr<QuotaAllocationTask> memory_task =
684 controller.ReserveMemoryQuota(
685 items, GetMemoryRequestCallbackToOutput(&memory_requested[i]));
686 if (memory_task) {
687 memory_tasks.push_back(std::move(memory_task));
688 }
689 all_items.insert(all_items.end(), items.begin(), items.end());
690 }
691 // We should have stored all of our memory quota, and no disk yet.
692 EXPECT_EQ(500u, controller.memory_usage());
693 EXPECT_EQ(0ull, controller.disk_usage());
694
695 EXPECT_FALSE(controller.CanReserveQuota(1u));
696 EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(1u, 1ull));
697 EXPECT_FALSE(file_runner_->HasPendingTask());
698
699 for (size_t i = 0; i < kBlobsThatCanFit; i++) {
700 EXPECT_EQ(i < kBlobsThatCanFit / 3, memory_requested[i]) << i;
701 if (memory_requested[i] &&
702 all_items[i]->state() != ItemState::POPULATED_WITH_QUOTA) {
703 EXPECT_TRUE(memory_requested[i]);
704 all_items[i]->set_state(ItemState::POPULATED_WITH_QUOTA);
705 std::vector<scoped_refptr<ShareableBlobDataItem>> temp_vector;
706 temp_vector.push_back(all_items[i]);
707 controller.NotifyMemoryItemsUsed(temp_vector);
708 }
709 }
710 EXPECT_TRUE(file_runner_->HasPendingTask());
711
712 // This will schedule one task. Paging starts as soon as there is enough
713 // memory to page, and multiple pagings can't happen at the same time.
714 EXPECT_EQ(10ull, controller.disk_usage());
715 RunFileThreadTasks();
716 base::RunLoop().RunUntilIdle();
717 // The rest of the tasks should be scheduled.
718 EXPECT_TRUE(file_runner_->HasPendingTask());
719 RunFileThreadTasks();
720 base::RunLoop().RunUntilIdle();
721 // Everything in memory should be on disk, and next batch of memory items
722 // should be granted.
723 EXPECT_EQ(500u, controller.memory_usage());
724 EXPECT_EQ(500ull, controller.disk_usage());
725
726 // Still can't add anything.
727 EXPECT_FALSE(controller.CanReserveQuota(1u));
728 EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(1u, 1ull));
729
730 // Flag next batch for saving to disk.
731 for (size_t i = 0; i < kBlobsThatCanFit; i++) {
732 // Note: this can fail if the bot's disk is almost full.
733 EXPECT_EQ(i < kBlobsThatCanFit * 2 / 3, memory_requested[i]) << i;
734 if (memory_requested[i] &&
735 all_items[i]->state() != ItemState::POPULATED_WITH_QUOTA) {
736 all_items[i]->set_state(ItemState::POPULATED_WITH_QUOTA);
737 std::vector<scoped_refptr<ShareableBlobDataItem>> temp_vector;
738 temp_vector.push_back(all_items[i]);
739 controller.NotifyMemoryItemsUsed(temp_vector);
740 }
741 }
742 EXPECT_TRUE(file_runner_->HasPendingTask());
743
744 // Same as before. One page task is scheduled, so run them twice.
745 EXPECT_EQ(510ull, controller.disk_usage());
746 RunFileThreadTasks();
747 base::RunLoop().RunUntilIdle();
748 // We page one time first, as it blocks paging once it starts.
749 RunFileThreadTasks();
750 base::RunLoop().RunUntilIdle();
751
752 // All quota should be allocated.
753 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
754 EXPECT_EQ(kTestBlobStorageMaxDiskSpace, controller.disk_usage());
755 EXPECT_FALSE(controller.CanReserveQuota(1u));
756 EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(1u, 1ull));
757
758 // Flag last batch as populated.
759 for (size_t i = 0; i < kBlobsThatCanFit; i++) {
760 // Note: this can fail if the bot's disk is almost full.
761 EXPECT_TRUE(memory_requested[i]);
762 if (memory_requested[i] &&
763 all_items[i]->state() != ItemState::POPULATED_WITH_QUOTA) {
764 all_items[i]->set_state(ItemState::POPULATED_WITH_QUOTA);
765 std::vector<scoped_refptr<ShareableBlobDataItem>> temp_vector;
766 temp_vector.push_back(all_items[i]);
767 controller.NotifyMemoryItemsUsed(temp_vector);
768 }
769 }
770
771 // There should be no more paging to disk, as we've reached the end.
772 EXPECT_FALSE(file_runner_->HasPendingTask());
773
774 // All quota should be allocated still.
775 EXPECT_EQ(500u, controller.memory_usage());
776 EXPECT_EQ(1000ull, controller.disk_usage());
777
778 // Still can't add anything.
779 EXPECT_FALSE(controller.CanReserveQuota(1u));
780 EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(1u, 1ull));
781 }
782
783 TEST_F(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) {
784 const std::string kFirstMemoryId = "id";
785 const uint64_t kFirstMemorySize = kTestBlobStorageMaxBlobMemorySize;
786 const std::string kSecondMemoryId = "id2";
787 const uint64_t kSecondMemorySize = 1;
788 const std::string kFileId = "id2";
789 const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
790
791 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
792 SetTestMemoryLimits(&controller);
793
794 char kDataMemoryData[kFirstMemorySize];
795 std::memset(kDataMemoryData, 'e', kFirstMemorySize);
796
797 // Add first memory item to fill up some memory quota.
798 BlobDataBuilder builder(kFirstMemoryId);
799 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
800
801 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
802 CreateSharedDataItems(builder);
803
804 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
805
806 // Create a second memory item that is just a little too big.
807 BlobDataBuilder builder2(kSecondMemoryId);
808 builder2.AppendFutureData(kSecondMemorySize);
809
810 // Reserve memory, which should request successfuly but we can't fit it yet.
811 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
812 CreateSharedDataItems(builder2);
813 base::WeakPtr<QuotaAllocationTask> memory_task =
814 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
815 // We don't count the usage yet.
816 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
817 EXPECT_EQ(0u, controller.disk_usage());
818
819 // Add our original item as populated so we start paging it to disk.
820 items[0]->item()->data_element_ptr()->SetToBytes(kDataMemoryData,
821 kFirstMemorySize);
822 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
823 controller.NotifyMemoryItemsUsed(items);
824
825 EXPECT_TRUE(file_runner_->HasPendingTask());
826 EXPECT_TRUE(memory_task);
827 EXPECT_EQ(kFirstMemorySize, controller.disk_usage());
828
829 // Add our file item now.
830 BlobDataBuilder file_builder(kFileId);
831 file_builder.AppendFutureFile(0, kFileBlobSize, 0);
832
833 std::vector<scoped_refptr<ShareableBlobDataItem>> file_items =
834 CreateSharedDataItems(file_builder);
835
836 base::WeakPtr<QuotaAllocationTask> file_task =
837 controller.ReserveFileQuota(file_items, GetFileCreationCallback());
838 EXPECT_TRUE(file_task);
839 EXPECT_TRUE(file_runner_->HasPendingTask());
840
841 // We should have both memory paging tasks and file paging tasks.
842 EXPECT_EQ(kFirstMemorySize, controller.memory_usage());
843 EXPECT_EQ(kFirstMemorySize + kFileBlobSize, controller.disk_usage());
844 file_quota_result_ = true;
845 memory_quota_result_ = true;
846
847 files_created_.clear();
848
849 // Disable paging! This should cancel all file-related tasks and leave us with
850 // only the first memory item.
851 controller.DisableFilePaging(base::File::FILE_ERROR_FAILED);
852 EXPECT_FALSE(file_quota_result_);
853 EXPECT_FALSE(memory_quota_result_);
854 EXPECT_FALSE(file_task);
855 EXPECT_FALSE(memory_task);
856
857 file_items.clear();
858 items.clear();
859
860 RunFileThreadTasks();
861 base::RunLoop().RunUntilIdle();
862
863 EXPECT_EQ(0ull, controller.disk_usage());
864 EXPECT_EQ(0ull, controller.memory_usage());
865 }
866
867 TEST_F(BlobMemoryControllerTest, DiskSpaceTooSmallForItem) {
868 const std::string kFileId = "id2";
869 const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
870
871 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
872 controller.set_testing_disk_space(&FakeDiskSpaceMethod);
873
874 BlobDataBuilder file_builder(kFileId);
875 file_builder.AppendFutureFile(0, kFileBlobSize, 0);
876
877 // When we have < kFileBlobSize, then we cancel our request.
878 SetTestMemoryLimits(&controller);
879
880 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
881 CreateSharedDataItems(file_builder);
882
883 file_quota_result_ = true;
884 controller.ReserveFileQuota(items, GetFileCreationCallback());
885
886 EXPECT_TRUE(file_runner_->HasPendingTask());
887 set_disk_space(kFileBlobSize - 1);
888
889 RunFileThreadTasks();
890 ExpectDiskSpaceCalled();
891 base::RunLoop().RunUntilIdle();
892
893 EXPECT_FALSE(file_quota_result_);
894 EXPECT_TRUE(controller.limits().IsDiskSpaceConstrained());
895 EXPECT_EQ(0ull, controller.limits().effective_max_disk_space);
896
897 EXPECT_EQ(0ull, controller.disk_usage());
898 EXPECT_EQ(0ull, controller.memory_usage());
899 }
900
901 TEST_F(BlobMemoryControllerTest, DiskSpaceHitMinAvailable) {
902 const std::string kFileId = "id2";
903 const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
904
905 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
906 controller.set_testing_disk_space(&FakeDiskSpaceMethod);
907
908 BlobDataBuilder file_builder(kFileId);
909 file_builder.AppendFutureFile(0, kFileBlobSize, 0);
910 // When we have < limits.min_available_external_disk_space(), then we'll
911 // modify our effective disk space to match our current usage to stop using
912 // more disk.
913
914 SetTestMemoryLimits(&controller);
915
916 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
917 CreateSharedDataItems(file_builder);
918
919 file_quota_result_ = false;
920 controller.ReserveFileQuota(items, GetFileCreationCallback());
921
922 EXPECT_TRUE(file_runner_->HasPendingTask());
923 set_disk_space(controller.limits().min_available_external_disk_space() - 1);
924
925 RunFileThreadTasks();
926 ExpectDiskSpaceCalled();
927 base::RunLoop().RunUntilIdle();
928
929 EXPECT_TRUE(file_quota_result_);
930 EXPECT_TRUE(controller.limits().IsDiskSpaceConstrained());
931 EXPECT_EQ(kFileBlobSize, controller.limits().effective_max_disk_space);
932
933 items.clear();
934 files_created_.clear();
935
936 RunFileThreadTasks();
937 base::RunLoop().RunUntilIdle();
938
939 EXPECT_EQ(0ull, controller.disk_usage());
940 EXPECT_EQ(0ull, controller.memory_usage());
941 }
942
943 TEST_F(BlobMemoryControllerTest, DiskSpaceBeforeMinAvailable) {
944 const std::string kFileId = "id2";
945
946 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
947 controller.set_testing_disk_space(&FakeDiskSpaceMethod);
948
949 BlobDataBuilder file_builder(kFileId);
950 file_builder.AppendFutureFile(0, kTestBlobStorageMaxBlobMemorySize, 0);
951
952 // When our desired total disk space is less than we're allowed given the
953 // minimum disk availability, we shorten the disk space.
954 SetTestMemoryLimits(&controller);
955
956 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
957 CreateSharedDataItems(file_builder);
958
959 file_quota_result_ = false;
960 controller.ReserveFileQuota(items, GetFileCreationCallback());
961
962 EXPECT_TRUE(file_runner_->HasPendingTask());
963 set_disk_space(controller.limits().desired_max_disk_space +
964 controller.limits().min_available_external_disk_space() + 1);
965
966 RunFileThreadTasks();
967 ExpectDiskSpaceCalled();
968 base::RunLoop().RunUntilIdle();
969
970 EXPECT_TRUE(file_quota_result_);
971 EXPECT_FALSE(controller.limits().IsDiskSpaceConstrained())
972 << controller.limits().effective_max_disk_space;
973
974 items.clear();
975 files_created_.clear();
976
977 RunFileThreadTasks();
978 base::RunLoop().RunUntilIdle();
979
980 EXPECT_EQ(0ull, controller.disk_usage());
981 EXPECT_EQ(0ull, controller.memory_usage());
982 }
983
984 TEST_F(BlobMemoryControllerTest, DiskSpaceNearMinAvailable) {
985 const std::string kFileId = "id2";
986
987 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
988 controller.set_testing_disk_space(&FakeDiskSpaceMethod);
989
990 BlobDataBuilder file_builder(kFileId);
991 file_builder.AppendFutureFile(0, kTestBlobStorageMaxBlobMemorySize, 0);
992
993 // When our desired total disk space is less than we're allowed given the
994 // minimum disk availability, we shorten the disk space.
995 SetTestMemoryLimits(&controller);
996
997 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
998 CreateSharedDataItems(file_builder);
999
1000 file_quota_result_ = false;
1001 controller.ReserveFileQuota(items, GetFileCreationCallback());
1002
1003 EXPECT_TRUE(file_runner_->HasPendingTask());
1004 set_disk_space(controller.limits().desired_max_disk_space +
1005 controller.limits().min_available_external_disk_space() - 1);
1006
1007 RunFileThreadTasks();
1008 ExpectDiskSpaceCalled();
1009 base::RunLoop().RunUntilIdle();
1010
1011 EXPECT_TRUE(file_quota_result_);
1012 EXPECT_TRUE(controller.limits().IsDiskSpaceConstrained());
1013 EXPECT_EQ(controller.limits().desired_max_disk_space - 1,
1014 controller.limits().effective_max_disk_space);
1015
1016 items.clear();
1017 files_created_.clear();
1018
1019 RunFileThreadTasks();
1020 base::RunLoop().RunUntilIdle();
1021
1022 EXPECT_EQ(0ull, controller.disk_usage());
1023 EXPECT_EQ(0ull, controller.memory_usage());
1024 }
1025
1026 TEST_F(BlobMemoryControllerTest, DiskSpaceResetAfterIncrease) {
1027 const std::string kFileId = "id2";
1028 const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
1029
1030 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
1031 controller.set_testing_disk_space(&FakeDiskSpaceMethod);
1032
1033 BlobDataBuilder file_builder(kFileId);
1034 file_builder.AppendFutureFile(0, kFileBlobSize, 0);
1035
1036 // When we do a file operation after disk has been freed (after we've been
1037 // limited), our effective size grows correctly.
1038 SetTestMemoryLimits(&controller);
1039
1040 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
1041 CreateSharedDataItems(file_builder);
1042
1043 controller.ReserveFileQuota(items, GetFileCreationCallback());
1044
1045 EXPECT_TRUE(file_runner_->HasPendingTask());
1046 set_disk_space(controller.limits().min_available_external_disk_space() - 1);
1047
1048 RunFileThreadTasks();
1049 base::RunLoop().RunUntilIdle();
1050
1051 // Check the effective limit is constrained.
1052 EXPECT_TRUE(controller.limits().IsDiskSpaceConstrained());
1053 EXPECT_EQ(kFileBlobSize, controller.limits().effective_max_disk_space);
1054
1055 // Delete the item so we have disk quota.
1056 items.clear();
1057 files_created_.clear();
1058
1059 RunFileThreadTasks();
1060 ExpectDiskSpaceCalled();
1061 base::RunLoop().RunUntilIdle();
1062
1063 EXPECT_EQ(0ull, controller.disk_usage());
1064 EXPECT_EQ(0ull, controller.memory_usage());
1065
1066 // Create the same item, but have the disk space report the minimum amount
1067 // needed to have the desired disk size.
1068 items = CreateSharedDataItems(file_builder);
1069
1070 controller.ReserveFileQuota(items, GetFileCreationCallback());
1071
1072 EXPECT_TRUE(file_runner_->HasPendingTask());
1073 set_disk_space(kTestBlobStorageMaxDiskSpace +
1074 controller.limits().min_available_external_disk_space());
1075
1076 RunFileThreadTasks();
1077 ExpectDiskSpaceCalled();
1078 base::RunLoop().RunUntilIdle();
1079
1080 EXPECT_FALSE(controller.limits().IsDiskSpaceConstrained());
1081 EXPECT_EQ(controller.limits().desired_max_disk_space,
1082 controller.limits().effective_max_disk_space);
1083
1084 items.clear();
1085 files_created_.clear();
1086
1087 RunFileThreadTasks();
1088 base::RunLoop().RunUntilIdle();
1089
1090 EXPECT_EQ(0ull, controller.disk_usage());
1091 EXPECT_EQ(0ull, controller.memory_usage());
1092 }
1093
1094 TEST_F(BlobMemoryControllerTest, DiskSpaceUnknown) {
1095 const std::string kFileId = "id2";
1096 const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
1097
1098 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
1099 controller.set_testing_disk_space(&FakeDiskSpaceMethod);
1100
1101 BlobDataBuilder file_builder(kFileId);
1102 file_builder.AppendFutureFile(0, kFileBlobSize, 0);
1103
1104 // If the disk space returns an error (-1), then we ignore that signal.
1105 SetTestMemoryLimits(&controller);
1106
1107 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
1108 CreateSharedDataItems(file_builder);
1109
1110 controller.ReserveFileQuota(items, GetFileCreationCallback());
1111
1112 EXPECT_TRUE(file_runner_->HasPendingTask());
1113 set_disk_space(-1ll);
1114
1115 RunFileThreadTasks();
1116 ExpectDiskSpaceCalled();
1117 base::RunLoop().RunUntilIdle();
1118
1119 // Check the effective limit is constrained.
1120 EXPECT_FALSE(controller.limits().IsDiskSpaceConstrained());
1121 }
1122
1123 } // namespace storage
OLDNEW
« no previous file with comments | « content/browser/blob_storage/blob_flattener_unittest.cc ('k') | content/browser/blob_storage/blob_slice_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698