OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_storage_context.h" |
| 6 |
| 7 #include <limits> |
| 8 #include <string> |
| 9 |
5 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
6 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
7 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
8 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
9 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
10 #include "base/time/time.h" | 15 #include "base/time/time.h" |
11 #include "content/browser/fileapi/blob_storage_host.h" | 16 #include "content/browser/fileapi/blob_storage_host.h" |
12 #include "storage/browser/blob/blob_data_builder.h" | 17 #include "storage/browser/blob/blob_data_builder.h" |
13 #include "storage/browser/blob/blob_data_handle.h" | 18 #include "storage/browser/blob/blob_data_handle.h" |
| 19 #include "storage/browser/blob/blob_data_item.h" |
14 #include "storage/browser/blob/blob_data_snapshot.h" | 20 #include "storage/browser/blob/blob_data_snapshot.h" |
15 #include "storage/browser/blob/blob_storage_context.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
17 | 22 |
18 using storage::BlobDataBuilder; | 23 using storage::BlobDataBuilder; |
19 using storage::BlobDataHandle; | 24 using storage::BlobDataHandle; |
| 25 using storage::BlobDataItem; |
20 using storage::BlobDataSnapshot; | 26 using storage::BlobDataSnapshot; |
21 using storage::BlobStorageContext; | 27 using storage::BlobStorageContext; |
22 using storage::DataElement; | 28 using storage::DataElement; |
23 | 29 |
24 namespace content { | 30 namespace content { |
25 | |
26 namespace { | 31 namespace { |
27 // This is necessary to clean up the blobs after the handles are released. | |
28 void RunEventLoopTillIdle() { | |
29 base::RunLoop run_loop; | |
30 run_loop.RunUntilIdle(); | |
31 } | |
32 | 32 |
33 void SetupBasicBlob(BlobStorageHost* host, const std::string& id) { | 33 void SetupBasicBlob(BlobStorageHost* host, const std::string& id) { |
34 EXPECT_TRUE(host->StartBuildingBlob(id)); | 34 EXPECT_TRUE(host->StartBuildingBlob(id)); |
35 DataElement item; | 35 DataElement item; |
36 item.SetToBytes("1", 1); | 36 item.SetToBytes("1", 1); |
37 EXPECT_TRUE(host->AppendBlobDataItem(id, item)); | 37 EXPECT_TRUE(host->AppendBlobDataItem(id, item)); |
38 EXPECT_TRUE(host->FinishBuildingBlob(id, "text/plain")); | 38 EXPECT_TRUE(host->FinishBuildingBlob(id, "text/plain")); |
39 EXPECT_FALSE(host->StartBuildingBlob(id)); | 39 EXPECT_FALSE(host->StartBuildingBlob(id)); |
40 } | 40 } |
| 41 |
41 } // namespace | 42 } // namespace |
42 | 43 |
43 TEST(BlobStorageContextTest, IncrementDecrementRef) { | 44 TEST(BlobStorageContextTest, IncrementDecrementRef) { |
44 BlobStorageContext context; | 45 BlobStorageContext context; |
45 BlobStorageHost host(&context); | 46 BlobStorageHost host(&context); |
46 base::MessageLoop fake_io_message_loop; | 47 base::MessageLoop fake_io_message_loop; |
47 | 48 |
48 // Build up a basic blob. | 49 // Build up a basic blob. |
49 const std::string kId("id"); | 50 const std::string kId("id"); |
50 SetupBasicBlob(&host, kId); | 51 SetupBasicBlob(&host, kId); |
51 | 52 |
52 // Make sure it's there, finish building implies a ref of one. | 53 // Make sure it's there, finish building implies a ref of one. |
53 scoped_ptr<BlobDataHandle> blob_data_handle; | 54 scoped_ptr<BlobDataHandle> blob_data_handle; |
54 blob_data_handle = context.GetBlobDataFromUUID(kId); | 55 blob_data_handle = context.GetBlobDataFromUUID(kId); |
55 EXPECT_TRUE(blob_data_handle); | 56 EXPECT_TRUE(blob_data_handle); |
56 blob_data_handle.reset(); | 57 blob_data_handle.reset(); |
57 RunEventLoopTillIdle(); | 58 base::RunLoop().RunUntilIdle(); |
58 | 59 |
59 // Make sure its still there after inc/dec. | 60 // Make sure its still there after inc/dec. |
60 EXPECT_TRUE(host.IncrementBlobRefCount(kId)); | 61 EXPECT_TRUE(host.IncrementBlobRefCount(kId)); |
61 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 62 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); |
62 blob_data_handle = context.GetBlobDataFromUUID(kId); | 63 blob_data_handle = context.GetBlobDataFromUUID(kId); |
63 EXPECT_TRUE(blob_data_handle); | 64 EXPECT_TRUE(blob_data_handle); |
64 blob_data_handle.reset(); | 65 blob_data_handle.reset(); |
65 RunEventLoopTillIdle(); | 66 base::RunLoop().RunUntilIdle(); |
66 | 67 |
67 // Make sure it goes away in the end. | 68 // Make sure it goes away in the end. |
68 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 69 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); |
69 blob_data_handle = context.GetBlobDataFromUUID(kId); | 70 blob_data_handle = context.GetBlobDataFromUUID(kId); |
70 EXPECT_FALSE(blob_data_handle); | 71 EXPECT_FALSE(blob_data_handle); |
71 EXPECT_FALSE(host.DecrementBlobRefCount(kId)); | 72 EXPECT_FALSE(host.DecrementBlobRefCount(kId)); |
72 EXPECT_FALSE(host.IncrementBlobRefCount(kId)); | 73 EXPECT_FALSE(host.IncrementBlobRefCount(kId)); |
73 } | 74 } |
74 | 75 |
75 TEST(BlobStorageContextTest, CancelBuildingBlob) { | 76 TEST(BlobStorageContextTest, CancelBuildingBlob) { |
(...skipping 30 matching lines...) Expand all Loading... |
106 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 107 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); |
107 | 108 |
108 // Should still be there due to the handle. | 109 // Should still be there due to the handle. |
109 scoped_ptr<BlobDataHandle> another_handle = | 110 scoped_ptr<BlobDataHandle> another_handle = |
110 context.GetBlobDataFromUUID(kId); | 111 context.GetBlobDataFromUUID(kId); |
111 EXPECT_TRUE(another_handle); | 112 EXPECT_TRUE(another_handle); |
112 | 113 |
113 // Should disappear after dropping both handles. | 114 // Should disappear after dropping both handles. |
114 blob_data_handle.reset(); | 115 blob_data_handle.reset(); |
115 another_handle.reset(); | 116 another_handle.reset(); |
116 RunEventLoopTillIdle(); | 117 base::RunLoop().RunUntilIdle(); |
117 | 118 |
118 blob_data_handle = context.GetBlobDataFromUUID(kId); | 119 blob_data_handle = context.GetBlobDataFromUUID(kId); |
119 EXPECT_FALSE(blob_data_handle); | 120 EXPECT_FALSE(blob_data_handle); |
120 } | 121 } |
121 | 122 |
122 TEST(BlobStorageContextTest, MemoryUsage) { | 123 TEST(BlobStorageContextTest, MemoryUsage) { |
123 const std::string kId1("id1"); | 124 const std::string kId1("id1"); |
124 const std::string kId2("id2"); | 125 const std::string kId2("id2"); |
125 | 126 |
126 base::MessageLoop fake_io_message_loop; | 127 base::MessageLoop fake_io_message_loop; |
(...skipping 13 matching lines...) Expand all Loading... |
140 EXPECT_EQ(0lu, context.memory_usage()); | 141 EXPECT_EQ(0lu, context.memory_usage()); |
141 | 142 |
142 scoped_ptr<BlobDataHandle> blob_data_handle = | 143 scoped_ptr<BlobDataHandle> blob_data_handle = |
143 context.AddFinishedBlob(&builder1); | 144 context.AddFinishedBlob(&builder1); |
144 EXPECT_EQ(10lu, context.memory_usage()); | 145 EXPECT_EQ(10lu, context.memory_usage()); |
145 scoped_ptr<BlobDataHandle> blob_data_handle2 = | 146 scoped_ptr<BlobDataHandle> blob_data_handle2 = |
146 context.AddFinishedBlob(&builder2); | 147 context.AddFinishedBlob(&builder2); |
147 EXPECT_EQ(10lu, context.memory_usage()); | 148 EXPECT_EQ(10lu, context.memory_usage()); |
148 | 149 |
149 blob_data_handle.reset(); | 150 blob_data_handle.reset(); |
150 RunEventLoopTillIdle(); | 151 base::RunLoop().RunUntilIdle(); |
151 | 152 |
152 EXPECT_EQ(10lu, context.memory_usage()); | 153 EXPECT_EQ(10lu, context.memory_usage()); |
153 blob_data_handle2.reset(); | 154 blob_data_handle2.reset(); |
154 RunEventLoopTillIdle(); | 155 base::RunLoop().RunUntilIdle(); |
155 | 156 |
156 EXPECT_EQ(0lu, context.memory_usage()); | 157 EXPECT_EQ(0lu, context.memory_usage()); |
157 } | 158 } |
158 | 159 |
159 TEST(BlobStorageContextTest, AddFinishedBlob) { | 160 TEST(BlobStorageContextTest, AddFinishedBlob) { |
160 const std::string kId1("id1"); | 161 const std::string kId1("id1"); |
161 const std::string kId2("id12"); | 162 const std::string kId2("id12"); |
162 const std::string kId2Prime("id2.prime"); | 163 const std::string kId2Prime("id2.prime"); |
163 const std::string kId3("id3"); | 164 const std::string kId3("id3"); |
164 const std::string kId3Prime("id3.prime"); | 165 const std::string kId3Prime("id3.prime"); |
(...skipping 18 matching lines...) Expand all Loading... |
183 | 184 |
184 ASSERT_TRUE(blob_data_handle); | 185 ASSERT_TRUE(blob_data_handle); |
185 ASSERT_TRUE(blob_data_handle2); | 186 ASSERT_TRUE(blob_data_handle2); |
186 scoped_ptr<BlobDataSnapshot> data1 = blob_data_handle->CreateSnapshot(); | 187 scoped_ptr<BlobDataSnapshot> data1 = blob_data_handle->CreateSnapshot(); |
187 scoped_ptr<BlobDataSnapshot> data2 = blob_data_handle2->CreateSnapshot(); | 188 scoped_ptr<BlobDataSnapshot> data2 = blob_data_handle2->CreateSnapshot(); |
188 EXPECT_EQ(*data1, builder1); | 189 EXPECT_EQ(*data1, builder1); |
189 EXPECT_EQ(*data2, canonicalized_blob_data2); | 190 EXPECT_EQ(*data2, canonicalized_blob_data2); |
190 blob_data_handle.reset(); | 191 blob_data_handle.reset(); |
191 data2.reset(); | 192 data2.reset(); |
192 | 193 |
193 RunEventLoopTillIdle(); | 194 base::RunLoop().RunUntilIdle(); |
194 | 195 |
195 blob_data_handle = context.GetBlobDataFromUUID(kId1); | 196 blob_data_handle = context.GetBlobDataFromUUID(kId1); |
196 EXPECT_FALSE(blob_data_handle); | 197 EXPECT_FALSE(blob_data_handle); |
197 EXPECT_TRUE(blob_data_handle2); | 198 EXPECT_TRUE(blob_data_handle2); |
198 data2 = blob_data_handle2->CreateSnapshot(); | 199 data2 = blob_data_handle2->CreateSnapshot(); |
199 EXPECT_EQ(*data2, canonicalized_blob_data2); | 200 EXPECT_EQ(*data2, canonicalized_blob_data2); |
200 | 201 |
201 // Test shared elements stick around. | 202 // Test shared elements stick around. |
202 BlobDataBuilder builder3(kId3); | 203 BlobDataBuilder builder3(kId3); |
203 builder3.AppendBlob(kId2); | 204 builder3.AppendBlob(kId2); |
204 builder3.AppendBlob(kId2); | 205 builder3.AppendBlob(kId2); |
205 scoped_ptr<BlobDataHandle> blob_data_handle3 = | 206 scoped_ptr<BlobDataHandle> blob_data_handle3 = |
206 context.AddFinishedBlob(&builder3); | 207 context.AddFinishedBlob(&builder3); |
207 blob_data_handle2.reset(); | 208 blob_data_handle2.reset(); |
208 RunEventLoopTillIdle(); | 209 base::RunLoop().RunUntilIdle(); |
209 | 210 |
210 blob_data_handle2 = context.GetBlobDataFromUUID(kId2); | 211 blob_data_handle2 = context.GetBlobDataFromUUID(kId2); |
211 EXPECT_FALSE(blob_data_handle2); | 212 EXPECT_FALSE(blob_data_handle2); |
212 EXPECT_TRUE(blob_data_handle3); | 213 EXPECT_TRUE(blob_data_handle3); |
213 scoped_ptr<BlobDataSnapshot> data3 = blob_data_handle3->CreateSnapshot(); | 214 scoped_ptr<BlobDataSnapshot> data3 = blob_data_handle3->CreateSnapshot(); |
214 | 215 |
215 BlobDataBuilder canonicalized_blob_data3(kId3Prime); | 216 BlobDataBuilder canonicalized_blob_data3(kId3Prime); |
216 canonicalized_blob_data3.AppendData("Data2"); | 217 canonicalized_blob_data3.AppendData("Data2"); |
217 canonicalized_blob_data3.AppendData(" is the best"); | 218 canonicalized_blob_data3.AppendData(" is the best"); |
218 canonicalized_blob_data3.AppendData("Data2"); | 219 canonicalized_blob_data3.AppendData("Data2"); |
219 canonicalized_blob_data3.AppendData(" is the best"); | 220 canonicalized_blob_data3.AppendData(" is the best"); |
220 EXPECT_EQ(*data3, canonicalized_blob_data3); | 221 EXPECT_EQ(*data3, canonicalized_blob_data3); |
221 | 222 |
222 blob_data_handle.reset(); | 223 blob_data_handle.reset(); |
223 blob_data_handle2.reset(); | 224 blob_data_handle2.reset(); |
224 blob_data_handle3.reset(); | 225 blob_data_handle3.reset(); |
225 RunEventLoopTillIdle(); | 226 base::RunLoop().RunUntilIdle(); |
| 227 } |
| 228 |
| 229 TEST(BlobStorageContextTest, AddFinishedBlob_LargeOffset) { |
| 230 // A value which does not fit in a 4-byte data type. Used to confirm that |
| 231 // large values are supported on 32-bit Chromium builds. Regression test for: |
| 232 // crbug.com/458122. |
| 233 const uint64_t kLargeSize = std::numeric_limits<uint64_t>::max(); |
| 234 |
| 235 const uint64_t kBlobLength = 5; |
| 236 const std::string kId1("id1"); |
| 237 const std::string kId2("id2"); |
| 238 base::MessageLoop fake_io_message_loop; |
| 239 |
| 240 BlobDataBuilder builder1(kId1); |
| 241 builder1.AppendFileSystemFile(GURL(), 0, kLargeSize, base::Time::Now()); |
| 242 |
| 243 BlobDataBuilder builder2(kId2); |
| 244 builder2.AppendBlob(kId1, kLargeSize - kBlobLength, kBlobLength); |
| 245 |
| 246 BlobStorageContext context; |
| 247 scoped_ptr<BlobDataHandle> blob_data_handle1 = |
| 248 context.AddFinishedBlob(&builder1); |
| 249 scoped_ptr<BlobDataHandle> blob_data_handle2 = |
| 250 context.AddFinishedBlob(&builder2); |
| 251 |
| 252 ASSERT_TRUE(blob_data_handle1); |
| 253 ASSERT_TRUE(blob_data_handle2); |
| 254 scoped_ptr<BlobDataSnapshot> data = blob_data_handle2->CreateSnapshot(); |
| 255 ASSERT_EQ(1u, data->items().size()); |
| 256 const scoped_refptr<BlobDataItem> item = data->items()[0]; |
| 257 EXPECT_EQ(kLargeSize - kBlobLength, item->offset()); |
| 258 EXPECT_EQ(kBlobLength, item->length()); |
| 259 |
| 260 blob_data_handle1.reset(); |
| 261 blob_data_handle2.reset(); |
| 262 base::RunLoop().RunUntilIdle(); |
226 } | 263 } |
227 | 264 |
228 TEST(BlobStorageContextTest, CompoundBlobs) { | 265 TEST(BlobStorageContextTest, CompoundBlobs) { |
229 const std::string kId1("id1"); | 266 const std::string kId1("id1"); |
230 const std::string kId2("id2"); | 267 const std::string kId2("id2"); |
231 const std::string kId2Prime("id2.prime"); | 268 const std::string kId2Prime("id2.prime"); |
232 | 269 |
233 base::MessageLoop fake_io_message_loop; | 270 base::MessageLoop fake_io_message_loop; |
234 | 271 |
235 // Setup a set of blob data for testing. | 272 // Setup a set of blob data for testing. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 EXPECT_EQ(*data, blob_data1); | 306 EXPECT_EQ(*data, blob_data1); |
270 | 307 |
271 // Test a blob composed in part with another blob. | 308 // Test a blob composed in part with another blob. |
272 blob_data_handle = context.AddFinishedBlob(&blob_data2); | 309 blob_data_handle = context.AddFinishedBlob(&blob_data2); |
273 data = blob_data_handle->CreateSnapshot(); | 310 data = blob_data_handle->CreateSnapshot(); |
274 ASSERT_TRUE(blob_data_handle); | 311 ASSERT_TRUE(blob_data_handle); |
275 ASSERT_TRUE(data); | 312 ASSERT_TRUE(data); |
276 EXPECT_EQ(*data, canonicalized_blob_data2); | 313 EXPECT_EQ(*data, canonicalized_blob_data2); |
277 | 314 |
278 blob_data_handle.reset(); | 315 blob_data_handle.reset(); |
279 RunEventLoopTillIdle(); | 316 base::RunLoop().RunUntilIdle(); |
280 } | 317 } |
281 | 318 |
282 TEST(BlobStorageContextTest, PublicBlobUrls) { | 319 TEST(BlobStorageContextTest, PublicBlobUrls) { |
283 BlobStorageContext context; | 320 BlobStorageContext context; |
284 BlobStorageHost host(&context); | 321 BlobStorageHost host(&context); |
285 base::MessageLoop fake_io_message_loop; | 322 base::MessageLoop fake_io_message_loop; |
286 | 323 |
287 // Build up a basic blob. | 324 // Build up a basic blob. |
288 const std::string kId("id"); | 325 const std::string kId("id"); |
289 SetupBasicBlob(&host, kId); | 326 SetupBasicBlob(&host, kId); |
290 | 327 |
291 // Now register a url for that blob. | 328 // Now register a url for that blob. |
292 GURL kUrl("blob:id"); | 329 GURL kUrl("blob:id"); |
293 EXPECT_TRUE(host.RegisterPublicBlobURL(kUrl, kId)); | 330 EXPECT_TRUE(host.RegisterPublicBlobURL(kUrl, kId)); |
294 scoped_ptr<BlobDataHandle> blob_data_handle = | 331 scoped_ptr<BlobDataHandle> blob_data_handle = |
295 context.GetBlobDataFromPublicURL(kUrl); | 332 context.GetBlobDataFromPublicURL(kUrl); |
296 ASSERT_TRUE(blob_data_handle.get()); | 333 ASSERT_TRUE(blob_data_handle.get()); |
297 EXPECT_EQ(kId, blob_data_handle->uuid()); | 334 EXPECT_EQ(kId, blob_data_handle->uuid()); |
298 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); | 335 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); |
299 blob_data_handle.reset(); | 336 blob_data_handle.reset(); |
300 RunEventLoopTillIdle(); | 337 base::RunLoop().RunUntilIdle(); |
301 | 338 |
302 // The url registration should keep the blob alive even after | 339 // The url registration should keep the blob alive even after |
303 // explicit references are dropped. | 340 // explicit references are dropped. |
304 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 341 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); |
305 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); | 342 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); |
306 EXPECT_TRUE(blob_data_handle); | 343 EXPECT_TRUE(blob_data_handle); |
307 blob_data_handle.reset(); | 344 blob_data_handle.reset(); |
308 RunEventLoopTillIdle(); | 345 base::RunLoop().RunUntilIdle(); |
309 | 346 |
310 // Finally get rid of the url registration and the blob. | 347 // Finally get rid of the url registration and the blob. |
311 EXPECT_TRUE(host.RevokePublicBlobURL(kUrl)); | 348 EXPECT_TRUE(host.RevokePublicBlobURL(kUrl)); |
312 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); | 349 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); |
313 EXPECT_TRUE(!blob_data_handle.get()); | 350 EXPECT_TRUE(!blob_data_handle.get()); |
314 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); | 351 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); |
315 } | 352 } |
316 | 353 |
317 TEST(BlobStorageContextTest, HostCleanup) { | 354 TEST(BlobStorageContextTest, HostCleanup) { |
318 BlobStorageContext context; | 355 BlobStorageContext context; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain")); | 387 EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain")); |
351 EXPECT_FALSE(host.RegisterPublicBlobURL(kUrl, kId)); | 388 EXPECT_FALSE(host.RegisterPublicBlobURL(kUrl, kId)); |
352 EXPECT_FALSE(host.IncrementBlobRefCount(kId)); | 389 EXPECT_FALSE(host.IncrementBlobRefCount(kId)); |
353 EXPECT_FALSE(host.DecrementBlobRefCount(kId)); | 390 EXPECT_FALSE(host.DecrementBlobRefCount(kId)); |
354 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); | 391 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); |
355 } | 392 } |
356 | 393 |
357 // TODO(michaeln): tests for the depcrecated url stuff | 394 // TODO(michaeln): tests for the depcrecated url stuff |
358 | 395 |
359 } // namespace content | 396 } // namespace content |
OLD | NEW |