Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / loader / upload_data_stream_builder_unittest.cc
blob57161eaf4caf1a281d91b2c5fd020e2c192f5f39
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"
7 #include <algorithm>
8 #include <string>
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/run_loop.h"
15 #include "base/time/time.h"
16 #include "content/common/resource_request_body.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/base/upload_bytes_element_reader.h"
21 #include "net/base/upload_data_stream.h"
22 #include "net/base/upload_file_element_reader.h"
23 #include "storage/browser/blob/blob_data_builder.h"
24 #include "storage/browser/blob/blob_storage_context.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "url/gurl.h"
28 using storage::BlobDataBuilder;
29 using storage::BlobDataHandle;
30 using storage::BlobStorageContext;
32 namespace content {
33 namespace {
35 bool AreElementsEqual(const net::UploadElementReader& reader,
36 const ResourceRequestBody::Element& element) {
37 switch(element.type()) {
38 case ResourceRequestBody::Element::TYPE_BYTES: {
39 const net::UploadBytesElementReader* bytes_reader =
40 reader.AsBytesReader();
41 return bytes_reader &&
42 element.length() == bytes_reader->length() &&
43 std::equal(element.bytes(), element.bytes() + element.length(),
44 bytes_reader->bytes());
46 case ResourceRequestBody::Element::TYPE_FILE: {
47 const net::UploadFileElementReader* file_reader = reader.AsFileReader();
48 return file_reader &&
49 file_reader->path() == element.path() &&
50 file_reader->range_offset() == element.offset() &&
51 file_reader->range_length() == element.length() &&
52 file_reader->expected_modification_time() ==
53 element.expected_modification_time();
54 break;
56 default:
57 NOTREACHED();
59 return false;
62 } // namespace
64 TEST(UploadDataStreamBuilderTest, CreateUploadDataStreamWithoutBlob) {
65 base::MessageLoop message_loop;
66 scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody;
68 const char kData[] = "123";
69 const base::FilePath::StringType kFilePath = FILE_PATH_LITERAL("abc");
70 const uint64 kFileOffset = 10U;
71 const uint64 kFileLength = 100U;
72 const base::Time kFileTime = base::Time::FromDoubleT(999);
73 const int64 kIdentifier = 12345;
75 request_body->AppendBytes(kData, arraysize(kData) - 1);
76 request_body->AppendFileRange(base::FilePath(kFilePath),
77 kFileOffset, kFileLength, kFileTime);
78 request_body->set_identifier(kIdentifier);
80 scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
81 request_body.get(), NULL, NULL, base::MessageLoopProxy::current().get()));
83 EXPECT_EQ(kIdentifier, upload->identifier());
84 ASSERT_TRUE(upload->GetElementReaders());
85 ASSERT_EQ(request_body->elements()->size(),
86 upload->GetElementReaders()->size());
88 const net::UploadBytesElementReader* r1 =
89 (*upload->GetElementReaders())[0]->AsBytesReader();
90 ASSERT_TRUE(r1);
91 EXPECT_EQ(kData, std::string(r1->bytes(), r1->length()));
93 const net::UploadFileElementReader* r2 =
94 (*upload->GetElementReaders())[1]->AsFileReader();
95 ASSERT_TRUE(r2);
96 EXPECT_EQ(kFilePath, r2->path().value());
97 EXPECT_EQ(kFileOffset, r2->range_offset());
98 EXPECT_EQ(kFileLength, r2->range_length());
99 EXPECT_EQ(kFileTime, r2->expected_modification_time());
102 TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
103 base::MessageLoop message_loop;
105 // Setup blob data for testing.
106 base::Time time1, time2;
107 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1);
108 base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2);
110 BlobStorageContext blob_storage_context;
112 const std::string blob_id0("id-0");
113 scoped_ptr<BlobDataBuilder> blob_data_builder(
114 new BlobDataBuilder(blob_id0));
115 scoped_ptr<BlobDataHandle> handle1 =
116 blob_storage_context.AddFinishedBlob(blob_data_builder.get());
118 const std::string blob_id1("id-1");
119 const std::string kBlobData = "BlobData";
120 blob_data_builder.reset(new BlobDataBuilder(blob_id1));
121 blob_data_builder->AppendData(kBlobData);
122 blob_data_builder->AppendFile(
123 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1);
124 scoped_ptr<BlobDataHandle> handle2 =
125 blob_storage_context.AddFinishedBlob(blob_data_builder.get());
127 // Setup upload data elements for comparison.
128 ResourceRequestBody::Element blob_element1, blob_element2;
129 blob_element1.SetToBytes(kBlobData.c_str(), kBlobData.size());
130 blob_element2.SetToFilePathRange(
131 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1);
133 ResourceRequestBody::Element upload_element1, upload_element2;
134 upload_element1.SetToBytes("Hello", 5);
135 upload_element2.SetToFilePathRange(
136 base::FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2);
138 // Test no blob reference.
139 scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
140 request_body->AppendBytes(
141 upload_element1.bytes(),
142 upload_element1.length());
143 request_body->AppendFileRange(
144 upload_element2.path(),
145 upload_element2.offset(),
146 upload_element2.length(),
147 upload_element2.expected_modification_time());
149 scoped_ptr<net::UploadDataStream> upload(
150 UploadDataStreamBuilder::Build(
151 request_body.get(),
152 &blob_storage_context,
153 NULL,
154 base::MessageLoopProxy::current().get()));
156 ASSERT_TRUE(upload->GetElementReaders());
157 ASSERT_EQ(2U, upload->GetElementReaders()->size());
158 EXPECT_TRUE(AreElementsEqual(
159 *(*upload->GetElementReaders())[0], upload_element1));
160 EXPECT_TRUE(AreElementsEqual(
161 *(*upload->GetElementReaders())[1], upload_element2));
163 // Test having only one blob reference that refers to empty blob data.
164 request_body = new ResourceRequestBody();
165 request_body->AppendBlob(blob_id0);
167 upload = UploadDataStreamBuilder::Build(
168 request_body.get(),
169 &blob_storage_context,
170 NULL,
171 base::MessageLoopProxy::current().get());
172 ASSERT_TRUE(upload->GetElementReaders());
173 ASSERT_EQ(0U, upload->GetElementReaders()->size());
175 // Test having only one blob reference.
176 request_body = new ResourceRequestBody();
177 request_body->AppendBlob(blob_id1);
179 upload = UploadDataStreamBuilder::Build(
180 request_body.get(),
181 &blob_storage_context,
182 NULL,
183 base::MessageLoopProxy::current().get());
184 ASSERT_TRUE(upload->GetElementReaders());
185 ASSERT_EQ(2U, upload->GetElementReaders()->size());
186 EXPECT_TRUE(AreElementsEqual(
187 *(*upload->GetElementReaders())[0], blob_element1));
188 EXPECT_TRUE(AreElementsEqual(
189 *(*upload->GetElementReaders())[1], blob_element2));
191 // Test having one blob reference at the beginning.
192 request_body = new ResourceRequestBody();
193 request_body->AppendBlob(blob_id1);
194 request_body->AppendBytes(
195 upload_element1.bytes(),
196 upload_element1.length());
197 request_body->AppendFileRange(
198 upload_element2.path(),
199 upload_element2.offset(),
200 upload_element2.length(),
201 upload_element2.expected_modification_time());
203 upload = UploadDataStreamBuilder::Build(
204 request_body.get(),
205 &blob_storage_context,
206 NULL,
207 base::MessageLoopProxy::current().get());
208 ASSERT_TRUE(upload->GetElementReaders());
209 ASSERT_EQ(4U, upload->GetElementReaders()->size());
210 EXPECT_TRUE(AreElementsEqual(
211 *(*upload->GetElementReaders())[0], blob_element1));
212 EXPECT_TRUE(AreElementsEqual(
213 *(*upload->GetElementReaders())[1], blob_element2));
214 EXPECT_TRUE(AreElementsEqual(
215 *(*upload->GetElementReaders())[2], upload_element1));
216 EXPECT_TRUE(AreElementsEqual(
217 *(*upload->GetElementReaders())[3], upload_element2));
219 // Test having one blob reference at the end.
220 request_body = new ResourceRequestBody();
221 request_body->AppendBytes(
222 upload_element1.bytes(),
223 upload_element1.length());
224 request_body->AppendFileRange(
225 upload_element2.path(),
226 upload_element2.offset(),
227 upload_element2.length(),
228 upload_element2.expected_modification_time());
229 request_body->AppendBlob(blob_id1);
231 upload =
232 UploadDataStreamBuilder::Build(request_body.get(),
233 &blob_storage_context,
234 NULL,
235 base::MessageLoopProxy::current().get());
236 ASSERT_TRUE(upload->GetElementReaders());
237 ASSERT_EQ(4U, upload->GetElementReaders()->size());
238 EXPECT_TRUE(AreElementsEqual(
239 *(*upload->GetElementReaders())[0], upload_element1));
240 EXPECT_TRUE(AreElementsEqual(
241 *(*upload->GetElementReaders())[1], upload_element2));
242 EXPECT_TRUE(AreElementsEqual(
243 *(*upload->GetElementReaders())[2], blob_element1));
244 EXPECT_TRUE(AreElementsEqual(
245 *(*upload->GetElementReaders())[3], blob_element2));
247 // Test having one blob reference in the middle.
248 request_body = new ResourceRequestBody();
249 request_body->AppendBytes(
250 upload_element1.bytes(),
251 upload_element1.length());
252 request_body->AppendBlob(blob_id1);
253 request_body->AppendFileRange(
254 upload_element2.path(),
255 upload_element2.offset(),
256 upload_element2.length(),
257 upload_element2.expected_modification_time());
259 upload = UploadDataStreamBuilder::Build(
260 request_body.get(),
261 &blob_storage_context,
262 NULL,
263 base::MessageLoopProxy::current().get());
264 ASSERT_TRUE(upload->GetElementReaders());
265 ASSERT_EQ(4U, upload->GetElementReaders()->size());
266 EXPECT_TRUE(AreElementsEqual(
267 *(*upload->GetElementReaders())[0], upload_element1));
268 EXPECT_TRUE(AreElementsEqual(
269 *(*upload->GetElementReaders())[1], blob_element1));
270 EXPECT_TRUE(AreElementsEqual(
271 *(*upload->GetElementReaders())[2], blob_element2));
272 EXPECT_TRUE(AreElementsEqual(
273 *(*upload->GetElementReaders())[3], upload_element2));
275 // Test having multiple blob references.
276 request_body = new ResourceRequestBody();
277 request_body->AppendBlob(blob_id1);
278 request_body->AppendBytes(
279 upload_element1.bytes(),
280 upload_element1.length());
281 request_body->AppendBlob(blob_id1);
282 request_body->AppendBlob(blob_id1);
283 request_body->AppendFileRange(
284 upload_element2.path(),
285 upload_element2.offset(),
286 upload_element2.length(),
287 upload_element2.expected_modification_time());
289 upload = UploadDataStreamBuilder::Build(
290 request_body.get(),
291 &blob_storage_context,
292 NULL,
293 base::MessageLoopProxy::current().get());
294 ASSERT_TRUE(upload->GetElementReaders());
295 ASSERT_EQ(8U, upload->GetElementReaders()->size());
296 EXPECT_TRUE(AreElementsEqual(
297 *(*upload->GetElementReaders())[0], blob_element1));
298 EXPECT_TRUE(AreElementsEqual(
299 *(*upload->GetElementReaders())[1], blob_element2));
300 EXPECT_TRUE(AreElementsEqual(
301 *(*upload->GetElementReaders())[2], upload_element1));
302 EXPECT_TRUE(AreElementsEqual(
303 *(*upload->GetElementReaders())[3], blob_element1));
304 EXPECT_TRUE(AreElementsEqual(
305 *(*upload->GetElementReaders())[4], blob_element2));
306 EXPECT_TRUE(AreElementsEqual(
307 *(*upload->GetElementReaders())[5], blob_element1));
308 EXPECT_TRUE(AreElementsEqual(
309 *(*upload->GetElementReaders())[6], blob_element2));
310 EXPECT_TRUE(AreElementsEqual(
311 *(*upload->GetElementReaders())[7], upload_element2));
313 // Clean up for ASAN.
314 base::RunLoop().RunUntilIdle();
317 TEST(UploadDataStreamBuilderTest,
318 WriteUploadDataStreamWithEmptyFileBackedBlob) {
319 base::MessageLoopForIO message_loop;
321 base::FilePath test_blob_path;
322 ASSERT_TRUE(base::CreateTemporaryFile(&test_blob_path));
324 const uint64_t kZeroLength = 0;
325 base::Time blob_time;
326 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &blob_time);
327 ASSERT_TRUE(base::TouchFile(test_blob_path, blob_time, blob_time));
329 BlobStorageContext blob_storage_context;
331 // A blob created from an empty file added several times.
332 const std::string blob_id("id-0");
333 scoped_ptr<BlobDataBuilder> blob_data_builder(new BlobDataBuilder(blob_id));
334 blob_data_builder->AppendFile(test_blob_path, 0, kZeroLength, blob_time);
335 scoped_ptr<BlobDataHandle> handle =
336 blob_storage_context.AddFinishedBlob(blob_data_builder.get());
338 ResourceRequestBody::Element blob_element;
339 blob_element.SetToFilePathRange(test_blob_path, 0, kZeroLength, blob_time);
341 scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
342 scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
343 request_body.get(), &blob_storage_context, NULL,
344 base::MessageLoopProxy::current().get()));
346 request_body = new ResourceRequestBody();
347 request_body->AppendBlob(blob_id);
348 request_body->AppendBlob(blob_id);
349 request_body->AppendBlob(blob_id);
351 upload = UploadDataStreamBuilder::Build(
352 request_body.get(), &blob_storage_context, NULL,
353 base::MessageLoopProxy::current().get());
354 ASSERT_TRUE(upload->GetElementReaders());
355 const auto& readers = *upload->GetElementReaders();
356 ASSERT_EQ(3U, readers.size());
357 EXPECT_TRUE(AreElementsEqual(*readers[0], blob_element));
358 EXPECT_TRUE(AreElementsEqual(*readers[1], blob_element));
359 EXPECT_TRUE(AreElementsEqual(*readers[2], blob_element));
361 net::TestCompletionCallback init_callback;
362 ASSERT_EQ(net::ERR_IO_PENDING, upload->Init(init_callback.callback()));
363 EXPECT_EQ(net::OK, init_callback.WaitForResult());
365 EXPECT_EQ(kZeroLength, upload->size());
367 // Purposely (try to) read more than what is in the stream. If we try to
368 // read zero bytes then UploadDataStream::Read will fail a DCHECK.
369 int kBufferLength = kZeroLength + 1;
370 scoped_ptr<char[]> buffer(new char[kBufferLength]);
371 scoped_refptr<net::IOBuffer> io_buffer =
372 new net::WrappedIOBuffer(buffer.get());
373 net::TestCompletionCallback read_callback;
374 int result =
375 upload->Read(io_buffer.get(), kBufferLength, read_callback.callback());
376 EXPECT_EQ(static_cast<int>(kZeroLength), read_callback.GetResult(result));
378 base::DeleteFile(test_blob_path, false);
380 // Clean up for ASAN.
381 base::RunLoop().RunUntilIdle();
383 } // namespace content