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

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

Issue 2339933004: [BlobStorage] BlobMemoryController & tests (Closed)
Patch Set: format and hopefully windows fix 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
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 size_t kTestBlobStorageInFlightMemory = 10;
34 const uint64_t kTestBlobStorageMaxDiskSpace = 1000;
35 const uint64_t kTestBlobStorageMinFileSizeBytes = 10;
36 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
37
38 class BlobMemoryControllerTest : public testing::Test {
39 protected:
40 BlobMemoryControllerTest() {}
41
42 void SetUp() override {
43 ASSERT_EQ(true, temp_dir_.CreateUniqueTempDir());
44 base::ThreadRestrictions::SetIOAllowed(false);
45 };
46
47 void TearDown() override {
48 files_created_.clear();
49 // Make sure we clean up the files.
50 base::RunLoop().RunUntilIdle();
51 RunFileThreadTasks();
52 base::RunLoop().RunUntilIdle();
53 base::ThreadRestrictions::SetIOAllowed(true);
54 ASSERT_EQ(true, temp_dir_.Delete());
55 }
56
57 std::vector<scoped_refptr<ShareableBlobDataItem>> CreateSharedDataItems(
58 const BlobDataBuilder& builder) {
59 std::vector<scoped_refptr<ShareableBlobDataItem>> result;
60 for (size_t i = 0; i < builder.items_.size(); ++i) {
61 result.push_back(make_scoped_refptr(
62 new ShareableBlobDataItem(builder.uuid(), builder.items_[i],
63 ShareableBlobDataItem::QUOTA_NEEDED)));
64 }
65 return result;
66 }
67
68 void SetTestMemoryLimits(BlobMemoryController* controller) {
69 BlobStorageLimits limits;
70 limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
71 limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
72 limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
73 limits.in_flight_space = kTestBlobStorageInFlightMemory;
74 limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace;
75 limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
76 limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
77 controller->set_limits_for_testing(limits);
78 }
79
80 void SaveFileCreationInfo(bool success, std::vector<FileCreationInfo> info) {
81 file_quota_result_ = success;
82 if (success)
83 files_created_.swap(info);
84 }
85
86 void SaveMemoryRequest(bool success) { memory_quota_result_ = success; }
87
88 BlobMemoryController::FileQuotaRequestCallback GetFileCreationCallback() {
89 return base::Bind(&BlobMemoryControllerTest::SaveFileCreationInfo,
90 base::Unretained(this));
91 }
92
93 BlobMemoryController::MemoryQuotaRequestCallback GetMemoryRequestCallback() {
94 return base::Bind(&BlobMemoryControllerTest::SaveMemoryRequest,
95 base::Unretained(this));
96 }
97
98 void CleanUpFileItemsFromController(
99 BlobMemoryController* controller,
100 std::vector<scoped_refptr<ShareableBlobDataItem>> items,
101 const std::string& blob_id) {
102 // Make items free from blob references
103 for (const auto& item : items) {
104 item->referencing_blobs_mutable()->erase(blob_id);
105 }
106
107 // We need the shareable file reference to go away, which schedules tasks
108 // that
109 // eventually calls back to our system and decrements our disk usage.
110 items.clear();
111 base::RunLoop().RunUntilIdle();
112 EXPECT_TRUE(file_runner_->HasPendingTask());
113 RunFileThreadTasks();
114 base::RunLoop().RunUntilIdle();
115 }
116
117 void RunFileThreadTasks() {
118 base::ThreadRestrictions::SetIOAllowed(true);
119 file_runner_->RunPendingTasks();
120 base::ThreadRestrictions::SetIOAllowed(false);
121 }
122
123 bool file_quota_result_ = false;
124 base::ScopedTempDir temp_dir_;
125 std::vector<FileCreationInfo> files_created_;
126 bool memory_quota_result_ = false;
127
128 scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner();
129
130 base::MessageLoop fake_io_message_loop_;
131 };
132
133 TEST_F(BlobMemoryControllerTest, Strategy) {
134 {
135 BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
136 SetTestMemoryLimits(&controller);
137
138 // No transportation needed.
139 EXPECT_EQ(Strategy::NONE_NEEDED, controller.DetermineStrategy(0, 0));
140
141 // IPC.
142 EXPECT_EQ(Strategy::IPC, controller.DetermineStrategy(
143 0, kTestBlobStorageIPCThresholdBytes));
144
145 // Shared Memory.
146 EXPECT_EQ(
147 Strategy::SHARED_MEMORY,
148 controller.DetermineStrategy(kTestBlobStorageIPCThresholdBytes,
149 kTestBlobStorageMaxSharedMemoryBytes));
150
151 // Not too large, as disk isn't enabled.
152 EXPECT_EQ(
153 Strategy::SHARED_MEMORY,
154 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize));
155
156 // Too large.
157 EXPECT_EQ(
158 Strategy::TOO_LARGE,
159 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize + 1));
160 }
161 {
162 // Enable disk, and check file strategies.
163 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
164 SetTestMemoryLimits(&controller);
165 EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
166 0, kTestBlobStorageMaxBlobMemorySize -
167 kTestBlobStorageInFlightMemory + 1));
168
169 EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
170 0, kTestBlobStorageMaxBlobMemorySize));
171
172 // Too large for disk.
173 EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(
174 0, kTestBlobStorageMaxDiskSpace + 1));
175 }
176 }
177
178 TEST_F(BlobMemoryControllerTest, GrantMemory) {
179 const std::string kId = "id";
180 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
181 SetTestMemoryLimits(&controller);
182
183 BlobDataBuilder builder(kId);
184 builder.AppendFutureData(10);
185 builder.AppendFutureData(20);
186 builder.AppendFutureData(30);
187
188 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
189 CreateSharedDataItems(builder);
190
191 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
192 EXPECT_TRUE(memory_quota_result_);
193 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
194 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[1]->state());
195 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[2]->state());
michaeln 2016/10/18 00:56:24 maybe also expect the memory_allocation_?
dmurph 2016/10/18 20:24:44 Done.
196 }
197
198 TEST_F(BlobMemoryControllerTest, SimpleMemoryRequest) {
199 const std::string kId = "id";
200 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
201 SetTestMemoryLimits(&controller);
202
203 // Add memory item that is the memory quota.
204 BlobDataBuilder builder(kId);
205 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
206
207 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
208 CreateSharedDataItems(builder);
209
210 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
michaeln 2016/10/18 00:56:24 also check the return values for the expected null
dmurph 2016/10/18 20:24:44 Done.
211 EXPECT_TRUE(memory_quota_result_);
212 memory_quota_result_ = false;
213 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
214 EXPECT_FALSE(file_runner_->HasPendingTask());
215 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
216 EXPECT_EQ(0u, controller.disk_usage());
217
218 items.clear();
219 EXPECT_EQ(0u, controller.memory_usage());
220 }
221
222 TEST_F(BlobMemoryControllerTest, PageToDisk) {
223 const std::string kId = "id";
224 const std::string kId2 = "id2";
225 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
226 SetTestMemoryLimits(&controller);
227
228 char kData[kTestBlobStorageMaxBlobMemorySize];
229 std::memset(kData, kTestBlobStorageMaxBlobMemorySize, 'e');
230
231 // Add memory item that is the memory quota.
232 BlobDataBuilder builder(kId);
233 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
234
235 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
236 CreateSharedDataItems(builder);
237
238 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
239 EXPECT_TRUE(memory_quota_result_);
240 memory_quota_result_ = false;
241 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
242 EXPECT_FALSE(file_runner_->HasPendingTask());
243 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
244 EXPECT_EQ(0u, controller.disk_usage());
245
246 // Create an item that is just a little too big.
247 BlobDataBuilder builder2(kId2);
248 builder2.AppendFutureData(kTestBlobStorageInFlightMemory + 1);
249
250 // Reserve memory, which should request successfuly but we can't fit it yet
251 // (no callback).
michaeln 2016/10/18 00:56:24 test for non-null task return value as the indicat
dmurph 2016/10/18 20:24:44 Done.
252 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
253 CreateSharedDataItems(builder2);
254 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
255 // We don't count the usage yet.
256 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
257 EXPECT_EQ(0u, controller.disk_usage());
258
259 EXPECT_FALSE(memory_quota_result_);
260 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
261 EXPECT_FALSE(file_runner_->HasPendingTask());
262
263 // Add our original item as populated so it's paged to disk.
264 items[0]->item()->data_element_ptr()->SetToBytes(
265 kData, kTestBlobStorageMaxBlobMemorySize);
266 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
267 controller.NotifyMemoryItemsUsed(items);
268
269 EXPECT_TRUE(file_runner_->HasPendingTask());
270 RunFileThreadTasks();
271 base::RunLoop().RunUntilIdle();
272 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
273 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
274 EXPECT_EQ(kTestBlobStorageInFlightMemory + 1, controller.memory_usage());
275 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
michaeln 2016/10/18 00:56:24 also test for a now-null task as the indicator of
dmurph 2016/10/18 20:24:44 Done.
276
277 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
278
279 items2.clear();
280 EXPECT_EQ(0u, controller.memory_usage());
281 items.clear();
282 EXPECT_TRUE(file_runner_->HasPendingTask());
283 RunFileThreadTasks();
284 base::RunLoop().RunUntilIdle();
285 EXPECT_EQ(0u, controller.disk_usage());
286 }
287
288 TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) {
289 const std::string kId = "id";
290 BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
291 SetTestMemoryLimits(&controller);
292
293 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxBlobMemorySize +
294 kTestBlobStorageInFlightMemory + 1));
295 }
296
297 TEST_F(BlobMemoryControllerTest, TooLargeForDisk) {
298 const std::string kId = "id";
299 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
300 SetTestMemoryLimits(&controller);
301
302 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace + 1));
303 }
304
305 TEST_F(BlobMemoryControllerTest, CancelMemoryRequest) {
306 const std::string kId = "id";
307 const std::string kId2 = "id2";
308 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
309 SetTestMemoryLimits(&controller);
310
311 char kData[kTestBlobStorageMaxBlobMemorySize];
312 std::memset(kData, kTestBlobStorageMaxBlobMemorySize, 'e');
313
314 // Add memory item that is the memory quota.
315 BlobDataBuilder builder(kId);
316 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
317
318 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
319 CreateSharedDataItems(builder);
320
321 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
322
323 // Create an item that is just a little too big.
324 BlobDataBuilder builder2(kId2);
325 builder2.AppendFutureData(kTestBlobStorageInFlightMemory + 1);
326
327 // Reserve memory, which should request successfuly but we can't fit it yet
328 // (no callback).
329 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
330 CreateSharedDataItems(builder2);
331 base::WeakPtr<QuotaAllocationTask> task =
332 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
333 // We don't count the usage yet.
334 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
335 EXPECT_EQ(0u, controller.disk_usage());
336
337 // Add our original item as populated so we start paging to disk.
338 items[0]->item()->data_element_ptr()->SetToBytes(
339 kData, kTestBlobStorageMaxBlobMemorySize);
340 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
341 controller.NotifyMemoryItemsUsed(items);
342
343 EXPECT_TRUE(file_runner_->HasPendingTask());
344 EXPECT_TRUE(task);
345
346 task->Cancel();
347 EXPECT_FALSE(task);
348 RunFileThreadTasks();
349 base::RunLoop().RunUntilIdle();
350 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
351 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
352 EXPECT_EQ(0u, controller.memory_usage());
353 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
354
355 CleanUpFileItemsFromController(&controller, std::move(items), kId);
356 EXPECT_EQ(0u, controller.disk_usage());
357 }
358
359 TEST_F(BlobMemoryControllerTest, FileRequest) {
360 const std::string kId = "id";
361 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
362
363 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
364 SetTestMemoryLimits(&controller);
365
366 char kData[kBlobSize];
367 std::memset(kData, kBlobSize, 'e');
368
369 // Add item that is the file quota.
370 BlobDataBuilder builder(kId);
371 builder.AppendFutureFile(0, kBlobSize, 0);
372
373 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
374 CreateSharedDataItems(builder);
375
376 file_quota_result_ = false;
377 base::WeakPtr<QuotaAllocationTask> task =
378 controller.ReserveFileQuota(items, GetFileCreationCallback());
379 EXPECT_TRUE(task);
380 EXPECT_FALSE(file_quota_result_);
381 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
382 EXPECT_TRUE(file_runner_->HasPendingTask());
383 EXPECT_EQ(0u, controller.memory_usage());
384 EXPECT_EQ(kBlobSize, controller.disk_usage());
385
386 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
387
388 RunFileThreadTasks();
389 base::RunLoop().RunUntilIdle();
390 EXPECT_TRUE(file_quota_result_);
391 EXPECT_FALSE(file_runner_->HasPendingTask());
392 EXPECT_FALSE(task);
393
394 // Do the work to populate the file.
395 EXPECT_EQ(1u, files_created_.size());
396 EXPECT_TRUE(
397 builder.PopulateFutureFile(0, std::move(files_created_[0].file_reference),
398 files_created_[0].last_modified));
399 base::ThreadRestrictions::SetIOAllowed(true);
400 files_created_.clear();
401 base::ThreadRestrictions::SetIOAllowed(false);
402 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
403 EXPECT_FALSE(
404 BlobDataBuilder::IsFutureFileItem(items[0]->item()->data_element()));
405
406 builder.Clear();
407 CleanUpFileItemsFromController(&controller, std::move(items), kId);
408 EXPECT_EQ(0u, controller.disk_usage());
409 }
410
411 TEST_F(BlobMemoryControllerTest, CancelFileRequest) {
412 const std::string kId = "id";
413 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
414
415 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
416 SetTestMemoryLimits(&controller);
417
418 char kData[kBlobSize];
419 std::memset(kData, kBlobSize, 'e');
420
421 // Add memory item that is the memory quota.
422 BlobDataBuilder builder(kId);
423 builder.AppendFutureFile(0, kBlobSize, 0);
424
425 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
426 CreateSharedDataItems(builder);
427
428 base::WeakPtr<QuotaAllocationTask> task =
429 controller.ReserveFileQuota(items, GetFileCreationCallback());
430 EXPECT_TRUE(task);
431 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
432 EXPECT_TRUE(file_runner_->HasPendingTask());
433 EXPECT_EQ(0u, controller.memory_usage());
434 EXPECT_EQ(kBlobSize, controller.disk_usage());
435
436 task->Cancel();
437 EXPECT_FALSE(task);
438 EXPECT_EQ(kBlobSize, controller.disk_usage());
439 EXPECT_TRUE(file_runner_->HasPendingTask());
440 RunFileThreadTasks();
441 base::RunLoop().RunUntilIdle();
442 EXPECT_EQ(0u, controller.disk_usage());
443 }
444
445 TEST_F(BlobMemoryControllerTest, MultipleFilesPaged) {
446 const std::string kId1 = "id";
447 const size_t kSize1 = kTestBlobStorageMaxFileSizeBytes;
448 char kData1[kSize1];
449 std::memset(kData1, kSize1, 'e');
450
451 const std::string kId2 = "id2";
452 const size_t kSize2 = kTestBlobStorageMaxFileSizeBytes;
michaeln 2016/10/18 00:56:24 ah... this test depends on (2 x maxfilesize) <= ma
dmurph 2016/10/18 20:24:44 Done.
453 char kData2[kSize2];
454 std::memset(kData2, kSize2, 'f');
455
456 const std::string kId3 = "id3";
457 const size_t kSize3 = kTestBlobStorageMaxBlobMemorySize - 1;
458
459 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
460 SetTestMemoryLimits(&controller);
461
462 // We add two items that should be their own files when we page to disk, and
463 // then add the last item to trigger the paging.
464
465 BlobDataBuilder builder1(kId1);
466 builder1.AppendFutureData(kSize1);
467 BlobDataBuilder builder2(kId2);
468 builder2.AppendFutureData(kSize2);
469
470 std::vector<scoped_refptr<ShareableBlobDataItem>> items1 =
471 CreateSharedDataItems(builder1);
472 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
473 CreateSharedDataItems(builder2);
474
475 memory_quota_result_ = false;
476 controller.ReserveMemoryQuota(items1, GetMemoryRequestCallback());
477 EXPECT_TRUE(memory_quota_result_);
478 memory_quota_result_ = false;
479 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
480 EXPECT_TRUE(memory_quota_result_);
481 EXPECT_EQ(ItemState::QUOTA_GRANTED, items1[0]->state());
482 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
483 EXPECT_FALSE(file_runner_->HasPendingTask());
484 EXPECT_EQ(kSize1 + kSize2, controller.memory_usage());
485 EXPECT_EQ(0u, controller.disk_usage());
486
487 // Create an item that is too big.
488 BlobDataBuilder builder3(kId3);
489 builder3.AppendFutureData(kSize3);
490
491 std::vector<scoped_refptr<ShareableBlobDataItem>> items3 =
492 CreateSharedDataItems(builder3);
493 memory_quota_result_ = false;
494 controller.ReserveMemoryQuota(items3, GetMemoryRequestCallback());
495 EXPECT_FALSE(memory_quota_result_);
496
497 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items3[0]->state());
498 EXPECT_FALSE(file_runner_->HasPendingTask());
499
500 // Add our original item as populated so it's paged to disk.
501 items1[0]->item()->data_element_ptr()->SetToBytes(kData1, kSize1);
502 items1[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
503 items2[0]->item()->data_element_ptr()->SetToBytes(kData2, kSize2);
504 items2[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
505
506 std::vector<scoped_refptr<ShareableBlobDataItem>> both_items = {items1[0],
507 items2[0]};
508 controller.NotifyMemoryItemsUsed(both_items);
509 both_items.clear();
510
511 EXPECT_TRUE(file_runner_->HasPendingTask());
512 RunFileThreadTasks();
513 base::RunLoop().RunUntilIdle();
514 EXPECT_TRUE(memory_quota_result_);
515 EXPECT_EQ(ItemState::QUOTA_GRANTED, items3[0]->state());
516 EXPECT_EQ(DataElement::TYPE_FILE, items1[0]->item()->type());
517 EXPECT_EQ(DataElement::TYPE_FILE, items2[0]->item()->type());
518 EXPECT_NE(items1[0]->item()->path(), items2[0]->item()->path());
519 EXPECT_EQ(kSize3, controller.memory_usage());
520 EXPECT_EQ(kSize1 + kSize2, controller.disk_usage());
521
522 items1.clear();
523 items2.clear();
524 items3.clear();
525
526 EXPECT_EQ(0u, controller.memory_usage());
527 base::RunLoop().RunUntilIdle();
528 EXPECT_TRUE(file_runner_->HasPendingTask());
529 RunFileThreadTasks();
530 base::RunLoop().RunUntilIdle();
531 EXPECT_EQ(0u, controller.disk_usage());
532 }
533
534 TEST_F(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) {
535 const std::string kFirstMemoryId = "id";
536 const uint64_t kFirstMemorySize = kTestBlobStorageMaxBlobMemorySize;
537 const std::string kSecondMemoryId = "id2";
538 const uint64_t kSecondMemorySize = 1;
539 const std::string kFileId = "id2";
540 const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
541
542 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
543 SetTestMemoryLimits(&controller);
544
545 char kDataMemoryData[kFirstMemorySize];
546 std::memset(kDataMemoryData, kFirstMemorySize, 'e');
547
548 // Add first memory item to fill up some memory quota.
549 BlobDataBuilder builder(kFirstMemoryId);
550 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
551
552 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
553 CreateSharedDataItems(builder);
554
555 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
556
557 // Create a second memory item that is just a little too big.
558 BlobDataBuilder builder2(kSecondMemoryId);
559 builder2.AppendFutureData(kSecondMemorySize);
560
561 // Reserve memory, which should request successfuly but we can't fit it yet.
562 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
563 CreateSharedDataItems(builder2);
564 base::WeakPtr<QuotaAllocationTask> memory_task =
565 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
566 // We don't count the usage yet.
567 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
568 EXPECT_EQ(0u, controller.disk_usage());
569
570 // Add our original item as populated so we start paging it to disk.
571 items[0]->item()->data_element_ptr()->SetToBytes(kDataMemoryData,
572 kFirstMemorySize);
573 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
574 controller.NotifyMemoryItemsUsed(items);
575
576 EXPECT_TRUE(file_runner_->HasPendingTask());
577 EXPECT_TRUE(memory_task);
578 EXPECT_EQ(kFirstMemorySize, controller.disk_usage());
579
580 // Add our file item now.
581 BlobDataBuilder file_builder(kFileId);
582 file_builder.AppendFutureFile(0, kFileBlobSize, 0);
583
584 std::vector<scoped_refptr<ShareableBlobDataItem>> file_items =
585 CreateSharedDataItems(file_builder);
586
587 base::WeakPtr<QuotaAllocationTask> file_task =
588 controller.ReserveFileQuota(file_items, GetFileCreationCallback());
589 EXPECT_TRUE(file_task);
590 EXPECT_TRUE(file_runner_->HasPendingTask());
591
592 // We should have both memory paging tasks and file paging tasks.
593 EXPECT_EQ(kFirstMemorySize, controller.memory_usage());
594 EXPECT_EQ(kFirstMemorySize + kFileBlobSize, controller.disk_usage());
595 file_quota_result_ = true;
596 memory_quota_result_ = true;
597
598 files_created_.clear();
599
600 // Disable paging! This should cancel all file-related tasks and leave us with
601 // only the first memory item.
602 controller.DisableFilePaging(base::File::FILE_ERROR_FAILED);
603 EXPECT_FALSE(file_quota_result_);
604 EXPECT_FALSE(memory_quota_result_);
605 EXPECT_FALSE(file_task);
606 EXPECT_FALSE(memory_task);
607
608 file_items.clear();
609 items.clear();
610
611 RunFileThreadTasks();
612 base::RunLoop().RunUntilIdle();
613
614 EXPECT_EQ(0ull, controller.disk_usage());
615 EXPECT_EQ(0ull, controller.memory_usage());
616 }
617 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698