1 // Copyright 2013 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 "content/browser/loader/upload_data_stream_builder.h"
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/run_loop.h"
14 #include "base/time/time.h"
15 #include "content/common/resource_request_body.h"
16 #include "net/base/upload_bytes_element_reader.h"
17 #include "net/base/upload_data_stream.h"
18 #include "net/base/upload_file_element_reader.h"
19 #include "storage/browser/blob/blob_data_builder.h"
20 #include "storage/browser/blob/blob_storage_context.h"
21 #include "testing/gtest/include/gtest/gtest.h"
24 using storage::BlobDataBuilder
;
25 using storage::BlobDataHandle
;
26 using storage::BlobStorageContext
;
31 bool AreElementsEqual(const net::UploadElementReader
& reader
,
32 const ResourceRequestBody::Element
& element
) {
33 switch(element
.type()) {
34 case ResourceRequestBody::Element::TYPE_BYTES
: {
35 const net::UploadBytesElementReader
* bytes_reader
=
36 reader
.AsBytesReader();
37 return bytes_reader
&&
38 element
.length() == bytes_reader
->length() &&
39 std::equal(element
.bytes(), element
.bytes() + element
.length(),
40 bytes_reader
->bytes());
42 case ResourceRequestBody::Element::TYPE_FILE
: {
43 const net::UploadFileElementReader
* file_reader
= reader
.AsFileReader();
45 file_reader
->path() == element
.path() &&
46 file_reader
->range_offset() == element
.offset() &&
47 file_reader
->range_length() == element
.length() &&
48 file_reader
->expected_modification_time() ==
49 element
.expected_modification_time();
60 TEST(UploadDataStreamBuilderTest
, CreateUploadDataStreamWithoutBlob
) {
61 base::MessageLoop message_loop
;
62 scoped_refptr
<ResourceRequestBody
> request_body
= new ResourceRequestBody
;
64 const char kData
[] = "123";
65 const base::FilePath::StringType kFilePath
= FILE_PATH_LITERAL("abc");
66 const uint64 kFileOffset
= 10U;
67 const uint64 kFileLength
= 100U;
68 const base::Time kFileTime
= base::Time::FromDoubleT(999);
69 const int64 kIdentifier
= 12345;
71 request_body
->AppendBytes(kData
, arraysize(kData
) - 1);
72 request_body
->AppendFileRange(base::FilePath(kFilePath
),
73 kFileOffset
, kFileLength
, kFileTime
);
74 request_body
->set_identifier(kIdentifier
);
76 scoped_ptr
<net::UploadDataStream
> upload(UploadDataStreamBuilder::Build(
77 request_body
.get(), NULL
, NULL
, base::MessageLoopProxy::current().get()));
79 EXPECT_EQ(kIdentifier
, upload
->identifier());
80 ASSERT_TRUE(upload
->GetElementReaders());
81 ASSERT_EQ(request_body
->elements()->size(),
82 upload
->GetElementReaders()->size());
84 const net::UploadBytesElementReader
* r1
=
85 (*upload
->GetElementReaders())[0]->AsBytesReader();
87 EXPECT_EQ(kData
, std::string(r1
->bytes(), r1
->length()));
89 const net::UploadFileElementReader
* r2
=
90 (*upload
->GetElementReaders())[1]->AsFileReader();
92 EXPECT_EQ(kFilePath
, r2
->path().value());
93 EXPECT_EQ(kFileOffset
, r2
->range_offset());
94 EXPECT_EQ(kFileLength
, r2
->range_length());
95 EXPECT_EQ(kFileTime
, r2
->expected_modification_time());
98 TEST(UploadDataStreamBuilderTest
, ResolveBlobAndCreateUploadDataStream
) {
99 base::MessageLoop message_loop
;
101 // Setup blob data for testing.
102 base::Time time1
, time2
;
103 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1
);
104 base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2
);
106 BlobStorageContext blob_storage_context
;
108 const std::string
blob_id0("id-0");
109 scoped_ptr
<BlobDataBuilder
> blob_data_builder(
110 new BlobDataBuilder(blob_id0
));
111 scoped_ptr
<BlobDataHandle
> handle1
=
112 blob_storage_context
.AddFinishedBlob(blob_data_builder
.get());
114 const std::string
blob_id1("id-1");
115 const std::string kBlobData
= "BlobData";
116 blob_data_builder
.reset(new BlobDataBuilder(blob_id1
));
117 blob_data_builder
->AppendData(kBlobData
);
118 blob_data_builder
->AppendFile(
119 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1
);
120 scoped_ptr
<BlobDataHandle
> handle2
=
121 blob_storage_context
.AddFinishedBlob(blob_data_builder
.get());
123 // Setup upload data elements for comparison.
124 ResourceRequestBody::Element blob_element1
, blob_element2
;
125 blob_element1
.SetToBytes(kBlobData
.c_str(), kBlobData
.size());
126 blob_element2
.SetToFilePathRange(
127 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1
);
129 ResourceRequestBody::Element upload_element1
, upload_element2
;
130 upload_element1
.SetToBytes("Hello", 5);
131 upload_element2
.SetToFilePathRange(
132 base::FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2
);
134 // Test no blob reference.
135 scoped_refptr
<ResourceRequestBody
> request_body(new ResourceRequestBody());
136 request_body
->AppendBytes(
137 upload_element1
.bytes(),
138 upload_element1
.length());
139 request_body
->AppendFileRange(
140 upload_element2
.path(),
141 upload_element2
.offset(),
142 upload_element2
.length(),
143 upload_element2
.expected_modification_time());
145 scoped_ptr
<net::UploadDataStream
> upload(
146 UploadDataStreamBuilder::Build(
148 &blob_storage_context
,
150 base::MessageLoopProxy::current().get()));
152 ASSERT_TRUE(upload
->GetElementReaders());
153 ASSERT_EQ(2U, upload
->GetElementReaders()->size());
154 EXPECT_TRUE(AreElementsEqual(
155 *(*upload
->GetElementReaders())[0], upload_element1
));
156 EXPECT_TRUE(AreElementsEqual(
157 *(*upload
->GetElementReaders())[1], upload_element2
));
159 // Test having only one blob reference that refers to empty blob data.
160 request_body
= new ResourceRequestBody();
161 request_body
->AppendBlob(blob_id0
);
163 upload
= UploadDataStreamBuilder::Build(
165 &blob_storage_context
,
167 base::MessageLoopProxy::current().get());
168 ASSERT_TRUE(upload
->GetElementReaders());
169 ASSERT_EQ(0U, upload
->GetElementReaders()->size());
171 // Test having only one blob reference.
172 request_body
= new ResourceRequestBody();
173 request_body
->AppendBlob(blob_id1
);
175 upload
= UploadDataStreamBuilder::Build(
177 &blob_storage_context
,
179 base::MessageLoopProxy::current().get());
180 ASSERT_TRUE(upload
->GetElementReaders());
181 ASSERT_EQ(2U, upload
->GetElementReaders()->size());
182 EXPECT_TRUE(AreElementsEqual(
183 *(*upload
->GetElementReaders())[0], blob_element1
));
184 EXPECT_TRUE(AreElementsEqual(
185 *(*upload
->GetElementReaders())[1], blob_element2
));
187 // Test having one blob reference at the beginning.
188 request_body
= new ResourceRequestBody();
189 request_body
->AppendBlob(blob_id1
);
190 request_body
->AppendBytes(
191 upload_element1
.bytes(),
192 upload_element1
.length());
193 request_body
->AppendFileRange(
194 upload_element2
.path(),
195 upload_element2
.offset(),
196 upload_element2
.length(),
197 upload_element2
.expected_modification_time());
199 upload
= UploadDataStreamBuilder::Build(
201 &blob_storage_context
,
203 base::MessageLoopProxy::current().get());
204 ASSERT_TRUE(upload
->GetElementReaders());
205 ASSERT_EQ(4U, upload
->GetElementReaders()->size());
206 EXPECT_TRUE(AreElementsEqual(
207 *(*upload
->GetElementReaders())[0], blob_element1
));
208 EXPECT_TRUE(AreElementsEqual(
209 *(*upload
->GetElementReaders())[1], blob_element2
));
210 EXPECT_TRUE(AreElementsEqual(
211 *(*upload
->GetElementReaders())[2], upload_element1
));
212 EXPECT_TRUE(AreElementsEqual(
213 *(*upload
->GetElementReaders())[3], upload_element2
));
215 // Test having one blob reference at the end.
216 request_body
= new ResourceRequestBody();
217 request_body
->AppendBytes(
218 upload_element1
.bytes(),
219 upload_element1
.length());
220 request_body
->AppendFileRange(
221 upload_element2
.path(),
222 upload_element2
.offset(),
223 upload_element2
.length(),
224 upload_element2
.expected_modification_time());
225 request_body
->AppendBlob(blob_id1
);
228 UploadDataStreamBuilder::Build(request_body
.get(),
229 &blob_storage_context
,
231 base::MessageLoopProxy::current().get());
232 ASSERT_TRUE(upload
->GetElementReaders());
233 ASSERT_EQ(4U, upload
->GetElementReaders()->size());
234 EXPECT_TRUE(AreElementsEqual(
235 *(*upload
->GetElementReaders())[0], upload_element1
));
236 EXPECT_TRUE(AreElementsEqual(
237 *(*upload
->GetElementReaders())[1], upload_element2
));
238 EXPECT_TRUE(AreElementsEqual(
239 *(*upload
->GetElementReaders())[2], blob_element1
));
240 EXPECT_TRUE(AreElementsEqual(
241 *(*upload
->GetElementReaders())[3], blob_element2
));
243 // Test having one blob reference in the middle.
244 request_body
= new ResourceRequestBody();
245 request_body
->AppendBytes(
246 upload_element1
.bytes(),
247 upload_element1
.length());
248 request_body
->AppendBlob(blob_id1
);
249 request_body
->AppendFileRange(
250 upload_element2
.path(),
251 upload_element2
.offset(),
252 upload_element2
.length(),
253 upload_element2
.expected_modification_time());
255 upload
= UploadDataStreamBuilder::Build(
257 &blob_storage_context
,
259 base::MessageLoopProxy::current().get());
260 ASSERT_TRUE(upload
->GetElementReaders());
261 ASSERT_EQ(4U, upload
->GetElementReaders()->size());
262 EXPECT_TRUE(AreElementsEqual(
263 *(*upload
->GetElementReaders())[0], upload_element1
));
264 EXPECT_TRUE(AreElementsEqual(
265 *(*upload
->GetElementReaders())[1], blob_element1
));
266 EXPECT_TRUE(AreElementsEqual(
267 *(*upload
->GetElementReaders())[2], blob_element2
));
268 EXPECT_TRUE(AreElementsEqual(
269 *(*upload
->GetElementReaders())[3], upload_element2
));
271 // Test having multiple blob references.
272 request_body
= new ResourceRequestBody();
273 request_body
->AppendBlob(blob_id1
);
274 request_body
->AppendBytes(
275 upload_element1
.bytes(),
276 upload_element1
.length());
277 request_body
->AppendBlob(blob_id1
);
278 request_body
->AppendBlob(blob_id1
);
279 request_body
->AppendFileRange(
280 upload_element2
.path(),
281 upload_element2
.offset(),
282 upload_element2
.length(),
283 upload_element2
.expected_modification_time());
285 upload
= UploadDataStreamBuilder::Build(
287 &blob_storage_context
,
289 base::MessageLoopProxy::current().get());
290 ASSERT_TRUE(upload
->GetElementReaders());
291 ASSERT_EQ(8U, upload
->GetElementReaders()->size());
292 EXPECT_TRUE(AreElementsEqual(
293 *(*upload
->GetElementReaders())[0], blob_element1
));
294 EXPECT_TRUE(AreElementsEqual(
295 *(*upload
->GetElementReaders())[1], blob_element2
));
296 EXPECT_TRUE(AreElementsEqual(
297 *(*upload
->GetElementReaders())[2], upload_element1
));
298 EXPECT_TRUE(AreElementsEqual(
299 *(*upload
->GetElementReaders())[3], blob_element1
));
300 EXPECT_TRUE(AreElementsEqual(
301 *(*upload
->GetElementReaders())[4], blob_element2
));
302 EXPECT_TRUE(AreElementsEqual(
303 *(*upload
->GetElementReaders())[5], blob_element1
));
304 EXPECT_TRUE(AreElementsEqual(
305 *(*upload
->GetElementReaders())[6], blob_element2
));
306 EXPECT_TRUE(AreElementsEqual(
307 *(*upload
->GetElementReaders())[7], upload_element2
));
309 // Clean up for ASAN.
310 base::RunLoop().RunUntilIdle();
313 } // namespace content