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" |
21 #include "net/base/upload_file_element_reader.h" | 22 #include "net/base/upload_file_element_reader.h" |
| 23 #include "net/disk_cache/disk_cache.h" |
22 #include "storage/browser/blob/blob_data_builder.h" | 24 #include "storage/browser/blob/blob_data_builder.h" |
23 #include "storage/browser/blob/blob_storage_context.h" | 25 #include "storage/browser/blob/blob_storage_context.h" |
24 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
25 #include "url/gurl.h" | 27 #include "url/gurl.h" |
26 | 28 |
27 using storage::BlobDataBuilder; | 29 using storage::BlobDataBuilder; |
28 using storage::BlobDataHandle; | 30 using storage::BlobDataHandle; |
29 using storage::BlobStorageContext; | 31 using storage::BlobStorageContext; |
30 | 32 |
31 namespace content { | 33 namespace content { |
32 namespace { | 34 namespace { |
33 | 35 |
| 36 const int kTestDiskCacheStreamIndex = 0; |
| 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 cb; |
| 48 int rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE, |
| 49 net::CACHE_BACKEND_DEFAULT, |
| 50 base::FilePath(), 0, |
| 51 false, NULL, NULL, &cache, |
| 52 cb.callback()); |
| 53 EXPECT_EQ(net::OK, cb.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* tmp_entry = nullptr; |
| 62 net::TestCompletionCallback cb; |
| 63 int rv = cache->CreateEntry(key, &tmp_entry, cb.callback()); |
| 64 if (cb.GetResult(rv) != net::OK) |
| 65 return nullptr; |
| 66 disk_cache::ScopedEntryPtr entry(tmp_entry); |
| 67 |
| 68 scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data); |
| 69 rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(), |
| 70 iobuffer->size(), cb.callback(), false); |
| 71 EXPECT_EQ(static_cast<int>(data.size()), cb.GetResult(rv)); |
| 72 return entry.Pass(); |
| 73 } |
| 74 |
34 bool AreElementsEqual(const net::UploadElementReader& reader, | 75 bool AreElementsEqual(const net::UploadElementReader& reader, |
35 const ResourceRequestBody::Element& element) { | 76 const ResourceRequestBody::Element& element) { |
36 switch(element.type()) { | 77 switch(element.type()) { |
37 case ResourceRequestBody::Element::TYPE_BYTES: { | 78 case ResourceRequestBody::Element::TYPE_BYTES: { |
38 const net::UploadBytesElementReader* bytes_reader = | 79 const net::UploadBytesElementReader* bytes_reader = |
39 reader.AsBytesReader(); | 80 reader.AsBytesReader(); |
40 return bytes_reader && | 81 return bytes_reader && |
41 element.length() == bytes_reader->length() && | 82 element.length() == bytes_reader->length() && |
42 std::equal(element.bytes(), element.bytes() + element.length(), | 83 std::equal(element.bytes(), element.bytes() + element.length(), |
43 bytes_reader->bytes()); | 84 bytes_reader->bytes()); |
44 } | 85 } |
45 case ResourceRequestBody::Element::TYPE_FILE: { | 86 case ResourceRequestBody::Element::TYPE_FILE: { |
46 const net::UploadFileElementReader* file_reader = reader.AsFileReader(); | 87 const net::UploadFileElementReader* file_reader = reader.AsFileReader(); |
47 return file_reader && | 88 return file_reader && |
48 file_reader->path() == element.path() && | 89 file_reader->path() == element.path() && |
49 file_reader->range_offset() == element.offset() && | 90 file_reader->range_offset() == element.offset() && |
50 file_reader->range_length() == element.length() && | 91 file_reader->range_length() == element.length() && |
51 file_reader->expected_modification_time() == | 92 file_reader->expected_modification_time() == |
52 element.expected_modification_time(); | 93 element.expected_modification_time(); |
53 break; | 94 break; |
54 } | 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 } |
55 default: | 109 default: |
56 NOTREACHED(); | 110 NOTREACHED(); |
57 } | 111 } |
58 return false; | 112 return false; |
59 } | 113 } |
60 | 114 |
61 } // namespace | 115 } // namespace |
62 | 116 |
63 TEST(UploadDataStreamBuilderTest, CreateUploadDataStreamWithoutBlob) { | 117 TEST(UploadDataStreamBuilderTest, CreateUploadDataStreamWithoutBlob) { |
64 base::MessageLoop message_loop; | 118 base::MessageLoop message_loop; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 | 171 |
118 const std::string blob_id1("id-1"); | 172 const std::string blob_id1("id-1"); |
119 const std::string kBlobData = "BlobData"; | 173 const std::string kBlobData = "BlobData"; |
120 blob_data_builder.reset(new BlobDataBuilder(blob_id1)); | 174 blob_data_builder.reset(new BlobDataBuilder(blob_id1)); |
121 blob_data_builder->AppendData(kBlobData); | 175 blob_data_builder->AppendData(kBlobData); |
122 blob_data_builder->AppendFile( | 176 blob_data_builder->AppendFile( |
123 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1); | 177 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1); |
124 scoped_ptr<BlobDataHandle> handle2 = | 178 scoped_ptr<BlobDataHandle> handle2 = |
125 blob_storage_context.AddFinishedBlob(blob_data_builder.get()); | 179 blob_storage_context.AddFinishedBlob(blob_data_builder.get()); |
126 | 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 |
127 // Setup upload data elements for comparison. | 196 // Setup upload data elements for comparison. |
128 ResourceRequestBody::Element blob_element1, blob_element2; | 197 ResourceRequestBody::Element blob_element1, blob_element2, blob_element3; |
129 blob_element1.SetToBytes(kBlobData.c_str(), kBlobData.size()); | 198 blob_element1.SetToBytes(kBlobData.c_str(), kBlobData.size()); |
130 blob_element2.SetToFilePathRange( | 199 blob_element2.SetToFilePathRange( |
131 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1); | 200 base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1); |
| 201 blob_element3.SetToDiskCacheEntryRange(0, kDiskCacheData.size()); |
132 | 202 |
133 ResourceRequestBody::Element upload_element1, upload_element2; | 203 ResourceRequestBody::Element upload_element1, upload_element2; |
134 upload_element1.SetToBytes("Hello", 5); | 204 upload_element1.SetToBytes("Hello", 5); |
135 upload_element2.SetToFilePathRange( | 205 upload_element2.SetToFilePathRange( |
136 base::FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2); | 206 base::FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2); |
137 | 207 |
138 // Test no blob reference. | 208 // Test no blob reference. |
139 scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody()); | 209 scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody()); |
140 request_body->AppendBytes( | 210 request_body->AppendBytes( |
141 upload_element1.bytes(), | 211 upload_element1.bytes(), |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 upload = UploadDataStreamBuilder::Build( | 244 upload = UploadDataStreamBuilder::Build( |
175 request_body.get(), &blob_storage_context, NULL, | 245 request_body.get(), &blob_storage_context, NULL, |
176 base::ThreadTaskRunnerHandle::Get().get()); | 246 base::ThreadTaskRunnerHandle::Get().get()); |
177 ASSERT_TRUE(upload->GetElementReaders()); | 247 ASSERT_TRUE(upload->GetElementReaders()); |
178 ASSERT_EQ(2U, upload->GetElementReaders()->size()); | 248 ASSERT_EQ(2U, upload->GetElementReaders()->size()); |
179 EXPECT_TRUE(AreElementsEqual( | 249 EXPECT_TRUE(AreElementsEqual( |
180 *(*upload->GetElementReaders())[0], blob_element1)); | 250 *(*upload->GetElementReaders())[0], blob_element1)); |
181 EXPECT_TRUE(AreElementsEqual( | 251 EXPECT_TRUE(AreElementsEqual( |
182 *(*upload->GetElementReaders())[1], blob_element2)); | 252 *(*upload->GetElementReaders())[1], blob_element2)); |
183 | 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, NULL, |
| 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 |
184 // Test having one blob reference at the beginning. | 266 // Test having one blob reference at the beginning. |
185 request_body = new ResourceRequestBody(); | 267 request_body = new ResourceRequestBody(); |
186 request_body->AppendBlob(blob_id1); | 268 request_body->AppendBlob(blob_id1); |
187 request_body->AppendBytes( | 269 request_body->AppendBytes( |
188 upload_element1.bytes(), | 270 upload_element1.bytes(), |
189 upload_element1.length()); | 271 upload_element1.length()); |
190 request_body->AppendFileRange( | 272 request_body->AppendFileRange( |
191 upload_element2.path(), | 273 upload_element2.path(), |
192 upload_element2.offset(), | 274 upload_element2.offset(), |
193 upload_element2.length(), | 275 upload_element2.length(), |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 int result = | 441 int result = |
360 upload->Read(io_buffer.get(), kBufferLength, read_callback.callback()); | 442 upload->Read(io_buffer.get(), kBufferLength, read_callback.callback()); |
361 EXPECT_EQ(static_cast<int>(kZeroLength), read_callback.GetResult(result)); | 443 EXPECT_EQ(static_cast<int>(kZeroLength), read_callback.GetResult(result)); |
362 | 444 |
363 base::DeleteFile(test_blob_path, false); | 445 base::DeleteFile(test_blob_path, false); |
364 } | 446 } |
365 // Clean up for ASAN. | 447 // Clean up for ASAN. |
366 base::RunLoop().RunUntilIdle(); | 448 base::RunLoop().RunUntilIdle(); |
367 } | 449 } |
368 } // namespace content | 450 } // namespace content |
OLD | NEW |