OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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_async_builder_host.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/logging.h" | |
9 #include "base/memory/shared_memory.h" | |
10 #include "storage/common/blob_storage/blob_storage_constants.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 | |
13 namespace storage { | |
14 namespace { | |
15 const std::string kBlobUUID = "blobUUIDYAY"; | |
16 const std::string kFakeBlobUUID = "fakeBlob"; | |
17 const std::string kBlobType = "blobtypeYAY"; | |
18 | |
19 const size_t kTestBlobStorageIPCThresholdBytes = 5; | |
20 const size_t kTestBlobStorageMaxSharedMemoryBytes = 20; | |
21 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; | |
22 | |
23 void PopulateBytes(char* bytes, size_t start_num, size_t length) { | |
kinuko
2015/11/20 15:19:42
Probably start_num should be of char type too.
| |
24 for (size_t i = 0; i < length; i++) { | |
25 bytes[i] = static_cast<char>(start_num + i); | |
26 } | |
27 } | |
28 | |
29 void PopulateBytes(char* bytes, size_t length) { | |
30 PopulateBytes(bytes, 0, length); | |
31 } | |
32 | |
33 void AddMemoryItem(size_t length, std::vector<DataElement>* out) { | |
34 DataElement bytes; | |
35 bytes.SetToBytesDescription(length); | |
36 out->push_back(bytes); | |
37 } | |
38 | |
39 void AddShortcutMemoryItem(size_t length, std::vector<DataElement>* out) { | |
40 DataElement bytes; | |
41 bytes.SetToAllocatedBytes(length); | |
42 PopulateBytes(bytes.mutable_bytes(), length); | |
43 out->push_back(bytes); | |
44 } | |
45 | |
46 void AddShortcutMemoryItem(size_t length, BlobDataBuilder* out) { | |
47 DataElement bytes; | |
48 bytes.SetToAllocatedBytes(length); | |
49 PopulateBytes(bytes.mutable_bytes(), length); | |
50 out->AppendData(bytes.bytes(), length); | |
51 } | |
52 | |
53 void AddBlobItem(std::vector<DataElement>* out) { | |
54 DataElement blob; | |
55 blob.SetToBlob(kFakeBlobUUID); | |
56 out->push_back(blob); | |
57 } | |
58 | |
59 class BlobAsyncBuilderHostTest : public testing::Test { | |
60 protected: | |
61 BlobAsyncBuilderHostTest() | |
62 : matching_builder_(nullptr), | |
63 done_called_(false), | |
64 cancel_called_(false), | |
65 cancel_code_(IPCBlobCreationCancelCode::UNKNOWN), | |
66 request_called_(false) {} | |
67 ~BlobAsyncBuilderHostTest() override {} | |
68 | |
69 void SetUp() override { | |
70 matching_builder_ = nullptr; | |
71 done_called_ = false; | |
72 cancel_called_ = false; | |
73 cancel_code_ = IPCBlobCreationCancelCode::UNKNOWN; | |
74 request_called_ = false; | |
75 requests_.clear(); | |
76 memory_handles_.clear(); | |
77 file_handles_.clear(); | |
78 host_.SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes, | |
79 kTestBlobStorageMaxSharedMemoryBytes, | |
80 kTestBlobStorageMaxFileSizeBytes); | |
81 } | |
82 | |
83 void SetMatchingBuilder(BlobDataBuilder* builder) { | |
84 matching_builder_ = builder; | |
85 } | |
86 | |
87 void CancelCallback(IPCBlobCreationCancelCode code) { | |
88 cancel_called_ = true; | |
89 cancel_code_ = code; | |
90 } | |
91 | |
92 void DoneCallback(BlobDataBuilder* builder) { | |
93 ASSERT_TRUE(builder); | |
94 if (matching_builder_) | |
95 EXPECT_EQ(*matching_builder_, *builder); | |
96 done_called_ = true; | |
97 } | |
98 | |
99 void RequestMemoryCallback( | |
100 const std::vector<storage::BlobItemBytesRequest>& requests, | |
101 const std::vector<base::SharedMemoryHandle>& sms, | |
102 const std::vector<uint64_t>& pfs) { | |
103 this->requests_ = requests; | |
104 memory_handles_ = sms; | |
105 file_handles_ = pfs; | |
106 request_called_ = true; | |
107 } | |
108 | |
109 void BuildBlobAsync(const std::vector<DataElement>& descriptions, | |
110 size_t memory_available) { | |
111 host_.StartBuildingBlob( | |
112 kBlobUUID, kBlobType, descriptions, memory_available, | |
113 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback, | |
114 base::Unretained(this)), | |
115 base::Bind(&BlobAsyncBuilderHostTest::DoneCallback, | |
116 base::Unretained(this)), | |
117 base::Bind(&BlobAsyncBuilderHostTest::CancelCallback, | |
118 base::Unretained(this))); | |
119 } | |
120 | |
121 BlobDataBuilder* matching_builder_; | |
122 BlobAsyncBuilderHost host_; | |
123 bool done_called_; | |
124 bool cancel_called_; | |
125 IPCBlobCreationCancelCode cancel_code_; | |
126 | |
127 bool request_called_; | |
128 std::vector<storage::BlobItemBytesRequest> requests_; | |
129 std::vector<base::SharedMemoryHandle> memory_handles_; | |
130 std::vector<uint64_t> file_handles_; | |
131 }; | |
132 | |
133 TEST_F(BlobAsyncBuilderHostTest, TestShortcut) { | |
134 std::vector<DataElement> descriptions; | |
135 | |
136 AddShortcutMemoryItem(10, &descriptions); | |
137 AddBlobItem(&descriptions); | |
138 AddShortcutMemoryItem(5000, &descriptions); | |
139 | |
140 BlobDataBuilder expected(kBlobUUID); | |
141 expected.set_content_type(kBlobType); | |
142 AddShortcutMemoryItem(10, &expected); | |
143 expected.AppendBlob(kFakeBlobUUID); | |
144 AddShortcutMemoryItem(5000, &expected); | |
145 SetMatchingBuilder(&expected); | |
146 | |
147 BuildBlobAsync(descriptions, 5010); | |
148 | |
149 EXPECT_TRUE(done_called_); | |
150 EXPECT_FALSE(cancel_called_); | |
151 EXPECT_FALSE(request_called_); | |
152 EXPECT_EQ(0u, host_.blob_building_count()); | |
153 }; | |
154 | |
155 TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) { | |
156 std::vector<DataElement> descriptions; | |
157 const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1; | |
158 AddMemoryItem(kSize, &descriptions); | |
159 | |
160 BuildBlobAsync(descriptions, kTestBlobStorageIPCThresholdBytes + 1); | |
161 | |
162 EXPECT_FALSE(done_called_); | |
163 EXPECT_FALSE(cancel_called_); | |
164 EXPECT_TRUE(request_called_); | |
165 EXPECT_EQ(1u, host_.blob_building_count()); | |
166 ASSERT_EQ(1u, requests_.size()); | |
167 request_called_ = false; | |
168 | |
169 EXPECT_EQ( | |
170 BlobItemBytesRequest::CreateSharedMemoryRequest(0, 0, 0, kSize, 0, 0), | |
171 requests_.at(0)); | |
172 }; | |
173 | |
174 TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) { | |
175 std::vector<DataElement> descriptions; | |
176 const size_t kSize = kTestBlobStorageMaxSharedMemoryBytes + 1; | |
177 const char kFirstBlockByte = 7; | |
178 const char kSecondBlockByte = 19; | |
179 AddMemoryItem(kSize, &descriptions); | |
180 | |
181 BlobDataBuilder expected(kBlobUUID); | |
182 expected.set_content_type(kBlobType); | |
183 char data[kSize]; | |
184 memset(data, kFirstBlockByte, kTestBlobStorageMaxSharedMemoryBytes); | |
185 expected.AppendData(data, kTestBlobStorageMaxSharedMemoryBytes); | |
186 expected.AppendData(&kSecondBlockByte, 1); | |
187 SetMatchingBuilder(&expected); | |
188 | |
189 BuildBlobAsync(descriptions, kTestBlobStorageMaxSharedMemoryBytes + 1); | |
190 | |
191 EXPECT_FALSE(done_called_); | |
192 EXPECT_FALSE(cancel_called_); | |
193 EXPECT_TRUE(request_called_); | |
194 EXPECT_EQ(1u, host_.blob_building_count()); | |
195 ASSERT_EQ(1u, requests_.size()); | |
196 request_called_ = false; | |
197 | |
198 // We need to grab a duplicate handle so we can have two blocks open at the | |
199 // same time. | |
200 base::SharedMemoryHandle handle = | |
201 base::SharedMemory::DuplicateHandle(memory_handles_.at(0)); | |
202 EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle)); | |
203 base::SharedMemory shared_memory(handle, false); | |
204 EXPECT_TRUE(shared_memory.Map(kTestBlobStorageMaxSharedMemoryBytes)); | |
205 | |
206 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( | |
207 0, 0, 0, kTestBlobStorageMaxSharedMemoryBytes, 0, 0), | |
208 requests_.at(0)); | |
209 | |
210 memset(shared_memory.memory(), kFirstBlockByte, | |
211 kTestBlobStorageMaxSharedMemoryBytes); | |
212 | |
213 BlobItemBytesResponse response(0); | |
214 std::vector<BlobItemBytesResponse> responses = {response}; | |
215 host_.OnMemoryResponses(kBlobUUID, responses); | |
216 | |
217 EXPECT_FALSE(done_called_); | |
218 EXPECT_FALSE(cancel_called_); | |
219 EXPECT_TRUE(request_called_); | |
220 EXPECT_EQ(1u, host_.blob_building_count()); | |
221 ASSERT_EQ(1u, requests_.size()); | |
222 request_called_ = false; | |
223 | |
224 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( | |
225 1, 0, kTestBlobStorageMaxSharedMemoryBytes, 1, 0, 0), | |
226 requests_.at(0)); | |
227 | |
228 memset(shared_memory.memory(), kSecondBlockByte, 1); | |
229 | |
230 response.request_number = 1; | |
231 responses[0] = response; | |
232 host_.OnMemoryResponses(kBlobUUID, responses); | |
233 EXPECT_TRUE(done_called_); | |
234 EXPECT_FALSE(cancel_called_); | |
235 EXPECT_FALSE(request_called_); | |
236 EXPECT_EQ(0u, host_.blob_building_count()); | |
237 }; | |
238 | |
239 } // namespace | |
240 } // namespace storage | |
OLD | NEW |