blob_storage_context_unittest.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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.
4
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/time/time.h"
10#include "content/browser/fileapi/blob_storage_host.h"
11#include "testing/gtest/include/gtest/gtest.h"
12#include "webkit/browser/blob/blob_data_handle.h"
13#include "webkit/browser/blob/blob_storage_context.h"
14
15using webkit_blob::BlobDataHandle;
16
17namespace content {
18
19namespace {
20void SetupBasicBlob(BlobStorageHost* host, const std::string& id) {
21  EXPECT_TRUE(host->StartBuildingBlob(id));
22  BlobData::Item item;
23  item.SetToBytes("1", 1);
24  EXPECT_TRUE(host->AppendBlobDataItem(id, item));
25  EXPECT_TRUE(host->FinishBuildingBlob(id, "text/plain"));
26  EXPECT_FALSE(host->StartBuildingBlob(id));
27}
28}  // namespace
29
30TEST(BlobStorageContextTest, IncrementDecrementRef) {
31  BlobStorageContext context;
32  BlobStorageHost host(&context);
33  base::MessageLoop fake_io_message_loop;
34
35  // Build up a basic blob.
36  const std::string kId("id");
37  SetupBasicBlob(&host, kId);
38
39  // Make sure it's there, finish building implies a ref of one.
40  scoped_ptr<BlobDataHandle> blob_data_handle;
41  blob_data_handle = context.GetBlobDataFromUUID(kId);
42  EXPECT_TRUE(blob_data_handle);
43  blob_data_handle.reset();
44
45  // Make sure its still there after inc/dec.
46  EXPECT_TRUE(host.IncrementBlobRefCount(kId));
47  EXPECT_TRUE(host.DecrementBlobRefCount(kId));
48  blob_data_handle = context.GetBlobDataFromUUID(kId);
49  EXPECT_TRUE(blob_data_handle);
50  blob_data_handle.reset();
51
52  // Make sure it goes away in the end.
53  EXPECT_TRUE(host.DecrementBlobRefCount(kId));
54  blob_data_handle = context.GetBlobDataFromUUID(kId);
55  EXPECT_FALSE(blob_data_handle);
56  EXPECT_FALSE(host.DecrementBlobRefCount(kId));
57  EXPECT_FALSE(host.IncrementBlobRefCount(kId));
58}
59
60TEST(BlobStorageContextTest, BlobDataHandle) {
61  BlobStorageContext context;
62  BlobStorageHost host(&context);
63  base::MessageLoop fake_io_message_loop;
64
65  // Build up a basic blob.
66  const std::string kId("id");
67  SetupBasicBlob(&host, kId);
68
69  // Get a handle to it.
70  scoped_ptr<BlobDataHandle> blob_data_handle =
71      context.GetBlobDataFromUUID(kId);
72  EXPECT_TRUE(blob_data_handle);
73
74  // Drop the host's ref to it.
75  EXPECT_TRUE(host.DecrementBlobRefCount(kId));
76
77  // Should still be there due to the handle.
78  scoped_ptr<BlobDataHandle> another_handle =
79      context.GetBlobDataFromUUID(kId);
80  EXPECT_TRUE(another_handle);
81
82  // Should disappear after dropping both handles.
83  blob_data_handle.reset();
84  another_handle.reset();
85  blob_data_handle = context.GetBlobDataFromUUID(kId);
86  EXPECT_FALSE(blob_data_handle);
87}
88
89TEST(BlobStorageContextTest, CompoundBlobs) {
90  const std::string kId1("id1");
91  const std::string kId2("id2");
92  const std::string kId2Prime("id2.prime");
93
94  base::MessageLoop fake_io_message_loop;
95
96  // Setup a set of blob data for testing.
97  base::Time time1, time2;
98  base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1);
99  base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2);
100
101  scoped_refptr<BlobData> blob_data1(new BlobData(kId1));
102  blob_data1->AppendData("Data1");
103  blob_data1->AppendData("Data2");
104  blob_data1->AppendFile(base::FilePath(FILE_PATH_LITERAL("File1.txt")),
105    10, 1024, time1);
106
107  scoped_refptr<BlobData> blob_data2(new BlobData(kId2));
108  blob_data2->AppendData("Data3");
109  blob_data2->AppendBlob(kId1, 8, 100);
110  blob_data2->AppendFile(base::FilePath(FILE_PATH_LITERAL("File2.txt")),
111      0, 20, time2);
112
113  scoped_refptr<BlobData> canonicalized_blob_data2(new BlobData(kId2Prime));
114  canonicalized_blob_data2->AppendData("Data3");
115  canonicalized_blob_data2->AppendData("a2___", 2);
116  canonicalized_blob_data2->AppendFile(
117      base::FilePath(FILE_PATH_LITERAL("File1.txt")),
118      10, 98, time1);
119  canonicalized_blob_data2->AppendFile(
120      base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2);
121
122  BlobStorageContext context;
123  scoped_ptr<BlobDataHandle> blob_data_handle;
124
125  // Test a blob referring to only data and a file.
126  blob_data_handle = context.AddFinishedBlob(blob_data1.get());
127  ASSERT_TRUE(blob_data_handle.get());
128  EXPECT_TRUE(*(blob_data_handle->data()) == *blob_data1.get());
129
130  // Test a blob composed in part with another blob.
131  blob_data_handle = context.AddFinishedBlob(blob_data2.get());
132  ASSERT_TRUE(blob_data_handle.get());
133  EXPECT_TRUE(*(blob_data_handle->data()) == *canonicalized_blob_data2.get());
134}
135
136TEST(BlobStorageContextTest, PublicBlobUrls) {
137  BlobStorageContext context;
138  BlobStorageHost host(&context);
139  base::MessageLoop fake_io_message_loop;
140
141  // Build up a basic blob.
142  const std::string kId("id");
143  SetupBasicBlob(&host, kId);
144
145  // Now register a url for that blob.
146  GURL kUrl("blob:id");
147  EXPECT_TRUE(host.RegisterPublicBlobURL(kUrl, kId));
148  scoped_ptr<BlobDataHandle> blob_data_handle =
149      context.GetBlobDataFromPublicURL(kUrl);
150  ASSERT_TRUE(blob_data_handle.get());
151  EXPECT_EQ(kId, blob_data_handle->data()->uuid());
152  blob_data_handle.reset();
153
154  // The url registration should keep the blob alive even after
155  // explicit references are dropped.
156  EXPECT_TRUE(host.DecrementBlobRefCount(kId));
157  blob_data_handle = context.GetBlobDataFromPublicURL(kUrl);
158  EXPECT_TRUE(blob_data_handle);
159  blob_data_handle.reset();
160
161  // Finally get rid of the url registration and the blob.
162  EXPECT_TRUE(host.RevokePublicBlobURL(kUrl));
163  blob_data_handle = context.GetBlobDataFromPublicURL(kUrl);
164  EXPECT_TRUE(!blob_data_handle.get());
165  EXPECT_FALSE(host.RevokePublicBlobURL(kUrl));
166}
167
168TEST(BlobStorageContextTest, HostCleanup) {
169  BlobStorageContext context;
170  scoped_ptr<BlobStorageHost> host(new BlobStorageHost(&context));
171  base::MessageLoop fake_io_message_loop;
172
173  // Build up a basic blob and register a url
174  const std::string kId("id");
175  GURL kUrl("blob:id");
176  SetupBasicBlob(host.get(), kId);
177  EXPECT_TRUE(host->RegisterPublicBlobURL(kUrl, kId));
178
179  // All should disappear upon host deletion.
180  host.reset();
181  scoped_ptr<BlobDataHandle> handle = context.GetBlobDataFromPublicURL(kUrl);
182  EXPECT_TRUE(!handle.get());
183  handle = context.GetBlobDataFromUUID(kId);
184  EXPECT_TRUE(!handle.get());
185}
186
187TEST(BlobStorageContextTest, EarlyContextDeletion) {
188  scoped_ptr<BlobStorageContext> context(new BlobStorageContext);
189  BlobStorageHost host(context.get());
190  base::MessageLoop fake_io_message_loop;
191
192  // Deleting the context should not induce crashes.
193  context.reset();
194
195  const std::string kId("id");
196  GURL kUrl("blob:id");
197  EXPECT_FALSE(host.StartBuildingBlob(kId));
198  BlobData::Item item;
199  item.SetToBytes("1", 1);
200  EXPECT_FALSE(host.AppendBlobDataItem(kId, item));
201  EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain"));
202  EXPECT_FALSE(host.RegisterPublicBlobURL(kUrl, kId));
203  EXPECT_FALSE(host.IncrementBlobRefCount(kId));
204  EXPECT_FALSE(host.DecrementBlobRefCount(kId));
205  EXPECT_FALSE(host.RevokePublicBlobURL(kUrl));
206}
207
208// TODO(michaeln): tests for the depcrecated url stuff
209
210}  // namespace content
211