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

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: comments Created 4 years, 9 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 BlobTransportResult register_result =
103 host_.RegisterBlobUUID(kBlobUUID, kContentType, kContentDisposition,
104 referenced_blob_uuids, &context_);
105 if (register_result != BlobTransportResult::DONE) {
106 return register_result;
107 }
114 return host_.StartBuildingBlob( 108 return host_.StartBuildingBlob(
115 kBlobUUID, kBlobType, descriptions, memory_available, 109 kBlobUUID, descriptions, memory_available, &context_,
116 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback, 110 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))); 111 base::Unretained(this)));
122 } 112 }
123 113
124 BlobDataBuilder* matching_builder_; 114 void DecrementBlobRefCount(const std::string& uuid) {
115 context_.DecrementBlobRefCount(uuid);
116 }
117
118 bool IsBeingBuiltInContext(const std::string& uuid) {
119 return context_.IsBeingBuilt(uuid);
120 }
121
122 content::TestBrowserThreadBundle browser_thread_bundle_;
123 BlobStorageContext context_;
125 BlobAsyncBuilderHost host_; 124 BlobAsyncBuilderHost host_;
126 bool done_called_;
127 bool cancel_called_;
128 IPCBlobCreationCancelCode cancel_code_; 125 IPCBlobCreationCancelCode cancel_code_;
129 126
130 bool request_called_; 127 bool request_called_;
131 std::vector<storage::BlobItemBytesRequest> requests_; 128 std::vector<storage::BlobItemBytesRequest> requests_;
132 std::vector<base::SharedMemoryHandle> memory_handles_; 129 std::vector<base::SharedMemoryHandle> memory_handles_;
133 std::vector<uint64_t> file_handles_; 130 std::set<std::string> completed_blob_uuid_set_;
131
132 scoped_ptr<BlobDataHandle> completed_blob_handle_;
134 }; 133 };
135 134
135 // The 'shortcut' method is when the data is included in the initial IPCs and
136 // the browser uses that instead of requesting the memory.
136 TEST_F(BlobAsyncBuilderHostTest, TestShortcut) { 137 TEST_F(BlobAsyncBuilderHostTest, TestShortcut) {
137 std::vector<DataElement> descriptions; 138 std::vector<DataElement> descriptions;
138 139
139 AddShortcutMemoryItem(10, &descriptions); 140 AddShortcutMemoryItem(10, &descriptions);
140 AddBlobItem(&descriptions); 141 AddBlobItem(&descriptions);
141 AddShortcutMemoryItem(5000, &descriptions); 142 AddShortcutMemoryItem(5000, &descriptions);
142 143
143 BlobDataBuilder expected(kBlobUUID); 144 BlobDataBuilder expected(kBlobUUID);
144 expected.set_content_type(kBlobType); 145 expected.set_content_type(kContentType);
146 expected.set_content_disposition(kContentDisposition);
145 AddShortcutMemoryItem(10, &expected); 147 AddShortcutMemoryItem(10, &expected);
146 expected.AppendBlob(kFakeBlobUUID); 148 expected.AppendData(kCompletedBlobData);
147 AddShortcutMemoryItem(5000, &expected); 149 AddShortcutMemoryItem(5000, &expected);
148 SetMatchingBuilder(&expected);
149 150
150 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 151 EXPECT_EQ(BlobTransportResult::DONE,
152 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
151 153
152 EXPECT_TRUE(done_called_); 154 EXPECT_FALSE(request_called_);
153 EXPECT_FALSE(cancel_called_); 155 EXPECT_EQ(0u, host_.blob_building_count());
156 scoped_ptr<BlobDataHandle> handle = context_.GetBlobDataFromUUID(kBlobUUID);
157 EXPECT_FALSE(handle->IsBeingBuilt());
158 EXPECT_FALSE(handle->IsBroken());
159 scoped_ptr<BlobDataSnapshot> data = handle->CreateSnapshot();
160 EXPECT_EQ(expected, *data);
161 data.reset();
162 handle.reset();
163 base::RunLoop().RunUntilIdle();
164 };
165
166 TEST_F(BlobAsyncBuilderHostTest, TestShortcutNoRoom) {
167 std::vector<DataElement> descriptions;
168
169 AddShortcutMemoryItem(10, &descriptions);
170 AddBlobItem(&descriptions);
171 AddShortcutMemoryItem(5000, &descriptions);
172
173 EXPECT_EQ(BlobTransportResult::CANCEL_MEMORY_FULL,
174 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5000));
175
154 EXPECT_FALSE(request_called_); 176 EXPECT_FALSE(request_called_);
155 EXPECT_EQ(0u, host_.blob_building_count()); 177 EXPECT_EQ(0u, host_.blob_building_count());
156 }; 178 };
157 179
158 TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) { 180 TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) {
159 std::vector<DataElement> descriptions; 181 std::vector<DataElement> descriptions;
160 const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1; 182 const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1;
161 AddMemoryItem(kSize, &descriptions); 183 AddMemoryItem(kSize, &descriptions);
162 184
163 EXPECT_TRUE( 185 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
164 BuildBlobAsync(descriptions, kTestBlobStorageIPCThresholdBytes + 1)); 186 BuildBlobAsync(descriptions, std::set<std::string>(),
187 kTestBlobStorageIPCThresholdBytes + 1));
165 188
166 EXPECT_FALSE(done_called_);
167 EXPECT_FALSE(cancel_called_);
168 EXPECT_TRUE(request_called_); 189 EXPECT_TRUE(request_called_);
169 EXPECT_EQ(1u, host_.blob_building_count()); 190 EXPECT_EQ(1u, host_.blob_building_count());
170 ASSERT_EQ(1u, requests_.size()); 191 ASSERT_EQ(1u, requests_.size());
171 request_called_ = false; 192 request_called_ = false;
172 193
173 EXPECT_EQ( 194 EXPECT_EQ(
174 BlobItemBytesRequest::CreateSharedMemoryRequest(0, 0, 0, kSize, 0, 0), 195 BlobItemBytesRequest::CreateSharedMemoryRequest(0, 0, 0, kSize, 0, 0),
175 requests_.at(0)); 196 requests_.at(0));
176 }; 197 };
177 198
178 TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) { 199 TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) {
179 std::vector<DataElement> descriptions; 200 std::vector<DataElement> descriptions;
180 const size_t kSize = kTestBlobStorageMaxSharedMemoryBytes + 1; 201 const size_t kSize = kTestBlobStorageMaxSharedMemoryBytes + 1;
181 const char kFirstBlockByte = 7; 202 const char kFirstBlockByte = 7;
182 const char kSecondBlockByte = 19; 203 const char kSecondBlockByte = 19;
183 AddMemoryItem(kSize, &descriptions); 204 AddMemoryItem(kSize, &descriptions);
184 205
185 BlobDataBuilder expected(kBlobUUID); 206 BlobDataBuilder expected(kBlobUUID);
186 expected.set_content_type(kBlobType); 207 expected.set_content_type(kContentType);
208 expected.set_content_disposition(kContentDisposition);
187 char data[kSize]; 209 char data[kSize];
188 memset(data, kFirstBlockByte, kTestBlobStorageMaxSharedMemoryBytes); 210 memset(data, kFirstBlockByte, kTestBlobStorageMaxSharedMemoryBytes);
189 expected.AppendData(data, kTestBlobStorageMaxSharedMemoryBytes); 211 expected.AppendData(data, kTestBlobStorageMaxSharedMemoryBytes);
190 expected.AppendData(&kSecondBlockByte, 1); 212 expected.AppendData(&kSecondBlockByte, 1);
191 SetMatchingBuilder(&expected);
192 213
193 EXPECT_TRUE( 214 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
194 BuildBlobAsync(descriptions, kTestBlobStorageMaxSharedMemoryBytes + 1)); 215 BuildBlobAsync(descriptions, std::set<std::string>(),
216 kTestBlobStorageMaxSharedMemoryBytes + 1));
195 217
196 EXPECT_FALSE(done_called_);
197 EXPECT_FALSE(cancel_called_);
198 EXPECT_TRUE(request_called_); 218 EXPECT_TRUE(request_called_);
199 EXPECT_EQ(1u, host_.blob_building_count()); 219 EXPECT_EQ(1u, host_.blob_building_count());
200 ASSERT_EQ(1u, requests_.size()); 220 ASSERT_EQ(1u, requests_.size());
201 request_called_ = false; 221 request_called_ = false;
202 222
203 // We need to grab a duplicate handle so we can have two blocks open at the 223 // We need to grab a duplicate handle so we can have two blocks open at the
204 // same time. 224 // same time.
205 base::SharedMemoryHandle handle = 225 base::SharedMemoryHandle handle =
206 base::SharedMemory::DuplicateHandle(memory_handles_.at(0)); 226 base::SharedMemory::DuplicateHandle(memory_handles_.at(0));
207 EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle)); 227 EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle));
208 base::SharedMemory shared_memory(handle, false); 228 base::SharedMemory shared_memory(handle, false);
209 EXPECT_TRUE(shared_memory.Map(kTestBlobStorageMaxSharedMemoryBytes)); 229 EXPECT_TRUE(shared_memory.Map(kTestBlobStorageMaxSharedMemoryBytes));
210 230
211 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( 231 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(
212 0, 0, 0, kTestBlobStorageMaxSharedMemoryBytes, 0, 0), 232 0, 0, 0, kTestBlobStorageMaxSharedMemoryBytes, 0, 0),
213 requests_.at(0)); 233 requests_.at(0));
214 234
215 memset(shared_memory.memory(), kFirstBlockByte, 235 memset(shared_memory.memory(), kFirstBlockByte,
216 kTestBlobStorageMaxSharedMemoryBytes); 236 kTestBlobStorageMaxSharedMemoryBytes);
217 237
218 BlobItemBytesResponse response(0); 238 BlobItemBytesResponse response(0);
219 std::vector<BlobItemBytesResponse> responses = {response}; 239 std::vector<BlobItemBytesResponse> responses = {response};
220 EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses)); 240 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
241 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
221 242
222 EXPECT_FALSE(done_called_);
223 EXPECT_FALSE(cancel_called_);
224 EXPECT_TRUE(request_called_); 243 EXPECT_TRUE(request_called_);
225 EXPECT_EQ(1u, host_.blob_building_count()); 244 EXPECT_EQ(1u, host_.blob_building_count());
226 ASSERT_EQ(1u, requests_.size()); 245 ASSERT_EQ(1u, requests_.size());
227 request_called_ = false; 246 request_called_ = false;
228 247
229 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( 248 EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(
230 1, 0, kTestBlobStorageMaxSharedMemoryBytes, 1, 0, 0), 249 1, 0, kTestBlobStorageMaxSharedMemoryBytes, 1, 0, 0),
231 requests_.at(0)); 250 requests_.at(0));
232 251
233 memset(shared_memory.memory(), kSecondBlockByte, 1); 252 memset(shared_memory.memory(), kSecondBlockByte, 1);
234 253
235 response.request_number = 1; 254 response.request_number = 1;
236 responses[0] = response; 255 responses[0] = response;
237 EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses)); 256 EXPECT_EQ(BlobTransportResult::DONE,
238 EXPECT_TRUE(done_called_); 257 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
239 EXPECT_FALSE(cancel_called_);
240 EXPECT_FALSE(request_called_); 258 EXPECT_FALSE(request_called_);
241 EXPECT_EQ(0u, host_.blob_building_count()); 259 EXPECT_EQ(0u, host_.blob_building_count());
260 scoped_ptr<BlobDataHandle> blob_handle =
261 context_.GetBlobDataFromUUID(kBlobUUID);
262 EXPECT_FALSE(blob_handle->IsBeingBuilt());
263 EXPECT_FALSE(blob_handle->IsBroken());
264 scoped_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
265 EXPECT_EQ(expected, *blob_data);
242 }; 266 };
243 267
244 TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) { 268 TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) {
245 std::vector<DataElement> descriptions; 269 std::vector<DataElement> descriptions;
246 270
247 AddMemoryItem(2, &descriptions); 271 AddMemoryItem(2, &descriptions);
248 AddBlobItem(&descriptions); 272 AddBlobItem(&descriptions);
249 AddMemoryItem(2, &descriptions); 273 AddMemoryItem(2, &descriptions);
250 274
251 BlobDataBuilder expected(kBlobUUID); 275 BlobDataBuilder expected(kBlobUUID);
252 expected.set_content_type(kBlobType); 276 expected.set_content_type(kContentType);
277 expected.set_content_disposition(kContentDisposition);
253 AddShortcutMemoryItem(2, &expected); 278 AddShortcutMemoryItem(2, &expected);
254 expected.AppendBlob(kFakeBlobUUID); 279 expected.AppendData(kCompletedBlobData);
255 AddShortcutMemoryItem(2, &expected); 280 AddShortcutMemoryItem(2, &expected);
256 SetMatchingBuilder(&expected);
257 281
258 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 282 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
259 host_.StopBuildingBlob(kBlobUUID); 283 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
260 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 284 host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
285 &context_);
261 286
262 EXPECT_FALSE(done_called_); 287 // Check that we're broken, and then remove the blob.
263 EXPECT_FALSE(cancel_called_); 288 scoped_ptr<BlobDataHandle> blob_handle =
289 context_.GetBlobDataFromUUID(kBlobUUID);
290 EXPECT_FALSE(blob_handle->IsBeingBuilt());
291 EXPECT_TRUE(blob_handle->IsBroken());
292 blob_handle.reset();
293 DecrementBlobRefCount(kBlobUUID);
294 base::RunLoop().RunUntilIdle();
295 blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
296 EXPECT_FALSE(blob_handle.get());
297
298 // This should succeed because we've removed all references to the blob.
299 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
300 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
301
264 EXPECT_TRUE(request_called_); 302 EXPECT_TRUE(request_called_);
265 EXPECT_EQ(1u, host_.blob_building_count()); 303 EXPECT_EQ(1u, host_.blob_building_count());
266 request_called_ = false; 304 request_called_ = false;
267 305
268 BlobItemBytesResponse response1(0); 306 BlobItemBytesResponse response1(0);
269 PopulateBytes(response1.allocate_mutable_data(2), 2); 307 PopulateBytes(response1.allocate_mutable_data(2), 2);
270 BlobItemBytesResponse response2(1); 308 BlobItemBytesResponse response2(1);
271 PopulateBytes(response2.allocate_mutable_data(2), 2); 309 PopulateBytes(response2.allocate_mutable_data(2), 2);
272 std::vector<BlobItemBytesResponse> responses = {response1, response2}; 310 std::vector<BlobItemBytesResponse> responses = {response1, response2};
273 EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses)); 311
274 EXPECT_TRUE(done_called_); 312 EXPECT_EQ(BlobTransportResult::DONE,
275 EXPECT_FALSE(cancel_called_); 313 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
276 EXPECT_FALSE(request_called_); 314 EXPECT_FALSE(request_called_);
277 EXPECT_EQ(0u, host_.blob_building_count()); 315 EXPECT_EQ(0u, host_.blob_building_count());
316 blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
317 EXPECT_FALSE(blob_handle->IsBeingBuilt());
318 EXPECT_FALSE(blob_handle->IsBroken());
319 scoped_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
320 EXPECT_EQ(expected, *blob_data);
321 };
322
323 TEST_F(BlobAsyncBuilderHostTest, TestBreakingAllBuilding) {
324 const std::string& kBlob1 = "blob1";
325 const std::string& kBlob2 = "blob2";
326 const std::string& kBlob3 = "blob3";
327
328 // Register blobs.
329 EXPECT_EQ(BlobTransportResult::DONE,
330 host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
331 std::set<std::string>(), &context_));
332 EXPECT_EQ(BlobTransportResult::DONE,
333 host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
334 std::set<std::string>(), &context_));
335 EXPECT_EQ(BlobTransportResult::DONE,
336 host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
337 std::set<std::string>(), &context_));
338
339 // Start building one of them.
340 std::vector<DataElement> descriptions;
341 AddMemoryItem(2, &descriptions);
342 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
343 host_.StartBuildingBlob(
344 kBlob1, descriptions, 2, &context_,
345 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
346 base::Unretained(this))));
347 EXPECT_TRUE(request_called_);
348
349 scoped_ptr<BlobDataHandle> blob_handle1 =
350 context_.GetBlobDataFromUUID(kBlob1);
351 scoped_ptr<BlobDataHandle> blob_handle2 =
352 context_.GetBlobDataFromUUID(kBlob2);
353 scoped_ptr<BlobDataHandle> blob_handle3 =
354 context_.GetBlobDataFromUUID(kBlob2);
355 EXPECT_TRUE(blob_handle1->IsBeingBuilt() && blob_handle2->IsBeingBuilt() &&
356 blob_handle3->IsBeingBuilt());
357 EXPECT_FALSE(blob_handle1->IsBroken() || blob_handle2->IsBroken() ||
358 blob_handle3->IsBroken());
359
360 host_.CancelAll(&context_);
361
362 EXPECT_FALSE(blob_handle1->IsBeingBuilt() || blob_handle2->IsBeingBuilt() ||
363 blob_handle3->IsBeingBuilt());
364 EXPECT_TRUE(blob_handle1->IsBroken() && blob_handle2->IsBroken() &&
365 blob_handle3->IsBroken());
366 blob_handle1.reset();
367 blob_handle2.reset();
368 blob_handle3.reset();
369 base::RunLoop().RunUntilIdle();
278 }; 370 };
279 371
280 TEST_F(BlobAsyncBuilderHostTest, TestBadIPCs) { 372 TEST_F(BlobAsyncBuilderHostTest, TestBadIPCs) {
281 std::vector<DataElement> descriptions; 373 std::vector<DataElement> descriptions;
282 374
283 // Test reusing same blob uuid. 375 // Test reusing same blob uuid.
284 SetMatchingBuilder(nullptr);
285 AddMemoryItem(10, &descriptions); 376 AddMemoryItem(10, &descriptions);
286 AddBlobItem(&descriptions); 377 AddBlobItem(&descriptions);
287 AddMemoryItem(5000, &descriptions); 378 AddMemoryItem(5000, &descriptions);
288 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 379 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
289 EXPECT_FALSE(BuildBlobAsync(descriptions, 5010)); 380 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
290 EXPECT_FALSE(done_called_); 381 EXPECT_EQ(BlobTransportResult::BAD_IPC,
291 EXPECT_FALSE(cancel_called_); 382 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
292 EXPECT_FALSE(request_called_); 383 EXPECT_FALSE(request_called_);
293 host_.StopBuildingBlob(kBlobUUID); 384 host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
294 385 &context_);
295 // Test we're _not_ an error if we get a bad uuid for responses. 386 base::RunLoop().RunUntilIdle();
387 DecrementBlobRefCount(kBlobUUID);
388 EXPECT_FALSE(context_.GetBlobDataFromUUID(kBlobUUID).get());
389
390 // Test we're an error if we get a bad uuid for responses.
296 BlobItemBytesResponse response(0); 391 BlobItemBytesResponse response(0);
297 std::vector<BlobItemBytesResponse> responses = {response}; 392 std::vector<BlobItemBytesResponse> responses = {response};
298 EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses)); 393 EXPECT_EQ(BlobTransportResult::BAD_IPC,
394 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
299 395
300 // Test empty responses. 396 // Test empty responses.
301 responses.clear(); 397 responses.clear();
302 EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses)); 398 EXPECT_EQ(BlobTransportResult::BAD_IPC,
399 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
303 400
304 // Test response problems below here. 401 // Test response problems below here.
305 descriptions.clear(); 402 descriptions.clear();
306 AddMemoryItem(2, &descriptions); 403 AddMemoryItem(2, &descriptions);
307 AddBlobItem(&descriptions); 404 AddBlobItem(&descriptions);
308 AddMemoryItem(2, &descriptions); 405 AddMemoryItem(2, &descriptions);
309 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 406 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
407 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
310 408
311 // Invalid request number. 409 // Invalid request number.
312 BlobItemBytesResponse response1(3); 410 BlobItemBytesResponse response1(3);
313 PopulateBytes(response1.allocate_mutable_data(2), 2); 411 PopulateBytes(response1.allocate_mutable_data(2), 2);
314 responses = {response1}; 412 responses = {response1};
315 EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses)); 413 EXPECT_EQ(BlobTransportResult::BAD_IPC,
414 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
415 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
416 DecrementBlobRefCount(kBlobUUID);
417 base::RunLoop().RunUntilIdle();
316 418
317 // Duplicate request number responses. 419 // Duplicate request number responses.
318 EXPECT_TRUE(BuildBlobAsync(descriptions, 5010)); 420 EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
421 BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
319 response1.request_number = 0; 422 response1.request_number = 0;
320 BlobItemBytesResponse response2(0); 423 BlobItemBytesResponse response2(0);
321 PopulateBytes(response2.allocate_mutable_data(2), 2); 424 PopulateBytes(response2.allocate_mutable_data(2), 2);
322 responses = {response1, response2}; 425 responses = {response1, response2};
323 EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses)); 426 EXPECT_EQ(BlobTransportResult::BAD_IPC,
324 }; 427 host_.OnMemoryResponses(kBlobUUID, responses, &context_));
325 428 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
326 } // namespace 429 DecrementBlobRefCount(kBlobUUID);
430 base::RunLoop().RunUntilIdle();
431 };
432
433 TEST_F(BlobAsyncBuilderHostTest, WaitOnReferencedBlob) {
434 const std::string& kBlob1 = "blob1";
435 const std::string& kBlob2 = "blob2";
436 const std::string& kBlob3 = "blob3";
437
438 // Register blobs.
439 EXPECT_EQ(BlobTransportResult::DONE,
440 host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
441 std::set<std::string>(), &context_));
442 EXPECT_EQ(BlobTransportResult::DONE,
443 host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
444 std::set<std::string>(), &context_));
445 EXPECT_EQ(BlobTransportResult::DONE,
446 host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
447 {kBlob1, kBlob2}, &context_));
448
449 // Finish the third one, with a reference to the first and second blob.
450 std::vector<DataElement> descriptions;
451 AddShortcutMemoryItem(2, &descriptions);
452 DataElement element;
453 element.SetToBlob(kBlob1);
454 descriptions.push_back(element);
455 element.SetToBlob(kBlob2);
456 descriptions.push_back(element);
457
458 // Finish the third, but we should still be 'building' it.
459 EXPECT_EQ(BlobTransportResult::DONE,
460 host_.StartBuildingBlob(
461 kBlob3, descriptions, 2, &context_,
462 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
463 base::Unretained(this))));
464 EXPECT_FALSE(request_called_);
465 EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
466 EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
467
468 // Finish the first.
469 descriptions.clear();
470 AddShortcutMemoryItem(2, &descriptions);
471 EXPECT_EQ(BlobTransportResult::DONE,
472 host_.StartBuildingBlob(
473 kBlob1, descriptions, 2, &context_,
474 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
475 base::Unretained(this))));
476 EXPECT_FALSE(request_called_);
477 EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
478 EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
479 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1));
480
481 // Run the message loop so we propogate the construction complete callbacks.
482 base::RunLoop().RunUntilIdle();
483 // Verify we're not done.
484 EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
485 EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
486
487 // Finish the second.
488 EXPECT_EQ(BlobTransportResult::DONE,
489 host_.StartBuildingBlob(
490 kBlob2, descriptions, 2, &context_,
491 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
492 base::Unretained(this))));
493 EXPECT_FALSE(request_called_);
494 EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
495 EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
496 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2));
497
498 // Run the message loop so we propogate the construction complete callbacks.
499 base::RunLoop().RunUntilIdle();
500 // Finally, we should be finished with third blob.
501 EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
502 EXPECT_FALSE(IsBeingBuiltInContext(kBlob3));
503 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob3));
504 };
505
506 TEST_F(BlobAsyncBuilderHostTest, IncorrectBlobDependencies) {
507 const std::string& kGoodBlob = "goodBlob";
508 const std::string& kBlob1 = "blob1";
509 const std::string& kBlob2 = "blob2";
510 const std::string& kBlob3 = "blob3";
511
512 // Register blobs. Blob 1 has a reference to itself, Blob 2 has a reference
513 // but doesn't use it, and blob 3 doesn't list it's reference.
514 EXPECT_EQ(BlobTransportResult::DONE,
515 host_.RegisterBlobUUID(kGoodBlob, kContentType, kContentDisposition,
516 std::set<std::string>(), &context_));
517 EXPECT_EQ(BlobTransportResult::BAD_IPC,
518 host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
519 {kBlob1}, &context_));
520 EXPECT_EQ(BlobTransportResult::DONE,
521 host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
522 {kGoodBlob}, &context_));
523 EXPECT_EQ(BlobTransportResult::DONE,
524 host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
525 std::set<std::string>(), &context_));
526
527 // The first blob shouldn't be building anymore.
528 EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
529 // Test we get BAD_IPC.
530 std::vector<DataElement> descriptions;
531 AddShortcutMemoryItem(2, &descriptions);
532 DataElement element;
533 element.SetToBlob(kBlob1);
534 descriptions.push_back(element);
535 EXPECT_EQ(BlobTransportResult::BAD_IPC,
536 host_.StartBuildingBlob(
537 kBlob1, descriptions, 2, &context_,
538 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
539 base::Unretained(this))));
540
541 // Try to finish the second one, without a reference to the first.
542 descriptions.clear();
543 AddShortcutMemoryItem(2, &descriptions);
544 EXPECT_EQ(BlobTransportResult::BAD_IPC,
545 host_.StartBuildingBlob(
546 kBlob2, descriptions, 2, &context_,
547 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
548 base::Unretained(this))));
549 EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
550
551 // Try to finish the third one with the reference we didn't declare earlier.
552 descriptions.clear();
553 AddShortcutMemoryItem(2, &descriptions);
554 element.SetToBlob(kGoodBlob);
555 descriptions.push_back(element);
556 EXPECT_EQ(BlobTransportResult::BAD_IPC,
557 host_.StartBuildingBlob(
558 kBlob3, descriptions, 2, &context_,
559 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
560 base::Unretained(this))));
561 EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
562 };
563
564 TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBreaks) {
565 const std::string& kBlob1 = "blob1";
566 const std::string& kBlob2 = "blob2";
567
568 // Register blobs.
569 EXPECT_EQ(BlobTransportResult::DONE,
570 host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
571 std::set<std::string>(), &context_));
572 EXPECT_EQ(BlobTransportResult::DONE,
573 host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
574 {kBlob1}, &context_));
575
576 // Finish the second one, with a reference to the first.
577 std::vector<DataElement> descriptions;
578 AddShortcutMemoryItem(2, &descriptions);
579 DataElement element;
580 element.SetToBlob(kBlob1);
581 descriptions.push_back(element);
582 EXPECT_EQ(BlobTransportResult::DONE,
583 host_.StartBuildingBlob(
584 kBlob2, descriptions, 2, &context_,
585 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
586 base::Unretained(this))));
587 EXPECT_FALSE(request_called_);
588 EXPECT_TRUE(host_.IsBeingBuilt(kBlob2));
589 EXPECT_TRUE(IsBeingBuiltInContext(kBlob2));
590
591 // Break the first.
592 descriptions.clear();
593 host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
594 &context_);
595 EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
596 EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
597 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1)->IsBroken());
598
599 // Run the message loop so we propogate the construction complete callbacks.
600 base::RunLoop().RunUntilIdle();
601 // We should be finished with third blob, and it should be broken.
602 EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
603 EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
604 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
605 };
606
607 TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBroken) {
608 const std::string& kBlob1 = "blob1";
609 const std::string& kBlob2 = "blob2";
610
611 // Register blobs.
612 EXPECT_EQ(BlobTransportResult::DONE,
613 host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
614 std::set<std::string>(), &context_));
615 host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
616 &context_);
617 EXPECT_EQ(BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN,
618 host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
619 {kBlob1}, &context_));
620 EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
621 EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
622 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
623
624 // Try to finish the second one, but we should get a BAD_IPC, as we are no
625 // longer being constructed.
626 std::vector<DataElement> descriptions;
627 AddShortcutMemoryItem(2, &descriptions);
628 DataElement element;
629 element.SetToBlob(kBlob1);
630 descriptions.push_back(element);
631 EXPECT_EQ(BlobTransportResult::BAD_IPC,
632 host_.StartBuildingBlob(
633 kBlob2, descriptions, 2, &context_,
634 base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
635 base::Unretained(this))));
636 EXPECT_FALSE(request_called_);
637 EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
638 };
639
327 } // namespace storage 640 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698