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

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

Issue 2339933004: [BlobStorage] BlobMemoryController & tests (Closed)
Patch Set: comments, added MemoryAllocation, and changed memory quota bookkeeping 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 + 1));
167
168 // Too large for disk.
169 EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(
170 0, kTestBlobStorageMaxDiskSpace + 1));
171 }
172 }
173
174 TEST_F(BlobMemoryControllerTest, GrantMemory) {
175 const std::string kId = "id";
176 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
177 SetTestMemoryLimits(&controller);
178
179 BlobDataBuilder builder(kId);
180 builder.AppendFutureData(10);
181 builder.AppendFutureData(20);
182 builder.AppendFutureData(30);
183
184 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
185 CreateSharedDataItems(builder);
186
187 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
188 EXPECT_TRUE(memory_quota_result_);
189 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
190 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[1]->state());
191 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[2]->state());
192 }
193
194 TEST_F(BlobMemoryControllerTest, SimpleMemoryRequest) {
195 const std::string kId = "id";
196 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
197 SetTestMemoryLimits(&controller);
198
199 // Add memory item that is the memory quota.
200 BlobDataBuilder builder(kId);
201 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
202
203 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
204 CreateSharedDataItems(builder);
205
206 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
207 EXPECT_TRUE(memory_quota_result_);
208 memory_quota_result_ = false;
209 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
210 EXPECT_FALSE(file_runner_->HasPendingTask());
211 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
212 EXPECT_EQ(0u, controller.disk_usage());
213
214 items.clear();
215 EXPECT_EQ(0u, controller.memory_usage());
216 }
217
218 TEST_F(BlobMemoryControllerTest, PageToDisk) {
219 const std::string kId = "id";
220 const std::string kId2 = "id2";
221 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
222 SetTestMemoryLimits(&controller);
223
224 char kData[kTestBlobStorageMaxBlobMemorySize];
225 std::memset(kData, kTestBlobStorageMaxBlobMemorySize, 'e');
226
227 // Add memory item that is the memory quota.
228 BlobDataBuilder builder(kId);
229 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
230
231 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
232 CreateSharedDataItems(builder);
233
234 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
235 EXPECT_TRUE(memory_quota_result_);
236 memory_quota_result_ = false;
237 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
238 EXPECT_FALSE(file_runner_->HasPendingTask());
239 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
240 EXPECT_EQ(0u, controller.disk_usage());
241
242 // Create an item that is just a little too big.
243 BlobDataBuilder builder2(kId2);
244 builder2.AppendFutureData(kTestBlobStorageInFlightMemory + 1);
245
246 // Reserve memory, which should request successfuly but we can't fit it yet
247 // (no callback).
248 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
249 CreateSharedDataItems(builder2);
250 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
251 // We don't count the usage yet.
252 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
253 EXPECT_EQ(0u, controller.disk_usage());
254
255 EXPECT_FALSE(memory_quota_result_);
256 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
257 EXPECT_FALSE(file_runner_->HasPendingTask());
258
259 // Add our original item as populated so it's paged to disk.
260 items[0]->item()->data_element_ptr()->SetToBytes(
261 kData, kTestBlobStorageMaxBlobMemorySize);
262 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
263 controller.NotifyMemoryItemUsed(items[0].get());
264
265 EXPECT_TRUE(file_runner_->HasPendingTask());
266 RunFileThreadTasks();
267 base::RunLoop().RunUntilIdle();
268 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
269 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
270 EXPECT_EQ(kTestBlobStorageInFlightMemory + 1, controller.memory_usage());
271 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
272
273 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
274
275 items2.clear();
276 EXPECT_EQ(0u, controller.memory_usage());
277 items.clear();
278 EXPECT_TRUE(file_runner_->HasPendingTask());
279 RunFileThreadTasks();
280 base::RunLoop().RunUntilIdle();
281 EXPECT_EQ(0u, controller.disk_usage());
282 }
283
284 TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) {
285 const std::string kId = "id";
286 BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
287 SetTestMemoryLimits(&controller);
288
289 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxBlobMemorySize +
290 kTestBlobStorageInFlightMemory + 1));
291 }
292
293 TEST_F(BlobMemoryControllerTest, TooLargeForDisk) {
294 const std::string kId = "id";
295 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
296 SetTestMemoryLimits(&controller);
297
298 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace + 1));
299 }
300
301 TEST_F(BlobMemoryControllerTest, CancelMemoryRequest) {
302 const std::string kId = "id";
303 const std::string kId2 = "id2";
304 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
305 SetTestMemoryLimits(&controller);
306
307 char kData[kTestBlobStorageMaxBlobMemorySize];
308 std::memset(kData, kTestBlobStorageMaxBlobMemorySize, 'e');
309
310 // Add memory item that is the memory quota.
311 BlobDataBuilder builder(kId);
312 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
313
314 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
315 CreateSharedDataItems(builder);
316
317 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
318
319 // Create an item that is just a little too big.
320 BlobDataBuilder builder2(kId2);
321 builder2.AppendFutureData(kTestBlobStorageInFlightMemory + 1);
322
323 // Reserve memory, which should request successfuly but we can't fit it yet
324 // (no callback).
325 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
326 CreateSharedDataItems(builder2);
327 base::WeakPtr<QuotaAllocationTask> task =
328 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
329 // We don't count the usage yet.
330 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
331 EXPECT_EQ(0u, controller.disk_usage());
332
333 // Add our original item as populated so we start paging to disk.
334 items[0]->item()->data_element_ptr()->SetToBytes(
335 kData, kTestBlobStorageMaxBlobMemorySize);
336 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
337 controller.NotifyMemoryItemUsed(items[0].get());
338
339 EXPECT_TRUE(file_runner_->HasPendingTask());
340 EXPECT_TRUE(task);
341
342 task->Cancel();
343 EXPECT_FALSE(task);
344 RunFileThreadTasks();
345 base::RunLoop().RunUntilIdle();
346 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
347 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
348 EXPECT_EQ(0u, controller.memory_usage());
349 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
350
351 CleanUpFileItemsFromController(&controller, std::move(items), kId);
352 EXPECT_EQ(0u, controller.disk_usage());
353 }
354
355 TEST_F(BlobMemoryControllerTest, FileRequest) {
356 const std::string kId = "id";
357 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
358
359 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
360 SetTestMemoryLimits(&controller);
361
362 char kData[kBlobSize];
363 std::memset(kData, kBlobSize, 'e');
364
365 // Add item that is the file quota.
366 BlobDataBuilder builder(kId);
367 builder.AppendFutureFile(0, kBlobSize, 0);
368
369 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
370 CreateSharedDataItems(builder);
371
372 file_quota_result_ = false;
373 base::WeakPtr<QuotaAllocationTask> task =
374 controller.ReserveFileQuota(items, GetFileCreationCallback());
375 EXPECT_TRUE(task);
376 EXPECT_FALSE(file_quota_result_);
377 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
378 EXPECT_TRUE(file_runner_->HasPendingTask());
379 EXPECT_EQ(0u, controller.memory_usage());
380 EXPECT_EQ(kBlobSize, controller.disk_usage());
381
382 EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
383
384 RunFileThreadTasks();
385 base::RunLoop().RunUntilIdle();
386 EXPECT_TRUE(file_quota_result_);
387 EXPECT_FALSE(file_runner_->HasPendingTask());
388 EXPECT_FALSE(task);
389
390 // Do the work to populate the file.
391 EXPECT_EQ(1u, files_created_.size());
392 EXPECT_TRUE(
393 builder.PopulateFutureFile(0, std::move(files_created_[0].file_reference),
394 files_created_[0].last_modified));
395 base::ThreadRestrictions::SetIOAllowed(true);
396 files_created_.clear();
397 base::ThreadRestrictions::SetIOAllowed(false);
398 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
399 EXPECT_FALSE(
400 BlobDataBuilder::IsFutureFileItem(items[0]->item()->data_element()));
401
402 builder.Clear();
403 CleanUpFileItemsFromController(&controller, std::move(items), kId);
404 EXPECT_EQ(0u, controller.disk_usage());
405 }
406
407 TEST_F(BlobMemoryControllerTest, CancelFileRequest) {
408 const std::string kId = "id";
409 const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
410
411 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
412 SetTestMemoryLimits(&controller);
413
414 char kData[kBlobSize];
415 std::memset(kData, kBlobSize, 'e');
416
417 // Add memory item that is the memory quota.
418 BlobDataBuilder builder(kId);
419 builder.AppendFutureFile(0, kBlobSize, 0);
420
421 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
422 CreateSharedDataItems(builder);
423
424 base::WeakPtr<QuotaAllocationTask> task =
425 controller.ReserveFileQuota(items, GetFileCreationCallback());
426 EXPECT_TRUE(task);
427 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
428 EXPECT_TRUE(file_runner_->HasPendingTask());
429 EXPECT_EQ(0u, controller.memory_usage());
430 EXPECT_EQ(kBlobSize, controller.disk_usage());
431
432 task->Cancel();
433 EXPECT_FALSE(task);
434 EXPECT_EQ(kBlobSize, controller.disk_usage());
435 EXPECT_TRUE(file_runner_->HasPendingTask());
436 RunFileThreadTasks();
437 base::RunLoop().RunUntilIdle();
438 EXPECT_EQ(0u, controller.disk_usage());
439 }
440
441 TEST_F(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) {
442 const std::string kFirstMemoryId = "id";
443 const uint64_t kFirstMemorySize = kTestBlobStorageMaxBlobMemorySize;
444 const std::string kSecondMemoryId = "id2";
445 const uint64_t kSecondMemorySize = 1;
446 const std::string kFileId = "id2";
447 const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
448
449 BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
450 SetTestMemoryLimits(&controller);
451
452 char kDataMemoryData[kFirstMemorySize];
453 std::memset(kDataMemoryData, kFirstMemorySize, 'e');
454
455 // Add first memory item to fill up some memory quota.
456 BlobDataBuilder builder(kFirstMemoryId);
457 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
458
459 std::vector<scoped_refptr<ShareableBlobDataItem>> items =
460 CreateSharedDataItems(builder);
461
462 controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
463
464 // Create a second memory item that is just a little too big.
465 BlobDataBuilder builder2(kSecondMemoryId);
466 builder2.AppendFutureData(kSecondMemorySize);
467
468 // Reserve memory, which should request successfuly but we can't fit it yet.
469 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
470 CreateSharedDataItems(builder2);
471 base::WeakPtr<QuotaAllocationTask> memory_task =
472 controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
473 // We don't count the usage yet.
474 EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
475 EXPECT_EQ(0u, controller.disk_usage());
476
477 // Add our original item as populated so we start paging it to disk.
478 items[0]->item()->data_element_ptr()->SetToBytes(kDataMemoryData,
479 kFirstMemorySize);
480 items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
481 controller.NotifyMemoryItemUsed(items[0].get());
482
483 EXPECT_TRUE(file_runner_->HasPendingTask());
484 EXPECT_TRUE(memory_task);
485 EXPECT_EQ(kFirstMemorySize, controller.disk_usage());
486
487 // Add our file item now.
488 BlobDataBuilder file_builder(kFileId);
489 file_builder.AppendFutureFile(0, kFileBlobSize, 0);
490
491 std::vector<scoped_refptr<ShareableBlobDataItem>> file_items =
492 CreateSharedDataItems(file_builder);
493
494 base::WeakPtr<QuotaAllocationTask> file_task =
495 controller.ReserveFileQuota(file_items, GetFileCreationCallback());
496 EXPECT_TRUE(file_task);
497 EXPECT_TRUE(file_runner_->HasPendingTask());
498
499 // We should have both memory paging tasks and file paging tasks.
500 EXPECT_EQ(kFirstMemorySize, controller.memory_usage());
501 EXPECT_EQ(kFirstMemorySize + kFileBlobSize, controller.disk_usage());
502 file_quota_result_ = true;
503 memory_quota_result_ = true;
504
505 files_created_.clear();
506
507 // Disable paging! This should cancel all file-related tasks and leave us with
508 // only the first memory item.
509 controller.DisableFilePaging(base::File::FILE_ERROR_FAILED);
510 EXPECT_FALSE(file_quota_result_);
511 EXPECT_FALSE(memory_quota_result_);
512 EXPECT_FALSE(file_task);
513 EXPECT_FALSE(memory_task);
514
515 file_items.clear();
516 items.clear();
517
518 RunFileThreadTasks();
519 base::RunLoop().RunUntilIdle();
520
521 EXPECT_EQ(0ull, controller.disk_usage());
522 EXPECT_EQ(0ull, controller.memory_usage());
523 }
524 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698