Home | History | Annotate | Download | only in fileapi
      1 // Copyright 2014 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 <string>
      6 #include <vector>
      7 
      8 #include "base/files/file.h"
      9 #include "base/files/file_path.h"
     10 #include "base/files/scoped_temp_dir.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/memory/weak_ptr.h"
     13 #include "base/platform_file.h"
     14 #include "base/run_loop.h"
     15 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
     16 #include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.h"
     17 #include "chrome/browser/chromeos/file_system_provider/service.h"
     18 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
     19 #include "chrome/test/base/testing_browser_process.h"
     20 #include "chrome/test/base/testing_profile.h"
     21 #include "chrome/test/base/testing_profile_manager.h"
     22 #include "content/public/test/test_browser_thread_bundle.h"
     23 #include "content/public/test/test_file_system_context.h"
     24 #include "extensions/browser/extension_registry.h"
     25 #include "net/base/io_buffer.h"
     26 #include "net/base/net_errors.h"
     27 #include "testing/gtest/include/gtest/gtest.h"
     28 #include "webkit/browser/fileapi/async_file_util.h"
     29 #include "webkit/browser/fileapi/external_mount_points.h"
     30 #include "webkit/browser/fileapi/file_system_url.h"
     31 
     32 namespace chromeos {
     33 namespace file_system_provider {
     34 namespace {
     35 
     36 const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
     37 const char kFileSystemId[] = "testing-file-system";
     38 
     39 // Logs callbacks invocations on the file stream reader.
     40 class EventLogger {
     41  public:
     42   EventLogger() : weak_ptr_factory_(this) {}
     43   virtual ~EventLogger() {}
     44 
     45   void OnRead(int result) { results_.push_back(result); }
     46   void OnGetLength(int64 result) { results_.push_back(result); }
     47 
     48   base::WeakPtr<EventLogger> GetWeakPtr() {
     49     return weak_ptr_factory_.GetWeakPtr();
     50   }
     51 
     52   const std::vector<int64>& results() const { return results_; }
     53 
     54  private:
     55   std::vector<int64> results_;
     56   base::WeakPtrFactory<EventLogger> weak_ptr_factory_;
     57 
     58   DISALLOW_COPY_AND_ASSIGN(EventLogger);
     59 };
     60 
     61 // Creates a cracked FileSystemURL for tests.
     62 fileapi::FileSystemURL CreateFileSystemURL(const std::string& mount_point_name,
     63                                            const base::FilePath& file_path) {
     64   const std::string origin = std::string("chrome-extension://") + kExtensionId;
     65   const fileapi::ExternalMountPoints* const mount_points =
     66       fileapi::ExternalMountPoints::GetSystemInstance();
     67   return mount_points->CreateCrackedFileSystemURL(
     68       GURL(origin),
     69       fileapi::kFileSystemTypeExternal,
     70       base::FilePath::FromUTF8Unsafe(mount_point_name).Append(file_path));
     71 }
     72 
     73 // Creates a Service instance. Used to be able to destroy the service in
     74 // TearDown().
     75 KeyedService* CreateService(content::BrowserContext* context) {
     76   return new Service(Profile::FromBrowserContext(context),
     77                      extensions::ExtensionRegistry::Get(context));
     78 }
     79 
     80 }  // namespace
     81 
     82 class FileSystemProviderFileStreamReader : public testing::Test {
     83  protected:
     84   FileSystemProviderFileStreamReader() {}
     85   virtual ~FileSystemProviderFileStreamReader() {}
     86 
     87   virtual void SetUp() OVERRIDE {
     88     ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
     89     profile_manager_.reset(
     90         new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
     91     ASSERT_TRUE(profile_manager_->SetUp());
     92     profile_ = profile_manager_->CreateTestingProfile("testing-profile");
     93 
     94     ServiceFactory::GetInstance()->SetTestingFactory(profile_, &CreateService);
     95     Service* service = Service::Get(profile_);  // Owned by its factory.
     96     service->SetFileSystemFactoryForTesting(
     97         base::Bind(&FakeProvidedFileSystem::Create));
     98 
     99     const bool result = service->MountFileSystem(
    100         kExtensionId, kFileSystemId, "Testing File System");
    101     ASSERT_TRUE(result);
    102     const ProvidedFileSystemInfo& file_system_info =
    103         service->GetProvidedFileSystem(kExtensionId, kFileSystemId)
    104             ->GetFileSystemInfo();
    105     const std::string mount_point_name =
    106         file_system_info.mount_path().BaseName().AsUTF8Unsafe();
    107 
    108     file_url_ = CreateFileSystemURL(
    109         mount_point_name, base::FilePath::FromUTF8Unsafe(kFakeFilePath + 1));
    110     ASSERT_TRUE(file_url_.is_valid());
    111     wrong_file_url_ = CreateFileSystemURL(
    112         mount_point_name, base::FilePath::FromUTF8Unsafe("im-not-here.txt"));
    113     ASSERT_TRUE(wrong_file_url_.is_valid());
    114   }
    115 
    116   virtual void TearDown() OVERRIDE {
    117     // Setting the testing factory to NULL will destroy the created service
    118     // associated with the testing profile.
    119     ServiceFactory::GetInstance()->SetTestingFactory(profile_, NULL);
    120   }
    121 
    122   content::TestBrowserThreadBundle thread_bundle_;
    123   base::ScopedTempDir data_dir_;
    124   scoped_ptr<TestingProfileManager> profile_manager_;
    125   TestingProfile* profile_;  // Owned by TestingProfileManager.
    126   fileapi::FileSystemURL file_url_;
    127   fileapi::FileSystemURL wrong_file_url_;
    128 };
    129 
    130 TEST_F(FileSystemProviderFileStreamReader, Read_AllAtOnce) {
    131   EventLogger logger;
    132 
    133   const int64 initial_offset = 0;
    134   FileStreamReader reader(NULL,
    135                           file_url_,
    136                           initial_offset,
    137                           base::Time::Now());  // Not used yet.
    138   scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(kFakeFileSize));
    139 
    140   const int result =
    141       reader.Read(io_buffer.get(),
    142                   kFakeFileSize,
    143                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    144   EXPECT_EQ(net::ERR_IO_PENDING, result);
    145   base::RunLoop().RunUntilIdle();
    146 
    147   ASSERT_EQ(1u, logger.results().size());
    148   EXPECT_LT(0, logger.results()[0]);
    149   EXPECT_EQ(kFakeFileSize, static_cast<size_t>(logger.results()[0]));
    150 
    151   std::string buffer_as_string(io_buffer->data(), kFakeFileSize);
    152   EXPECT_EQ(kFakeFileText, buffer_as_string);
    153 }
    154 
    155 TEST_F(FileSystemProviderFileStreamReader, Read_WrongFile) {
    156   EventLogger logger;
    157 
    158   const int64 initial_offset = 0;
    159   FileStreamReader reader(NULL,
    160                           wrong_file_url_,
    161                           initial_offset,
    162                           base::Time::Now());  // Not used yet.
    163   scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(kFakeFileSize));
    164 
    165   const int result =
    166       reader.Read(io_buffer.get(),
    167                   kFakeFileSize,
    168                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    169   EXPECT_EQ(net::ERR_IO_PENDING, result);
    170   base::RunLoop().RunUntilIdle();
    171 
    172   ASSERT_EQ(1u, logger.results().size());
    173   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]);
    174 }
    175 
    176 TEST_F(FileSystemProviderFileStreamReader, Read_InChunks) {
    177   EventLogger logger;
    178 
    179   const int64 initial_offset = 0;
    180   FileStreamReader reader(NULL,
    181                           file_url_,
    182                           initial_offset,
    183                           base::Time::Now());  // Not used yet.
    184 
    185   for (size_t offset = 0; offset < kFakeFileSize; ++offset) {
    186     scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(1));
    187     const int result =
    188         reader.Read(io_buffer.get(),
    189                     1,
    190                     base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    191     EXPECT_EQ(net::ERR_IO_PENDING, result);
    192     base::RunLoop().RunUntilIdle();
    193     ASSERT_EQ(offset + 1u, logger.results().size());
    194     EXPECT_EQ(1, logger.results()[offset]);
    195     EXPECT_EQ(kFakeFileText[offset], io_buffer->data()[0]);
    196   }
    197 }
    198 
    199 TEST_F(FileSystemProviderFileStreamReader, Read_Slice) {
    200   EventLogger logger;
    201 
    202   // Trim first 3 and last 3 characters.
    203   const int64 initial_offset = 3;
    204   const int length = static_cast<int>(kFakeFileSize) - initial_offset - 3;
    205   ASSERT_GT(kFakeFileSize, static_cast<size_t>(initial_offset));
    206   ASSERT_LT(0, length);
    207 
    208   FileStreamReader reader(NULL,
    209                           file_url_,
    210                           initial_offset,
    211                           base::Time::Now());  // Not used yet.
    212   scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length));
    213 
    214   const int result =
    215       reader.Read(io_buffer.get(),
    216                   length,
    217                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    218   EXPECT_EQ(net::ERR_IO_PENDING, result);
    219   base::RunLoop().RunUntilIdle();
    220 
    221   ASSERT_EQ(1u, logger.results().size());
    222   EXPECT_EQ(length, logger.results()[0]);
    223 
    224   std::string buffer_as_string(io_buffer->data(), length);
    225   std::string expected_buffer(kFakeFileText + initial_offset, length);
    226   EXPECT_EQ(expected_buffer, buffer_as_string);
    227 }
    228 
    229 TEST_F(FileSystemProviderFileStreamReader, Read_Beyond) {
    230   EventLogger logger;
    231 
    232   // Request reading 1KB more than available.
    233   const int64 initial_offset = 0;
    234   const int length = static_cast<int>(kFakeFileSize) + 1024;
    235 
    236   FileStreamReader reader(NULL,
    237                           file_url_,
    238                           initial_offset,
    239                           base::Time::Now());  // Not used yet.
    240   scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length));
    241 
    242   const int result =
    243       reader.Read(io_buffer.get(),
    244                   length,
    245                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    246   EXPECT_EQ(net::ERR_IO_PENDING, result);
    247   base::RunLoop().RunUntilIdle();
    248 
    249   ASSERT_EQ(1u, logger.results().size());
    250   EXPECT_LT(0, logger.results()[0]);
    251   EXPECT_EQ(kFakeFileSize, static_cast<size_t>(logger.results()[0]));
    252 
    253   std::string buffer_as_string(io_buffer->data(), kFakeFileSize);
    254   EXPECT_EQ(kFakeFileText, buffer_as_string);
    255 }
    256 
    257 TEST_F(FileSystemProviderFileStreamReader, GetLength) {
    258   EventLogger logger;
    259 
    260   const int64 initial_offset = 0;
    261   FileStreamReader reader(NULL,
    262                           file_url_,
    263                           initial_offset,
    264                           base::Time::Now());  // Not used yet.
    265 
    266   const int result = reader.GetLength(
    267       base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
    268   EXPECT_EQ(net::ERR_IO_PENDING, result);
    269   base::RunLoop().RunUntilIdle();
    270 
    271   ASSERT_EQ(1u, logger.results().size());
    272   EXPECT_LT(0, logger.results()[0]);
    273   EXPECT_EQ(kFakeFileSize, static_cast<size_t>(logger.results()[0]));
    274 }
    275 
    276 TEST_F(FileSystemProviderFileStreamReader, GetLength_WrongFile) {
    277   EventLogger logger;
    278 
    279   const int64 initial_offset = 0;
    280   FileStreamReader reader(NULL,
    281                           wrong_file_url_,
    282                           initial_offset,
    283                           base::Time::Now());  // Not used yet.
    284 
    285   const int result = reader.GetLength(
    286       base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
    287   EXPECT_EQ(net::ERR_IO_PENDING, result);
    288   base::RunLoop().RunUntilIdle();
    289 
    290   ASSERT_EQ(1u, logger.results().size());
    291   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]);
    292 }
    293 
    294 }  // namespace file_system_provider
    295 }  // namespace chromeos
    296