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_storage_context.h"
20 #include "testing/gtest/include/gtest/gtest.h"
23 using storage::BlobData
;
24 using storage::BlobDataHandle
;
25 using storage::BlobStorageContext
;
30 bool AreElementsEqual(const net::UploadElementReader
& reader
,
31 const ResourceRequestBody::Element
& element
) {
32 switch(element
.type()) {
33 case ResourceRequestBody::Element::TYPE_BYTES
: {
34 const net::UploadBytesElementReader
* bytes_reader
=
35 reader
.AsBytesReader();
36 return bytes_reader
&&
37 element
.length() == bytes_reader
->length() &&
38 std::equal(element
.bytes(), element
.bytes() + element
.length(),
39 bytes_reader
->bytes());
41 case ResourceRequestBody::Element::TYPE_FILE
: {
42 const net::UploadFileElementReader
* file_reader
= reader
.AsFileReader();
44 file_reader
->path() == element
.path() &&
45 file_reader
->range_offset() == element
.offset() &&
46 file_reader
->range_length() == element
.length() &&
47 file_reader
->expected_modification_time() ==
48 element
.expected_modification_time();
59 TEST(UploadDataStreamBuilderTest
, CreateUploadDataStreamWithoutBlob
) {
60 base::MessageLoop message_loop
;
61 scoped_refptr
<ResourceRequestBody
> request_body
= new ResourceRequestBody
;
63 const char kData
[] = "123";
64 const base::FilePath::StringType kFilePath
= FILE_PATH_LITERAL("abc");
65 const uint64 kFileOffset
= 10U;
66 const uint64 kFileLength
= 100U;
67 const base::Time kFileTime
= base::Time::FromDoubleT(999);
68 const int64 kIdentifier
= 12345;
70 request_body
->AppendBytes(kData
, arraysize(kData
) - 1);
71 request_body
->AppendFileRange(base::FilePath(kFilePath
),
72 kFileOffset
, kFileLength
, kFileTime
);
73 request_body
->set_identifier(kIdentifier
);
75 scoped_ptr
<net::UploadDataStream
> upload(UploadDataStreamBuilder::Build(
76 request_body
.get(), NULL
, NULL
, base::MessageLoopProxy::current().get()));
78 EXPECT_EQ(kIdentifier
, upload
->identifier());
79 ASSERT_TRUE(upload
->GetElementReaders());
80 ASSERT_EQ(request_body
->elements()->size(),
81 upload
->GetElementReaders()->size());
83 const net::UploadBytesElementReader
* r1
=
84 (*upload
->GetElementReaders())[0]->AsBytesReader();
86 EXPECT_EQ(kData
, std::string(r1
->bytes(), r1
->length()));
88 const net::UploadFileElementReader
* r2
=
89 (*upload
->GetElementReaders())[1]->AsFileReader();
91 EXPECT_EQ(kFilePath
, r2
->path().value());
92 EXPECT_EQ(kFileOffset
, r2
->range_offset());
93 EXPECT_EQ(kFileLength
, r2
->range_length());
94 EXPECT_EQ(kFileTime
, r2
->expected_modification_time());
97 TEST(UploadDataStreamBuilderTest
, ResolveBlobAndCreateUploadDataStream
) {
98 base::MessageLoop message_loop
;
100 // Setup blob data for testing.
101 base::Time time1
, time2
;
102 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1
);
103 base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2
);
105 BlobStorageContext blob_storage_context
;
107 const std::string
blob_id0("id-0");
108 scoped_refptr
<BlobData
> blob_data(new BlobData(blob_id0
));
109 scoped_ptr
<BlobDataHandle
> handle1
=
110 blob_storage_context
.AddFinishedBlob(blob_data
.get());
112 const std::string
blob_id1("id-1");
113 blob_data
= new BlobData(blob_id1
);
114 blob_data
->AppendData("BlobData");
115 blob_data
->AppendFile(
116 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1
);
117 scoped_ptr
<BlobDataHandle
> handle2
=
118 blob_storage_context
.AddFinishedBlob(blob_data
.get());
120 // Setup upload data elements for comparison.
121 ResourceRequestBody::Element blob_element1
, blob_element2
;
122 blob_element1
.SetToBytes(
123 blob_data
->items().at(0).bytes() +
124 static_cast<int>(blob_data
->items().at(0).offset()),
125 static_cast<int>(blob_data
->items().at(0).length()));
126 blob_element2
.SetToFilePathRange(
127 blob_data
->items().at(1).path(),
128 blob_data
->items().at(1).offset(),
129 blob_data
->items().at(1).length(),
130 blob_data
->items().at(1).expected_modification_time());
132 ResourceRequestBody::Element upload_element1
, upload_element2
;
133 upload_element1
.SetToBytes("Hello", 5);
134 upload_element2
.SetToFilePathRange(
135 base::FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2
);
137 // Test no blob reference.
138 scoped_refptr
<ResourceRequestBody
> request_body(new ResourceRequestBody());
139 request_body
->AppendBytes(
140 upload_element1
.bytes(),
141 upload_element1
.length());
142 request_body
->AppendFileRange(
143 upload_element2
.path(),
144 upload_element2
.offset(),
145 upload_element2
.length(),
146 upload_element2
.expected_modification_time());
148 scoped_ptr
<net::UploadDataStream
> upload(
149 UploadDataStreamBuilder::Build(
151 &blob_storage_context
,
153 base::MessageLoopProxy::current().get()));
155 ASSERT_TRUE(upload
->GetElementReaders());
156 ASSERT_EQ(2U, upload
->GetElementReaders()->size());
157 EXPECT_TRUE(AreElementsEqual(
158 *(*upload
->GetElementReaders())[0], upload_element1
));
159 EXPECT_TRUE(AreElementsEqual(
160 *(*upload
->GetElementReaders())[1], upload_element2
));
162 // Test having only one blob reference that refers to empty blob data.
163 request_body
= new ResourceRequestBody();
164 request_body
->AppendBlob(blob_id0
);
166 upload
= UploadDataStreamBuilder::Build(
168 &blob_storage_context
,
170 base::MessageLoopProxy::current().get());
171 ASSERT_TRUE(upload
->GetElementReaders());
172 ASSERT_EQ(0U, upload
->GetElementReaders()->size());
174 // Test having only one blob reference.
175 request_body
= new ResourceRequestBody();
176 request_body
->AppendBlob(blob_id1
);
178 upload
= UploadDataStreamBuilder::Build(
180 &blob_storage_context
,
182 base::MessageLoopProxy::current().get());
183 ASSERT_TRUE(upload
->GetElementReaders());
184 ASSERT_EQ(2U, upload
->GetElementReaders()->size());
185 EXPECT_TRUE(AreElementsEqual(
186 *(*upload
->GetElementReaders())[0], blob_element1
));
187 EXPECT_TRUE(AreElementsEqual(
188 *(*upload
->GetElementReaders())[1], blob_element2
));
190 // Test having one blob reference at the beginning.
191 request_body
= new ResourceRequestBody();
192 request_body
->AppendBlob(blob_id1
);
193 request_body
->AppendBytes(
194 upload_element1
.bytes(),
195 upload_element1
.length());
196 request_body
->AppendFileRange(
197 upload_element2
.path(),
198 upload_element2
.offset(),
199 upload_element2
.length(),
200 upload_element2
.expected_modification_time());
202 upload
= UploadDataStreamBuilder::Build(
204 &blob_storage_context
,
206 base::MessageLoopProxy::current().get());
207 ASSERT_TRUE(upload
->GetElementReaders());
208 ASSERT_EQ(4U, upload
->GetElementReaders()->size());
209 EXPECT_TRUE(AreElementsEqual(
210 *(*upload
->GetElementReaders())[0], blob_element1
));
211 EXPECT_TRUE(AreElementsEqual(
212 *(*upload
->GetElementReaders())[1], blob_element2
));
213 EXPECT_TRUE(AreElementsEqual(
214 *(*upload
->GetElementReaders())[2], upload_element1
));
215 EXPECT_TRUE(AreElementsEqual(
216 *(*upload
->GetElementReaders())[3], upload_element2
));
218 // Test having one blob reference at the end.
219 request_body
= new ResourceRequestBody();
220 request_body
->AppendBytes(
221 upload_element1
.bytes(),
222 upload_element1
.length());
223 request_body
->AppendFileRange(
224 upload_element2
.path(),
225 upload_element2
.offset(),
226 upload_element2
.length(),
227 upload_element2
.expected_modification_time());
228 request_body
->AppendBlob(blob_id1
);
231 UploadDataStreamBuilder::Build(request_body
.get(),
232 &blob_storage_context
,
234 base::MessageLoopProxy::current().get());
235 ASSERT_TRUE(upload
->GetElementReaders());
236 ASSERT_EQ(4U, upload
->GetElementReaders()->size());
237 EXPECT_TRUE(AreElementsEqual(
238 *(*upload
->GetElementReaders())[0], upload_element1
));
239 EXPECT_TRUE(AreElementsEqual(
240 *(*upload
->GetElementReaders())[1], upload_element2
));
241 EXPECT_TRUE(AreElementsEqual(
242 *(*upload
->GetElementReaders())[2], blob_element1
));
243 EXPECT_TRUE(AreElementsEqual(
244 *(*upload
->GetElementReaders())[3], blob_element2
));
246 // Test having one blob reference in the middle.
247 request_body
= new ResourceRequestBody();
248 request_body
->AppendBytes(
249 upload_element1
.bytes(),
250 upload_element1
.length());
251 request_body
->AppendBlob(blob_id1
);
252 request_body
->AppendFileRange(
253 upload_element2
.path(),
254 upload_element2
.offset(),
255 upload_element2
.length(),
256 upload_element2
.expected_modification_time());
258 upload
= UploadDataStreamBuilder::Build(
260 &blob_storage_context
,
262 base::MessageLoopProxy::current().get());
263 ASSERT_TRUE(upload
->GetElementReaders());
264 ASSERT_EQ(4U, upload
->GetElementReaders()->size());
265 EXPECT_TRUE(AreElementsEqual(
266 *(*upload
->GetElementReaders())[0], upload_element1
));
267 EXPECT_TRUE(AreElementsEqual(
268 *(*upload
->GetElementReaders())[1], blob_element1
));
269 EXPECT_TRUE(AreElementsEqual(
270 *(*upload
->GetElementReaders())[2], blob_element2
));
271 EXPECT_TRUE(AreElementsEqual(
272 *(*upload
->GetElementReaders())[3], upload_element2
));
274 // Test having multiple blob references.
275 request_body
= new ResourceRequestBody();
276 request_body
->AppendBlob(blob_id1
);
277 request_body
->AppendBytes(
278 upload_element1
.bytes(),
279 upload_element1
.length());
280 request_body
->AppendBlob(blob_id1
);
281 request_body
->AppendBlob(blob_id1
);
282 request_body
->AppendFileRange(
283 upload_element2
.path(),
284 upload_element2
.offset(),
285 upload_element2
.length(),
286 upload_element2
.expected_modification_time());
288 upload
= UploadDataStreamBuilder::Build(
290 &blob_storage_context
,
292 base::MessageLoopProxy::current().get());
293 ASSERT_TRUE(upload
->GetElementReaders());
294 ASSERT_EQ(8U, upload
->GetElementReaders()->size());
295 EXPECT_TRUE(AreElementsEqual(
296 *(*upload
->GetElementReaders())[0], blob_element1
));
297 EXPECT_TRUE(AreElementsEqual(
298 *(*upload
->GetElementReaders())[1], blob_element2
));
299 EXPECT_TRUE(AreElementsEqual(
300 *(*upload
->GetElementReaders())[2], upload_element1
));
301 EXPECT_TRUE(AreElementsEqual(
302 *(*upload
->GetElementReaders())[3], blob_element1
));
303 EXPECT_TRUE(AreElementsEqual(
304 *(*upload
->GetElementReaders())[4], blob_element2
));
305 EXPECT_TRUE(AreElementsEqual(
306 *(*upload
->GetElementReaders())[5], blob_element1
));
307 EXPECT_TRUE(AreElementsEqual(
308 *(*upload
->GetElementReaders())[6], blob_element2
));
309 EXPECT_TRUE(AreElementsEqual(
310 *(*upload
->GetElementReaders())[7], upload_element2
));
312 // Clean up for ASAN.
313 base::RunLoop().RunUntilIdle();
316 } // namespace content