Home | History | Annotate | Download | only in fileapi
      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/fileapi/upload_file_system_file_element_reader.h"
      6 
      7 #include "base/files/scoped_temp_dir.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/run_loop.h"
     10 #include "content/public/test/async_file_test_helper.h"
     11 #include "content/public/test/test_file_system_context.h"
     12 #include "net/base/io_buffer.h"
     13 #include "net/base/test_completion_callback.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "webkit/browser/fileapi/file_system_backend.h"
     16 #include "webkit/browser/fileapi/file_system_context.h"
     17 #include "webkit/browser/fileapi/file_system_operation_context.h"
     18 #include "webkit/browser/fileapi/file_system_url.h"
     19 
     20 using content::AsyncFileTestHelper;
     21 using fileapi::FileSystemContext;
     22 using fileapi::FileSystemType;
     23 using fileapi::FileSystemURL;
     24 
     25 namespace content {
     26 
     27 namespace {
     28 
     29 const char kFileSystemURLOrigin[] = "http://remote";
     30 const fileapi::FileSystemType kFileSystemType =
     31     fileapi::kFileSystemTypeTemporary;
     32 
     33 }  // namespace
     34 
     35 class UploadFileSystemFileElementReaderTest : public testing::Test {
     36  public:
     37   UploadFileSystemFileElementReaderTest() {}
     38 
     39   virtual void SetUp() OVERRIDE {
     40     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     41 
     42     file_system_context_ = CreateFileSystemContextForTesting(
     43         NULL, temp_dir_.path());
     44 
     45     file_system_context_->OpenFileSystem(
     46         GURL(kFileSystemURLOrigin),
     47         kFileSystemType,
     48         fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
     49         base::Bind(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem,
     50                    base::Unretained(this)));
     51     base::RunLoop().RunUntilIdle();
     52     ASSERT_TRUE(file_system_root_url_.is_valid());
     53 
     54     // Prepare a file on file system.
     55     const char kTestData[] = "abcdefghijklmnop0123456789";
     56     file_data_.assign(kTestData, kTestData + arraysize(kTestData) - 1);
     57     const char kFilename[] = "File.dat";
     58     file_url_ = GetFileSystemURL(kFilename);
     59     WriteFileSystemFile(kFilename, &file_data_[0], file_data_.size(),
     60                         &file_modification_time_);
     61 
     62     // Create and initialize a reader.
     63     reader_.reset(
     64         new UploadFileSystemFileElementReader(file_system_context_.get(),
     65                                               file_url_,
     66                                               0,
     67                                               kuint64max,
     68                                               file_modification_time_));
     69     net::TestCompletionCallback callback;
     70     ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(callback.callback()));
     71     EXPECT_EQ(net::OK, callback.WaitForResult());
     72     EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
     73     EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
     74     EXPECT_FALSE(reader_->IsInMemory());
     75   }
     76 
     77  virtual void TearDown() OVERRIDE {
     78     reader_.reset();
     79     base::RunLoop().RunUntilIdle();
     80  }
     81 
     82  protected:
     83   GURL GetFileSystemURL(const std::string& filename) {
     84     return GURL(file_system_root_url_.spec() + filename);
     85   }
     86 
     87   void WriteFileSystemFile(const std::string& filename,
     88                            const char* buf,
     89                            int buf_size,
     90                            base::Time* modification_time) {
     91     fileapi::FileSystemURL url =
     92         file_system_context_->CreateCrackedFileSystemURL(
     93             GURL(kFileSystemURLOrigin),
     94             kFileSystemType,
     95             base::FilePath().AppendASCII(filename));
     96 
     97     ASSERT_EQ(base::File::FILE_OK,
     98               AsyncFileTestHelper::CreateFileWithData(
     99                   file_system_context_, url, buf, buf_size));
    100 
    101     base::File::Info file_info;
    102     ASSERT_EQ(base::File::FILE_OK,
    103               AsyncFileTestHelper::GetMetadata(
    104                   file_system_context_, url, &file_info));
    105     *modification_time = file_info.last_modified;
    106   }
    107 
    108   void OnOpenFileSystem(const GURL& root,
    109                         const std::string& name,
    110                         base::File::Error result) {
    111     ASSERT_EQ(base::File::FILE_OK, result);
    112     ASSERT_TRUE(root.is_valid());
    113     file_system_root_url_ = root;
    114   }
    115 
    116   base::MessageLoopForIO message_loop_;
    117   base::ScopedTempDir temp_dir_;
    118   scoped_refptr<FileSystemContext> file_system_context_;
    119   GURL file_system_root_url_;
    120   std::vector<char> file_data_;
    121   GURL file_url_;
    122   base::Time file_modification_time_;
    123   scoped_ptr<UploadFileSystemFileElementReader> reader_;
    124 };
    125 
    126 TEST_F(UploadFileSystemFileElementReaderTest, ReadAll) {
    127   scoped_refptr<net::IOBufferWithSize> buf =
    128       new net::IOBufferWithSize(file_data_.size());
    129   net::TestCompletionCallback read_callback;
    130   ASSERT_EQ(net::ERR_IO_PENDING,
    131             reader_->Read(buf.get(), buf->size(), read_callback.callback()));
    132   EXPECT_EQ(buf->size(), read_callback.WaitForResult());
    133   EXPECT_EQ(0U, reader_->BytesRemaining());
    134   EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
    135   // Try to read again.
    136   EXPECT_EQ(0, reader_->Read(buf.get(), buf->size(), read_callback.callback()));
    137 }
    138 
    139 TEST_F(UploadFileSystemFileElementReaderTest, ReadPartially) {
    140   const size_t kHalfSize = file_data_.size() / 2;
    141   ASSERT_EQ(file_data_.size(), kHalfSize * 2);
    142 
    143   scoped_refptr<net::IOBufferWithSize> buf =
    144       new net::IOBufferWithSize(kHalfSize);
    145 
    146   net::TestCompletionCallback read_callback1;
    147   ASSERT_EQ(net::ERR_IO_PENDING,
    148             reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
    149   EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
    150   EXPECT_EQ(file_data_.size() - buf->size(), reader_->BytesRemaining());
    151   EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + kHalfSize,
    152                          buf->data()));
    153 
    154   net::TestCompletionCallback read_callback2;
    155   EXPECT_EQ(net::ERR_IO_PENDING,
    156             reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
    157   EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
    158   EXPECT_EQ(0U, reader_->BytesRemaining());
    159   EXPECT_TRUE(std::equal(file_data_.begin() + kHalfSize, file_data_.end(),
    160                          buf->data()));
    161 }
    162 
    163 TEST_F(UploadFileSystemFileElementReaderTest, ReadTooMuch) {
    164   const size_t kTooLargeSize = file_data_.size() * 2;
    165   scoped_refptr<net::IOBufferWithSize> buf =
    166       new net::IOBufferWithSize(kTooLargeSize);
    167   net::TestCompletionCallback read_callback;
    168   ASSERT_EQ(net::ERR_IO_PENDING,
    169             reader_->Read(buf.get(), buf->size(), read_callback.callback()));
    170   EXPECT_EQ(static_cast<int>(file_data_.size()), read_callback.WaitForResult());
    171   EXPECT_EQ(0U, reader_->BytesRemaining());
    172   EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
    173 }
    174 
    175 TEST_F(UploadFileSystemFileElementReaderTest, MultipleInit) {
    176   scoped_refptr<net::IOBufferWithSize> buf =
    177       new net::IOBufferWithSize(file_data_.size());
    178 
    179   // Read all.
    180   net::TestCompletionCallback read_callback1;
    181   ASSERT_EQ(net::ERR_IO_PENDING,
    182             reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
    183   EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
    184   EXPECT_EQ(0U, reader_->BytesRemaining());
    185   EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
    186 
    187   // Call Init() again to reset the state.
    188   net::TestCompletionCallback init_callback;
    189   ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
    190   EXPECT_EQ(net::OK, init_callback.WaitForResult());
    191   EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
    192   EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
    193 
    194   // Read again.
    195   net::TestCompletionCallback read_callback2;
    196   ASSERT_EQ(net::ERR_IO_PENDING,
    197             reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
    198   EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
    199   EXPECT_EQ(0U, reader_->BytesRemaining());
    200   EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
    201 }
    202 
    203 TEST_F(UploadFileSystemFileElementReaderTest, InitDuringAsyncOperation) {
    204   scoped_refptr<net::IOBufferWithSize> buf =
    205       new net::IOBufferWithSize(file_data_.size());
    206 
    207   // Start reading all.
    208   net::TestCompletionCallback read_callback1;
    209   EXPECT_EQ(net::ERR_IO_PENDING,
    210             reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
    211 
    212   // Call Init to cancel the previous read.
    213   net::TestCompletionCallback init_callback1;
    214   EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback1.callback()));
    215 
    216   // Call Init again to cancel the previous init.
    217   net::TestCompletionCallback init_callback2;
    218   EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback2.callback()));
    219   EXPECT_EQ(net::OK, init_callback2.WaitForResult());
    220   EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
    221   EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
    222 
    223   // Read half.
    224   scoped_refptr<net::IOBufferWithSize> buf2 =
    225       new net::IOBufferWithSize(file_data_.size() / 2);
    226   net::TestCompletionCallback read_callback2;
    227   EXPECT_EQ(net::ERR_IO_PENDING,
    228             reader_->Read(buf2.get(), buf2->size(), read_callback2.callback()));
    229   EXPECT_EQ(buf2->size(), read_callback2.WaitForResult());
    230   EXPECT_EQ(file_data_.size() - buf2->size(), reader_->BytesRemaining());
    231   EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + buf2->size(),
    232                          buf2->data()));
    233 
    234   // Make sure callbacks are not called for cancelled operations.
    235   EXPECT_FALSE(read_callback1.have_result());
    236   EXPECT_FALSE(init_callback1.have_result());
    237 }
    238 
    239 TEST_F(UploadFileSystemFileElementReaderTest, Range) {
    240   const int kOffset = 2;
    241   const int kLength = file_data_.size() - kOffset * 3;
    242   reader_.reset(new UploadFileSystemFileElementReader(
    243       file_system_context_.get(), file_url_, kOffset, kLength, base::Time()));
    244   net::TestCompletionCallback init_callback;
    245   ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
    246   EXPECT_EQ(net::OK, init_callback.WaitForResult());
    247   EXPECT_EQ(static_cast<uint64>(kLength), reader_->GetContentLength());
    248   EXPECT_EQ(static_cast<uint64>(kLength), reader_->BytesRemaining());
    249   scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(kLength);
    250   net::TestCompletionCallback read_callback;
    251   ASSERT_EQ(net::ERR_IO_PENDING,
    252             reader_->Read(buf.get(), buf->size(), read_callback.callback()));
    253   EXPECT_EQ(kLength, read_callback.WaitForResult());
    254   EXPECT_TRUE(std::equal(file_data_.begin() + kOffset,
    255                          file_data_.begin() + kOffset + kLength,
    256                          buf->data()));
    257 }
    258 
    259 TEST_F(UploadFileSystemFileElementReaderTest, FileChanged) {
    260   // Expect one second before the actual modification time to simulate change.
    261   const base::Time expected_modification_time =
    262       file_modification_time_ - base::TimeDelta::FromSeconds(1);
    263   reader_.reset(
    264       new UploadFileSystemFileElementReader(file_system_context_.get(),
    265                                             file_url_,
    266                                             0,
    267                                             kuint64max,
    268                                             expected_modification_time));
    269   net::TestCompletionCallback init_callback;
    270   ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
    271   EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, init_callback.WaitForResult());
    272 }
    273 
    274 TEST_F(UploadFileSystemFileElementReaderTest, WrongURL) {
    275   const GURL wrong_url = GetFileSystemURL("wrong_file_name.dat");
    276   reader_.reset(new UploadFileSystemFileElementReader(
    277       file_system_context_.get(), wrong_url, 0, kuint64max, base::Time()));
    278   net::TestCompletionCallback init_callback;
    279   ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
    280   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, init_callback.WaitForResult());
    281 }
    282 
    283 }  // namespace content
    284