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/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/time/time.h"
14 #include "content/common/resource_request_body.h"
15 #include "net/base/upload_bytes_element_reader.h"
16 #include "net/base/upload_data_stream.h"
17 #include "net/base/upload_file_element_reader.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 #include "webkit/browser/blob/blob_storage_context.h"
22 using webkit_blob::BlobData;
23 using webkit_blob::BlobDataHandle;
24 using webkit_blob::BlobStorageContext;
29 bool AreElementsEqual(const net::UploadElementReader& reader,
30 const ResourceRequestBody::Element& element) {
31 switch(element.type()) {
32 case ResourceRequestBody::Element::TYPE_BYTES: {
33 const net::UploadBytesElementReader* bytes_reader =
34 reader.AsBytesReader();
35 return bytes_reader &&
36 element.length() == bytes_reader->length() &&
37 std::equal(element.bytes(), element.bytes() + element.length(),
38 bytes_reader->bytes());
40 case ResourceRequestBody::Element::TYPE_FILE: {
41 const net::UploadFileElementReader* file_reader = reader.AsFileReader();
43 file_reader->path() == element.path() &&
44 file_reader->range_offset() == element.offset() &&
45 file_reader->range_length() == element.length() &&
46 file_reader->expected_modification_time() ==
47 element.expected_modification_time();
58 TEST(UploadDataStreamBuilderTest, CreateUploadDataStreamWithoutBlob) {
59 base::MessageLoop message_loop;
60 scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody;
62 const char kData[] = "123";
63 const base::FilePath::StringType kFilePath = FILE_PATH_LITERAL("abc");
64 const uint64 kFileOffset = 10U;
65 const uint64 kFileLength = 100U;
66 const base::Time kFileTime = base::Time::FromDoubleT(999);
67 const int64 kIdentifier = 12345;
69 request_body->AppendBytes(kData, arraysize(kData) - 1);
70 request_body->AppendFileRange(base::FilePath(kFilePath),
71 kFileOffset, kFileLength, kFileTime);
72 request_body->set_identifier(kIdentifier);
74 scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
75 request_body.get(), NULL, NULL, base::MessageLoopProxy::current().get()));
77 EXPECT_EQ(kIdentifier, upload->identifier());
78 ASSERT_EQ(request_body->elements()->size(), upload->element_readers().size());
80 const net::UploadBytesElementReader* r1 =
81 upload->element_readers()[0]->AsBytesReader();
83 EXPECT_EQ(kData, std::string(r1->bytes(), r1->length()));
85 const net::UploadFileElementReader* r2 =
86 upload->element_readers()[1]->AsFileReader();
88 EXPECT_EQ(kFilePath, r2->path().value());
89 EXPECT_EQ(kFileOffset, r2->range_offset());
90 EXPECT_EQ(kFileLength, r2->range_length());
91 EXPECT_EQ(kFileTime, r2->expected_modification_time());
94 TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
95 base::MessageLoop message_loop;
96 // Setup 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);
101 BlobStorageContext blob_storage_context;
103 const std::string blob_id0("id-0");
104 scoped_refptr<BlobData> blob_data(new BlobData(blob_id0));
105 scoped_ptr<BlobDataHandle> handle1 =
106 blob_storage_context.AddFinishedBlob(blob_data);
108 const std::string blob_id1("id-1");
109 blob_data = new BlobData(blob_id1);
110 blob_data->AppendData("BlobData");
111 blob_data->AppendFile(
112 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1);
113 scoped_ptr<BlobDataHandle> handle2 =
114 blob_storage_context.AddFinishedBlob(blob_data);
116 // Setup upload data elements for comparison.
117 ResourceRequestBody::Element blob_element1, blob_element2;
118 blob_element1.SetToBytes(
119 blob_data->items().at(0).bytes() +
120 static_cast<int>(blob_data->items().at(0).offset()),
121 static_cast<int>(blob_data->items().at(0).length()));
122 blob_element2.SetToFilePathRange(
123 blob_data->items().at(1).path(),
124 blob_data->items().at(1).offset(),
125 blob_data->items().at(1).length(),
126 blob_data->items().at(1).expected_modification_time());
128 ResourceRequestBody::Element upload_element1, upload_element2;
129 upload_element1.SetToBytes("Hello", 5);
130 upload_element2.SetToFilePathRange(
131 base::FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2);
133 // Test no blob reference.
134 scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
135 request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
136 request_body->AppendFileRange(upload_element2.path(),
137 upload_element2.offset(),
138 upload_element2.length(),
139 upload_element2.expected_modification_time());
141 scoped_ptr<net::UploadDataStream> upload(
142 UploadDataStreamBuilder::Build(request_body.get(),
143 &blob_storage_context,
145 base::MessageLoopProxy::current().get()));
147 ASSERT_EQ(2U, upload->element_readers().size());
148 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], upload_element1));
149 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], upload_element2));
151 // Test having only one blob reference that refers to empty blob data.
152 request_body = new ResourceRequestBody();
153 request_body->AppendBlob(blob_id0);
156 UploadDataStreamBuilder::Build(request_body.get(),
157 &blob_storage_context,
159 base::MessageLoopProxy::current().get());
160 ASSERT_EQ(0U, upload->element_readers().size());
162 // Test having only one blob reference.
163 request_body = new ResourceRequestBody();
164 request_body->AppendBlob(blob_id1);
167 UploadDataStreamBuilder::Build(request_body.get(),
168 &blob_storage_context,
170 base::MessageLoopProxy::current().get());
171 ASSERT_EQ(2U, upload->element_readers().size());
172 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], blob_element1));
173 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], blob_element2));
175 // Test having one blob reference at the beginning.
176 request_body = new ResourceRequestBody();
177 request_body->AppendBlob(blob_id1);
178 request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
179 request_body->AppendFileRange(upload_element2.path(),
180 upload_element2.offset(),
181 upload_element2.length(),
182 upload_element2.expected_modification_time());
185 UploadDataStreamBuilder::Build(request_body.get(),
186 &blob_storage_context,
188 base::MessageLoopProxy::current().get());
189 ASSERT_EQ(4U, upload->element_readers().size());
190 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], blob_element1));
191 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], blob_element2));
192 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[2], upload_element1));
193 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[3], upload_element2));
195 // Test having one blob reference at the end.
196 request_body = new ResourceRequestBody();
197 request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
198 request_body->AppendFileRange(upload_element2.path(),
199 upload_element2.offset(),
200 upload_element2.length(),
201 upload_element2.expected_modification_time());
202 request_body->AppendBlob(blob_id1);
205 UploadDataStreamBuilder::Build(request_body.get(),
206 &blob_storage_context,
208 base::MessageLoopProxy::current().get());
209 ASSERT_EQ(4U, upload->element_readers().size());
210 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], upload_element1));
211 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], upload_element2));
212 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[2], blob_element1));
213 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[3], blob_element2));
215 // Test having one blob reference in the middle.
216 request_body = new ResourceRequestBody();
217 request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
218 request_body->AppendBlob(blob_id1);
219 request_body->AppendFileRange(upload_element2.path(),
220 upload_element2.offset(),
221 upload_element2.length(),
222 upload_element2.expected_modification_time());
225 UploadDataStreamBuilder::Build(request_body.get(),
226 &blob_storage_context,
228 base::MessageLoopProxy::current().get());
229 ASSERT_EQ(4U, upload->element_readers().size());
230 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], upload_element1));
231 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], blob_element1));
232 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[2], blob_element2));
233 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[3], upload_element2));
235 // Test having multiple blob references.
236 request_body = new ResourceRequestBody();
237 request_body->AppendBlob(blob_id1);
238 request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
239 request_body->AppendBlob(blob_id1);
240 request_body->AppendBlob(blob_id1);
241 request_body->AppendFileRange(upload_element2.path(),
242 upload_element2.offset(),
243 upload_element2.length(),
244 upload_element2.expected_modification_time());
247 UploadDataStreamBuilder::Build(request_body.get(),
248 &blob_storage_context,
250 base::MessageLoopProxy::current().get());
251 ASSERT_EQ(8U, upload->element_readers().size());
252 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], blob_element1));
253 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], blob_element2));
254 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[2], upload_element1));
255 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[3], blob_element1));
256 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[4], blob_element2));
257 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[5], blob_element1));
258 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[6], blob_element2));
259 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[7], upload_element2));
262 } // namespace content