OLD | NEW |
---|---|
(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/message_loop/message_loop.h" | |
10 #include "base/run_loop.h" | |
11 #include "base/test/test_simple_task_runner.h" | |
12 #include "base/threading/thread_task_runner_handle.h" | |
13 #include "storage/browser/blob/blob_data_builder.h" | |
14 #include "storage/browser/blob/blob_data_item.h" | |
15 #include "storage/browser/blob/shareable_blob_data_item.h" | |
16 #include "storage/common/data_element.h" | |
17 #include "testing/gtest/include/gtest/gtest.h" | |
18 | |
19 namespace storage { | |
20 | |
21 using Strategy = BlobMemoryController::Strategy; | |
22 using FileCreationInfo = BlobMemoryController::FileCreationInfo; | |
23 using base::TestSimpleTaskRunner; | |
24 using ItemState = ShareableBlobDataItem::State; | |
25 | |
26 const std::string kBlobStorageDirectory = "blob_storage"; | |
27 const size_t kTestBlobStorageIPCThresholdBytes = 20; | |
28 const size_t kTestBlobStorageMaxSharedMemoryBytes = 50; | |
29 const size_t kTestBlobStorageMaxBlobMemorySize = 400; | |
30 const size_t kTestBlobStorageInFlightMemory = 10; | |
31 const uint64_t kTestBlobStorageMaxDiskSpace = 1000; | |
32 const uint64_t kTestBlobStorageMinFileSizeBytes = 10; | |
33 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; | |
34 | |
35 class BlobMemoryControllerTest : public testing::Test { | |
36 protected: | |
37 BlobMemoryControllerTest() {} | |
38 | |
39 void SetUp() override { | |
40 ASSERT_EQ(true, base::CreateNewTempDirectory("blob_storage", &temp_dir_)); | |
41 }; | |
42 | |
43 void TearDown() override { | |
44 files_created_.clear(); | |
45 // Make sure we clean up the files. | |
46 base::RunLoop().RunUntilIdle(); | |
47 file_runner_->RunPendingTasks(); | |
48 base::RunLoop().RunUntilIdle(); | |
49 ASSERT_EQ(true, base::DeleteFile(temp_dir_, true)); | |
50 } | |
51 | |
52 std::vector<scoped_refptr<ShareableBlobDataItem>> CreateSharedDataItems( | |
53 const BlobDataBuilder& builder, | |
54 const std::vector<ItemState>& states, | |
55 std::vector<ShareableBlobDataItem*>* pointers_out) { | |
56 std::vector<scoped_refptr<ShareableBlobDataItem>> result; | |
57 EXPECT_EQ(builder.items_.size(), states.size()); | |
58 for (size_t i = 0; i < builder.items_.size(); ++i) { | |
59 result.push_back(make_scoped_refptr(new ShareableBlobDataItem( | |
60 builder.uuid(), builder.items_[i], states[i]))); | |
61 pointers_out->push_back(result.back().get()); | |
62 } | |
63 return result; | |
64 } | |
65 | |
66 void SetTestMemoryLimits(BlobMemoryController* controller) { | |
67 BlobStorageLimits limits; | |
68 limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes; | |
69 limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes; | |
70 limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize; | |
71 limits.in_flight_space = kTestBlobStorageInFlightMemory; | |
72 limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace; | |
73 limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes; | |
74 limits.max_file_size = kTestBlobStorageMaxFileSizeBytes; | |
75 controller->SetLimitsForTesting(limits); | |
76 } | |
77 | |
78 void SaveFileCreationInfo(bool success, std::vector<FileCreationInfo> info) { | |
79 file_quota_result_ = success; | |
80 if (success) | |
81 files_created_.swap(info); | |
82 } | |
83 | |
84 void SaveMemoryRequest(bool success) { memory_quota_result_ = success; } | |
85 | |
86 BlobMemoryController::FileQuotaRequestCallback GetFileCreationCallback() { | |
87 return base::Bind(&BlobMemoryControllerTest::SaveFileCreationInfo, | |
88 base::Unretained(this)); | |
89 } | |
90 | |
91 BlobMemoryController::MemoryQuotaRequestCallback GetMemoryRequestCallback() { | |
92 return base::Bind(&BlobMemoryControllerTest::SaveMemoryRequest, | |
93 base::Unretained(this)); | |
94 } | |
95 | |
96 void SetItemState(ShareableBlobDataItem* item, ItemState state) { | |
97 item->state_ = state; | |
98 } | |
99 | |
100 bool file_quota_result_ = false; | |
101 base::FilePath temp_dir_; | |
102 std::vector<FileCreationInfo> files_created_; | |
103 bool memory_quota_result_ = false; | |
104 | |
105 scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner(); | |
106 | |
107 base::MessageLoop fake_io_message_loop_; | |
108 }; | |
109 | |
110 TEST_F(BlobMemoryControllerTest, Strategy) { | |
111 BlobMemoryController controller; | |
112 SetTestMemoryLimits(&controller); | |
113 | |
114 // No transportation needed. | |
115 EXPECT_EQ(Strategy::NONE_NEEDED, controller.DetermineStrategy(0, 0)); | |
116 | |
117 // IPC. | |
118 EXPECT_EQ(Strategy::IPC, | |
119 controller.DetermineStrategy(0, kTestBlobStorageIPCThresholdBytes)); | |
120 | |
121 // Shared Memory. | |
122 EXPECT_EQ(Strategy::SHARED_MEMORY, | |
123 controller.DetermineStrategy(kTestBlobStorageIPCThresholdBytes, | |
124 kTestBlobStorageMaxSharedMemoryBytes)); | |
125 | |
126 // Not too large, as disk isn't enabled. | |
127 EXPECT_EQ( | |
128 Strategy::SHARED_MEMORY, | |
129 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize + | |
130 kTestBlobStorageInFlightMemory)); | |
131 | |
132 // Too large. | |
133 EXPECT_EQ( | |
134 Strategy::TOO_LARGE, | |
135 controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize + | |
136 kTestBlobStorageInFlightMemory + 1)); | |
137 | |
138 // Enable disk, and check file strategies. | |
139 controller.EnableFilePaging(temp_dir_, file_runner_); | |
140 EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy( | |
141 0, kTestBlobStorageMaxBlobMemorySize + 1)); | |
142 | |
143 // Too large for disk. | |
144 controller.EnableFilePaging(temp_dir_, file_runner_); | |
145 EXPECT_EQ(Strategy::TOO_LARGE, | |
146 controller.DetermineStrategy(0, kTestBlobStorageMaxDiskSpace + 1)); | |
147 } | |
148 | |
149 TEST_F(BlobMemoryControllerTest, GrantMemory) { | |
150 const std::string kId = "id"; | |
151 BlobMemoryController controller; | |
152 SetTestMemoryLimits(&controller); | |
153 | |
154 BlobDataBuilder builder(kId); | |
155 builder.AppendFutureData(10); | |
156 builder.AppendFutureData(20); | |
157 builder.AppendFutureData(30); | |
158 | |
159 std::vector<ShareableBlobDataItem*> pointers; | |
160 std::vector<scoped_refptr<ShareableBlobDataItem>> items = | |
161 CreateSharedDataItems(builder, | |
162 {ItemState::QUOTA_NEEDED, ItemState::QUOTA_NEEDED, | |
163 ItemState::QUOTA_NEEDED}, | |
164 &pointers); | |
165 | |
166 controller.ReserveMemoryQuota(pointers, GetMemoryRequestCallback()); | |
167 EXPECT_EQ(true, memory_quota_result_); | |
168 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state()); | |
169 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[1]->state()); | |
170 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[2]->state()); | |
171 } | |
172 | |
173 TEST_F(BlobMemoryControllerTest, GrantMemoryWithPagingFileWaiting) { | |
174 const std::string kId = "id"; | |
175 BlobMemoryController controller; | |
176 SetTestMemoryLimits(&controller); | |
177 | |
178 char kData[kTestBlobStorageMaxBlobMemorySize]; | |
179 std::memset(kData, kTestBlobStorageMaxBlobMemorySize, 'e'); | |
180 | |
181 // Add memory item that is the memory quota. | |
182 BlobDataBuilder builder(kId); | |
183 builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize); | |
184 | |
185 std::vector<ShareableBlobDataItem*> pointers; | |
186 std::vector<scoped_refptr<ShareableBlobDataItem>> items = | |
187 CreateSharedDataItems(builder, {ItemState::QUOTA_NEEDED}, &pointers); | |
188 | |
189 controller.ReserveMemoryQuota(pointers, GetMemoryRequestCallback()); | |
190 EXPECT_EQ(true, memory_quota_result_); | |
191 memory_quota_result_ = false; | |
192 EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state()); | |
193 | |
194 // Enable disk. | |
195 controller.EnableFilePaging(temp_dir_, file_runner_); | |
196 | |
197 // Create an item that is just a little too big. | |
198 BlobDataBuilder builder2(kId); | |
199 builder2.AppendFutureData(kTestBlobStorageInFlightMemory + 1); | |
200 | |
201 // Reserve memory, which should request successfuly but we can't fit it yet | |
202 // (no callback). | |
203 pointers.clear(); | |
204 std::vector<scoped_refptr<ShareableBlobDataItem>> items2 = | |
205 CreateSharedDataItems(builder2, {ItemState::QUOTA_NEEDED}, &pointers); | |
206 controller.ReserveMemoryQuota(pointers, GetMemoryRequestCallback()); | |
207 | |
208 EXPECT_EQ(false, memory_quota_result_); | |
209 EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state()); | |
210 EXPECT_FALSE(file_runner_->HasPendingTask()); | |
211 | |
212 // Add our original item as populated so it's paged to disk. | |
213 items[0]->item()->data_element_ptr()->SetToBytes( | |
214 kData, kTestBlobStorageMaxBlobMemorySize); | |
215 SetItemState(items[0].get(), ItemState::POPULATED_WITH_QUOTA); | |
216 controller.UpdateBlobItemInRecents(items[0].get()); | |
217 | |
218 EXPECT_TRUE(file_runner_->HasPendingTask()); | |
219 file_runner_->RunPendingTasks(); | |
220 base::RunLoop().RunUntilIdle(); | |
221 EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state()); | |
222 EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type()); | |
223 } | |
224 | |
225 // TODO(dmurph): | |
pwnall
2016/09/21 09:03:35
Can you crbug this please?
dmurph
2016/09/21 23:45:52
This will be in this patch, no need for crbug. Jus
| |
226 // * Write test for memory request when quota is available. | |
227 // * Write test for memory request that fails because disk isn't enabled. | |
228 // * Write test for memory request when quota isn't available and we're waiting | |
229 // on disk paging. | |
230 // * Same as above but then we cancel it. | |
231 // * Write test for memory request that's pending, and then disk is disabled. | |
232 // * Write test for file request where we have quota. | |
233 // * Write test for file request where we don't have quota (and just fail). | |
234 // * Write test for file request and then we disable disk. | |
235 | |
236 } // namespace storage | |
OLD | NEW |