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 "webkit/browser/fileapi/file_system_file_stream_reader.h"
      6 
      7 #include <limits>
      8 #include <string>
      9 
     10 #include "base/files/scoped_temp_dir.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/platform_file.h"
     13 #include "base/run_loop.h"
     14 #include "content/public/test/test_file_system_context.h"
     15 #include "net/base/io_buffer.h"
     16 #include "net/base/net_errors.h"
     17 #include "net/base/test_completion_callback.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 #include "webkit/browser/fileapi/async_file_test_helper.h"
     20 #include "webkit/browser/fileapi/external_mount_points.h"
     21 #include "webkit/browser/fileapi/file_system_context.h"
     22 #include "webkit/browser/fileapi/file_system_file_util.h"
     23 
     24 namespace fileapi {
     25 
     26 namespace {
     27 
     28 const char kURLOrigin[] = "http://remote/";
     29 const char kTestFileName[] = "test.dat";
     30 const char kTestData[] = "0123456789";
     31 const int kTestDataSize = arraysize(kTestData) - 1;
     32 
     33 void ReadFromReader(FileSystemFileStreamReader* reader,
     34                     std::string* data,
     35                     size_t size,
     36                     int* result) {
     37   ASSERT_TRUE(reader != NULL);
     38   ASSERT_TRUE(result != NULL);
     39   *result = net::OK;
     40   net::TestCompletionCallback callback;
     41   size_t total_bytes_read = 0;
     42   while (total_bytes_read < size) {
     43     scoped_refptr<net::IOBufferWithSize> buf(
     44         new net::IOBufferWithSize(size - total_bytes_read));
     45     int rv = reader->Read(buf.get(), buf->size(), callback.callback());
     46     if (rv == net::ERR_IO_PENDING)
     47       rv = callback.WaitForResult();
     48     if (rv < 0)
     49       *result = rv;
     50     if (rv <= 0)
     51       break;
     52     total_bytes_read += rv;
     53     data->append(buf->data(), rv);
     54   }
     55 }
     56 
     57 void NeverCalled(int unused) { ADD_FAILURE(); }
     58 
     59 }  // namespace
     60 
     61 class FileSystemFileStreamReaderTest : public testing::Test {
     62  public:
     63   FileSystemFileStreamReaderTest() {}
     64 
     65   virtual void SetUp() OVERRIDE {
     66     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     67 
     68     file_system_context_ = CreateFileSystemContextForTesting(
     69         NULL, temp_dir_.path());
     70 
     71     file_system_context_->OpenFileSystem(
     72         GURL(kURLOrigin), kFileSystemTypeTemporary,
     73         OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
     74         base::Bind(&OnOpenFileSystem));
     75     base::RunLoop().RunUntilIdle();
     76 
     77     WriteFile(kTestFileName, kTestData, kTestDataSize,
     78               &test_file_modification_time_);
     79   }
     80 
     81   virtual void TearDown() OVERRIDE {
     82     base::RunLoop().RunUntilIdle();
     83   }
     84 
     85  protected:
     86   FileSystemFileStreamReader* CreateFileReader(
     87       const std::string& file_name,
     88       int64 initial_offset,
     89       const base::Time& expected_modification_time) {
     90     return new FileSystemFileStreamReader(file_system_context_.get(),
     91                                           GetFileSystemURL(file_name),
     92                                           initial_offset,
     93                                           expected_modification_time);
     94   }
     95 
     96   base::Time test_file_modification_time() const {
     97     return test_file_modification_time_;
     98   }
     99 
    100   void WriteFile(const std::string& file_name,
    101                  const char* buf,
    102                  int buf_size,
    103                  base::Time* modification_time) {
    104     FileSystemURL url = GetFileSystemURL(file_name);
    105 
    106     ASSERT_EQ(base::PLATFORM_FILE_OK,
    107               fileapi::AsyncFileTestHelper::CreateFileWithData(
    108                   file_system_context_, url, buf, buf_size));
    109 
    110     base::PlatformFileInfo file_info;
    111     ASSERT_EQ(base::PLATFORM_FILE_OK,
    112               AsyncFileTestHelper::GetMetadata(
    113                   file_system_context_, url, &file_info));
    114     if (modification_time)
    115       *modification_time = file_info.last_modified;
    116   }
    117 
    118  private:
    119   static void OnOpenFileSystem(const GURL& root_url,
    120                                const std::string& name,
    121                                base::PlatformFileError result) {
    122     ASSERT_EQ(base::PLATFORM_FILE_OK, result);
    123   }
    124 
    125   FileSystemURL GetFileSystemURL(const std::string& file_name) {
    126     return file_system_context_->CreateCrackedFileSystemURL(
    127         GURL(kURLOrigin),
    128         kFileSystemTypeTemporary,
    129         base::FilePath().AppendASCII(file_name));
    130   }
    131 
    132   base::MessageLoopForIO message_loop_;
    133   base::ScopedTempDir temp_dir_;
    134   scoped_refptr<FileSystemContext> file_system_context_;
    135   base::Time test_file_modification_time_;
    136 };
    137 
    138 TEST_F(FileSystemFileStreamReaderTest, NonExistent) {
    139   const char kFileName[] = "nonexistent";
    140   scoped_ptr<FileSystemFileStreamReader> reader(
    141       CreateFileReader(kFileName, 0, base::Time()));
    142   int result = 0;
    143   std::string data;
    144   ReadFromReader(reader.get(), &data, 10, &result);
    145   ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result);
    146   ASSERT_EQ(0U, data.size());
    147 }
    148 
    149 TEST_F(FileSystemFileStreamReaderTest, Empty) {
    150   const char kFileName[] = "empty";
    151   WriteFile(kFileName, NULL, 0, NULL);
    152 
    153   scoped_ptr<FileSystemFileStreamReader> reader(
    154       CreateFileReader(kFileName, 0, base::Time()));
    155   int result = 0;
    156   std::string data;
    157   ReadFromReader(reader.get(), &data, 10, &result);
    158   ASSERT_EQ(net::OK, result);
    159   ASSERT_EQ(0U, data.size());
    160 
    161   net::TestInt64CompletionCallback callback;
    162   int64 length_result = reader->GetLength(callback.callback());
    163   if (length_result == net::ERR_IO_PENDING)
    164     length_result = callback.WaitForResult();
    165   ASSERT_EQ(0, length_result);
    166 }
    167 
    168 TEST_F(FileSystemFileStreamReaderTest, GetLengthNormal) {
    169   scoped_ptr<FileSystemFileStreamReader> reader(
    170       CreateFileReader(kTestFileName, 0, test_file_modification_time()));
    171   net::TestInt64CompletionCallback callback;
    172   int64 result = reader->GetLength(callback.callback());
    173   if (result == net::ERR_IO_PENDING)
    174     result = callback.WaitForResult();
    175   ASSERT_EQ(kTestDataSize, result);
    176 }
    177 
    178 TEST_F(FileSystemFileStreamReaderTest, GetLengthAfterModified) {
    179   // Pass a fake expected modifictaion time so that the expectation fails.
    180   base::Time fake_expected_modification_time =
    181       test_file_modification_time() - base::TimeDelta::FromSeconds(10);
    182 
    183   scoped_ptr<FileSystemFileStreamReader> reader(
    184       CreateFileReader(kTestFileName, 0, fake_expected_modification_time));
    185   net::TestInt64CompletionCallback callback;
    186   int64 result = reader->GetLength(callback.callback());
    187   if (result == net::ERR_IO_PENDING)
    188     result = callback.WaitForResult();
    189   ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
    190 
    191   // With NULL expected modification time this should work.
    192   reader.reset(CreateFileReader(kTestFileName, 0, base::Time()));
    193   result = reader->GetLength(callback.callback());
    194   if (result == net::ERR_IO_PENDING)
    195     result = callback.WaitForResult();
    196   ASSERT_EQ(kTestDataSize, result);
    197 }
    198 
    199 TEST_F(FileSystemFileStreamReaderTest, GetLengthWithOffset) {
    200   scoped_ptr<FileSystemFileStreamReader> reader(
    201       CreateFileReader(kTestFileName, 3, base::Time()));
    202   net::TestInt64CompletionCallback callback;
    203   int64 result = reader->GetLength(callback.callback());
    204   if (result == net::ERR_IO_PENDING)
    205     result = callback.WaitForResult();
    206   // Initial offset does not affect the result of GetLength.
    207   ASSERT_EQ(kTestDataSize, result);
    208 }
    209 
    210 TEST_F(FileSystemFileStreamReaderTest, ReadNormal) {
    211   scoped_ptr<FileSystemFileStreamReader> reader(
    212       CreateFileReader(kTestFileName, 0, test_file_modification_time()));
    213   int result = 0;
    214   std::string data;
    215   ReadFromReader(reader.get(), &data, kTestDataSize, &result);
    216   ASSERT_EQ(net::OK, result);
    217   ASSERT_EQ(kTestData, data);
    218 }
    219 
    220 TEST_F(FileSystemFileStreamReaderTest, ReadAfterModified) {
    221   // Pass a fake expected modifictaion time so that the expectation fails.
    222   base::Time fake_expected_modification_time =
    223       test_file_modification_time() - base::TimeDelta::FromSeconds(10);
    224 
    225   scoped_ptr<FileSystemFileStreamReader> reader(
    226       CreateFileReader(kTestFileName, 0, fake_expected_modification_time));
    227   int result = 0;
    228   std::string data;
    229   ReadFromReader(reader.get(), &data, kTestDataSize, &result);
    230   ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
    231   ASSERT_EQ(0U, data.size());
    232 
    233   // With NULL expected modification time this should work.
    234   data.clear();
    235   reader.reset(CreateFileReader(kTestFileName, 0, base::Time()));
    236   ReadFromReader(reader.get(), &data, kTestDataSize, &result);
    237   ASSERT_EQ(net::OK, result);
    238   ASSERT_EQ(kTestData, data);
    239 }
    240 
    241 TEST_F(FileSystemFileStreamReaderTest, ReadWithOffset) {
    242   scoped_ptr<FileSystemFileStreamReader> reader(
    243       CreateFileReader(kTestFileName, 3, base::Time()));
    244   int result = 0;
    245   std::string data;
    246   ReadFromReader(reader.get(), &data, kTestDataSize, &result);
    247   ASSERT_EQ(net::OK, result);
    248   ASSERT_EQ(&kTestData[3], data);
    249 }
    250 
    251 TEST_F(FileSystemFileStreamReaderTest, DeleteWithUnfinishedRead) {
    252   scoped_ptr<FileSystemFileStreamReader> reader(
    253       CreateFileReader(kTestFileName, 0, base::Time()));
    254 
    255   net::TestCompletionCallback callback;
    256   scoped_refptr<net::IOBufferWithSize> buf(
    257       new net::IOBufferWithSize(kTestDataSize));
    258   int rv = reader->Read(buf.get(), buf->size(), base::Bind(&NeverCalled));
    259   ASSERT_TRUE(rv == net::ERR_IO_PENDING || rv >= 0);
    260 
    261   // Delete immediately.
    262   // Should not crash; nor should NeverCalled be callback.
    263   reader.reset();
    264 }
    265 
    266 }  // namespace fileapi
    267