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

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

Issue 1234813004: [BlobAsync] Asynchronous Blob Construction Final Patch (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@blob-protocol-change
Patch Set: added shared memory test, and fixed memory leak Created 4 years, 10 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "storage/browser/blob/blob_async_builder_host.h" 5 #include "storage/browser/blob/blob_async_builder_host.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <string.h> 9 #include <string.h>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/shared_memory.h" 13 #include "base/memory/shared_memory.h"
14 #include "base/run_loop.h"
15 #include "content/public/test/test_browser_thread_bundle.h"
16 #include "storage/browser/blob/blob_data_builder.h"
17 #include "storage/browser/blob/blob_data_handle.h"
18 #include "storage/browser/blob/blob_storage_context.h"
14 #include "storage/common/blob_storage/blob_storage_constants.h" 19 #include "storage/common/blob_storage/blob_storage_constants.h"
15 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
16 21
17 namespace storage { 22 namespace storage {
18 namespace { 23 namespace {
19 const std::string kBlobUUID = "blobUUIDYAY"; 24 const std::string kBlobUUID = "blobUUIDYAY";
20 const std::string kFakeBlobUUID = "fakeBlob"; 25 const std::string kContentType = "content_type";
21 const std::string kBlobType = "blobtypeYAY"; 26 const std::string kContentDisposition = "content_disposition";
27 const std::string kCompletedBlobUUID = "completedBlob";
28 const std::string kCompletedBlobData = "completedBlobData";
22 29
23 const size_t kTestBlobStorageIPCThresholdBytes = 5; 30 const size_t kTestBlobStorageIPCThresholdBytes = 5;
24 const size_t kTestBlobStorageMaxSharedMemoryBytes = 20; 31 const size_t kTestBlobStorageMaxSharedMemoryBytes = 20;
25 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; 32 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
26 33
27 void PopulateBytes(char* bytes, size_t length) { 34 void PopulateBytes(char* bytes, size_t length) {
28 for (size_t i = 0; i < length; i++) { 35 for (size_t i = 0; i < length; i++) {
29 bytes[i] = static_cast<char>(i); 36 bytes[i] = static_cast<char>(i);
30 } 37 }
31 } 38 }
(...skipping 13 matching lines...) Expand all
45 52
46 void AddShortcutMemoryItem(size_t length, BlobDataBuilder* out) { 53 void AddShortcutMemoryItem(size_t length, BlobDataBuilder* out) {
47 DataElement bytes; 54 DataElement bytes;
48 bytes.SetToAllocatedBytes(length); 55 bytes.SetToAllocatedBytes(length);
49 PopulateBytes(bytes.mutable_bytes(), length); 56 PopulateBytes(bytes.mutable_bytes(), length);
50 out->AppendData(bytes.bytes(), length); 57 out->AppendData(bytes.bytes(), length);
51 } 58 }
52 59
53 void AddBlobItem(std::vector<DataElement>* out) { 60 void AddBlobItem(std::vector<DataElement>* out) {
54 DataElement blob; 61 DataElement blob;
55 blob.SetToBlob(kFakeBlobUUID); 62 blob.SetToBlob(kCompletedBlobUUID);
56 out->push_back(blob); 63 out->push_back(blob);
57 } 64 }
65 } // namespace
58 66
59 class BlobAsyncBuilderHostTest : public testing::Test { 67 class BlobAsyncBuilderHostTest : public testing::Test {
60 protected: 68 public:
61 BlobAsyncBuilderHostTest() 69 BlobAsyncBuilderHostTest()
62 : matching_builder_(nullptr), 70 : cancel_code_(IPCBlobCreationCancelCode::UNKNOWN),
63 done_called_(false),
64 cancel_called_(false),
65 cancel_code_(IPCBlobCreationCancelCode::UNKNOWN),
66 request_called_(false) {} 71 request_called_(false) {}
67 ~BlobAsyncBuilderHostTest() override {} 72 ~BlobAsyncBuilderHostTest() override {}
68 73
69 void SetUp() override { 74 void SetUp() override {
70 matching_builder_ = nullptr;
71 done_called_ = false;
72 cancel_called_ = false;
73 cancel_code_ = IPCBlobCreationCancelCode::UNKNOWN; 75 cancel_code_ = IPCBlobCreationCancelCode::UNKNOWN;
74 request_called_ = false; 76 request_called_ = false;
75 requests_.clear(); 77 requests_.clear();
76 memory_handles_.clear(); 78 memory_handles_.clear();
77 file_handles_.clear();
78 host_.SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes, 79 host_.SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes,
79 kTestBlobStorageMaxSharedMemoryBytes, 80 kTestBlobStorageMaxSharedMemoryBytes,
80 kTestBlobStorageMaxFileSizeBytes); 81 kTestBlobStorageMaxFileSizeBytes);
81 } 82 BlobDataBuilder builder(kCompletedBlobUUID);
82 83 builder.AppendData(kCompletedBlobData);
83 void SetMatchingBuilder(BlobDataBuilder* builder) { 84 completed_blob_handle_ = context_.AddFinishedBlob(builder);
84 matching_builder_ = builder; 85 completed_blob_uuid_set_ = {kCompletedBlobUUID};
85 }
86
87 void CancelCallback(IPCBlobCreationCancelCode code) {
88 cancel_called_ = true;
89 cancel_code_ = code;
90 }
91
92 void DoneCallback(const BlobDataBuilder& builder) {
93 // This does a deep comparison, including internal data items.
94 if (matching_builder_)
95 EXPECT_EQ(*matching_builder_, builder);
96 done_called_ = true;
97 } 86 }
98 87
99 void RequestMemoryCallback( 88 void RequestMemoryCallback(
100 const std::vector<storage::BlobItemBytesRequest>& requests, 89 scoped_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
101 const std::vector<base::SharedMemoryHandle>& shared_memory_handles, 90 scoped_ptr<std::vector<base::SharedMemoryHandle>> shared_memory_handles,
102 const std::vector<uint64_t>& file_sizes) { 91 scoped_ptr<std::vector<base::File>> files) {
103 this->requests_ = requests; 92 requests_ = std::move(*requests);
104 memory_handles_ = shared_memory_handles; 93 memory_handles_ = std::move(*shared_memory_handles);
105 file_handles_ = file_sizes;
106 request_called_ = true; 94 request_called_ = true;
107 } 95 }
108 96
109 bool BuildBlobAsync(const std::vector<DataElement>& descriptions, 97 BlobTransportResult BuildBlobAsync(
110 size_t memory_available) { 98 const std::vector<DataElement>& descriptions,
111 done_called_ = false; 99 const std::set<std::string>& referenced_blob_uuids,
112 cancel_called_ = false; 100 size_t memory_available) {
113 request_called_ = false; 101 request_called_ = false;
102 if (!host_.RegisterBlobUUID(kBlobUUID, kContentType, kContentDisposition,
103 referenced_blob_uuids, &context_)) {
104 return BlobTransportResult::BAD_IPC;
105 }
114 return host_.StartBuildingBlob( 106 return host_.StartBuildingBlob(
115 kBlobUUID, kBlobType, descriptions, memory_available, 107 kBlobUUID, descriptions, memory_available, &context_,
116 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback, 108 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
117 base::Unretained(this)),
118 base::Bind(&BlobAsyncBuilderHostTest::DoneCallback,
119 base::Unretained(this)),
120 base::Bind(&BlobAsyncBuilderHostTest::CancelCallback,
121 base::Unretained(this))); 109 base::Unretained(this)));
122 } 110 }
123 111
124 BlobDataBuilder* matching_builder_; 112 void DecrementBlobRefCount(const std::string& uuid) {
113 context_.DecrementBlobRefCount(uuid);
114 }
115
116 bool IsBeingBuiltInContext(const std::string& uuid) {
117 return context_.IsBeingBuilt(uuid);
118 }
119
120 content::TestBrowserThreadBundle browser_thread_bundle_;
121 BlobStorageContext context_;
125 BlobAsyncBuilderHost host_; 122 BlobAsyncBuilderHost host_;
126 bool done_called_;
127 bool cancel_called_;
128 IPCBlobCreationCancelCode cancel_code_; 123 IPCBlobCreationCancelCode cancel_code_;
129 124
130 bool request_called_; 125 bool request_called_;
131 std::vector<storage::BlobItemBytesRequest> requests_; 126 std::vector<storage::BlobItemBytesRequest> requests_;
132 std::vector<base::SharedMemoryHandle> memory_handles_; 127 std::vector<base::SharedMemoryHandle> memory_handles_;
133 std::vector<uint64_t> file_handles_; 128 std::set<std::string> completed_blob_uuid_set_;
129
130 scoped_ptr<BlobDataHandle> completed_blob_handle_;
134 }; 131 };
135 132
133 // The 'shortcut' method is when the data is included in the initial IPCs and
134 // the browser uses that instead of requesting the memory.
136 TEST_F(BlobAsyncBuilderHostTest, TestShortcut) { 135 TEST_F(BlobAsyncBuilderHostTest, TestShortcut) {
137 std::vector<DataElement> descriptions; 136 std::vector<DataElement> descriptions;
138 137
139 AddShortcutMemoryItem(10, &descriptions); 138 AddShortcutMemoryItem(10, &descriptions);
140 AddBlobItem(&descriptions); 139 AddBlobItem(&descriptions);
141 AddShortcutMemoryItem(5000, &descriptions); 140 AddShortcutMemoryItem(5000, &descriptions);
142 141
143 BlobDataBuilder expected(kBlobUUID); 142 BlobDataBuilder expected(kBlobUUID);
144 expected.set_content_type(kBlobType); 143 expected.set_content_type(kContentType);
144 expected.set_content_disposition(kContentDisposition);
145 AddShortcutMemoryItem(10, &expected); 145 AddShortcutMemoryItem(10, &expected);
146 expected.AppendBlob(kFakeBlobUUID); 146 expected.AppendData(kCompletedBlobData);
147 AddShortcutMemoryItem(5000, &expected); 147 AddShortcutMemoryItem(5000, &expected);
148 SetMatchingBuilder(&expected);
149 148
150 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 149 EXPECT_EQ(BlobTransportResult::DONE,
150 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
151 151
152 EXPECT_TRUE(done_called_); 152 EXPECT_FALSE(request_called_);
153 EXPECT_FALSE(cancel_called_); 153 EXPECT_EQ(0u, host_.blob_building_count());
154 scoped_ptr<BlobDataHandle> handle = context_.GetBlobDataFromUUID(kBlobUUID);
155 EXPECT_FALSE(handle->IsBeingBuilt());
156 EXPECT_FALSE(handle->IsBroken());
157 scoped_ptr<BlobDataSnapshot> data = handle->CreateSnapshot();
158 EXPECT_EQ(expected, *data);
159 data.reset();
160 handle.reset();
161 base::RunLoop().RunUntilIdle();
162 };
163
164 TEST_F(BlobAsyncBuilderHostTest, TestShortcutNoRoom) {
165 std::vector<DataElement> descriptions;
166
167 AddShortcutMemoryItem(10, &descriptions);
168 AddBlobItem(&descriptions);
169 AddShortcutMemoryItem(5000, &descriptions);
170
171 EXPECT_EQ(BlobTransportResult::CANCEL_MEMORY_FULL,
172 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5000));
173
154 EXPECT_FALSE(request_called_); 174 EXPECT_FALSE(request_called_);
155 EXPECT_EQ(0u, host_.blob_building_count()); 175 EXPECT_EQ(0u, host_.blob_building_count());
156 }; 176 };
157 177
158 TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) { 178 TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) {
159 std::vector<DataElement> descriptions; 179 std::vector<DataElement> descriptions;
160 const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1; 180 const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1;
161 AddMemoryItem(kSize, &descriptions); 181 AddMemoryItem(kSize, &descriptions);
162 182
163 EXPECT_TRUE( 183 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
164 BuildBlobAsync(descriptions, kTestBlobStorageIPCThresholdBytes + 1)); 184 BuildBlobAsync(descriptions, std::set<std::string>(),
185 kTestBlobStorageIPCThresholdBytes + 1));
165 186
166 EXPECT_FALSE(done_called_);
167 EXPECT_FALSE(cancel_called_);
168 EXPECT_TRUE(request_called_); 187 EXPECT_TRUE(request_called_);
169 EXPECT_EQ(1u, host_.blob_building_count()); 188 EXPECT_EQ(1u, host_.blob_building_count());
170 ASSERT_EQ(1u, requests_.size()); 189 ASSERT_EQ(1u, requests_.size());
171 request_called_ = false; 190 request_called_ = false;
172 191
173 EXPECT_EQ( 192 EXPECT_EQ(
174 BlobItemBytesRequest::CreateSharedMemoryRequest(0, 0, 0, kSize, 0, 0), 193 BlobItemBytesRequest::CreateSharedMemoryRequest(0, 0, 0, kSize, 0, 0),
175 requests_.at(0)); 194 requests_.at(0));
176 }; 195 };
177 196
178 TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) { 197 TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) {
179 std::vector<DataElement> descriptions; 198 std::vector<DataElement> descriptions;
180 const size_t kSize = kTestBlobStorageMaxSharedMemoryBytes + 1; 199 const size_t kSize = kTestBlobStorageMaxSharedMemoryBytes + 1;
181 const char kFirstBlockByte = 7; 200 const char kFirstBlockByte = 7;
182 const char kSecondBlockByte = 19; 201 const char kSecondBlockByte = 19;
183 AddMemoryItem(kSize, &descriptions); 202 AddMemoryItem(kSize, &descriptions);
184 203
185 BlobDataBuilder expected(kBlobUUID); 204 BlobDataBuilder expected(kBlobUUID);
186 expected.set_content_type(kBlobType); 205 expected.set_content_type(kContentType);
206 expected.set_content_disposition(kContentDisposition);
187 char data[kSize]; 207 char data[kSize];
188 memset(data, kFirstBlockByte, kTestBlobStorageMaxSharedMemoryBytes); 208 memset(data, kFirstBlockByte, kTestBlobStorageMaxSharedMemoryBytes);
189 expected.AppendData(data, kTestBlobStorageMaxSharedMemoryBytes); 209 expected.AppendData(data, kTestBlobStorageMaxSharedMemoryBytes);
190 expected.AppendData(&kSecondBlockByte, 1); 210 expected.AppendData(&kSecondBlockByte, 1);
191 SetMatchingBuilder(&expected);
192 211
193 EXPECT_TRUE( 212 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
194 BuildBlobAsync(descriptions, kTestBlobStorageMaxSharedMemoryBytes + 1)); 213 BuildBlobAsync(descriptions, std::set<std::string>(),
214 kTestBlobStorageMaxSharedMemoryBytes + 1));
195 215
196 EXPECT_FALSE(done_called_);
197 EXPECT_FALSE(cancel_called_);
198 EXPECT_TRUE(request_called_); 216 EXPECT_TRUE(request_called_);
199 EXPECT_EQ(1u, host_.blob_building_count()); 217 EXPECT_EQ(1u, host_.blob_building_count());
200 ASSERT_EQ(1u, requests_.size()); 218 ASSERT_EQ(1u, requests_.size());
201 request_called_ = false; 219 request_called_ = false;
202 220
203 // We need to grab a duplicate handle so we can have two blocks open at the 221 // We need to grab a duplicate handle so we can have two blocks open at the
204 // same time. 222 // same time.
205 base::SharedMemoryHandle handle = 223 base::SharedMemoryHandle handle =
206 base::SharedMemory::DuplicateHandle(memory_handles_.at(0)); 224 base::SharedMemory::DuplicateHandle(memory_handles_.at(0));
207 EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle)); 225 EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle));
208 base::SharedMemory shared_memory(handle, false); 226 base::SharedMemory shared_memory(handle, false);
209 EXPECT_TRUE(shared_memory.Map(kTestBlobStorageMaxSharedMemoryBytes)); 227 EXPECT_TRUE(shared_memory.Map(kTestBlobStorageMaxSharedMemoryBytes));
210 228
211 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( 229 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(
212 0, 0, 0, kTestBlobStorageMaxSharedMemoryBytes, 0, 0), 230 0, 0, 0, kTestBlobStorageMaxSharedMemoryBytes, 0, 0),
213 requests_.at(0)); 231 requests_.at(0));
214 232
215 memset(shared_memory.memory(), kFirstBlockByte, 233 memset(shared_memory.memory(), kFirstBlockByte,
216 kTestBlobStorageMaxSharedMemoryBytes); 234 kTestBlobStorageMaxSharedMemoryBytes);
217 235
218 BlobItemBytesResponse response(0); 236 BlobItemBytesResponse response(0);
219 std::vector<BlobItemBytesResponse> responses = {response}; 237 std::vector<BlobItemBytesResponse> responses = {response};
220 EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses)); 238 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
239 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
221 240
222 EXPECT_FALSE(done_called_);
223 EXPECT_FALSE(cancel_called_);
224 EXPECT_TRUE(request_called_); 241 EXPECT_TRUE(request_called_);
225 EXPECT_EQ(1u, host_.blob_building_count()); 242 EXPECT_EQ(1u, host_.blob_building_count());
226 ASSERT_EQ(1u, requests_.size()); 243 ASSERT_EQ(1u, requests_.size());
227 request_called_ = false; 244 request_called_ = false;
228 245
229 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( 246 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(
230 1, 0, kTestBlobStorageMaxSharedMemoryBytes, 1, 0, 0), 247 1, 0, kTestBlobStorageMaxSharedMemoryBytes, 1, 0, 0),
231 requests_.at(0)); 248 requests_.at(0));
232 249
233 memset(shared_memory.memory(), kSecondBlockByte, 1); 250 memset(shared_memory.memory(), kSecondBlockByte, 1);
234 251
235 response.request_number = 1; 252 response.request_number = 1;
236 responses[0] = response; 253 responses[0] = response;
237 EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses)); 254 EXPECT_EQ(BlobTransportResult::DONE,
238 EXPECT_TRUE(done_called_); 255 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
239 EXPECT_FALSE(cancel_called_);
240 EXPECT_FALSE(request_called_); 256 EXPECT_FALSE(request_called_);
241 EXPECT_EQ(0u, host_.blob_building_count()); 257 EXPECT_EQ(0u, host_.blob_building_count());
258 scoped_ptr<BlobDataHandle> blob_handle =
259 context_.GetBlobDataFromUUID(kBlobUUID);
260 EXPECT_FALSE(blob_handle->IsBeingBuilt());
261 EXPECT_FALSE(blob_handle->IsBroken());
262 scoped_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
263 EXPECT_EQ(expected, *blob_data);
242 }; 264 };
243 265
244 TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) { 266 TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) {
245 std::vector<DataElement> descriptions; 267 std::vector<DataElement> descriptions;
246 268
247 AddMemoryItem(2, &descriptions); 269 AddMemoryItem(2, &descriptions);
248 AddBlobItem(&descriptions); 270 AddBlobItem(&descriptions);
249 AddMemoryItem(2, &descriptions); 271 AddMemoryItem(2, &descriptions);
250 272
251 BlobDataBuilder expected(kBlobUUID); 273 BlobDataBuilder expected(kBlobUUID);
252 expected.set_content_type(kBlobType); 274 expected.set_content_type(kContentType);
275 expected.set_content_disposition(kContentDisposition);
253 AddShortcutMemoryItem(2, &expected); 276 AddShortcutMemoryItem(2, &expected);
254 expected.AppendBlob(kFakeBlobUUID); 277 expected.AppendData(kCompletedBlobData);
255 AddShortcutMemoryItem(2, &expected); 278 AddShortcutMemoryItem(2, &expected);
256 SetMatchingBuilder(&expected);
257 279
258 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 280 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
259 host_.StopBuildingBlob(kBlobUUID); 281 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
260 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 282 host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
283 &context_);
261 284
262 EXPECT_FALSE(done_called_); 285 // Check that we're broken, and then remove the blob.
263 EXPECT_FALSE(cancel_called_); 286 scoped_ptr<BlobDataHandle> blob_handle =
287 context_.GetBlobDataFromUUID(kBlobUUID);
288 EXPECT_FALSE(blob_handle->IsBeingBuilt());
289 EXPECT_TRUE(blob_handle->IsBroken());
290 blob_handle.reset();
291 DecrementBlobRefCount(kBlobUUID);
292 base::RunLoop().RunUntilIdle();
293 blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
294 EXPECT_FALSE(blob_handle.get());
295
296 // This should succeed because we've removed all references to the blob.
297 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
298 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
299
264 EXPECT_TRUE(request_called_); 300 EXPECT_TRUE(request_called_);
265 EXPECT_EQ(1u, host_.blob_building_count()); 301 EXPECT_EQ(1u, host_.blob_building_count());
266 request_called_ = false; 302 request_called_ = false;
267 303
268 BlobItemBytesResponse response1(0); 304 BlobItemBytesResponse response1(0);
269 PopulateBytes(response1.allocate_mutable_data(2), 2); 305 PopulateBytes(response1.allocate_mutable_data(2), 2);
270 BlobItemBytesResponse response2(1); 306 BlobItemBytesResponse response2(1);
271 PopulateBytes(response2.allocate_mutable_data(2), 2); 307 PopulateBytes(response2.allocate_mutable_data(2), 2);
272 std::vector<BlobItemBytesResponse> responses = {response1, response2}; 308 std::vector<BlobItemBytesResponse> responses = {response1, response2};
273 EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses)); 309
274 EXPECT_TRUE(done_called_); 310 EXPECT_EQ(BlobTransportResult::DONE,
275 EXPECT_FALSE(cancel_called_); 311 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
276 EXPECT_FALSE(request_called_); 312 EXPECT_FALSE(request_called_);
277 EXPECT_EQ(0u, host_.blob_building_count()); 313 EXPECT_EQ(0u, host_.blob_building_count());
314 blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
315 EXPECT_FALSE(blob_handle->IsBeingBuilt());
316 EXPECT_FALSE(blob_handle->IsBroken());
317 scoped_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
318 EXPECT_EQ(expected, *blob_data);
319 };
320
321 TEST_F(BlobAsyncBuilderHostTest, TestBreakingAllBuilding) {
322 const std::string& kBlob1 = "blob1";
323 const std::string& kBlob2 = "blob2";
324 const std::string& kBlob3 = "blob3";
325
326 // Register blobs.
327 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
328 std::set<std::string>(), &context_));
329 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
330 std::set<std::string>(), &context_));
331 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
332 std::set<std::string>(), &context_));
333
334 // Start building one of them.
335 std::vector<DataElement> descriptions;
336 AddMemoryItem(2, &descriptions);
337 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
338 host_.StartBuildingBlob(
339 kBlob1, descriptions, 2, &context_,
340 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
341 base::Unretained(this))));
342 EXPECT_TRUE(request_called_);
343
344 scoped_ptr<BlobDataHandle> blob_handle1 =
345 context_.GetBlobDataFromUUID(kBlob1);
346 scoped_ptr<BlobDataHandle> blob_handle2 =
347 context_.GetBlobDataFromUUID(kBlob2);
348 scoped_ptr<BlobDataHandle> blob_handle3 =
349 context_.GetBlobDataFromUUID(kBlob2);
350 EXPECT_TRUE(blob_handle1->IsBeingBuilt() && blob_handle2->IsBeingBuilt() &&
351 blob_handle3->IsBeingBuilt());
352 EXPECT_FALSE(blob_handle1->IsBroken() || blob_handle2->IsBroken() ||
353 blob_handle3->IsBroken());
354
355 host_.CancelAll(&context_);
356
357 EXPECT_FALSE(blob_handle1->IsBeingBuilt() || blob_handle2->IsBeingBuilt() ||
358 blob_handle3->IsBeingBuilt());
359 EXPECT_TRUE(blob_handle1->IsBroken() && blob_handle2->IsBroken() &&
360 blob_handle3->IsBroken());
361 blob_handle1.reset();
362 blob_handle2.reset();
363 blob_handle3.reset();
364 base::RunLoop().RunUntilIdle();
278 }; 365 };
279 366
280 TEST_F(BlobAsyncBuilderHostTest, TestBadIPCs) { 367 TEST_F(BlobAsyncBuilderHostTest, TestBadIPCs) {
281 std::vector<DataElement> descriptions; 368 std::vector<DataElement> descriptions;
282 369
283 // Test reusing same blob uuid. 370 // Test reusing same blob uuid.
284 SetMatchingBuilder(nullptr);
285 AddMemoryItem(10, &descriptions); 371 AddMemoryItem(10, &descriptions);
286 AddBlobItem(&descriptions); 372 AddBlobItem(&descriptions);
287 AddMemoryItem(5000, &descriptions); 373 AddMemoryItem(5000, &descriptions);
288 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 374 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
289 EXPECT_FALSE(BuildBlobAsync(descriptions, 5010)); 375 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
290 EXPECT_FALSE(done_called_); 376 EXPECT_EQ(BlobTransportResult::BAD_IPC,
291 EXPECT_FALSE(cancel_called_); 377 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
292 EXPECT_FALSE(request_called_); 378 EXPECT_FALSE(request_called_);
293 host_.StopBuildingBlob(kBlobUUID); 379 host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
294 380 &context_);
295 // Test we're _not_ an error if we get a bad uuid for responses. 381 base::RunLoop().RunUntilIdle();
382 DecrementBlobRefCount(kBlobUUID);
383 EXPECT_FALSE(context_.GetBlobDataFromUUID(kBlobUUID).get());
384
385 // Test we're an error if we get a bad uuid for responses.
296 BlobItemBytesResponse response(0); 386 BlobItemBytesResponse response(0);
297 std::vector<BlobItemBytesResponse> responses = {response}; 387 std::vector<BlobItemBytesResponse> responses = {response};
298 EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses)); 388 EXPECT_EQ(BlobTransportResult::BAD_IPC,
389 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
299 390
300 // Test empty responses. 391 // Test empty responses.
301 responses.clear(); 392 responses.clear();
302 EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses)); 393 EXPECT_EQ(BlobTransportResult::BAD_IPC,
394 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
303 395
304 // Test response problems below here. 396 // Test response problems below here.
305 descriptions.clear(); 397 descriptions.clear();
306 AddMemoryItem(2, &descriptions); 398 AddMemoryItem(2, &descriptions);
307 AddBlobItem(&descriptions); 399 AddBlobItem(&descriptions);
308 AddMemoryItem(2, &descriptions); 400 AddMemoryItem(2, &descriptions);
309 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 401 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
402 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
310 403
311 // Invalid request number. 404 // Invalid request number.
312 BlobItemBytesResponse response1(3); 405 BlobItemBytesResponse response1(3);
313 PopulateBytes(response1.allocate_mutable_data(2), 2); 406 PopulateBytes(response1.allocate_mutable_data(2), 2);
314 responses = {response1}; 407 responses = {response1};
315 EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses)); 408 EXPECT_EQ(BlobTransportResult::BAD_IPC,
409 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
410 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
411 DecrementBlobRefCount(kBlobUUID);
412 base::RunLoop().RunUntilIdle();
316 413
317 // Duplicate request number responses. 414 // Duplicate request number responses.
318 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 415 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
416 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
319 response1.request_number = 0; 417 response1.request_number = 0;
320 BlobItemBytesResponse response2(0); 418 BlobItemBytesResponse response2(0);
321 PopulateBytes(response2.allocate_mutable_data(2), 2); 419 PopulateBytes(response2.allocate_mutable_data(2), 2);
322 responses = {response1, response2}; 420 responses = {response1, response2};
323 EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses)); 421 EXPECT_EQ(BlobTransportResult::BAD_IPC,
324 }; 422 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
325 423 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
326 } // namespace 424 DecrementBlobRefCount(kBlobUUID);
425 base::RunLoop().RunUntilIdle();
426 };
427
428 TEST_F(BlobAsyncBuilderHostTest, WaitOnReferencedBlob) {
429 const std::string& kBlob1 = "blob1";
430 const std::string& kBlob2 = "blob2";
431 const std::string& kBlob3 = "blob3";
432
433 // Register blobs.
434 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
435 std::set<std::string>(), &context_));
436 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
437 std::set<std::string>(), &context_));
438 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
439 {kBlob1, kBlob2}, &context_));
440
441 // Finish the third one, with a reference to the first and second blob.
442 std::vector<DataElement> descriptions;
443 AddShortcutMemoryItem(2, &descriptions);
444 DataElement element;
445 element.SetToBlob(kBlob1);
446 descriptions.push_back(element);
447 element.SetToBlob(kBlob2);
448 descriptions.push_back(element);
449
450 // Finish the third, but we should still be 'building' it.
451 EXPECT_EQ(BlobTransportResult::DONE,
452 host_.StartBuildingBlob(
453 kBlob3, descriptions, 2, &context_,
454 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
455 base::Unretained(this))));
456 EXPECT_FALSE(request_called_);
457 EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
458 EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
459
460 // Finish the first.
461 descriptions.clear();
462 AddShortcutMemoryItem(2, &descriptions);
463 EXPECT_EQ(BlobTransportResult::DONE,
464 host_.StartBuildingBlob(
465 kBlob1, descriptions, 2, &context_,
466 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
467 base::Unretained(this))));
468 EXPECT_FALSE(request_called_);
469 EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
470 EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
471 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1));
472
473 // Run the message loop so we propogate the construction complete callbacks.
474 base::RunLoop().RunUntilIdle();
475 // Verify we're not done.
476 EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
477 EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
478
479 // Finish the second.
480 EXPECT_EQ(BlobTransportResult::DONE,
481 host_.StartBuildingBlob(
482 kBlob2, descriptions, 2, &context_,
483 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
484 base::Unretained(this))));
485 EXPECT_FALSE(request_called_);
486 EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
487 EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
488 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2));
489
490 // Run the message loop so we propogate the construction complete callbacks.
491 base::RunLoop().RunUntilIdle();
492 // Finally, we should be finished with third blob.
493 EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
494 EXPECT_FALSE(IsBeingBuiltInContext(kBlob3));
495 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob3));
496 };
497
498 TEST_F(BlobAsyncBuilderHostTest, IncorrectBlobDependencies) {
499 const std::string& kGoodBlob = "goodBlob";
500 const std::string& kBlob1 = "blob1";
501 const std::string& kBlob2 = "blob2";
502 const std::string& kBlob3 = "blob3";
503
504 // Register blobs. Blob 1 has a reference to itself, Blob 2 has a reference
505 // but doesn't use it, and blob 3 doesn't list it's reference.
506 EXPECT_TRUE(host_.RegisterBlobUUID(kGoodBlob, kContentType,
507 kContentDisposition,
508 std::set<std::string>(), &context_));
509 EXPECT_FALSE(host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
510 {kBlob1}, &context_));
511 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
512 {kGoodBlob}, &context_));
513 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
514 std::set<std::string>(), &context_));
515
516 // The first blob shouldn't be building anymore.
517 EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
518 // Test we get BAD_IPC.
519 std::vector<DataElement> descriptions;
520 AddShortcutMemoryItem(2, &descriptions);
521 DataElement element;
522 element.SetToBlob(kBlob1);
523 descriptions.push_back(element);
524 EXPECT_EQ(BlobTransportResult::BAD_IPC,
525 host_.StartBuildingBlob(
526 kBlob1, descriptions, 2, &context_,
527 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
528 base::Unretained(this))));
529
530 // Try to finish the second one, without a reference to the first.
531 descriptions.clear();
532 AddShortcutMemoryItem(2, &descriptions);
533 EXPECT_EQ(BlobTransportResult::BAD_IPC,
534 host_.StartBuildingBlob(
535 kBlob2, descriptions, 2, &context_,
536 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
537 base::Unretained(this))));
538 EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
539
540 // Try to finish the third one with the reference we didn't declare earlier.
541 descriptions.clear();
542 AddShortcutMemoryItem(2, &descriptions);
543 element.SetToBlob(kGoodBlob);
544 descriptions.push_back(element);
545 EXPECT_EQ(BlobTransportResult::BAD_IPC,
546 host_.StartBuildingBlob(
547 kBlob3, descriptions, 2, &context_,
548 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
549 base::Unretained(this))));
550 EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
551 };
552
553 TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBreaks) {
554 const std::string& kBlob1 = "blob1";
555 const std::string& kBlob2 = "blob2";
556
557 // Register blobs.
558 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
559 std::set<std::string>(), &context_));
560 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
561 {kBlob1}, &context_));
562
563 // Finish the second one, with a reference to the first.
564 std::vector<DataElement> descriptions;
565 AddShortcutMemoryItem(2, &descriptions);
566 DataElement element;
567 element.SetToBlob(kBlob1);
568 descriptions.push_back(element);
569 EXPECT_EQ(BlobTransportResult::DONE,
570 host_.StartBuildingBlob(
571 kBlob2, descriptions, 2, &context_,
572 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
573 base::Unretained(this))));
574 EXPECT_FALSE(request_called_);
575 EXPECT_TRUE(host_.IsBeingBuilt(kBlob2));
576 EXPECT_TRUE(IsBeingBuiltInContext(kBlob2));
577
578 // Break the first.
579 descriptions.clear();
580 host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
581 &context_);
582 EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
583 EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
584 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1)->IsBroken());
585
586 // Run the message loop so we propogate the construction complete callbacks.
587 base::RunLoop().RunUntilIdle();
588 // We should be finished with third blob, and it should be broken.
589 EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
590 EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
591 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
592 };
593
594 TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBroken) {
595 const std::string& kBlob1 = "blob1";
596 const std::string& kBlob2 = "blob2";
597
598 // Register blobs.
599 EXPECT_TRUE(host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
600 std::set<std::string>(), &context_));
601 host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
602 &context_);
603 EXPECT_FALSE(host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
604 {kBlob1}, &context_));
605 EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
606 EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
607 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
608
609 // Try to finish the second one, but we should get a BAD_IPC, as we are no
610 // longer being constructed.
611 std::vector<DataElement> descriptions;
612 AddShortcutMemoryItem(2, &descriptions);
613 DataElement element;
614 element.SetToBlob(kBlob1);
615 descriptions.push_back(element);
616 EXPECT_EQ(BlobTransportResult::BAD_IPC,
617 host_.StartBuildingBlob(
618 kBlob2, descriptions, 2, &context_,
619 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
620 base::Unretained(this))));
621 EXPECT_FALSE(request_called_);
622 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
623 };
624
327 } // namespace storage 625 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698