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

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

Issue 2339933004: [BlobStorage] BlobMemoryController & tests (Closed)
Patch Set: histograms and 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 HasMemoryAllocation(ShareableBlobDataItem* item) {
124 return static_cast<bool>(item->memory_allocation_);
125 }
126
127 bool file_quota_result_ = false;
128 base::ScopedTempDir temp_dir_;
129 std::vector<FileCreationInfo> files_created_;
130 bool memory_quota_result_ = false;
131
132 scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner();
133
134 base::MessageLoop fake_io_message_loop_;
135 };
136
137 TEST_F(BlobMemoryControllerTest, Strategy) {
138 {
139 BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
140 SetTestMemoryLimits(&controller);
141
142 // No transportation needed.
143 EXPECT_EQ(Strategy::NONE_NEEDED, controller.DetermineStrategy(0, 0));
144
145 // IPC.
146 EXPECT_EQ(Strategy::IPC, controller.DetermineStrategy(
147 0, kTestBlobStorageIPCThresholdBytes));
148
149 // Shared Memory.
150 EXPECT_EQ(
151 Strategy::SHARED_MEMORY,
152 controller.DetermineStrategy(kTestBlobStorageIPCThresholdBytes,
153 kTestBlobStorageMaxSharedMemoryBytes));
154
155 // Not too large, as disk isn't enabled.
pwnall 2016/10/18 23:20:13 Does the "as disk isn't enabled" fragment belong t
dmurph 2016/10/20 00:09:48 Done.
156 EXPECT_EQ(
157 Strategy::SHARED_MEMORY,
158 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize));
159
160 // Too large.
161 EXPECT_EQ(
162 Strategy::TOO_LARGE,
163 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize + 1));
164 }
165 {
166 // Enable disk, and check file strategies.
167 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
168 SetTestMemoryLimits(&controller);
169 EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
pwnall 2016/10/18 23:20:13 Is this a fencepost test? If so, should it be prec
dmurph 2016/10/20 00:09:48 Done.
170 0, kTestBlobStorageMaxBlobMemorySize -
171 kTestBlobStorageInFlightMemory + 1));
172
173 EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
174 0, kTestBlobStorageMaxBlobMemorySize));
175
176 // Too large for disk.
177 EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(
178 0, kTestBlobStorageMaxDiskSpace + 1));
179 }
180 }
181
182 TEST_F(BlobMemoryControllerTest, GrantMemory) {
183 const std::string kId = "id";
184 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
185 SetTestMemoryLimits(&controller);
186
187 BlobDataBuilder builder(kId);
188 builder.AppendFutureData(10);
189 builder.AppendFutureData(20);
190 builder.AppendFutureData(30);
191
192 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
193 CreateSharedDataItems(builder);
194
195 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
196 EXPECT_TRUE(memory_quota_result_);
197 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
198 EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
199 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[1]->state());
200 EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
201 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[2]->state());
202 EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
203 }
204
205 TEST_F(BlobMemoryControllerTest, SimpleMemoryRequest) {
206 const std::string kId = "id";
207 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
208 SetTestMemoryLimits(&controller);
209
210 // Add memory item that is the memory quota.
211 BlobDataBuilder builder(kId);
212 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
213
214 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
215 CreateSharedDataItems(builder);
216
217 base::WeakPtr<QuotaAllocationTask> task =
218 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
219 EXPECT_EQ(nullptr, task);
220 EXPECT_TRUE(memory_quota_result_);
221 memory_quota_result_ = false;
222 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
223 EXPECT_FALSE(file_runner_->HasPendingTask());
224 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
225 EXPECT_EQ(0u, controller.disk_usage());
226
227 items.clear();
228 EXPECT_EQ(0u, controller.memory_usage());
229 }
230
231 TEST_F(BlobMemoryControllerTest, PageToDisk) {
232 const std::string kId = "id";
233 const std::string kId2 = "id2";
234 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
235 SetTestMemoryLimits(&controller);
236
237 char kData[kTestBlobStorageMaxBlobMemorySize];
238 std::memset(kData, kTestBlobStorageMaxBlobMemorySize, 'e');
239
240 // Add memory item that is the memory quota.
241 BlobDataBuilder builder(kId);
242 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
243
244 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
245 CreateSharedDataItems(builder);
246
247 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
248 EXPECT_TRUE(memory_quota_result_);
249 memory_quota_result_ = false;
250 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
251 EXPECT_FALSE(file_runner_->HasPendingTask());
252 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
253 EXPECT_EQ(0u, controller.disk_usage());
254
255 // Create an item that is just a little too big.
256 BlobDataBuilder builder2(kId2);
257 builder2.AppendFutureData(kTestBlobStorageInFlightMemory + 1);
258
259 // Reserve memory, which should request successfuly but we can't fit it yet
260 // (no callback).
261 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
262 CreateSharedDataItems(builder2);
263 base::WeakPtr<QuotaAllocationTask> task =
264 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
265 EXPECT_NE(nullptr, task);
266 // We don't count the usage yet.
267 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
268 EXPECT_EQ(0u, controller.disk_usage());
269
270 EXPECT_FALSE(memory_quota_result_);
271 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
272 EXPECT_FALSE(file_runner_->HasPendingTask());
273
274 // Add our original item as populated so it's paged to disk.
275 items[0]->item()->data_element_ptr()->SetToBytes(
276 kData, kTestBlobStorageMaxBlobMemorySize);
277 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
278 controller.NotifyMemoryItemsUsed(items);
279
280 EXPECT_TRUE(file_runner_->HasPendingTask());
281 RunFileThreadTasks();
282 base::RunLoop().RunUntilIdle();
283 // items2 are successfuly allocated.
284 EXPECT_EQ(nullptr, task);
285 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
286 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
287 EXPECT_EQ(kTestBlobStorageInFlightMemory + 1, controller.memory_usage());
288 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
289
290 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
291
292 items2.clear();
293 EXPECT_EQ(0u, controller.memory_usage());
294 items.clear();
295 EXPECT_TRUE(file_runner_->HasPendingTask());
296 RunFileThreadTasks();
297 base::RunLoop().RunUntilIdle();
298 EXPECT_EQ(0u, controller.disk_usage());
299 }
300
301 TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) {
302 const std::string kId = "id";
303 BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
304 SetTestMemoryLimits(&controller);
305
306 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxBlobMemorySize +
307 kTestBlobStorageInFlightMemory + 1));
308 }
309
310 TEST_F(BlobMemoryControllerTest, TooLargeForDisk) {
311 const std::string kId = "id";
312 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
313 SetTestMemoryLimits(&controller);
314
315 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace + 1));
316 }
317
318 TEST_F(BlobMemoryControllerTest, CancelMemoryRequest) {
319 const std::string kId = "id";
320 const std::string kId2 = "id2";
321 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
322 SetTestMemoryLimits(&controller);
323
324 char kData[kTestBlobStorageMaxBlobMemorySize];
325 std::memset(kData, kTestBlobStorageMaxBlobMemorySize, 'e');
326
327 // Add memory item that is the memory quota.
328 BlobDataBuilder builder(kId);
329 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
330
331 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
332 CreateSharedDataItems(builder);
333
334 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
335
336 // Create an item that is just a little too big.
337 BlobDataBuilder builder2(kId2);
338 builder2.AppendFutureData(kTestBlobStorageInFlightMemory + 1);
339
340 // Reserve memory, which should request successfuly but we can't fit it yet
341 // (no callback).
342 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
343 CreateSharedDataItems(builder2);
344 base::WeakPtr<QuotaAllocationTask> task =
345 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
346 // We don't count the usage yet.
347 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
348 EXPECT_EQ(0u, controller.disk_usage());
349
350 // Add our original item as populated so we start paging to disk.
351 items[0]->item()->data_element_ptr()->SetToBytes(
352 kData, kTestBlobStorageMaxBlobMemorySize);
353 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
354 controller.NotifyMemoryItemsUsed(items);
355
356 EXPECT_TRUE(file_runner_->HasPendingTask());
357 EXPECT_TRUE(task);
358
359 task->Cancel();
360 EXPECT_FALSE(task);
361 RunFileThreadTasks();
362 base::RunLoop().RunUntilIdle();
363 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
364 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
365 EXPECT_EQ(0u, controller.memory_usage());
366 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
367
368 CleanUpFileItemsFromController(&controller, std::move(items), kId);
369 EXPECT_EQ(0u, controller.disk_usage());
370 }
371
372 TEST_F(BlobMemoryControllerTest, FileRequest) {
373 const std::string kId = "id";
374 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
375
376 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
377 SetTestMemoryLimits(&controller);
378
379 char kData[kBlobSize];
380 std::memset(kData, kBlobSize, 'e');
381
382 // Add item that is the file quota.
383 BlobDataBuilder builder(kId);
384 builder.AppendFutureFile(0, kBlobSize, 0);
385
386 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
387 CreateSharedDataItems(builder);
388
389 file_quota_result_ = false;
390 base::WeakPtr<QuotaAllocationTask> task =
391 controller.ReserveFileQuota(items, GetFileCreationCallback());
392 EXPECT_TRUE(task);
393 EXPECT_FALSE(file_quota_result_);
394 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
395 EXPECT_TRUE(file_runner_->HasPendingTask());
396 EXPECT_EQ(0u, controller.memory_usage());
397 EXPECT_EQ(kBlobSize, controller.disk_usage());
398
399 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
400
401 RunFileThreadTasks();
402 base::RunLoop().RunUntilIdle();
403 EXPECT_TRUE(file_quota_result_);
404 EXPECT_FALSE(file_runner_->HasPendingTask());
405 EXPECT_FALSE(task);
406
407 // Do the work to populate the file.
408 EXPECT_EQ(1u, files_created_.size());
409 EXPECT_TRUE(
410 builder.PopulateFutureFile(0, std::move(files_created_[0].file_reference),
411 files_created_[0].last_modified));
412 base::ThreadRestrictions::SetIOAllowed(true);
413 files_created_.clear();
414 base::ThreadRestrictions::SetIOAllowed(false);
415 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
416 EXPECT_FALSE(
417 BlobDataBuilder::IsFutureFileItem(items[0]->item()->data_element()));
418
419 builder.Clear();
420 CleanUpFileItemsFromController(&controller, std::move(items), kId);
421 EXPECT_EQ(0u, controller.disk_usage());
422 }
423
424 TEST_F(BlobMemoryControllerTest, CancelFileRequest) {
425 const std::string kId = "id";
426 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
427
428 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
429 SetTestMemoryLimits(&controller);
430
431 char kData[kBlobSize];
432 std::memset(kData, kBlobSize, 'e');
433
434 // Add memory item that is the memory quota.
435 BlobDataBuilder builder(kId);
436 builder.AppendFutureFile(0, kBlobSize, 0);
437
438 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
439 CreateSharedDataItems(builder);
440
441 base::WeakPtr<QuotaAllocationTask> task =
442 controller.ReserveFileQuota(items, GetFileCreationCallback());
443 EXPECT_TRUE(task);
444 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
445 EXPECT_TRUE(file_runner_->HasPendingTask());
446 EXPECT_EQ(0u, controller.memory_usage());
447 EXPECT_EQ(kBlobSize, controller.disk_usage());
448
449 task->Cancel();
450 EXPECT_FALSE(task);
451 EXPECT_EQ(kBlobSize, controller.disk_usage());
452 EXPECT_TRUE(file_runner_->HasPendingTask());
453 RunFileThreadTasks();
454 base::RunLoop().RunUntilIdle();
455 EXPECT_EQ(0u, controller.disk_usage());
456 }
457
458 TEST_F(BlobMemoryControllerTest, MultipleFilesPaged) {
459 const std::string kId1 = "id";
460 const size_t kSize1 = kTestBlobStorageMaxFileSizeBytes;
461 char kData1[kSize1];
462 std::memset(kData1, 'e', kSize1);
463
464 const std::string kId2 = "id2";
465 const size_t kSize2 = kTestBlobStorageMaxFileSizeBytes;
466 char kData2[kSize2];
467 std::memset(kData2, 'f', kSize2);
468
469 const std::string kId3 = "id3";
470 const size_t kSize3 = kTestBlobStorageMaxBlobMemorySize - 1;
471
472 // Assert we shouldn't trigger paging preemptively.
473 ASSERT_LE(kSize1 + kSize2, kTestBlobStorageMaxBlobMemorySize);
474
475 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
476 SetTestMemoryLimits(&controller);
477
478 // We add two items that should be their own files when we page to disk, and
479 // then add the last item to trigger the paging.
480
481 BlobDataBuilder builder1(kId1);
482 builder1.AppendFutureData(kSize1);
483 BlobDataBuilder builder2(kId2);
484 builder2.AppendFutureData(kSize2);
485
486 std::vector<scoped_refptr<ShareableBlobDataItem>> items1 =
487 CreateSharedDataItems(builder1);
488 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
489 CreateSharedDataItems(builder2);
490
491 memory_quota_result_ = false;
492 controller.ReserveMemoryQuota(items1, GetMemoryRequestCallback());
493 EXPECT_TRUE(memory_quota_result_);
494 memory_quota_result_ = false;
495 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
496 EXPECT_TRUE(memory_quota_result_);
497 EXPECT_EQ(ItemState::QUOTA_GRANTED, items1[0]->state());
498 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
499 EXPECT_FALSE(file_runner_->HasPendingTask());
500 EXPECT_EQ(kSize1 + kSize2, controller.memory_usage());
501 EXPECT_EQ(0u, controller.disk_usage());
502
503 // Create an item that is too big.
504 BlobDataBuilder builder3(kId3);
505 builder3.AppendFutureData(kSize3);
506
507 std::vector<scoped_refptr<ShareableBlobDataItem>> items3 =
508 CreateSharedDataItems(builder3);
509 memory_quota_result_ = false;
510 controller.ReserveMemoryQuota(items3, GetMemoryRequestCallback());
511 EXPECT_FALSE(memory_quota_result_);
512
513 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items3[0]->state());
514 EXPECT_FALSE(file_runner_->HasPendingTask());
515
516 // Add our original item as populated so it's paged to disk.
517 items1[0]->item()->data_element_ptr()->SetToBytes(kData1, kSize1);
518 items1[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
519 items2[0]->item()->data_element_ptr()->SetToBytes(kData2, kSize2);
520 items2[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
521
522 std::vector<scoped_refptr<ShareableBlobDataItem>> both_items = {items1[0],
523 items2[0]};
524 controller.NotifyMemoryItemsUsed(both_items);
525 both_items.clear();
526
527 EXPECT_TRUE(file_runner_->HasPendingTask());
528 RunFileThreadTasks();
529 base::RunLoop().RunUntilIdle();
530 EXPECT_TRUE(memory_quota_result_);
531 EXPECT_EQ(ItemState::QUOTA_GRANTED, items3[0]->state());
532 EXPECT_EQ(DataElement::TYPE_FILE, items1[0]->item()->type());
533 EXPECT_EQ(DataElement::TYPE_FILE, items2[0]->item()->type());
534 EXPECT_NE(items1[0]->item()->path(), items2[0]->item()->path());
535 EXPECT_EQ(kSize3, controller.memory_usage());
536 EXPECT_EQ(kSize1 + kSize2, controller.disk_usage());
537
538 items1.clear();
539 items2.clear();
540 items3.clear();
541
542 EXPECT_EQ(0u, controller.memory_usage());
543 base::RunLoop().RunUntilIdle();
544 EXPECT_TRUE(file_runner_->HasPendingTask());
545 RunFileThreadTasks();
546 base::RunLoop().RunUntilIdle();
547 EXPECT_EQ(0u, controller.disk_usage());
548 }
549
550 TEST_F(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) {
551 const std::string kFirstMemoryId = "id";
552 const uint64_t kFirstMemorySize = kTestBlobStorageMaxBlobMemorySize;
553 const std::string kSecondMemoryId = "id2";
554 const uint64_t kSecondMemorySize = 1;
555 const std::string kFileId = "id2";
556 const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
557
558 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
559 SetTestMemoryLimits(&controller);
560
561 char kDataMemoryData[kFirstMemorySize];
562 std::memset(kDataMemoryData, kFirstMemorySize, 'e');
563
564 // Add first memory item to fill up some memory quota.
565 BlobDataBuilder builder(kFirstMemoryId);
566 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
567
568 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
569 CreateSharedDataItems(builder);
570
571 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
572
573 // Create a second memory item that is just a little too big.
574 BlobDataBuilder builder2(kSecondMemoryId);
575 builder2.AppendFutureData(kSecondMemorySize);
576
577 // Reserve memory, which should request successfuly but we can't fit it yet.
578 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
579 CreateSharedDataItems(builder2);
580 base::WeakPtr<QuotaAllocationTask> memory_task =
581 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
582 // We don't count the usage yet.
583 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
584 EXPECT_EQ(0u, controller.disk_usage());
585
586 // Add our original item as populated so we start paging it to disk.
587 items[0]->item()->data_element_ptr()->SetToBytes(kDataMemoryData,
588 kFirstMemorySize);
589 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
590 controller.NotifyMemoryItemsUsed(items);
591
592 EXPECT_TRUE(file_runner_->HasPendingTask());
593 EXPECT_TRUE(memory_task);
594 EXPECT_EQ(kFirstMemorySize, controller.disk_usage());
595
596 // Add our file item now.
597 BlobDataBuilder file_builder(kFileId);
598 file_builder.AppendFutureFile(0, kFileBlobSize, 0);
599
600 std::vector<scoped_refptr<ShareableBlobDataItem>> file_items =
601 CreateSharedDataItems(file_builder);
602
603 base::WeakPtr<QuotaAllocationTask> file_task =
604 controller.ReserveFileQuota(file_items, GetFileCreationCallback());
605 EXPECT_TRUE(file_task);
606 EXPECT_TRUE(file_runner_->HasPendingTask());
607
608 // We should have both memory paging tasks and file paging tasks.
609 EXPECT_EQ(kFirstMemorySize, controller.memory_usage());
610 EXPECT_EQ(kFirstMemorySize + kFileBlobSize, controller.disk_usage());
611 file_quota_result_ = true;
612 memory_quota_result_ = true;
613
614 files_created_.clear();
615
616 // Disable paging! This should cancel all file-related tasks and leave us with
617 // only the first memory item.
618 controller.DisableFilePaging(base::File::FILE_ERROR_FAILED);
619 EXPECT_FALSE(file_quota_result_);
620 EXPECT_FALSE(memory_quota_result_);
621 EXPECT_FALSE(file_task);
622 EXPECT_FALSE(memory_task);
623
624 file_items.clear();
625 items.clear();
626
627 RunFileThreadTasks();
628 base::RunLoop().RunUntilIdle();
629
630 EXPECT_EQ(0ull, controller.disk_usage());
631 EXPECT_EQ(0ull, controller.memory_usage());
632 }
633 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698