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" | 5 #include "storage/browser/blob/blob_storage_context.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <limits> | 9 #include <limits> |
10 #include <string> | 10 #include <string> |
11 | 11 |
| 12 #include "base/files/file.h" |
12 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
13 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
15 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
16 #include "base/run_loop.h" | 17 #include "base/run_loop.h" |
17 #include "base/time/time.h" | 18 #include "base/time/time.h" |
18 #include "content/browser/fileapi/blob_storage_host.h" | 19 #include "content/browser/blob_storage/blob_dispatcher_host.h" |
| 20 #include "content/browser/fileapi/chrome_blob_storage_context.h" |
| 21 #include "content/public/test/test_browser_context.h" |
19 #include "net/base/io_buffer.h" | 22 #include "net/base/io_buffer.h" |
20 #include "net/base/test_completion_callback.h" | 23 #include "net/base/test_completion_callback.h" |
21 #include "net/disk_cache/disk_cache.h" | 24 #include "net/disk_cache/disk_cache.h" |
| 25 #include "storage/browser/blob/blob_async_builder_host.h" |
22 #include "storage/browser/blob/blob_data_builder.h" | 26 #include "storage/browser/blob/blob_data_builder.h" |
23 #include "storage/browser/blob/blob_data_handle.h" | 27 #include "storage/browser/blob/blob_data_handle.h" |
24 #include "storage/browser/blob/blob_data_item.h" | 28 #include "storage/browser/blob/blob_data_item.h" |
25 #include "storage/browser/blob/blob_data_snapshot.h" | 29 #include "storage/browser/blob/blob_data_snapshot.h" |
| 30 #include "storage/browser/blob/blob_transport_result.h" |
| 31 #include "storage/common/blob_storage/blob_item_bytes_request.h" |
| 32 #include "storage/common/blob_storage/blob_item_bytes_response.h" |
26 #include "testing/gtest/include/gtest/gtest.h" | 33 #include "testing/gtest/include/gtest/gtest.h" |
27 | 34 |
28 using storage::BlobDataBuilder; | 35 using RequestMemoryCallback = |
29 using storage::BlobDataHandle; | 36 storage::BlobAsyncBuilderHost::RequestMemoryCallback; |
30 using storage::BlobDataItem; | |
31 using storage::BlobDataSnapshot; | |
32 using storage::BlobStorageContext; | |
33 using storage::DataElement; | |
34 | 37 |
35 namespace content { | 38 namespace storage { |
36 namespace { | 39 namespace { |
37 | 40 |
| 41 const char kContentType[] = "text/plain"; |
| 42 const char kContentDisposition[] = "content_disposition"; |
38 const int kTestDiskCacheStreamIndex = 0; | 43 const int kTestDiskCacheStreamIndex = 0; |
39 | 44 |
40 // Our disk cache tests don't need a real data handle since the tests themselves | 45 // Our disk cache tests don't need a real data handle since the tests themselves |
41 // scope the disk cache and entries. | 46 // scope the disk cache and entries. |
42 class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle { | 47 class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle { |
43 private: | 48 private: |
44 ~EmptyDataHandle() override {} | 49 ~EmptyDataHandle() override {} |
45 }; | 50 }; |
46 | 51 |
47 scoped_ptr<disk_cache::Backend> CreateInMemoryDiskCache() { | 52 scoped_ptr<disk_cache::Backend> CreateInMemoryDiskCache() { |
(...skipping 19 matching lines...) Expand all Loading... |
67 return nullptr; | 72 return nullptr; |
68 disk_cache::ScopedEntryPtr entry(temp_entry); | 73 disk_cache::ScopedEntryPtr entry(temp_entry); |
69 | 74 |
70 scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data); | 75 scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data); |
71 rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(), | 76 rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(), |
72 iobuffer->size(), callback.callback(), false); | 77 iobuffer->size(), callback.callback(), false); |
73 EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv)); | 78 EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv)); |
74 return entry; | 79 return entry; |
75 } | 80 } |
76 | 81 |
77 void SetupBasicBlob(BlobStorageHost* host, const std::string& id) { | |
78 EXPECT_TRUE(host->StartBuildingBlob(id)); | |
79 DataElement item; | |
80 item.SetToBytes("1", 1); | |
81 EXPECT_TRUE(host->AppendBlobDataItem(id, item)); | |
82 EXPECT_TRUE(host->FinishBuildingBlob(id, "text/plain")); | |
83 EXPECT_FALSE(host->StartBuildingBlob(id)); | |
84 } | |
85 | 82 |
86 } // namespace | 83 } // namespace |
87 | 84 |
88 TEST(BlobStorageContextTest, IncrementDecrementRef) { | 85 class BlobStorageContextTest : public testing::Test { |
89 BlobStorageContext context; | 86 protected: |
90 BlobStorageHost host(&context); | 87 BlobStorageContextTest() {} |
| 88 ~BlobStorageContextTest() override {} |
| 89 |
| 90 scoped_ptr<BlobDataHandle> SetupBasicBlob(const std::string& id) { |
| 91 BlobDataBuilder builder(id); |
| 92 builder.AppendData("1", 1); |
| 93 builder.set_content_type("text/plain"); |
| 94 return context_.AddFinishedBlob(builder); |
| 95 } |
| 96 |
| 97 BlobStorageContext context_; |
| 98 }; |
| 99 |
| 100 TEST_F(BlobStorageContextTest, IncrementDecrementRef) { |
91 base::MessageLoop fake_io_message_loop; | 101 base::MessageLoop fake_io_message_loop; |
92 | 102 |
93 // Build up a basic blob. | 103 // Build up a basic blob. |
94 const std::string kId("id"); | 104 const std::string kId("id"); |
95 SetupBasicBlob(&host, kId); | 105 scoped_ptr<BlobDataHandle> blob_data_handle = SetupBasicBlob(kId); |
96 | 106 |
97 // Make sure it's there, finish building implies a ref of one. | 107 // Do an extra increment to keep it around after we kill the handle. |
98 scoped_ptr<BlobDataHandle> blob_data_handle; | 108 context_.IncrementBlobRefCount(kId); |
99 blob_data_handle = context.GetBlobDataFromUUID(kId); | 109 context_.IncrementBlobRefCount(kId); |
| 110 context_.DecrementBlobRefCount(kId); |
| 111 blob_data_handle = context_.GetBlobDataFromUUID(kId); |
100 EXPECT_TRUE(blob_data_handle); | 112 EXPECT_TRUE(blob_data_handle); |
101 blob_data_handle.reset(); | 113 blob_data_handle.reset(); |
102 base::RunLoop().RunUntilIdle(); | 114 base::RunLoop().RunUntilIdle(); |
103 | 115 |
104 // Make sure its still there after inc/dec. | 116 EXPECT_TRUE(context_.registry().HasEntry(kId)); |
105 EXPECT_TRUE(host.IncrementBlobRefCount(kId)); | 117 context_.DecrementBlobRefCount(kId); |
106 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 118 EXPECT_FALSE(context_.registry().HasEntry(kId)); |
107 blob_data_handle = context.GetBlobDataFromUUID(kId); | |
108 EXPECT_TRUE(blob_data_handle); | |
109 blob_data_handle.reset(); | |
110 base::RunLoop().RunUntilIdle(); | |
111 | 119 |
112 // Make sure it goes away in the end. | 120 // Make sure it goes away in the end. |
113 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 121 blob_data_handle = context_.GetBlobDataFromUUID(kId); |
114 blob_data_handle = context.GetBlobDataFromUUID(kId); | |
115 EXPECT_FALSE(blob_data_handle); | 122 EXPECT_FALSE(blob_data_handle); |
116 EXPECT_FALSE(host.DecrementBlobRefCount(kId)); | |
117 EXPECT_FALSE(host.IncrementBlobRefCount(kId)); | |
118 } | 123 } |
119 | 124 |
120 TEST(BlobStorageContextTest, CancelBuildingBlob) { | 125 TEST_F(BlobStorageContextTest, OnCancelBuildingBlob) { |
121 BlobStorageContext context; | |
122 BlobStorageHost host(&context); | |
123 base::MessageLoop fake_io_message_loop; | 126 base::MessageLoop fake_io_message_loop; |
124 | 127 |
125 // Build up a basic blob. | 128 // Build up a basic blob. |
126 const std::string kId("id"); | 129 const std::string kId("id"); |
127 EXPECT_TRUE(host.StartBuildingBlob(kId)); | 130 context_.CreatePendingBlob(kId, std::string(kContentType), |
128 DataElement item; | 131 std::string(kContentDisposition)); |
129 item.SetToBytes("1", 1); | 132 EXPECT_TRUE(context_.IsBeingBuilt(kId)); |
130 EXPECT_TRUE(host.AppendBlobDataItem(kId, item)); | 133 context_.CancelPendingBlob(kId, IPCBlobCreationCancelCode::OUT_OF_MEMORY); |
131 EXPECT_TRUE(host.CancelBuildingBlob(kId)); | 134 EXPECT_TRUE(context_.registry().HasEntry(kId)); |
132 EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain")); | 135 EXPECT_FALSE(context_.IsBeingBuilt(kId)); |
133 EXPECT_TRUE(host.StartBuildingBlob(kId)); | 136 EXPECT_TRUE(context_.IsBroken(kId)); |
134 } | 137 } |
135 | 138 |
136 TEST(BlobStorageContextTest, BlobDataHandle) { | 139 TEST_F(BlobStorageContextTest, BlobDataHandle) { |
137 BlobStorageContext context; | |
138 BlobStorageHost host(&context); | |
139 base::MessageLoop fake_io_message_loop; | 140 base::MessageLoop fake_io_message_loop; |
140 | 141 |
141 // Build up a basic blob. | 142 // Build up a basic blob. |
142 const std::string kId("id"); | 143 const std::string kId("id"); |
143 SetupBasicBlob(&host, kId); | 144 scoped_ptr<BlobDataHandle> blob_data_handle = SetupBasicBlob(kId); |
144 | |
145 // Get a handle to it. | |
146 scoped_ptr<BlobDataHandle> blob_data_handle = | |
147 context.GetBlobDataFromUUID(kId); | |
148 EXPECT_TRUE(blob_data_handle); | 145 EXPECT_TRUE(blob_data_handle); |
149 | 146 |
150 // Drop the host's ref to it. | 147 // Get another handle |
151 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 148 scoped_ptr<BlobDataHandle> another_handle = context_.GetBlobDataFromUUID(kId); |
152 | |
153 // Should still be there due to the handle. | |
154 scoped_ptr<BlobDataHandle> another_handle = | |
155 context.GetBlobDataFromUUID(kId); | |
156 EXPECT_TRUE(another_handle); | 149 EXPECT_TRUE(another_handle); |
157 | 150 |
158 // Should disappear after dropping both handles. | 151 // Should disappear after dropping both handles. |
159 blob_data_handle.reset(); | 152 blob_data_handle.reset(); |
| 153 base::RunLoop().RunUntilIdle(); |
| 154 |
| 155 EXPECT_TRUE(context_.registry().HasEntry(kId)); |
| 156 |
160 another_handle.reset(); | 157 another_handle.reset(); |
161 base::RunLoop().RunUntilIdle(); | 158 base::RunLoop().RunUntilIdle(); |
162 | 159 |
163 blob_data_handle = context.GetBlobDataFromUUID(kId); | 160 blob_data_handle = context_.GetBlobDataFromUUID(kId); |
164 EXPECT_FALSE(blob_data_handle); | 161 EXPECT_FALSE(blob_data_handle); |
165 } | 162 } |
166 | 163 |
167 TEST(BlobStorageContextTest, MemoryUsage) { | 164 TEST_F(BlobStorageContextTest, MemoryUsage) { |
168 const std::string kId1("id1"); | 165 const std::string kId1("id1"); |
169 const std::string kId2("id2"); | 166 const std::string kId2("id2"); |
170 | 167 |
171 base::MessageLoop fake_io_message_loop; | 168 base::MessageLoop fake_io_message_loop; |
172 | 169 |
173 BlobDataBuilder builder1(kId1); | 170 BlobDataBuilder builder1(kId1); |
174 BlobDataBuilder builder2(kId2); | 171 BlobDataBuilder builder2(kId2); |
175 builder1.AppendData("Data1Data2"); | 172 builder1.AppendData("Data1Data2"); |
176 builder2.AppendBlob(kId1); | 173 builder2.AppendBlob(kId1); |
177 builder2.AppendBlob(kId1); | 174 builder2.AppendBlob(kId1); |
178 builder2.AppendBlob(kId1); | 175 builder2.AppendBlob(kId1); |
179 builder2.AppendBlob(kId1); | 176 builder2.AppendBlob(kId1); |
180 builder2.AppendBlob(kId1); | 177 builder2.AppendBlob(kId1); |
181 builder2.AppendBlob(kId1); | 178 builder2.AppendBlob(kId1); |
182 builder2.AppendBlob(kId1); | 179 builder2.AppendBlob(kId1); |
183 | 180 |
184 BlobStorageContext context; | 181 EXPECT_EQ(0lu, context_.memory_usage()); |
185 EXPECT_EQ(0lu, context.memory_usage()); | |
186 | 182 |
187 scoped_ptr<BlobDataHandle> blob_data_handle = | 183 scoped_ptr<BlobDataHandle> blob_data_handle = |
188 context.AddFinishedBlob(&builder1); | 184 context_.AddFinishedBlob(&builder1); |
189 EXPECT_EQ(10lu, context.memory_usage()); | 185 EXPECT_EQ(10lu, context_.memory_usage()); |
190 scoped_ptr<BlobDataHandle> blob_data_handle2 = | 186 scoped_ptr<BlobDataHandle> blob_data_handle2 = |
191 context.AddFinishedBlob(&builder2); | 187 context_.AddFinishedBlob(&builder2); |
192 EXPECT_EQ(10lu, context.memory_usage()); | 188 EXPECT_EQ(10lu, context_.memory_usage()); |
| 189 |
| 190 EXPECT_EQ(2u, context_.registry().blob_count()); |
193 | 191 |
194 blob_data_handle.reset(); | 192 blob_data_handle.reset(); |
195 base::RunLoop().RunUntilIdle(); | 193 base::RunLoop().RunUntilIdle(); |
196 | 194 |
197 EXPECT_EQ(10lu, context.memory_usage()); | 195 EXPECT_EQ(10lu, context_.memory_usage()); |
| 196 EXPECT_EQ(1u, context_.registry().blob_count()); |
198 blob_data_handle2.reset(); | 197 blob_data_handle2.reset(); |
199 base::RunLoop().RunUntilIdle(); | 198 base::RunLoop().RunUntilIdle(); |
200 | 199 |
201 EXPECT_EQ(0lu, context.memory_usage()); | 200 EXPECT_EQ(0lu, context_.memory_usage()); |
| 201 EXPECT_EQ(0u, context_.registry().blob_count()); |
202 } | 202 } |
203 | 203 |
204 TEST(BlobStorageContextTest, AddFinishedBlob) { | 204 TEST_F(BlobStorageContextTest, AddFinishedBlob) { |
205 const std::string kId1("id1"); | 205 const std::string kId1("id1"); |
206 const std::string kId2("id12"); | 206 const std::string kId2("id12"); |
207 const std::string kId2Prime("id2.prime"); | 207 const std::string kId2Prime("id2.prime"); |
208 const std::string kId3("id3"); | 208 const std::string kId3("id3"); |
209 const std::string kId3Prime("id3.prime"); | 209 const std::string kId3Prime("id3.prime"); |
210 | 210 |
211 base::MessageLoop fake_io_message_loop; | 211 base::MessageLoop fake_io_message_loop; |
212 | 212 |
213 BlobDataBuilder builder1(kId1); | 213 BlobDataBuilder builder1(kId1); |
214 BlobDataBuilder builder2(kId2); | 214 BlobDataBuilder builder2(kId2); |
215 BlobDataBuilder canonicalized_blob_data2(kId2Prime); | 215 BlobDataBuilder canonicalized_blob_data2(kId2Prime); |
216 builder1.AppendData("Data1Data2"); | 216 builder1.AppendData("Data1Data2"); |
217 builder2.AppendBlob(kId1, 5, 5); | 217 builder2.AppendBlob(kId1, 5, 5); |
218 builder2.AppendData(" is the best"); | 218 builder2.AppendData(" is the best"); |
219 canonicalized_blob_data2.AppendData("Data2"); | 219 canonicalized_blob_data2.AppendData("Data2"); |
220 canonicalized_blob_data2.AppendData(" is the best"); | 220 canonicalized_blob_data2.AppendData(" is the best"); |
221 | 221 |
222 BlobStorageContext context; | 222 BlobStorageContext context; |
223 | 223 |
224 scoped_ptr<BlobDataHandle> blob_data_handle = | 224 scoped_ptr<BlobDataHandle> blob_data_handle = |
225 context.AddFinishedBlob(&builder1); | 225 context_.AddFinishedBlob(&builder1); |
226 scoped_ptr<BlobDataHandle> blob_data_handle2 = | 226 scoped_ptr<BlobDataHandle> blob_data_handle2 = |
227 context.AddFinishedBlob(&builder2); | 227 context_.AddFinishedBlob(&builder2); |
228 | 228 |
229 ASSERT_TRUE(blob_data_handle); | 229 ASSERT_TRUE(blob_data_handle); |
230 ASSERT_TRUE(blob_data_handle2); | 230 ASSERT_TRUE(blob_data_handle2); |
231 scoped_ptr<BlobDataSnapshot> data1 = blob_data_handle->CreateSnapshot(); | 231 scoped_ptr<BlobDataSnapshot> data1 = blob_data_handle->CreateSnapshot(); |
232 scoped_ptr<BlobDataSnapshot> data2 = blob_data_handle2->CreateSnapshot(); | 232 scoped_ptr<BlobDataSnapshot> data2 = blob_data_handle2->CreateSnapshot(); |
233 EXPECT_EQ(*data1, builder1); | 233 EXPECT_EQ(*data1, builder1); |
234 EXPECT_EQ(*data2, canonicalized_blob_data2); | 234 EXPECT_EQ(*data2, canonicalized_blob_data2); |
235 blob_data_handle.reset(); | 235 blob_data_handle.reset(); |
236 data2.reset(); | 236 data2.reset(); |
237 | 237 |
238 base::RunLoop().RunUntilIdle(); | 238 base::RunLoop().RunUntilIdle(); |
239 | 239 |
240 blob_data_handle = context.GetBlobDataFromUUID(kId1); | 240 blob_data_handle = context_.GetBlobDataFromUUID(kId1); |
241 EXPECT_FALSE(blob_data_handle); | 241 EXPECT_FALSE(blob_data_handle); |
242 EXPECT_TRUE(blob_data_handle2); | 242 EXPECT_TRUE(blob_data_handle2); |
243 data2 = blob_data_handle2->CreateSnapshot(); | 243 data2 = blob_data_handle2->CreateSnapshot(); |
244 EXPECT_EQ(*data2, canonicalized_blob_data2); | 244 EXPECT_EQ(*data2, canonicalized_blob_data2); |
245 | 245 |
246 // Test shared elements stick around. | 246 // Test shared elements stick around. |
247 BlobDataBuilder builder3(kId3); | 247 BlobDataBuilder builder3(kId3); |
248 builder3.AppendBlob(kId2); | 248 builder3.AppendBlob(kId2); |
249 builder3.AppendBlob(kId2); | 249 builder3.AppendBlob(kId2); |
250 scoped_ptr<BlobDataHandle> blob_data_handle3 = | 250 scoped_ptr<BlobDataHandle> blob_data_handle3 = |
251 context.AddFinishedBlob(&builder3); | 251 context_.AddFinishedBlob(&builder3); |
252 blob_data_handle2.reset(); | 252 blob_data_handle2.reset(); |
253 base::RunLoop().RunUntilIdle(); | 253 base::RunLoop().RunUntilIdle(); |
254 | 254 |
255 blob_data_handle2 = context.GetBlobDataFromUUID(kId2); | 255 blob_data_handle2 = context_.GetBlobDataFromUUID(kId2); |
256 EXPECT_FALSE(blob_data_handle2); | 256 EXPECT_FALSE(blob_data_handle2); |
257 EXPECT_TRUE(blob_data_handle3); | 257 EXPECT_TRUE(blob_data_handle3); |
258 scoped_ptr<BlobDataSnapshot> data3 = blob_data_handle3->CreateSnapshot(); | 258 scoped_ptr<BlobDataSnapshot> data3 = blob_data_handle3->CreateSnapshot(); |
259 | 259 |
260 BlobDataBuilder canonicalized_blob_data3(kId3Prime); | 260 BlobDataBuilder canonicalized_blob_data3(kId3Prime); |
261 canonicalized_blob_data3.AppendData("Data2"); | 261 canonicalized_blob_data3.AppendData("Data2"); |
262 canonicalized_blob_data3.AppendData(" is the best"); | 262 canonicalized_blob_data3.AppendData(" is the best"); |
263 canonicalized_blob_data3.AppendData("Data2"); | 263 canonicalized_blob_data3.AppendData("Data2"); |
264 canonicalized_blob_data3.AppendData(" is the best"); | 264 canonicalized_blob_data3.AppendData(" is the best"); |
265 EXPECT_EQ(*data3, canonicalized_blob_data3); | 265 EXPECT_EQ(*data3, canonicalized_blob_data3); |
266 | 266 |
267 blob_data_handle.reset(); | 267 blob_data_handle.reset(); |
268 blob_data_handle2.reset(); | 268 blob_data_handle2.reset(); |
269 blob_data_handle3.reset(); | 269 blob_data_handle3.reset(); |
270 base::RunLoop().RunUntilIdle(); | 270 base::RunLoop().RunUntilIdle(); |
271 } | 271 } |
272 | 272 |
273 TEST(BlobStorageContextTest, AddFinishedBlob_LargeOffset) { | 273 TEST_F(BlobStorageContextTest, AddFinishedBlob_LargeOffset) { |
274 // A value which does not fit in a 4-byte data type. Used to confirm that | 274 // A value which does not fit in a 4-byte data type. Used to confirm that |
275 // large values are supported on 32-bit Chromium builds. Regression test for: | 275 // large values are supported on 32-bit Chromium builds. Regression test for: |
276 // crbug.com/458122. | 276 // crbug.com/458122. |
277 const uint64_t kLargeSize = std::numeric_limits<uint64_t>::max(); | 277 const uint64_t kLargeSize = std::numeric_limits<uint64_t>::max(); |
278 | 278 |
279 const uint64_t kBlobLength = 5; | 279 const uint64_t kBlobLength = 5; |
280 const std::string kId1("id1"); | 280 const std::string kId1("id1"); |
281 const std::string kId2("id2"); | 281 const std::string kId2("id2"); |
282 base::MessageLoop fake_io_message_loop; | 282 base::MessageLoop fake_io_message_loop; |
283 | 283 |
284 BlobDataBuilder builder1(kId1); | 284 BlobDataBuilder builder1(kId1); |
285 builder1.AppendFileSystemFile(GURL(), 0, kLargeSize, base::Time::Now()); | 285 builder1.AppendFileSystemFile(GURL(), 0, kLargeSize, base::Time::Now()); |
286 | 286 |
287 BlobDataBuilder builder2(kId2); | 287 BlobDataBuilder builder2(kId2); |
288 builder2.AppendBlob(kId1, kLargeSize - kBlobLength, kBlobLength); | 288 builder2.AppendBlob(kId1, kLargeSize - kBlobLength, kBlobLength); |
289 | 289 |
290 BlobStorageContext context; | |
291 scoped_ptr<BlobDataHandle> blob_data_handle1 = | 290 scoped_ptr<BlobDataHandle> blob_data_handle1 = |
292 context.AddFinishedBlob(&builder1); | 291 context_.AddFinishedBlob(&builder1); |
293 scoped_ptr<BlobDataHandle> blob_data_handle2 = | 292 scoped_ptr<BlobDataHandle> blob_data_handle2 = |
294 context.AddFinishedBlob(&builder2); | 293 context_.AddFinishedBlob(&builder2); |
295 | 294 |
296 ASSERT_TRUE(blob_data_handle1); | 295 ASSERT_TRUE(blob_data_handle1); |
297 ASSERT_TRUE(blob_data_handle2); | 296 ASSERT_TRUE(blob_data_handle2); |
298 scoped_ptr<BlobDataSnapshot> data = blob_data_handle2->CreateSnapshot(); | 297 scoped_ptr<BlobDataSnapshot> data = blob_data_handle2->CreateSnapshot(); |
299 ASSERT_EQ(1u, data->items().size()); | 298 ASSERT_EQ(1u, data->items().size()); |
300 const scoped_refptr<BlobDataItem> item = data->items()[0]; | 299 const scoped_refptr<BlobDataItem> item = data->items()[0]; |
301 EXPECT_EQ(kLargeSize - kBlobLength, item->offset()); | 300 EXPECT_EQ(kLargeSize - kBlobLength, item->offset()); |
302 EXPECT_EQ(kBlobLength, item->length()); | 301 EXPECT_EQ(kBlobLength, item->length()); |
303 | 302 |
304 blob_data_handle1.reset(); | 303 blob_data_handle1.reset(); |
305 blob_data_handle2.reset(); | 304 blob_data_handle2.reset(); |
306 base::RunLoop().RunUntilIdle(); | 305 base::RunLoop().RunUntilIdle(); |
307 } | 306 } |
308 | 307 |
309 TEST(BlobStorageContextTest, BuildDiskCacheBlob) { | 308 TEST_F(BlobStorageContextTest, BuildDiskCacheBlob) { |
310 base::MessageLoop fake_io_message_loop; | 309 base::MessageLoop fake_io_message_loop; |
311 scoped_refptr<BlobDataBuilder::DataHandle> | 310 scoped_refptr<BlobDataBuilder::DataHandle> |
312 data_handle = new EmptyDataHandle(); | 311 data_handle = new EmptyDataHandle(); |
313 | 312 |
314 { | 313 { |
315 scoped_ptr<BlobStorageContext> context(new BlobStorageContext); | 314 BlobStorageContext context; |
316 BlobStorageHost host(context.get()); | |
317 | 315 |
318 scoped_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); | 316 scoped_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); |
319 ASSERT_TRUE(cache); | 317 ASSERT_TRUE(cache); |
320 | 318 |
321 const std::string kTestBlobData = "Test Blob Data"; | 319 const std::string kTestBlobData = "Test Blob Data"; |
322 disk_cache::ScopedEntryPtr entry = | 320 disk_cache::ScopedEntryPtr entry = |
323 CreateDiskCacheEntry(cache.get(), "test entry", kTestBlobData); | 321 CreateDiskCacheEntry(cache.get(), "test entry", kTestBlobData); |
324 | 322 |
325 const std::string kId1Prime("id1.prime"); | 323 const std::string kId1Prime("id1.prime"); |
326 BlobDataBuilder canonicalized_blob_data(kId1Prime); | 324 BlobDataBuilder canonicalized_blob_data(kId1Prime); |
327 canonicalized_blob_data.AppendData(kTestBlobData.c_str()); | 325 canonicalized_blob_data.AppendData(kTestBlobData.c_str()); |
328 | 326 |
329 const std::string kId1("id1"); | 327 const std::string kId1("id1"); |
330 BlobDataBuilder builder(kId1); | 328 BlobDataBuilder builder(kId1); |
331 | 329 |
332 builder.AppendDiskCacheEntry( | 330 builder.AppendDiskCacheEntry( |
333 data_handle, entry.get(), kTestDiskCacheStreamIndex); | 331 data_handle, entry.get(), kTestDiskCacheStreamIndex); |
334 | 332 |
335 scoped_ptr<BlobDataHandle> blob_data_handle = | 333 scoped_ptr<BlobDataHandle> blob_data_handle = |
336 context->AddFinishedBlob(&builder); | 334 context.AddFinishedBlob(&builder); |
337 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); | 335 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); |
338 EXPECT_EQ(*data, builder); | 336 EXPECT_EQ(*data, builder); |
339 EXPECT_FALSE(data_handle->HasOneRef()) | 337 EXPECT_FALSE(data_handle->HasOneRef()) |
340 << "Data handle was destructed while context and builder still exist."; | 338 << "Data handle was destructed while context and builder still exist."; |
341 } | 339 } |
342 EXPECT_TRUE(data_handle->HasOneRef()) | 340 EXPECT_TRUE(data_handle->HasOneRef()) |
343 << "Data handle was not destructed along with blob storage context."; | 341 << "Data handle was not destructed along with blob storage context."; |
344 base::RunLoop().RunUntilIdle(); | 342 base::RunLoop().RunUntilIdle(); |
345 } | 343 } |
346 | 344 |
347 TEST(BlobStorageContextTest, CompoundBlobs) { | 345 TEST_F(BlobStorageContextTest, CompoundBlobs) { |
348 const std::string kId1("id1"); | 346 const std::string kId1("id1"); |
349 const std::string kId2("id2"); | 347 const std::string kId2("id2"); |
350 const std::string kId3("id3"); | 348 const std::string kId3("id3"); |
351 const std::string kId2Prime("id2.prime"); | 349 const std::string kId2Prime("id2.prime"); |
352 | 350 |
353 base::MessageLoop fake_io_message_loop; | 351 base::MessageLoop fake_io_message_loop; |
354 | 352 |
355 // Setup a set of blob data for testing. | 353 // Setup a set of blob data for testing. |
356 base::Time time1, time2; | 354 base::Time time1, time2; |
357 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); | 355 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); |
(...skipping 25 matching lines...) Expand all Loading... |
383 canonicalized_blob_data2.AppendData("a2___", 2); | 381 canonicalized_blob_data2.AppendData("a2___", 2); |
384 canonicalized_blob_data2.AppendFile( | 382 canonicalized_blob_data2.AppendFile( |
385 base::FilePath(FILE_PATH_LITERAL("File1.txt")), 10, 98, time1); | 383 base::FilePath(FILE_PATH_LITERAL("File1.txt")), 10, 98, time1); |
386 canonicalized_blob_data2.AppendFile( | 384 canonicalized_blob_data2.AppendFile( |
387 base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2); | 385 base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2); |
388 | 386 |
389 BlobStorageContext context; | 387 BlobStorageContext context; |
390 scoped_ptr<BlobDataHandle> blob_data_handle; | 388 scoped_ptr<BlobDataHandle> blob_data_handle; |
391 | 389 |
392 // Test a blob referring to only data and a file. | 390 // Test a blob referring to only data and a file. |
393 blob_data_handle = context.AddFinishedBlob(&blob_data1); | 391 blob_data_handle = context_.AddFinishedBlob(&blob_data1); |
394 | 392 |
395 ASSERT_TRUE(blob_data_handle); | 393 ASSERT_TRUE(blob_data_handle); |
396 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); | 394 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); |
397 ASSERT_TRUE(blob_data_handle); | 395 ASSERT_TRUE(blob_data_handle); |
398 EXPECT_EQ(*data, blob_data1); | 396 EXPECT_EQ(*data, blob_data1); |
399 | 397 |
400 // Test a blob composed in part with another blob. | 398 // Test a blob composed in part with another blob. |
401 blob_data_handle = context.AddFinishedBlob(&blob_data2); | 399 blob_data_handle = context_.AddFinishedBlob(&blob_data2); |
402 data = blob_data_handle->CreateSnapshot(); | 400 data = blob_data_handle->CreateSnapshot(); |
403 ASSERT_TRUE(blob_data_handle); | 401 ASSERT_TRUE(blob_data_handle); |
404 ASSERT_TRUE(data); | 402 ASSERT_TRUE(data); |
405 EXPECT_EQ(*data, canonicalized_blob_data2); | 403 EXPECT_EQ(*data, canonicalized_blob_data2); |
406 | 404 |
407 // Test a blob referring to only data and a disk cache entry. | 405 // Test a blob referring to only data and a disk cache entry. |
408 blob_data_handle = context.AddFinishedBlob(&blob_data3); | 406 blob_data_handle = context_.AddFinishedBlob(&blob_data3); |
409 data = blob_data_handle->CreateSnapshot(); | 407 data = blob_data_handle->CreateSnapshot(); |
410 ASSERT_TRUE(blob_data_handle); | 408 ASSERT_TRUE(blob_data_handle); |
411 EXPECT_EQ(*data, blob_data3); | 409 EXPECT_EQ(*data, blob_data3); |
412 | 410 |
413 blob_data_handle.reset(); | 411 blob_data_handle.reset(); |
414 base::RunLoop().RunUntilIdle(); | 412 base::RunLoop().RunUntilIdle(); |
415 } | 413 } |
416 | 414 |
417 TEST(BlobStorageContextTest, PublicBlobUrls) { | 415 TEST_F(BlobStorageContextTest, PublicBlobUrls) { |
418 BlobStorageContext context; | |
419 BlobStorageHost host(&context); | |
420 base::MessageLoop fake_io_message_loop; | 416 base::MessageLoop fake_io_message_loop; |
421 | 417 |
422 // Build up a basic blob. | 418 // Build up a basic blob. |
423 const std::string kId("id"); | 419 const std::string kId("id"); |
424 SetupBasicBlob(&host, kId); | 420 scoped_ptr<BlobDataHandle> first_handle = SetupBasicBlob(kId); |
425 | 421 |
426 // Now register a url for that blob. | 422 // Now register a url for that blob. |
427 GURL kUrl("blob:id"); | 423 GURL kUrl("blob:id"); |
428 EXPECT_TRUE(host.RegisterPublicBlobURL(kUrl, kId)); | 424 context_.RegisterPublicBlobURL(kUrl, kId); |
429 scoped_ptr<BlobDataHandle> blob_data_handle = | 425 scoped_ptr<BlobDataHandle> blob_data_handle = |
430 context.GetBlobDataFromPublicURL(kUrl); | 426 context_.GetBlobDataFromPublicURL(kUrl); |
431 ASSERT_TRUE(blob_data_handle.get()); | 427 ASSERT_TRUE(blob_data_handle.get()); |
432 EXPECT_EQ(kId, blob_data_handle->uuid()); | 428 EXPECT_EQ(kId, blob_data_handle->uuid()); |
433 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); | 429 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); |
434 blob_data_handle.reset(); | 430 blob_data_handle.reset(); |
| 431 first_handle.reset(); |
435 base::RunLoop().RunUntilIdle(); | 432 base::RunLoop().RunUntilIdle(); |
436 | 433 |
437 // The url registration should keep the blob alive even after | 434 // The url registration should keep the blob alive even after |
438 // explicit references are dropped. | 435 // explicit references are dropped. |
439 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 436 blob_data_handle = context_.GetBlobDataFromPublicURL(kUrl); |
440 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); | |
441 EXPECT_TRUE(blob_data_handle); | 437 EXPECT_TRUE(blob_data_handle); |
442 blob_data_handle.reset(); | 438 blob_data_handle.reset(); |
443 base::RunLoop().RunUntilIdle(); | 439 base::RunLoop().RunUntilIdle(); |
444 | 440 |
445 // Finally get rid of the url registration and the blob. | 441 // Finally get rid of the url registration and the blob. |
446 EXPECT_TRUE(host.RevokePublicBlobURL(kUrl)); | 442 context_.RevokePublicBlobURL(kUrl); |
447 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); | 443 blob_data_handle = context_.GetBlobDataFromPublicURL(kUrl); |
448 EXPECT_TRUE(!blob_data_handle.get()); | 444 EXPECT_FALSE(blob_data_handle.get()); |
449 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); | 445 EXPECT_FALSE(context_.registry().HasEntry(kId)); |
450 } | 446 } |
451 | 447 |
452 TEST(BlobStorageContextTest, HostCleanup) { | 448 TEST_F(BlobStorageContextTest, TestUnknownBrokenAndBuildingBlobReference) { |
453 BlobStorageContext context; | |
454 scoped_ptr<BlobStorageHost> host(new BlobStorageHost(&context)); | |
455 base::MessageLoop fake_io_message_loop; | 449 base::MessageLoop fake_io_message_loop; |
| 450 const std::string kBrokenId("broken_id"); |
| 451 const std::string kBuildingId("building_id"); |
| 452 const std::string kReferencingId("referencing_id"); |
| 453 const std::string kUnknownId("unknown_id"); |
456 | 454 |
457 // Build up a basic blob and register a url | 455 // Create a broken blob and a building blob. |
458 const std::string kId("id"); | 456 context_.CreatePendingBlob(kBuildingId, "", ""); |
459 GURL kUrl("blob:id"); | 457 context_.CreatePendingBlob(kBrokenId, "", ""); |
460 SetupBasicBlob(host.get(), kId); | 458 context_.CancelPendingBlob(kBrokenId, IPCBlobCreationCancelCode::UNKNOWN); |
461 EXPECT_TRUE(host->RegisterPublicBlobURL(kUrl, kId)); | 459 EXPECT_TRUE(context_.IsBroken(kBrokenId)); |
| 460 EXPECT_TRUE(context_.registry().HasEntry(kBrokenId)); |
462 | 461 |
463 // All should disappear upon host deletion. | 462 // Try to create a blob with a reference to an unknown blob. |
464 host.reset(); | 463 BlobDataBuilder builder(kReferencingId); |
465 scoped_ptr<BlobDataHandle> handle = context.GetBlobDataFromPublicURL(kUrl); | 464 builder.AppendData("data"); |
466 EXPECT_TRUE(!handle.get()); | 465 builder.AppendBlob(kUnknownId); |
467 handle = context.GetBlobDataFromUUID(kId); | 466 scoped_ptr<BlobDataHandle> handle = context_.AddFinishedBlob(builder); |
468 EXPECT_TRUE(!handle.get()); | 467 EXPECT_TRUE(handle->IsBroken()); |
469 } | 468 EXPECT_TRUE(context_.registry().HasEntry(kReferencingId)); |
| 469 handle.reset(); |
| 470 base::RunLoop().RunUntilIdle(); |
| 471 EXPECT_FALSE(context_.registry().HasEntry(kReferencingId)); |
470 | 472 |
471 TEST(BlobStorageContextTest, EarlyContextDeletion) { | 473 // Try to create a blob with a reference to the broken blob. |
472 scoped_ptr<BlobStorageContext> context(new BlobStorageContext); | 474 BlobDataBuilder builder2(kReferencingId); |
473 BlobStorageHost host(context.get()); | 475 builder2.AppendData("data"); |
474 base::MessageLoop fake_io_message_loop; | 476 builder2.AppendBlob(kBrokenId); |
| 477 handle = context_.AddFinishedBlob(builder2); |
| 478 EXPECT_TRUE(handle->IsBroken()); |
| 479 EXPECT_TRUE(context_.registry().HasEntry(kReferencingId)); |
| 480 handle.reset(); |
| 481 base::RunLoop().RunUntilIdle(); |
| 482 EXPECT_FALSE(context_.registry().HasEntry(kReferencingId)); |
475 | 483 |
476 // Deleting the context should not induce crashes. | 484 // Try to create a blob with a reference to the building blob. |
477 context.reset(); | 485 BlobDataBuilder builder3(kReferencingId); |
478 | 486 builder3.AppendData("data"); |
479 const std::string kId("id"); | 487 builder3.AppendBlob(kBuildingId); |
480 GURL kUrl("blob:id"); | 488 handle = context_.AddFinishedBlob(builder3); |
481 EXPECT_FALSE(host.StartBuildingBlob(kId)); | 489 EXPECT_TRUE(handle->IsBroken()); |
482 DataElement item; | 490 EXPECT_TRUE(context_.registry().HasEntry(kReferencingId)); |
483 item.SetToBytes("1", 1); | 491 handle.reset(); |
484 EXPECT_FALSE(host.AppendBlobDataItem(kId, item)); | 492 base::RunLoop().RunUntilIdle(); |
485 EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain")); | 493 EXPECT_FALSE(context_.registry().HasEntry(kReferencingId)); |
486 EXPECT_FALSE(host.RegisterPublicBlobURL(kUrl, kId)); | |
487 EXPECT_FALSE(host.IncrementBlobRefCount(kId)); | |
488 EXPECT_FALSE(host.DecrementBlobRefCount(kId)); | |
489 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); | |
490 } | 494 } |
491 | 495 |
492 // TODO(michaeln): tests for the depcrecated url stuff | 496 // TODO(michaeln): tests for the depcrecated url stuff |
493 | 497 |
494 } // namespace content | 498 } // namespace content |
OLD | NEW |