| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/loader/upload_data_stream_builder.h" | 5 #include "content/browser/loader/upload_data_stream_builder.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
| 13 #include "base/thread_task_runner_handle.h" | 13 #include "base/thread_task_runner_handle.h" |
| 14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 15 #include "content/common/resource_request_body.h" | 15 #include "content/common/resource_request_body.h" |
| 16 #include "net/base/io_buffer.h" | 16 #include "net/base/io_buffer.h" |
| 17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 18 #include "net/base/test_completion_callback.h" | 18 #include "net/base/test_completion_callback.h" |
| 19 #include "net/base/upload_bytes_element_reader.h" | 19 #include "net/base/upload_bytes_element_reader.h" |
| 20 #include "net/base/upload_data_stream.h" | 20 #include "net/base/upload_data_stream.h" |
| 21 #include "net/base/upload_disk_cache_entry_element_reader.h" | |
| 22 #include "net/base/upload_file_element_reader.h" | 21 #include "net/base/upload_file_element_reader.h" |
| 23 #include "net/disk_cache/disk_cache.h" | |
| 24 #include "storage/browser/blob/blob_data_builder.h" | 22 #include "storage/browser/blob/blob_data_builder.h" |
| 23 #include "storage/browser/blob/blob_data_handle.h" |
| 25 #include "storage/browser/blob/blob_storage_context.h" | 24 #include "storage/browser/blob/blob_storage_context.h" |
| 25 #include "storage/browser/blob/upload_blob_element_reader.h" |
| 26 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
| 27 #include "url/gurl.h" | 27 #include "url/gurl.h" |
| 28 | 28 |
| 29 using storage::BlobDataBuilder; | 29 using storage::BlobDataBuilder; |
| 30 using storage::BlobDataHandle; | 30 using storage::BlobDataHandle; |
| 31 using storage::BlobStorageContext; | 31 using storage::BlobStorageContext; |
| 32 | 32 |
| 33 namespace content { | 33 namespace content { |
| 34 namespace { | |
| 35 | 34 |
| 36 const int kTestDiskCacheStreamIndex = 0; | 35 TEST(UploadDataStreamBuilderTest, CreateUploadDataStream) { |
| 37 | |
| 38 // Our disk cache tests don't need a real data handle since the tests themselves | |
| 39 // scope the disk cache and entries. | |
| 40 class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle { | |
| 41 private: | |
| 42 ~EmptyDataHandle() override {} | |
| 43 }; | |
| 44 | |
| 45 scoped_ptr<disk_cache::Backend> CreateInMemoryDiskCache() { | |
| 46 scoped_ptr<disk_cache::Backend> cache; | |
| 47 net::TestCompletionCallback callback; | |
| 48 int rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE, | |
| 49 net::CACHE_BACKEND_DEFAULT, | |
| 50 base::FilePath(), 0, | |
| 51 false, nullptr, nullptr, &cache, | |
| 52 callback.callback()); | |
| 53 EXPECT_EQ(net::OK, callback.GetResult(rv)); | |
| 54 | |
| 55 return cache.Pass(); | |
| 56 } | |
| 57 | |
| 58 disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache, | |
| 59 const char* key, | |
| 60 const std::string& data) { | |
| 61 disk_cache::Entry* temp_entry = nullptr; | |
| 62 net::TestCompletionCallback callback; | |
| 63 int rv = cache->CreateEntry(key, &temp_entry, callback.callback()); | |
| 64 if (callback.GetResult(rv) != net::OK) | |
| 65 return nullptr; | |
| 66 disk_cache::ScopedEntryPtr entry(temp_entry); | |
| 67 | |
| 68 scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data); | |
| 69 rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(), | |
| 70 iobuffer->size(), callback.callback(), false); | |
| 71 EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv)); | |
| 72 return entry.Pass(); | |
| 73 } | |
| 74 | |
| 75 bool AreElementsEqual(const net::UploadElementReader& reader, | |
| 76 const ResourceRequestBody::Element& element) { | |
| 77 switch(element.type()) { | |
| 78 case ResourceRequestBody::Element::TYPE_BYTES: { | |
| 79 const net::UploadBytesElementReader* bytes_reader = | |
| 80 reader.AsBytesReader(); | |
| 81 return bytes_reader && | |
| 82 element.length() == bytes_reader->length() && | |
| 83 std::equal(element.bytes(), element.bytes() + element.length(), | |
| 84 bytes_reader->bytes()); | |
| 85 } | |
| 86 case ResourceRequestBody::Element::TYPE_FILE: { | |
| 87 const net::UploadFileElementReader* file_reader = reader.AsFileReader(); | |
| 88 return file_reader && | |
| 89 file_reader->path() == element.path() && | |
| 90 file_reader->range_offset() == element.offset() && | |
| 91 file_reader->range_length() == element.length() && | |
| 92 file_reader->expected_modification_time() == | |
| 93 element.expected_modification_time(); | |
| 94 break; | |
| 95 } | |
| 96 case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: { | |
| 97 // TODO(gavinp): Should we be comparing a higher level structure | |
| 98 // such as the BlobDataItem so that we can do stronger equality | |
| 99 // comparisons? | |
| 100 const net::UploadDiskCacheEntryElementReader* disk_cache_entry_reader = | |
| 101 reader.AsDiskCacheEntryReaderForTests(); | |
| 102 return disk_cache_entry_reader && | |
| 103 disk_cache_entry_reader->range_offset_for_tests() == | |
| 104 static_cast<int>(element.offset()) && | |
| 105 disk_cache_entry_reader->range_length_for_tests() == | |
| 106 static_cast<int>(element.length()); | |
| 107 break; | |
| 108 } | |
| 109 default: | |
| 110 NOTREACHED(); | |
| 111 } | |
| 112 return false; | |
| 113 } | |
| 114 | |
| 115 } // namespace | |
| 116 | |
| 117 TEST(UploadDataStreamBuilderTest, CreateUploadDataStreamWithoutBlob) { | |
| 118 base::MessageLoop message_loop; | |
| 119 scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody; | |
| 120 | |
| 121 const char kData[] = "123"; | |
| 122 const base::FilePath::StringType kFilePath = FILE_PATH_LITERAL("abc"); | |
| 123 const uint64 kFileOffset = 10U; | |
| 124 const uint64 kFileLength = 100U; | |
| 125 const base::Time kFileTime = base::Time::FromDoubleT(999); | |
| 126 const int64 kIdentifier = 12345; | |
| 127 | |
| 128 request_body->AppendBytes(kData, arraysize(kData) - 1); | |
| 129 request_body->AppendFileRange(base::FilePath(kFilePath), | |
| 130 kFileOffset, kFileLength, kFileTime); | |
| 131 request_body->set_identifier(kIdentifier); | |
| 132 | |
| 133 scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build( | |
| 134 request_body.get(), NULL, NULL, | |
| 135 base::ThreadTaskRunnerHandle::Get().get())); | |
| 136 | |
| 137 EXPECT_EQ(kIdentifier, upload->identifier()); | |
| 138 ASSERT_TRUE(upload->GetElementReaders()); | |
| 139 ASSERT_EQ(request_body->elements()->size(), | |
| 140 upload->GetElementReaders()->size()); | |
| 141 | |
| 142 const net::UploadBytesElementReader* r1 = | |
| 143 (*upload->GetElementReaders())[0]->AsBytesReader(); | |
| 144 ASSERT_TRUE(r1); | |
| 145 EXPECT_EQ(kData, std::string(r1->bytes(), r1->length())); | |
| 146 | |
| 147 const net::UploadFileElementReader* r2 = | |
| 148 (*upload->GetElementReaders())[1]->AsFileReader(); | |
| 149 ASSERT_TRUE(r2); | |
| 150 EXPECT_EQ(kFilePath, r2->path().value()); | |
| 151 EXPECT_EQ(kFileOffset, r2->range_offset()); | |
| 152 EXPECT_EQ(kFileLength, r2->range_length()); | |
| 153 EXPECT_EQ(kFileTime, r2->expected_modification_time()); | |
| 154 } | |
| 155 | |
| 156 TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { | |
| 157 base::MessageLoop message_loop; | 36 base::MessageLoop message_loop; |
| 158 { | 37 { |
| 159 // Setup blob data for testing. | 38 scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody; |
| 160 base::Time time1, time2; | |
| 161 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); | |
| 162 base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2); | |
| 163 | 39 |
| 164 BlobStorageContext blob_storage_context; | 40 const std::string kBlob = "blobuuid"; |
| 41 const std::string kBlobData = "blobdata"; |
| 42 const char kData[] = "123"; |
| 43 const base::FilePath::StringType kFilePath = FILE_PATH_LITERAL("abc"); |
| 44 const uint64 kFileOffset = 10U; |
| 45 const uint64 kFileLength = 100U; |
| 46 const base::Time kFileTime = base::Time::FromDoubleT(999); |
| 47 const int64 kIdentifier = 12345; |
| 165 | 48 |
| 166 const std::string blob_id0("id-0"); | 49 BlobStorageContext context; |
| 167 scoped_ptr<BlobDataBuilder> blob_data_builder( | 50 BlobDataBuilder builder(kBlob); |
| 168 new BlobDataBuilder(blob_id0)); | 51 builder.AppendData(kBlobData); |
| 169 scoped_ptr<BlobDataHandle> handle1 = | 52 scoped_ptr<BlobDataHandle> handle = context.AddFinishedBlob(&builder); |
| 170 blob_storage_context.AddFinishedBlob(blob_data_builder.get()); | |
| 171 | 53 |
| 172 const std::string blob_id1("id-1"); | 54 request_body->AppendBytes(kData, arraysize(kData) - 1); |
| 173 const std::string kBlobData = "BlobData"; | 55 request_body->AppendFileRange(base::FilePath(kFilePath), kFileOffset, |
| 174 blob_data_builder.reset(new BlobDataBuilder(blob_id1)); | 56 kFileLength, kFileTime); |
| 175 blob_data_builder->AppendData(kBlobData); | 57 request_body->AppendBlob(kBlob); |
| 176 blob_data_builder->AppendFile( | 58 request_body->set_identifier(kIdentifier); |
| 177 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1); | |
| 178 scoped_ptr<BlobDataHandle> handle2 = | |
| 179 blob_storage_context.AddFinishedBlob(blob_data_builder.get()); | |
| 180 | |
| 181 const std::string blob_id2("id-2"); | |
| 182 const std::string kDiskCacheData = "DiskCacheData"; | |
| 183 scoped_ptr<disk_cache::Backend> disk_cache_backend = | |
| 184 CreateInMemoryDiskCache(); | |
| 185 ASSERT_TRUE(disk_cache_backend); | |
| 186 disk_cache::ScopedEntryPtr disk_cache_entry = | |
| 187 CreateDiskCacheEntry(disk_cache_backend.get(), "a key", kDiskCacheData); | |
| 188 ASSERT_TRUE(disk_cache_entry); | |
| 189 blob_data_builder.reset(new BlobDataBuilder(blob_id2)); | |
| 190 blob_data_builder->AppendDiskCacheEntry( | |
| 191 new EmptyDataHandle(), disk_cache_entry.get(), | |
| 192 kTestDiskCacheStreamIndex); | |
| 193 scoped_ptr<BlobDataHandle> handle3 = | |
| 194 blob_storage_context.AddFinishedBlob(blob_data_builder.get()); | |
| 195 | |
| 196 // Setup upload data elements for comparison. | |
| 197 ResourceRequestBody::Element blob_element1, blob_element2, blob_element3; | |
| 198 blob_element1.SetToBytes(kBlobData.c_str(), kBlobData.size()); | |
| 199 blob_element2.SetToFilePathRange( | |
| 200 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1); | |
| 201 blob_element3.SetToDiskCacheEntryRange(0, kDiskCacheData.size()); | |
| 202 | |
| 203 ResourceRequestBody::Element upload_element1, upload_element2; | |
| 204 upload_element1.SetToBytes("Hello", 5); | |
| 205 upload_element2.SetToFilePathRange( | |
| 206 base::FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2); | |
| 207 | |
| 208 // Test no blob reference. | |
| 209 scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody()); | |
| 210 request_body->AppendBytes( | |
| 211 upload_element1.bytes(), | |
| 212 upload_element1.length()); | |
| 213 request_body->AppendFileRange( | |
| 214 upload_element2.path(), | |
| 215 upload_element2.offset(), | |
| 216 upload_element2.length(), | |
| 217 upload_element2.expected_modification_time()); | |
| 218 | 59 |
| 219 scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build( | 60 scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build( |
| 220 request_body.get(), &blob_storage_context, NULL, | 61 request_body.get(), &context, NULL, |
| 221 base::ThreadTaskRunnerHandle::Get().get())); | 62 base::ThreadTaskRunnerHandle::Get().get())); |
| 222 | 63 |
| 64 EXPECT_EQ(kIdentifier, upload->identifier()); |
| 223 ASSERT_TRUE(upload->GetElementReaders()); | 65 ASSERT_TRUE(upload->GetElementReaders()); |
| 224 ASSERT_EQ(2U, upload->GetElementReaders()->size()); | 66 ASSERT_EQ(request_body->elements()->size(), |
| 225 EXPECT_TRUE(AreElementsEqual( | 67 upload->GetElementReaders()->size()); |
| 226 *(*upload->GetElementReaders())[0], upload_element1)); | |
| 227 EXPECT_TRUE(AreElementsEqual( | |
| 228 *(*upload->GetElementReaders())[1], upload_element2)); | |
| 229 | 68 |
| 230 // Test having only one blob reference that refers to empty blob data. | 69 const net::UploadBytesElementReader* r1 = |
| 231 request_body = new ResourceRequestBody(); | 70 (*upload->GetElementReaders())[0]->AsBytesReader(); |
| 232 request_body->AppendBlob(blob_id0); | 71 ASSERT_TRUE(r1); |
| 72 EXPECT_EQ(kData, std::string(r1->bytes(), r1->length())); |
| 233 | 73 |
| 234 upload = UploadDataStreamBuilder::Build( | 74 const net::UploadFileElementReader* r2 = |
| 235 request_body.get(), &blob_storage_context, NULL, | 75 (*upload->GetElementReaders())[1]->AsFileReader(); |
| 236 base::ThreadTaskRunnerHandle::Get().get()); | 76 ASSERT_TRUE(r2); |
| 237 ASSERT_TRUE(upload->GetElementReaders()); | 77 EXPECT_EQ(kFilePath, r2->path().value()); |
| 238 ASSERT_EQ(0U, upload->GetElementReaders()->size()); | 78 EXPECT_EQ(kFileOffset, r2->range_offset()); |
| 79 EXPECT_EQ(kFileLength, r2->range_length()); |
| 80 EXPECT_EQ(kFileTime, r2->expected_modification_time()); |
| 239 | 81 |
| 240 // Test having only one blob reference. | 82 const storage::UploadBlobElementReader* r3 = |
| 241 request_body = new ResourceRequestBody(); | 83 static_cast<storage::UploadBlobElementReader*>( |
| 242 request_body->AppendBlob(blob_id1); | 84 (*upload->GetElementReaders())[2]); |
| 243 | 85 ASSERT_TRUE(r3); |
| 244 upload = UploadDataStreamBuilder::Build( | 86 EXPECT_EQ("blobuuid", r3->uuid()); |
| 245 request_body.get(), &blob_storage_context, NULL, | |
| 246 base::ThreadTaskRunnerHandle::Get().get()); | |
| 247 ASSERT_TRUE(upload->GetElementReaders()); | |
| 248 ASSERT_EQ(2U, upload->GetElementReaders()->size()); | |
| 249 EXPECT_TRUE(AreElementsEqual( | |
| 250 *(*upload->GetElementReaders())[0], blob_element1)); | |
| 251 EXPECT_TRUE(AreElementsEqual( | |
| 252 *(*upload->GetElementReaders())[1], blob_element2)); | |
| 253 | |
| 254 // Test having one blob reference which refers to a disk cache entry. | |
| 255 request_body = new ResourceRequestBody(); | |
| 256 request_body->AppendBlob(blob_id2); | |
| 257 | |
| 258 upload = UploadDataStreamBuilder::Build( | |
| 259 request_body.get(), &blob_storage_context, nullptr, | |
| 260 base::ThreadTaskRunnerHandle::Get().get()); | |
| 261 ASSERT_TRUE(upload->GetElementReaders()); | |
| 262 ASSERT_EQ(1U, upload->GetElementReaders()->size()); | |
| 263 EXPECT_TRUE(AreElementsEqual( | |
| 264 *(*upload->GetElementReaders())[0], blob_element3)); | |
| 265 | |
| 266 // Test having one blob reference at the beginning. | |
| 267 request_body = new ResourceRequestBody(); | |
| 268 request_body->AppendBlob(blob_id1); | |
| 269 request_body->AppendBytes( | |
| 270 upload_element1.bytes(), | |
| 271 upload_element1.length()); | |
| 272 request_body->AppendFileRange( | |
| 273 upload_element2.path(), | |
| 274 upload_element2.offset(), | |
| 275 upload_element2.length(), | |
| 276 upload_element2.expected_modification_time()); | |
| 277 | |
| 278 upload = UploadDataStreamBuilder::Build( | |
| 279 request_body.get(), &blob_storage_context, NULL, | |
| 280 base::ThreadTaskRunnerHandle::Get().get()); | |
| 281 ASSERT_TRUE(upload->GetElementReaders()); | |
| 282 ASSERT_EQ(4U, upload->GetElementReaders()->size()); | |
| 283 EXPECT_TRUE(AreElementsEqual( | |
| 284 *(*upload->GetElementReaders())[0], blob_element1)); | |
| 285 EXPECT_TRUE(AreElementsEqual( | |
| 286 *(*upload->GetElementReaders())[1], blob_element2)); | |
| 287 EXPECT_TRUE(AreElementsEqual( | |
| 288 *(*upload->GetElementReaders())[2], upload_element1)); | |
| 289 EXPECT_TRUE(AreElementsEqual( | |
| 290 *(*upload->GetElementReaders())[3], upload_element2)); | |
| 291 | |
| 292 // Test having one blob reference at the end. | |
| 293 request_body = new ResourceRequestBody(); | |
| 294 request_body->AppendBytes( | |
| 295 upload_element1.bytes(), | |
| 296 upload_element1.length()); | |
| 297 request_body->AppendFileRange( | |
| 298 upload_element2.path(), | |
| 299 upload_element2.offset(), | |
| 300 upload_element2.length(), | |
| 301 upload_element2.expected_modification_time()); | |
| 302 request_body->AppendBlob(blob_id1); | |
| 303 | |
| 304 upload = UploadDataStreamBuilder::Build( | |
| 305 request_body.get(), &blob_storage_context, NULL, | |
| 306 base::ThreadTaskRunnerHandle::Get().get()); | |
| 307 ASSERT_TRUE(upload->GetElementReaders()); | |
| 308 ASSERT_EQ(4U, upload->GetElementReaders()->size()); | |
| 309 EXPECT_TRUE(AreElementsEqual( | |
| 310 *(*upload->GetElementReaders())[0], upload_element1)); | |
| 311 EXPECT_TRUE(AreElementsEqual( | |
| 312 *(*upload->GetElementReaders())[1], upload_element2)); | |
| 313 EXPECT_TRUE(AreElementsEqual( | |
| 314 *(*upload->GetElementReaders())[2], blob_element1)); | |
| 315 EXPECT_TRUE(AreElementsEqual( | |
| 316 *(*upload->GetElementReaders())[3], blob_element2)); | |
| 317 | |
| 318 // Test having one blob reference in the middle. | |
| 319 request_body = new ResourceRequestBody(); | |
| 320 request_body->AppendBytes( | |
| 321 upload_element1.bytes(), | |
| 322 upload_element1.length()); | |
| 323 request_body->AppendBlob(blob_id1); | |
| 324 request_body->AppendFileRange( | |
| 325 upload_element2.path(), | |
| 326 upload_element2.offset(), | |
| 327 upload_element2.length(), | |
| 328 upload_element2.expected_modification_time()); | |
| 329 | |
| 330 upload = UploadDataStreamBuilder::Build( | |
| 331 request_body.get(), &blob_storage_context, NULL, | |
| 332 base::ThreadTaskRunnerHandle::Get().get()); | |
| 333 ASSERT_TRUE(upload->GetElementReaders()); | |
| 334 ASSERT_EQ(4U, upload->GetElementReaders()->size()); | |
| 335 EXPECT_TRUE(AreElementsEqual( | |
| 336 *(*upload->GetElementReaders())[0], upload_element1)); | |
| 337 EXPECT_TRUE(AreElementsEqual( | |
| 338 *(*upload->GetElementReaders())[1], blob_element1)); | |
| 339 EXPECT_TRUE(AreElementsEqual( | |
| 340 *(*upload->GetElementReaders())[2], blob_element2)); | |
| 341 EXPECT_TRUE(AreElementsEqual( | |
| 342 *(*upload->GetElementReaders())[3], upload_element2)); | |
| 343 | |
| 344 // Test having multiple blob references. | |
| 345 request_body = new ResourceRequestBody(); | |
| 346 request_body->AppendBlob(blob_id1); | |
| 347 request_body->AppendBytes( | |
| 348 upload_element1.bytes(), | |
| 349 upload_element1.length()); | |
| 350 request_body->AppendBlob(blob_id1); | |
| 351 request_body->AppendBlob(blob_id1); | |
| 352 request_body->AppendFileRange( | |
| 353 upload_element2.path(), | |
| 354 upload_element2.offset(), | |
| 355 upload_element2.length(), | |
| 356 upload_element2.expected_modification_time()); | |
| 357 | |
| 358 upload = UploadDataStreamBuilder::Build( | |
| 359 request_body.get(), &blob_storage_context, NULL, | |
| 360 base::ThreadTaskRunnerHandle::Get().get()); | |
| 361 ASSERT_TRUE(upload->GetElementReaders()); | |
| 362 ASSERT_EQ(8U, upload->GetElementReaders()->size()); | |
| 363 EXPECT_TRUE(AreElementsEqual( | |
| 364 *(*upload->GetElementReaders())[0], blob_element1)); | |
| 365 EXPECT_TRUE(AreElementsEqual( | |
| 366 *(*upload->GetElementReaders())[1], blob_element2)); | |
| 367 EXPECT_TRUE(AreElementsEqual( | |
| 368 *(*upload->GetElementReaders())[2], upload_element1)); | |
| 369 EXPECT_TRUE(AreElementsEqual( | |
| 370 *(*upload->GetElementReaders())[3], blob_element1)); | |
| 371 EXPECT_TRUE(AreElementsEqual( | |
| 372 *(*upload->GetElementReaders())[4], blob_element2)); | |
| 373 EXPECT_TRUE(AreElementsEqual( | |
| 374 *(*upload->GetElementReaders())[5], blob_element1)); | |
| 375 EXPECT_TRUE(AreElementsEqual( | |
| 376 *(*upload->GetElementReaders())[6], blob_element2)); | |
| 377 EXPECT_TRUE(AreElementsEqual( | |
| 378 *(*upload->GetElementReaders())[7], upload_element2)); | |
| 379 } | 87 } |
| 380 // Clean up for ASAN. | 88 // Clean up for ASAN. |
| 381 base::RunLoop().RunUntilIdle(); | 89 base::RunLoop().RunUntilIdle(); |
| 382 } | 90 } |
| 383 | 91 |
| 384 TEST(UploadDataStreamBuilderTest, | 92 TEST(UploadDataStreamBuilderTest, |
| 385 WriteUploadDataStreamWithEmptyFileBackedBlob) { | 93 WriteUploadDataStreamWithEmptyFileBackedBlob) { |
| 386 base::MessageLoopForIO message_loop; | 94 base::MessageLoopForIO message_loop; |
| 387 { | 95 { |
| 388 base::FilePath test_blob_path; | 96 base::FilePath test_blob_path; |
| 389 ASSERT_TRUE(base::CreateTemporaryFile(&test_blob_path)); | 97 ASSERT_TRUE(base::CreateTemporaryFile(&test_blob_path)); |
| 390 | 98 |
| 391 const uint64_t kZeroLength = 0; | 99 const uint64_t kZeroLength = 0; |
| 392 base::Time blob_time; | 100 base::Time blob_time; |
| 393 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &blob_time); | 101 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &blob_time); |
| 394 ASSERT_TRUE(base::TouchFile(test_blob_path, blob_time, blob_time)); | 102 ASSERT_TRUE(base::TouchFile(test_blob_path, blob_time, blob_time)); |
| 395 | 103 |
| 396 BlobStorageContext blob_storage_context; | 104 BlobStorageContext blob_storage_context; |
| 397 | 105 |
| 398 // A blob created from an empty file added several times. | 106 // A blob created from an empty file added several times. |
| 399 const std::string blob_id("id-0"); | 107 const std::string blob_id("id-0"); |
| 400 scoped_ptr<BlobDataBuilder> blob_data_builder(new BlobDataBuilder(blob_id)); | 108 scoped_ptr<BlobDataBuilder> blob_data_builder(new BlobDataBuilder(blob_id)); |
| 401 blob_data_builder->AppendFile(test_blob_path, 0, kZeroLength, blob_time); | 109 blob_data_builder->AppendFile(test_blob_path, 0, kZeroLength, blob_time); |
| 402 scoped_ptr<BlobDataHandle> handle = | 110 scoped_ptr<BlobDataHandle> handle = |
| 403 blob_storage_context.AddFinishedBlob(blob_data_builder.get()); | 111 blob_storage_context.AddFinishedBlob(blob_data_builder.get()); |
| 404 | 112 |
| 405 ResourceRequestBody::Element blob_element; | |
| 406 blob_element.SetToFilePathRange(test_blob_path, 0, kZeroLength, blob_time); | |
| 407 | |
| 408 scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody()); | 113 scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody()); |
| 409 scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build( | 114 scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build( |
| 410 request_body.get(), &blob_storage_context, NULL, | 115 request_body.get(), &blob_storage_context, NULL, |
| 411 base::ThreadTaskRunnerHandle::Get().get())); | 116 base::ThreadTaskRunnerHandle::Get().get())); |
| 412 | 117 |
| 413 request_body = new ResourceRequestBody(); | 118 request_body = new ResourceRequestBody(); |
| 414 request_body->AppendBlob(blob_id); | 119 request_body->AppendBlob(blob_id); |
| 415 request_body->AppendBlob(blob_id); | 120 request_body->AppendBlob(blob_id); |
| 416 request_body->AppendBlob(blob_id); | 121 request_body->AppendBlob(blob_id); |
| 417 | 122 |
| 418 upload = UploadDataStreamBuilder::Build( | 123 upload = UploadDataStreamBuilder::Build( |
| 419 request_body.get(), &blob_storage_context, NULL, | 124 request_body.get(), &blob_storage_context, NULL, |
| 420 base::ThreadTaskRunnerHandle::Get().get()); | 125 base::ThreadTaskRunnerHandle::Get().get()); |
| 421 ASSERT_TRUE(upload->GetElementReaders()); | 126 ASSERT_TRUE(upload->GetElementReaders()); |
| 422 const auto& readers = *upload->GetElementReaders(); | 127 const auto& readers = *upload->GetElementReaders(); |
| 423 ASSERT_EQ(3U, readers.size()); | 128 ASSERT_EQ(3U, readers.size()); |
| 424 EXPECT_TRUE(AreElementsEqual(*readers[0], blob_element)); | |
| 425 EXPECT_TRUE(AreElementsEqual(*readers[1], blob_element)); | |
| 426 EXPECT_TRUE(AreElementsEqual(*readers[2], blob_element)); | |
| 427 | 129 |
| 428 net::TestCompletionCallback init_callback; | 130 net::TestCompletionCallback init_callback; |
| 429 ASSERT_EQ(net::ERR_IO_PENDING, upload->Init(init_callback.callback())); | 131 ASSERT_EQ(net::ERR_IO_PENDING, upload->Init(init_callback.callback())); |
| 430 EXPECT_EQ(net::OK, init_callback.WaitForResult()); | 132 EXPECT_EQ(net::OK, init_callback.WaitForResult()); |
| 431 | 133 |
| 432 EXPECT_EQ(kZeroLength, upload->size()); | 134 EXPECT_EQ(kZeroLength, upload->size()); |
| 433 | 135 |
| 434 // Purposely (try to) read more than what is in the stream. If we try to | 136 // Purposely (try to) read more than what is in the stream. If we try to |
| 435 // read zero bytes then UploadDataStream::Read will fail a DCHECK. | 137 // read zero bytes then UploadDataStream::Read will fail a DCHECK. |
| 436 int kBufferLength = kZeroLength + 1; | 138 int kBufferLength = kZeroLength + 1; |
| 437 scoped_ptr<char[]> buffer(new char[kBufferLength]); | 139 scoped_ptr<char[]> buffer(new char[kBufferLength]); |
| 438 scoped_refptr<net::IOBuffer> io_buffer = | 140 scoped_refptr<net::IOBuffer> io_buffer = |
| 439 new net::WrappedIOBuffer(buffer.get()); | 141 new net::WrappedIOBuffer(buffer.get()); |
| 440 net::TestCompletionCallback read_callback; | 142 net::TestCompletionCallback read_callback; |
| 441 int result = | 143 int result = |
| 442 upload->Read(io_buffer.get(), kBufferLength, read_callback.callback()); | 144 upload->Read(io_buffer.get(), kBufferLength, read_callback.callback()); |
| 443 EXPECT_EQ(static_cast<int>(kZeroLength), read_callback.GetResult(result)); | 145 EXPECT_EQ(static_cast<int>(kZeroLength), read_callback.GetResult(result)); |
| 444 | 146 |
| 445 base::DeleteFile(test_blob_path, false); | 147 base::DeleteFile(test_blob_path, false); |
| 446 } | 148 } |
| 447 // Clean up for ASAN. | 149 // Clean up for ASAN. |
| 448 base::RunLoop().RunUntilIdle(); | 150 base::RunLoop().RunUntilIdle(); |
| 449 } | 151 } |
| 450 } // namespace content | 152 } // namespace content |
| OLD | NEW |