Home | History | Annotate | Download | only in loader
      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.
      4 
      5 #include "content/browser/loader/upload_data_stream_builder.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/files/file_path.h"
     10 #include "base/files/file_util.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/message_loop/message_loop_proxy.h"
     13 #include "base/run_loop.h"
     14 #include "base/time/time.h"
     15 #include "content/common/resource_request_body.h"
     16 #include "net/base/upload_bytes_element_reader.h"
     17 #include "net/base/upload_data_stream.h"
     18 #include "net/base/upload_file_element_reader.h"
     19 #include "storage/browser/blob/blob_storage_context.h"
     20 #include "testing/gtest/include/gtest/gtest.h"
     21 #include "url/gurl.h"
     22 
     23 using storage::BlobData;
     24 using storage::BlobDataHandle;
     25 using storage::BlobStorageContext;
     26 
     27 namespace content {
     28 namespace {
     29 
     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());
     40     }
     41     case ResourceRequestBody::Element::TYPE_FILE: {
     42       const net::UploadFileElementReader* file_reader = reader.AsFileReader();
     43       return file_reader &&
     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();
     49       break;
     50     }
     51     default:
     52       NOTREACHED();
     53   }
     54   return false;
     55 }
     56 
     57 }  // namespace
     58 
     59 TEST(UploadDataStreamBuilderTest, CreateUploadDataStreamWithoutBlob) {
     60   base::MessageLoop message_loop;
     61   scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody;
     62 
     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;
     69 
     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);
     74 
     75   scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
     76       request_body.get(), NULL, NULL, base::MessageLoopProxy::current().get()));
     77 
     78   EXPECT_EQ(kIdentifier, upload->identifier());
     79   ASSERT_EQ(request_body->elements()->size(), upload->element_readers().size());
     80 
     81   const net::UploadBytesElementReader* r1 =
     82       upload->element_readers()[0]->AsBytesReader();
     83   ASSERT_TRUE(r1);
     84   EXPECT_EQ(kData, std::string(r1->bytes(), r1->length()));
     85 
     86   const net::UploadFileElementReader* r2 =
     87       upload->element_readers()[1]->AsFileReader();
     88   ASSERT_TRUE(r2);
     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());
     93 }
     94 
     95 TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
     96   base::MessageLoop message_loop;
     97   {
     98     // Setup blob data for testing.
     99     base::Time time1, time2;
    100     base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1);
    101     base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2);
    102 
    103     BlobStorageContext blob_storage_context;
    104 
    105     const std::string blob_id0("id-0");
    106     scoped_refptr<BlobData> blob_data(new BlobData(blob_id0));
    107     scoped_ptr<BlobDataHandle> handle1 =
    108         blob_storage_context.AddFinishedBlob(blob_data.get());
    109 
    110     const std::string blob_id1("id-1");
    111     blob_data = new BlobData(blob_id1);
    112     blob_data->AppendData("BlobData");
    113     blob_data->AppendFile(
    114         base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1);
    115     scoped_ptr<BlobDataHandle> handle2 =
    116         blob_storage_context.AddFinishedBlob(blob_data.get());
    117 
    118     // Setup upload data elements for comparison.
    119     ResourceRequestBody::Element blob_element1, blob_element2;
    120     blob_element1.SetToBytes(
    121         blob_data->items().at(0).bytes() +
    122         static_cast<int>(blob_data->items().at(0).offset()),
    123         static_cast<int>(blob_data->items().at(0).length()));
    124     blob_element2.SetToFilePathRange(
    125         blob_data->items().at(1).path(),
    126         blob_data->items().at(1).offset(),
    127         blob_data->items().at(1).length(),
    128         blob_data->items().at(1).expected_modification_time());
    129 
    130     ResourceRequestBody::Element upload_element1, upload_element2;
    131     upload_element1.SetToBytes("Hello", 5);
    132     upload_element2.SetToFilePathRange(
    133         base::FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2);
    134 
    135     // Test no blob reference.
    136     scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
    137     request_body->AppendBytes(
    138         upload_element1.bytes(),
    139         upload_element1.length());
    140     request_body->AppendFileRange(
    141         upload_element2.path(),
    142         upload_element2.offset(),
    143         upload_element2.length(),
    144         upload_element2.expected_modification_time());
    145 
    146     scoped_ptr<net::UploadDataStream> upload(
    147         UploadDataStreamBuilder::Build(
    148             request_body.get(),
    149             &blob_storage_context,
    150             NULL,
    151             base::MessageLoopProxy::current().get()));
    152 
    153     ASSERT_EQ(2U, upload->element_readers().size());
    154     EXPECT_TRUE(AreElementsEqual(
    155         *upload->element_readers()[0], upload_element1));
    156     EXPECT_TRUE(AreElementsEqual(
    157         *upload->element_readers()[1], upload_element2));
    158 
    159     // Test having only one blob reference that refers to empty blob data.
    160     request_body = new ResourceRequestBody();
    161     request_body->AppendBlob(blob_id0);
    162 
    163     upload = UploadDataStreamBuilder::Build(
    164         request_body.get(),
    165         &blob_storage_context,
    166         NULL,
    167         base::MessageLoopProxy::current().get());
    168     ASSERT_EQ(0U, upload->element_readers().size());
    169 
    170     // Test having only one blob reference.
    171     request_body = new ResourceRequestBody();
    172     request_body->AppendBlob(blob_id1);
    173 
    174     upload = UploadDataStreamBuilder::Build(
    175         request_body.get(),
    176         &blob_storage_context,
    177         NULL,
    178         base::MessageLoopProxy::current().get());
    179     ASSERT_EQ(2U, upload->element_readers().size());
    180     EXPECT_TRUE(AreElementsEqual(
    181         *upload->element_readers()[0], blob_element1));
    182     EXPECT_TRUE(AreElementsEqual(
    183         *upload->element_readers()[1], blob_element2));
    184 
    185     // Test having one blob reference at the beginning.
    186     request_body = new ResourceRequestBody();
    187     request_body->AppendBlob(blob_id1);
    188     request_body->AppendBytes(
    189         upload_element1.bytes(),
    190         upload_element1.length());
    191     request_body->AppendFileRange(
    192         upload_element2.path(),
    193         upload_element2.offset(),
    194         upload_element2.length(),
    195         upload_element2.expected_modification_time());
    196 
    197     upload = UploadDataStreamBuilder::Build(
    198         request_body.get(),
    199         &blob_storage_context,
    200         NULL,
    201         base::MessageLoopProxy::current().get());
    202     ASSERT_EQ(4U, upload->element_readers().size());
    203     EXPECT_TRUE(AreElementsEqual(
    204         *upload->element_readers()[0], blob_element1));
    205     EXPECT_TRUE(AreElementsEqual(
    206         *upload->element_readers()[1], blob_element2));
    207     EXPECT_TRUE(AreElementsEqual(
    208         *upload->element_readers()[2], upload_element1));
    209     EXPECT_TRUE(AreElementsEqual(
    210         *upload->element_readers()[3], upload_element2));
    211 
    212     // Test having one blob reference at the end.
    213     request_body = new ResourceRequestBody();
    214     request_body->AppendBytes(
    215         upload_element1.bytes(),
    216         upload_element1.length());
    217     request_body->AppendFileRange(
    218         upload_element2.path(),
    219         upload_element2.offset(),
    220         upload_element2.length(),
    221         upload_element2.expected_modification_time());
    222     request_body->AppendBlob(blob_id1);
    223 
    224     upload =
    225         UploadDataStreamBuilder::Build(request_body.get(),
    226                                        &blob_storage_context,
    227                                        NULL,
    228                                        base::MessageLoopProxy::current().get());
    229     ASSERT_EQ(4U, upload->element_readers().size());
    230     EXPECT_TRUE(AreElementsEqual(
    231         *upload->element_readers()[0], upload_element1));
    232     EXPECT_TRUE(AreElementsEqual(
    233         *upload->element_readers()[1], upload_element2));
    234     EXPECT_TRUE(AreElementsEqual(
    235         *upload->element_readers()[2], blob_element1));
    236     EXPECT_TRUE(AreElementsEqual(
    237           *upload->element_readers()[3], blob_element2));
    238 
    239     // Test having one blob reference in the middle.
    240     request_body = new ResourceRequestBody();
    241     request_body->AppendBytes(
    242         upload_element1.bytes(),
    243         upload_element1.length());
    244     request_body->AppendBlob(blob_id1);
    245     request_body->AppendFileRange(
    246         upload_element2.path(),
    247         upload_element2.offset(),
    248         upload_element2.length(),
    249         upload_element2.expected_modification_time());
    250 
    251     upload = UploadDataStreamBuilder::Build(
    252         request_body.get(),
    253         &blob_storage_context,
    254         NULL,
    255         base::MessageLoopProxy::current().get());
    256     ASSERT_EQ(4U, upload->element_readers().size());
    257     EXPECT_TRUE(AreElementsEqual(
    258         *upload->element_readers()[0], upload_element1));
    259     EXPECT_TRUE(AreElementsEqual(
    260         *upload->element_readers()[1], blob_element1));
    261     EXPECT_TRUE(AreElementsEqual(
    262         *upload->element_readers()[2], blob_element2));
    263     EXPECT_TRUE(AreElementsEqual(
    264         *upload->element_readers()[3], upload_element2));
    265 
    266     // Test having multiple blob references.
    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->AppendBlob(blob_id1);
    273     request_body->AppendBlob(blob_id1);
    274     request_body->AppendFileRange(
    275         upload_element2.path(),
    276         upload_element2.offset(),
    277         upload_element2.length(),
    278         upload_element2.expected_modification_time());
    279 
    280     upload = UploadDataStreamBuilder::Build(
    281         request_body.get(),
    282         &blob_storage_context,
    283         NULL,
    284         base::MessageLoopProxy::current().get());
    285     ASSERT_EQ(8U, upload->element_readers().size());
    286     EXPECT_TRUE(AreElementsEqual(
    287         *upload->element_readers()[0], blob_element1));
    288     EXPECT_TRUE(AreElementsEqual(
    289         *upload->element_readers()[1], blob_element2));
    290     EXPECT_TRUE(AreElementsEqual(
    291         *upload->element_readers()[2], upload_element1));
    292     EXPECT_TRUE(AreElementsEqual(
    293         *upload->element_readers()[3], blob_element1));
    294     EXPECT_TRUE(AreElementsEqual(
    295         *upload->element_readers()[4], blob_element2));
    296     EXPECT_TRUE(AreElementsEqual(
    297         *upload->element_readers()[5], blob_element1));
    298     EXPECT_TRUE(AreElementsEqual(
    299         *upload->element_readers()[6], blob_element2));
    300     EXPECT_TRUE(AreElementsEqual(
    301         *upload->element_readers()[7], upload_element2));
    302   }
    303   // Clean up for ASAN.
    304   base::RunLoop().RunUntilIdle();
    305 }
    306 
    307 }  // namespace content
    308