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 "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.h"
      6 
      7 #include <string>
      8 #include <vector>
      9 
     10 #include "base/files/file.h"
     11 #include "base/files/file_path.h"
     12 #include "base/files/scoped_temp_dir.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/memory/weak_ptr.h"
     15 #include "base/run_loop.h"
     16 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.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 "storage/browser/fileapi/async_file_util.h"
     28 #include "storage/browser/fileapi/external_mount_points.h"
     29 #include "storage/browser/fileapi/file_system_url.h"
     30 #include "testing/gtest/include/gtest/gtest.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 storage::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 storage::ExternalMountPoints* const mount_points =
     66       storage::ExternalMountPoints::GetSystemInstance();
     67   return mount_points->CreateCrackedFileSystemURL(
     68       GURL(origin),
     69       storage::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() : profile_(NULL), fake_file_(NULL) {}
     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(kExtensionId,
    100                                                  kFileSystemId,
    101                                                  "Testing File System",
    102                                                  false /* writable */);
    103     ASSERT_TRUE(result);
    104     FakeProvidedFileSystem* provided_file_system =
    105         static_cast<FakeProvidedFileSystem*>(
    106             service->GetProvidedFileSystem(kExtensionId, kFileSystemId));
    107     ASSERT_TRUE(provided_file_system);
    108     fake_file_ = provided_file_system->GetEntry(
    109         base::FilePath::FromUTF8Unsafe(kFakeFilePath));
    110     ASSERT_TRUE(fake_file_);
    111     const ProvidedFileSystemInfo& file_system_info =
    112         service->GetProvidedFileSystem(kExtensionId, kFileSystemId)
    113             ->GetFileSystemInfo();
    114     const std::string mount_point_name =
    115         file_system_info.mount_path().BaseName().AsUTF8Unsafe();
    116 
    117     file_url_ = CreateFileSystemURL(
    118         mount_point_name, base::FilePath::FromUTF8Unsafe(kFakeFilePath + 1));
    119     ASSERT_TRUE(file_url_.is_valid());
    120     wrong_file_url_ = CreateFileSystemURL(
    121         mount_point_name, base::FilePath::FromUTF8Unsafe("im-not-here.txt"));
    122     ASSERT_TRUE(wrong_file_url_.is_valid());
    123   }
    124 
    125   virtual void TearDown() OVERRIDE {
    126     // Setting the testing factory to NULL will destroy the created service
    127     // associated with the testing profile.
    128     ServiceFactory::GetInstance()->SetTestingFactory(profile_, NULL);
    129   }
    130 
    131   content::TestBrowserThreadBundle thread_bundle_;
    132   base::ScopedTempDir data_dir_;
    133   scoped_ptr<TestingProfileManager> profile_manager_;
    134   TestingProfile* profile_;     // Owned by TestingProfileManager.
    135   const FakeEntry* fake_file_;  // Owned by FakePRovidedFileSystem.
    136   storage::FileSystemURL file_url_;
    137   storage::FileSystemURL wrong_file_url_;
    138 };
    139 
    140 TEST_F(FileSystemProviderFileStreamReader, Read_AllAtOnce) {
    141   EventLogger logger;
    142 
    143   const int64 initial_offset = 0;
    144   FileStreamReader reader(
    145       NULL, file_url_, initial_offset, fake_file_->metadata->modification_time);
    146   scoped_refptr<net::IOBuffer> io_buffer(
    147       new net::IOBuffer(fake_file_->metadata->size));
    148 
    149   const int result =
    150       reader.Read(io_buffer.get(),
    151                   fake_file_->metadata->size,
    152                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    153   EXPECT_EQ(net::ERR_IO_PENDING, result);
    154   base::RunLoop().RunUntilIdle();
    155 
    156   ASSERT_EQ(1u, logger.results().size());
    157   EXPECT_LT(0, logger.results()[0]);
    158   EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]);
    159 
    160   std::string buffer_as_string(io_buffer->data(), fake_file_->metadata->size);
    161   EXPECT_EQ(fake_file_->contents, buffer_as_string);
    162 }
    163 
    164 TEST_F(FileSystemProviderFileStreamReader, Read_WrongFile) {
    165   EventLogger logger;
    166 
    167   const int64 initial_offset = 0;
    168   FileStreamReader reader(NULL,
    169                           wrong_file_url_,
    170                           initial_offset,
    171                           fake_file_->metadata->modification_time);
    172   scoped_refptr<net::IOBuffer> io_buffer(
    173       new net::IOBuffer(fake_file_->metadata->size));
    174 
    175   const int result =
    176       reader.Read(io_buffer.get(),
    177                   fake_file_->metadata->size,
    178                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    179   EXPECT_EQ(net::ERR_IO_PENDING, result);
    180   base::RunLoop().RunUntilIdle();
    181 
    182   ASSERT_EQ(1u, logger.results().size());
    183   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]);
    184 }
    185 
    186 TEST_F(FileSystemProviderFileStreamReader, Read_InChunks) {
    187   EventLogger logger;
    188 
    189   const int64 initial_offset = 0;
    190   FileStreamReader reader(
    191       NULL, file_url_, initial_offset, fake_file_->metadata->modification_time);
    192 
    193   for (int64 offset = 0; offset < fake_file_->metadata->size; ++offset) {
    194     scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(1));
    195     const int result =
    196         reader.Read(io_buffer.get(),
    197                     1,
    198                     base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    199     EXPECT_EQ(net::ERR_IO_PENDING, result);
    200     base::RunLoop().RunUntilIdle();
    201     ASSERT_EQ(offset + 1, static_cast<int64>(logger.results().size()));
    202     EXPECT_EQ(1, logger.results()[offset]);
    203     EXPECT_EQ(fake_file_->contents[offset], io_buffer->data()[0]);
    204   }
    205 }
    206 
    207 TEST_F(FileSystemProviderFileStreamReader, Read_Slice) {
    208   EventLogger logger;
    209 
    210   // Trim first 3 and last 3 characters.
    211   const int64 initial_offset = 3;
    212   const int length = fake_file_->metadata->size - initial_offset - 3;
    213   ASSERT_GT(fake_file_->metadata->size, initial_offset);
    214   ASSERT_LT(0, length);
    215 
    216   FileStreamReader reader(
    217       NULL, file_url_, initial_offset, fake_file_->metadata->modification_time);
    218   scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length));
    219 
    220   const int result =
    221       reader.Read(io_buffer.get(),
    222                   length,
    223                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    224   EXPECT_EQ(net::ERR_IO_PENDING, result);
    225   base::RunLoop().RunUntilIdle();
    226 
    227   ASSERT_EQ(1u, logger.results().size());
    228   EXPECT_EQ(length, logger.results()[0]);
    229 
    230   std::string buffer_as_string(io_buffer->data(), length);
    231   std::string expected_buffer(fake_file_->contents.data() + initial_offset,
    232                               length);
    233   EXPECT_EQ(expected_buffer, buffer_as_string);
    234 }
    235 
    236 TEST_F(FileSystemProviderFileStreamReader, Read_Beyond) {
    237   EventLogger logger;
    238 
    239   // Request reading 1KB more than available.
    240   const int64 initial_offset = 0;
    241   const int length = fake_file_->metadata->size + 1024;
    242 
    243   FileStreamReader reader(
    244       NULL, file_url_, initial_offset, fake_file_->metadata->modification_time);
    245   scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length));
    246 
    247   const int result =
    248       reader.Read(io_buffer.get(),
    249                   length,
    250                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    251   EXPECT_EQ(net::ERR_IO_PENDING, result);
    252   base::RunLoop().RunUntilIdle();
    253 
    254   ASSERT_EQ(1u, logger.results().size());
    255   EXPECT_LT(0, logger.results()[0]);
    256   EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]);
    257 
    258   std::string buffer_as_string(io_buffer->data(), fake_file_->metadata->size);
    259   EXPECT_EQ(fake_file_->contents, buffer_as_string);
    260 }
    261 
    262 TEST_F(FileSystemProviderFileStreamReader, Read_ModifiedFile) {
    263   EventLogger logger;
    264 
    265   const int64 initial_offset = 0;
    266   FileStreamReader reader(NULL, file_url_, initial_offset, base::Time::Max());
    267 
    268   scoped_refptr<net::IOBuffer> io_buffer(
    269       new net::IOBuffer(fake_file_->metadata->size));
    270   const int result =
    271       reader.Read(io_buffer.get(),
    272                   fake_file_->metadata->size,
    273                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    274 
    275   EXPECT_EQ(net::ERR_IO_PENDING, result);
    276   base::RunLoop().RunUntilIdle();
    277 
    278   ASSERT_EQ(1u, logger.results().size());
    279   EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, logger.results()[0]);
    280 }
    281 
    282 TEST_F(FileSystemProviderFileStreamReader, Read_ExpectedModificationTimeNull) {
    283   EventLogger logger;
    284 
    285   const int64 initial_offset = 0;
    286   FileStreamReader reader(NULL, file_url_, initial_offset, base::Time());
    287 
    288   scoped_refptr<net::IOBuffer> io_buffer(
    289       new net::IOBuffer(fake_file_->metadata->size));
    290   const int result =
    291       reader.Read(io_buffer.get(),
    292                   fake_file_->metadata->size,
    293                   base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
    294 
    295   EXPECT_EQ(net::ERR_IO_PENDING, result);
    296   base::RunLoop().RunUntilIdle();
    297 
    298   ASSERT_EQ(1u, logger.results().size());
    299   EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]);
    300 
    301   std::string buffer_as_string(io_buffer->data(), fake_file_->metadata->size);
    302   EXPECT_EQ(fake_file_->contents, buffer_as_string);
    303 }
    304 
    305 TEST_F(FileSystemProviderFileStreamReader, GetLength) {
    306   EventLogger logger;
    307 
    308   const int64 initial_offset = 0;
    309   FileStreamReader reader(
    310       NULL, file_url_, initial_offset, fake_file_->metadata->modification_time);
    311 
    312   const int result = reader.GetLength(
    313       base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
    314   EXPECT_EQ(net::ERR_IO_PENDING, result);
    315   base::RunLoop().RunUntilIdle();
    316 
    317   ASSERT_EQ(1u, logger.results().size());
    318   EXPECT_LT(0, logger.results()[0]);
    319   EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]);
    320 }
    321 
    322 TEST_F(FileSystemProviderFileStreamReader, GetLength_WrongFile) {
    323   EventLogger logger;
    324 
    325   const int64 initial_offset = 0;
    326   FileStreamReader reader(NULL,
    327                           wrong_file_url_,
    328                           initial_offset,
    329                           fake_file_->metadata->modification_time);
    330 
    331   const int result = reader.GetLength(
    332       base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
    333   EXPECT_EQ(net::ERR_IO_PENDING, result);
    334   base::RunLoop().RunUntilIdle();
    335 
    336   ASSERT_EQ(1u, logger.results().size());
    337   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]);
    338 }
    339 
    340 TEST_F(FileSystemProviderFileStreamReader, GetLength_ModifiedFile) {
    341   EventLogger logger;
    342 
    343   const int64 initial_offset = 0;
    344   FileStreamReader reader(NULL, file_url_, initial_offset, base::Time::Max());
    345 
    346   const int result = reader.GetLength(
    347       base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
    348   EXPECT_EQ(net::ERR_IO_PENDING, result);
    349   base::RunLoop().RunUntilIdle();
    350 
    351   ASSERT_EQ(1u, logger.results().size());
    352   EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, logger.results()[0]);
    353 }
    354 
    355 TEST_F(FileSystemProviderFileStreamReader,
    356        GetLength_ExpectedModificationTimeNull) {
    357   EventLogger logger;
    358 
    359   const int64 initial_offset = 0;
    360   FileStreamReader reader(NULL, file_url_, initial_offset, base::Time());
    361 
    362   const int result = reader.GetLength(
    363       base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
    364   EXPECT_EQ(net::ERR_IO_PENDING, result);
    365   base::RunLoop().RunUntilIdle();
    366 
    367   ASSERT_EQ(1u, logger.results().size());
    368   EXPECT_LT(0, logger.results()[0]);
    369   EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]);
    370 }
    371 
    372 }  // namespace file_system_provider
    373 }  // namespace chromeos
    374