Home | History | Annotate | Download | only in operations
      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/memory/scoped_ptr.h"
     11 #include "base/memory/scoped_vector.h"
     12 #include "chrome/browser/chromeos/file_system_provider/operations/open_file.h"
     13 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
     14 #include "chrome/common/extensions/api/file_system_provider.h"
     15 #include "chrome/common/extensions/api/file_system_provider_internal.h"
     16 #include "extensions/browser/event_router.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 #include "webkit/browser/fileapi/async_file_util.h"
     19 
     20 namespace chromeos {
     21 namespace file_system_provider {
     22 namespace operations {
     23 namespace {
     24 
     25 const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
     26 const char kFileSystemId[] = "testing-file-system";
     27 const int kRequestId = 2;
     28 const base::FilePath::CharType kFilePath[] = "/directory/blueberries.txt";
     29 
     30 // Fake event dispatcher implementation with extra logging capability. Acts as
     31 // a providing extension end-point.
     32 class LoggingDispatchEventImpl {
     33  public:
     34   explicit LoggingDispatchEventImpl(bool dispatch_reply)
     35       : dispatch_reply_(dispatch_reply) {}
     36   virtual ~LoggingDispatchEventImpl() {}
     37 
     38   bool OnDispatchEventImpl(scoped_ptr<extensions::Event> event) {
     39     events_.push_back(event->DeepCopy());
     40     return dispatch_reply_;
     41   }
     42 
     43   ScopedVector<extensions::Event>& events() { return events_; }
     44 
     45  private:
     46   ScopedVector<extensions::Event> events_;
     47   bool dispatch_reply_;
     48 
     49   DISALLOW_COPY_AND_ASSIGN(LoggingDispatchEventImpl);
     50 };
     51 
     52 // Callback invocation logger. Acts as a fileapi end-point.
     53 class CallbackLogger {
     54  public:
     55   class Event {
     56    public:
     57     Event(int file_handle, base::File::Error result)
     58         : file_handle_(file_handle), result_(result) {}
     59     virtual ~Event() {}
     60 
     61     int file_handle() { return file_handle_; }
     62     base::File::Error result() { return result_; }
     63 
     64    private:
     65     int file_handle_;
     66     base::File::Error result_;
     67 
     68     DISALLOW_COPY_AND_ASSIGN(Event);
     69   };
     70 
     71   CallbackLogger() : weak_ptr_factory_(this) {}
     72   virtual ~CallbackLogger() {}
     73 
     74   void OnOpenFile(int file_handle, base::File::Error result) {
     75     events_.push_back(new Event(file_handle, result));
     76   }
     77 
     78   ScopedVector<Event>& events() { return events_; }
     79 
     80   base::WeakPtr<CallbackLogger> GetWeakPtr() {
     81     return weak_ptr_factory_.GetWeakPtr();
     82   }
     83 
     84  private:
     85   ScopedVector<Event> events_;
     86   bool dispatch_reply_;
     87   base::WeakPtrFactory<CallbackLogger> weak_ptr_factory_;
     88 
     89   DISALLOW_COPY_AND_ASSIGN(CallbackLogger);
     90 };
     91 
     92 }  // namespace
     93 
     94 class FileSystemProviderOperationsOpenFileTest : public testing::Test {
     95  protected:
     96   FileSystemProviderOperationsOpenFileTest() {}
     97   virtual ~FileSystemProviderOperationsOpenFileTest() {}
     98 
     99   virtual void SetUp() OVERRIDE {
    100     file_system_info_ =
    101         ProvidedFileSystemInfo(kExtensionId,
    102                                kFileSystemId,
    103                                "" /* file_system_name */,
    104                                base::FilePath() /* mount_path */);
    105   }
    106 
    107   ProvidedFileSystemInfo file_system_info_;
    108 };
    109 
    110 TEST_F(FileSystemProviderOperationsOpenFileTest, Execute) {
    111   LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
    112   CallbackLogger callback_logger;
    113 
    114   OpenFile open_file(
    115       NULL,
    116       file_system_info_,
    117       base::FilePath::FromUTF8Unsafe(kFilePath),
    118       ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
    119       false /* create */,
    120       base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr()));
    121   open_file.SetDispatchEventImplForTesting(
    122       base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
    123                  base::Unretained(&dispatcher)));
    124 
    125   EXPECT_TRUE(open_file.Execute(kRequestId));
    126 
    127   ASSERT_EQ(1u, dispatcher.events().size());
    128   extensions::Event* event = dispatcher.events()[0];
    129   EXPECT_EQ(
    130       extensions::api::file_system_provider::OnOpenFileRequested::kEventName,
    131       event->event_name);
    132   base::ListValue* event_args = event->event_args.get();
    133   ASSERT_EQ(1u, event_args->GetSize());
    134 
    135   base::DictionaryValue* options = NULL;
    136   ASSERT_TRUE(event_args->GetDictionary(0, &options));
    137 
    138   std::string event_file_system_id;
    139   EXPECT_TRUE(options->GetString("fileSystemId", &event_file_system_id));
    140   EXPECT_EQ(kFileSystemId, event_file_system_id);
    141 
    142   int event_request_id = -1;
    143   EXPECT_TRUE(options->GetInteger("requestId", &event_request_id));
    144   EXPECT_EQ(kRequestId, event_request_id);
    145 
    146   std::string event_file_path;
    147   EXPECT_TRUE(options->GetString("filePath", &event_file_path));
    148   EXPECT_EQ(kFilePath, event_file_path);
    149 
    150   std::string event_file_open_mode;
    151   EXPECT_TRUE(options->GetString("mode", &event_file_open_mode));
    152   const std::string expected_file_open_mode =
    153       extensions::api::file_system_provider::ToString(
    154           extensions::api::file_system_provider::OPEN_FILE_MODE_READ);
    155   EXPECT_EQ(expected_file_open_mode, event_file_open_mode);
    156 
    157   bool event_create;
    158   EXPECT_TRUE(options->GetBoolean("create", &event_create));
    159   EXPECT_FALSE(event_create);
    160 }
    161 
    162 TEST_F(FileSystemProviderOperationsOpenFileTest, Execute_NoListener) {
    163   LoggingDispatchEventImpl dispatcher(false /* dispatch_reply */);
    164   CallbackLogger callback_logger;
    165 
    166   OpenFile open_file(
    167       NULL,
    168       file_system_info_,
    169       base::FilePath::FromUTF8Unsafe(kFilePath),
    170       ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
    171       false /* create */,
    172       base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr()));
    173   open_file.SetDispatchEventImplForTesting(
    174       base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
    175                  base::Unretained(&dispatcher)));
    176 
    177   EXPECT_FALSE(open_file.Execute(kRequestId));
    178 }
    179 
    180 TEST_F(FileSystemProviderOperationsOpenFileTest, OnSuccess) {
    181   using extensions::api::file_system_provider_internal::
    182       OpenFileRequestedSuccess::Params;
    183 
    184   LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
    185   CallbackLogger callback_logger;
    186 
    187   OpenFile open_file(
    188       NULL,
    189       file_system_info_,
    190       base::FilePath::FromUTF8Unsafe(kFilePath),
    191       ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
    192       false /* create */,
    193       base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr()));
    194   open_file.SetDispatchEventImplForTesting(
    195       base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
    196                  base::Unretained(&dispatcher)));
    197 
    198   EXPECT_TRUE(open_file.Execute(kRequestId));
    199 
    200   open_file.OnSuccess(kRequestId,
    201                       scoped_ptr<RequestValue>(new RequestValue()),
    202                       false /* has_more */);
    203   ASSERT_EQ(1u, callback_logger.events().size());
    204   CallbackLogger::Event* event = callback_logger.events()[0];
    205   EXPECT_EQ(base::File::FILE_OK, event->result());
    206   EXPECT_LT(0, event->file_handle());
    207 }
    208 
    209 TEST_F(FileSystemProviderOperationsOpenFileTest, OnError) {
    210   using extensions::api::file_system_provider_internal::OpenFileRequestedError::
    211       Params;
    212 
    213   LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
    214   CallbackLogger callback_logger;
    215 
    216   OpenFile open_file(
    217       NULL,
    218       file_system_info_,
    219       base::FilePath::FromUTF8Unsafe(kFilePath),
    220       ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
    221       false /* create */,
    222       base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr()));
    223   open_file.SetDispatchEventImplForTesting(
    224       base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
    225                  base::Unretained(&dispatcher)));
    226 
    227   EXPECT_TRUE(open_file.Execute(kRequestId));
    228 
    229   open_file.OnError(kRequestId, base::File::FILE_ERROR_TOO_MANY_OPENED);
    230   ASSERT_EQ(1u, callback_logger.events().size());
    231   CallbackLogger::Event* event = callback_logger.events()[0];
    232   EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, event->result());
    233   ASSERT_EQ(0, event->file_handle());
    234 }
    235 
    236 }  // namespace operations
    237 }  // namespace file_system_provider
    238 }  // namespace chromeos
    239