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 "net/base/upload_bytes_element_reader.h"
15 #include "net/base/upload_data_stream.h"
16 #include "net/base/upload_file_element_reader.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 #include "webkit/browser/blob/blob_storage_context.h"
20 #include "webkit/common/resource_request_body.h"
22 using webkit_blob::BlobData;
23 using webkit_blob::BlobDataHandle;
24 using webkit_blob::BlobStorageContext;
25 using webkit_glue::ResourceRequestBody;
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_EQ(request_body->elements()->size(), upload->element_readers().size());
81 const net::UploadBytesElementReader* r1 =
82 upload->element_readers()[0]->AsBytesReader();
84 EXPECT_EQ(kData, std::string(r1->bytes(), r1->length()));
86 const net::UploadFileElementReader* r2 =
87 upload->element_readers()[1]->AsFileReader();
89 EXPECT_EQ(kFilePath, r2->path().value());
90 EXPECT_EQ(kFileOffset, r2->range_offset());
91 EXPECT_EQ(kFileLength, r2->range_length());
92 EXPECT_EQ(kFileTime, r2->expected_modification_time());
95 TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
96 base::MessageLoop message_loop;
97 // Setup blob data for testing.
98 base::Time time1, time2;
99 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1);
100 base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2);
102 BlobStorageContext blob_storage_context;
104 const std::string blob_id0("id-0");
105 scoped_refptr<BlobData> blob_data(new BlobData(blob_id0));
106 scoped_ptr<BlobDataHandle> handle1 =
107 blob_storage_context.AddFinishedBlob(blob_data);
109 const std::string blob_id1("id-1");
110 blob_data = new BlobData(blob_id1);
111 blob_data->AppendData("BlobData");
112 blob_data->AppendFile(
113 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1);
114 scoped_ptr<BlobDataHandle> handle2 =
115 blob_storage_context.AddFinishedBlob(blob_data);
117 // Setup upload data elements for comparison.
118 ResourceRequestBody::Element blob_element1, blob_element2;
119 blob_element1.SetToBytes(
120 blob_data->items().at(0).bytes() +
121 static_cast<int>(blob_data->items().at(0).offset()),
122 static_cast<int>(blob_data->items().at(0).length()));
123 blob_element2.SetToFilePathRange(
124 blob_data->items().at(1).path(),
125 blob_data->items().at(1).offset(),
126 blob_data->items().at(1).length(),
127 blob_data->items().at(1).expected_modification_time());
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(upload_element1.bytes(), upload_element1.length());
137 request_body->AppendFileRange(upload_element2.path(),
138 upload_element2.offset(),
139 upload_element2.length(),
140 upload_element2.expected_modification_time());
142 scoped_ptr<net::UploadDataStream> upload(
143 UploadDataStreamBuilder::Build(request_body.get(),
144 &blob_storage_context,
146 base::MessageLoopProxy::current().get()));
148 ASSERT_EQ(2U, upload->element_readers().size());
149 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], upload_element1));
150 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], upload_element2));
152 // Test having only one blob reference that refers to empty blob data.
153 request_body = new ResourceRequestBody();
154 request_body->AppendBlob(blob_id0);
157 UploadDataStreamBuilder::Build(request_body.get(),
158 &blob_storage_context,
160 base::MessageLoopProxy::current().get());
161 ASSERT_EQ(0U, upload->element_readers().size());
163 // Test having only one blob reference.
164 request_body = new ResourceRequestBody();
165 request_body->AppendBlob(blob_id1);
168 UploadDataStreamBuilder::Build(request_body.get(),
169 &blob_storage_context,
171 base::MessageLoopProxy::current().get());
172 ASSERT_EQ(2U, upload->element_readers().size());
173 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], blob_element1));
174 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], blob_element2));
176 // Test having one blob reference at the beginning.
177 request_body = new ResourceRequestBody();
178 request_body->AppendBlob(blob_id1);
179 request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
180 request_body->AppendFileRange(upload_element2.path(),
181 upload_element2.offset(),
182 upload_element2.length(),
183 upload_element2.expected_modification_time());
186 UploadDataStreamBuilder::Build(request_body.get(),
187 &blob_storage_context,
189 base::MessageLoopProxy::current().get());
190 ASSERT_EQ(4U, upload->element_readers().size());
191 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], blob_element1));
192 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], blob_element2));
193 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[2], upload_element1));
194 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[3], upload_element2));
196 // Test having one blob reference at the end.
197 request_body = new ResourceRequestBody();
198 request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
199 request_body->AppendFileRange(upload_element2.path(),
200 upload_element2.offset(),
201 upload_element2.length(),
202 upload_element2.expected_modification_time());
203 request_body->AppendBlob(blob_id1);
206 UploadDataStreamBuilder::Build(request_body.get(),
207 &blob_storage_context,
209 base::MessageLoopProxy::current().get());
210 ASSERT_EQ(4U, upload->element_readers().size());
211 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], upload_element1));
212 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], upload_element2));
213 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[2], blob_element1));
214 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[3], blob_element2));
216 // Test having one blob reference in the middle.
217 request_body = new ResourceRequestBody();
218 request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
219 request_body->AppendBlob(blob_id1);
220 request_body->AppendFileRange(upload_element2.path(),
221 upload_element2.offset(),
222 upload_element2.length(),
223 upload_element2.expected_modification_time());
226 UploadDataStreamBuilder::Build(request_body.get(),
227 &blob_storage_context,
229 base::MessageLoopProxy::current().get());
230 ASSERT_EQ(4U, upload->element_readers().size());
231 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], upload_element1));
232 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], blob_element1));
233 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[2], blob_element2));
234 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[3], upload_element2));
236 // Test having multiple blob references.
237 request_body = new ResourceRequestBody();
238 request_body->AppendBlob(blob_id1);
239 request_body->AppendBytes(upload_element1.bytes(), upload_element1.length());
240 request_body->AppendBlob(blob_id1);
241 request_body->AppendBlob(blob_id1);
242 request_body->AppendFileRange(upload_element2.path(),
243 upload_element2.offset(),
244 upload_element2.length(),
245 upload_element2.expected_modification_time());
248 UploadDataStreamBuilder::Build(request_body.get(),
249 &blob_storage_context,
251 base::MessageLoopProxy::current().get());
252 ASSERT_EQ(8U, upload->element_readers().size());
253 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[0], blob_element1));
254 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[1], blob_element2));
255 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[2], upload_element1));
256 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[3], blob_element1));
257 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[4], blob_element2));
258 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[5], blob_element1));
259 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[6], blob_element2));
260 EXPECT_TRUE(AreElementsEqual(*upload->element_readers()[7], upload_element2));
263 } // namespace content