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