Refactor FacetManager into a separate file.
[chromium-blink-merge.git] / content / browser / fileapi / blob_storage_context_unittest.cc
blob9602b3adcd02d0674441a7adeadbe23b7fa0ba50
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
3 // found in the LICENSE file.
5 #include "base/files/file_path.h"
6 #include "base/memory/ref_counted.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/time/time.h"
11 #include "content/browser/fileapi/blob_storage_host.h"
12 #include "storage/browser/blob/blob_data_builder.h"
13 #include "storage/browser/blob/blob_data_handle.h"
14 #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"
18 using storage::BlobDataBuilder;
19 using storage::BlobDataHandle;
20 using storage::BlobDataSnapshot;
21 using storage::BlobStorageContext;
22 using storage::DataElement;
24 namespace content {
26 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();
33 void SetupBasicBlob(BlobStorageHost* host, const std::string& id) {
34 EXPECT_TRUE(host->StartBuildingBlob(id));
35 DataElement item;
36 item.SetToBytes("1", 1);
37 EXPECT_TRUE(host->AppendBlobDataItem(id, item));
38 EXPECT_TRUE(host->FinishBuildingBlob(id, "text/plain"));
39 EXPECT_FALSE(host->StartBuildingBlob(id));
41 } // namespace
43 TEST(BlobStorageContextTest, IncrementDecrementRef) {
44 BlobStorageContext context;
45 BlobStorageHost host(&context);
46 base::MessageLoop fake_io_message_loop;
48 // Build up a basic blob.
49 const std::string kId("id");
50 SetupBasicBlob(&host, kId);
52 // Make sure it's there, finish building implies a ref of one.
53 scoped_ptr<BlobDataHandle> blob_data_handle;
54 blob_data_handle = context.GetBlobDataFromUUID(kId);
55 EXPECT_TRUE(blob_data_handle);
56 blob_data_handle.reset();
57 RunEventLoopTillIdle();
59 // Make sure its still there after inc/dec.
60 EXPECT_TRUE(host.IncrementBlobRefCount(kId));
61 EXPECT_TRUE(host.DecrementBlobRefCount(kId));
62 blob_data_handle = context.GetBlobDataFromUUID(kId);
63 EXPECT_TRUE(blob_data_handle);
64 blob_data_handle.reset();
65 RunEventLoopTillIdle();
67 // Make sure it goes away in the end.
68 EXPECT_TRUE(host.DecrementBlobRefCount(kId));
69 blob_data_handle = context.GetBlobDataFromUUID(kId);
70 EXPECT_FALSE(blob_data_handle);
71 EXPECT_FALSE(host.DecrementBlobRefCount(kId));
72 EXPECT_FALSE(host.IncrementBlobRefCount(kId));
75 TEST(BlobStorageContextTest, CancelBuildingBlob) {
76 BlobStorageContext context;
77 BlobStorageHost host(&context);
78 base::MessageLoop fake_io_message_loop;
80 // Build up a basic blob.
81 const std::string kId("id");
82 EXPECT_TRUE(host.StartBuildingBlob(kId));
83 DataElement item;
84 item.SetToBytes("1", 1);
85 EXPECT_TRUE(host.AppendBlobDataItem(kId, item));
86 EXPECT_TRUE(host.CancelBuildingBlob(kId));
87 EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain"));
88 EXPECT_TRUE(host.StartBuildingBlob(kId));
91 TEST(BlobStorageContextTest, BlobDataHandle) {
92 BlobStorageContext context;
93 BlobStorageHost host(&context);
94 base::MessageLoop fake_io_message_loop;
96 // Build up a basic blob.
97 const std::string kId("id");
98 SetupBasicBlob(&host, kId);
100 // Get a handle to it.
101 scoped_ptr<BlobDataHandle> blob_data_handle =
102 context.GetBlobDataFromUUID(kId);
103 EXPECT_TRUE(blob_data_handle);
105 // Drop the host's ref to it.
106 EXPECT_TRUE(host.DecrementBlobRefCount(kId));
108 // Should still be there due to the handle.
109 scoped_ptr<BlobDataHandle> another_handle =
110 context.GetBlobDataFromUUID(kId);
111 EXPECT_TRUE(another_handle);
113 // Should disappear after dropping both handles.
114 blob_data_handle.reset();
115 another_handle.reset();
116 RunEventLoopTillIdle();
118 blob_data_handle = context.GetBlobDataFromUUID(kId);
119 EXPECT_FALSE(blob_data_handle);
122 TEST(BlobStorageContextTest, MemoryUsage) {
123 const std::string kId1("id1");
124 const std::string kId2("id2");
126 base::MessageLoop fake_io_message_loop;
128 BlobDataBuilder builder1(kId1);
129 BlobDataBuilder builder2(kId2);
130 builder1.AppendData("Data1Data2");
131 builder2.AppendBlob(kId1);
132 builder2.AppendBlob(kId1);
133 builder2.AppendBlob(kId1);
134 builder2.AppendBlob(kId1);
135 builder2.AppendBlob(kId1);
136 builder2.AppendBlob(kId1);
137 builder2.AppendBlob(kId1);
139 BlobStorageContext context;
140 EXPECT_EQ(0lu, context.memory_usage());
142 scoped_ptr<BlobDataHandle> blob_data_handle =
143 context.AddFinishedBlob(&builder1);
144 EXPECT_EQ(10lu, context.memory_usage());
145 scoped_ptr<BlobDataHandle> blob_data_handle2 =
146 context.AddFinishedBlob(&builder2);
147 EXPECT_EQ(10lu, context.memory_usage());
149 blob_data_handle.reset();
150 RunEventLoopTillIdle();
152 EXPECT_EQ(10lu, context.memory_usage());
153 blob_data_handle2.reset();
154 RunEventLoopTillIdle();
156 EXPECT_EQ(0lu, context.memory_usage());
159 TEST(BlobStorageContextTest, AddFinishedBlob) {
160 const std::string kId1("id1");
161 const std::string kId2("id12");
162 const std::string kId2Prime("id2.prime");
163 const std::string kId3("id3");
164 const std::string kId3Prime("id3.prime");
166 base::MessageLoop fake_io_message_loop;
168 BlobDataBuilder builder1(kId1);
169 BlobDataBuilder builder2(kId2);
170 BlobDataBuilder canonicalized_blob_data2(kId2Prime);
171 builder1.AppendData("Data1Data2");
172 builder2.AppendBlob(kId1, 5, 5);
173 builder2.AppendData(" is the best");
174 canonicalized_blob_data2.AppendData("Data2");
175 canonicalized_blob_data2.AppendData(" is the best");
177 BlobStorageContext context;
179 scoped_ptr<BlobDataHandle> blob_data_handle =
180 context.AddFinishedBlob(&builder1);
181 scoped_ptr<BlobDataHandle> blob_data_handle2 =
182 context.AddFinishedBlob(&builder2);
184 ASSERT_TRUE(blob_data_handle);
185 ASSERT_TRUE(blob_data_handle2);
186 scoped_ptr<BlobDataSnapshot> data1 = blob_data_handle->CreateSnapshot();
187 scoped_ptr<BlobDataSnapshot> data2 = blob_data_handle2->CreateSnapshot();
188 EXPECT_EQ(*data1, builder1);
189 EXPECT_EQ(*data2, canonicalized_blob_data2);
190 blob_data_handle.reset();
191 data2.reset();
193 RunEventLoopTillIdle();
195 blob_data_handle = context.GetBlobDataFromUUID(kId1);
196 EXPECT_FALSE(blob_data_handle);
197 EXPECT_TRUE(blob_data_handle2);
198 data2 = blob_data_handle2->CreateSnapshot();
199 EXPECT_EQ(*data2, canonicalized_blob_data2);
201 // Test shared elements stick around.
202 BlobDataBuilder builder3(kId3);
203 builder3.AppendBlob(kId2);
204 builder3.AppendBlob(kId2);
205 scoped_ptr<BlobDataHandle> blob_data_handle3 =
206 context.AddFinishedBlob(&builder3);
207 blob_data_handle2.reset();
208 RunEventLoopTillIdle();
210 blob_data_handle2 = context.GetBlobDataFromUUID(kId2);
211 EXPECT_FALSE(blob_data_handle2);
212 EXPECT_TRUE(blob_data_handle3);
213 scoped_ptr<BlobDataSnapshot> data3 = blob_data_handle3->CreateSnapshot();
215 BlobDataBuilder canonicalized_blob_data3(kId3Prime);
216 canonicalized_blob_data3.AppendData("Data2");
217 canonicalized_blob_data3.AppendData(" is the best");
218 canonicalized_blob_data3.AppendData("Data2");
219 canonicalized_blob_data3.AppendData(" is the best");
220 EXPECT_EQ(*data3, canonicalized_blob_data3);
222 blob_data_handle.reset();
223 blob_data_handle2.reset();
224 blob_data_handle3.reset();
225 RunEventLoopTillIdle();
228 TEST(BlobStorageContextTest, CompoundBlobs) {
229 const std::string kId1("id1");
230 const std::string kId2("id2");
231 const std::string kId2Prime("id2.prime");
233 base::MessageLoop fake_io_message_loop;
235 // Setup a set of blob data for testing.
236 base::Time time1, time2;
237 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1);
238 base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2);
240 BlobDataBuilder blob_data1(kId1);
241 blob_data1.AppendData("Data1");
242 blob_data1.AppendData("Data2");
243 blob_data1.AppendFile(base::FilePath(FILE_PATH_LITERAL("File1.txt")), 10,
244 1024, time1);
246 BlobDataBuilder blob_data2(kId2);
247 blob_data2.AppendData("Data3");
248 blob_data2.AppendBlob(kId1, 8, 100);
249 blob_data2.AppendFile(base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20,
250 time2);
252 BlobDataBuilder canonicalized_blob_data2(kId2Prime);
253 canonicalized_blob_data2.AppendData("Data3");
254 canonicalized_blob_data2.AppendData("a2___", 2);
255 canonicalized_blob_data2.AppendFile(
256 base::FilePath(FILE_PATH_LITERAL("File1.txt")), 10, 98, time1);
257 canonicalized_blob_data2.AppendFile(
258 base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2);
260 BlobStorageContext context;
261 scoped_ptr<BlobDataHandle> blob_data_handle;
263 // Test a blob referring to only data and a file.
264 blob_data_handle = context.AddFinishedBlob(&blob_data1);
266 ASSERT_TRUE(blob_data_handle);
267 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot();
268 ASSERT_TRUE(blob_data_handle);
269 EXPECT_EQ(*data, blob_data1);
271 // Test a blob composed in part with another blob.
272 blob_data_handle = context.AddFinishedBlob(&blob_data2);
273 data = blob_data_handle->CreateSnapshot();
274 ASSERT_TRUE(blob_data_handle);
275 ASSERT_TRUE(data);
276 EXPECT_EQ(*data, canonicalized_blob_data2);
278 blob_data_handle.reset();
279 RunEventLoopTillIdle();
282 TEST(BlobStorageContextTest, PublicBlobUrls) {
283 BlobStorageContext context;
284 BlobStorageHost host(&context);
285 base::MessageLoop fake_io_message_loop;
287 // Build up a basic blob.
288 const std::string kId("id");
289 SetupBasicBlob(&host, kId);
291 // Now register a url for that blob.
292 GURL kUrl("blob:id");
293 EXPECT_TRUE(host.RegisterPublicBlobURL(kUrl, kId));
294 scoped_ptr<BlobDataHandle> blob_data_handle =
295 context.GetBlobDataFromPublicURL(kUrl);
296 ASSERT_TRUE(blob_data_handle.get());
297 EXPECT_EQ(kId, blob_data_handle->uuid());
298 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot();
299 blob_data_handle.reset();
300 RunEventLoopTillIdle();
302 // The url registration should keep the blob alive even after
303 // explicit references are dropped.
304 EXPECT_TRUE(host.DecrementBlobRefCount(kId));
305 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl);
306 EXPECT_TRUE(blob_data_handle);
307 blob_data_handle.reset();
308 RunEventLoopTillIdle();
310 // Finally get rid of the url registration and the blob.
311 EXPECT_TRUE(host.RevokePublicBlobURL(kUrl));
312 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl);
313 EXPECT_TRUE(!blob_data_handle.get());
314 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl));
317 TEST(BlobStorageContextTest, HostCleanup) {
318 BlobStorageContext context;
319 scoped_ptr<BlobStorageHost> host(new BlobStorageHost(&context));
320 base::MessageLoop fake_io_message_loop;
322 // Build up a basic blob and register a url
323 const std::string kId("id");
324 GURL kUrl("blob:id");
325 SetupBasicBlob(host.get(), kId);
326 EXPECT_TRUE(host->RegisterPublicBlobURL(kUrl, kId));
328 // All should disappear upon host deletion.
329 host.reset();
330 scoped_ptr<BlobDataHandle> handle = context.GetBlobDataFromPublicURL(kUrl);
331 EXPECT_TRUE(!handle.get());
332 handle = context.GetBlobDataFromUUID(kId);
333 EXPECT_TRUE(!handle.get());
336 TEST(BlobStorageContextTest, EarlyContextDeletion) {
337 scoped_ptr<BlobStorageContext> context(new BlobStorageContext);
338 BlobStorageHost host(context.get());
339 base::MessageLoop fake_io_message_loop;
341 // Deleting the context should not induce crashes.
342 context.reset();
344 const std::string kId("id");
345 GURL kUrl("blob:id");
346 EXPECT_FALSE(host.StartBuildingBlob(kId));
347 DataElement item;
348 item.SetToBytes("1", 1);
349 EXPECT_FALSE(host.AppendBlobDataItem(kId, item));
350 EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain"));
351 EXPECT_FALSE(host.RegisterPublicBlobURL(kUrl, kId));
352 EXPECT_FALSE(host.IncrementBlobRefCount(kId));
353 EXPECT_FALSE(host.DecrementBlobRefCount(kId));
354 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl));
357 // TODO(michaeln): tests for the depcrecated url stuff
359 } // namespace content