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 
      7 #include "base/files/file.h"
      8 #include "base/files/file_path.h"
      9 #include "base/memory/ref_counted.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/memory/scoped_vector.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/chromeos/file_system_provider/operations/read_file.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 "net/base/io_buffer.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 #include "webkit/browser/fileapi/async_file_util.h"
     20 
     21 namespace chromeos {
     22 namespace file_system_provider {
     23 namespace operations {
     24 namespace {
     25 
     26 const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
     27 const char kFileSystemId[] = "testing-file-system";
     28 const int kRequestId = 2;
     29 const int kFileHandle = 3;
     30 const int kOffset = 10;
     31 const int kLength = 5;
     32 
     33 // Fake event dispatcher implementation with extra logging capability. Acts as
     34 // a providing extension end-point.
     35 class LoggingDispatchEventImpl {
     36  public:
     37   explicit LoggingDispatchEventImpl(bool dispatch_reply)
     38       : dispatch_reply_(dispatch_reply) {}
     39   virtual ~LoggingDispatchEventImpl() {}
     40 
     41   bool OnDispatchEventImpl(scoped_ptr<extensions::Event> event) {
     42     events_.push_back(event->DeepCopy());
     43     return dispatch_reply_;
     44   }
     45 
     46   ScopedVector<extensions::Event>& events() { return events_; }
     47 
     48  private:
     49   ScopedVector<extensions::Event> events_;
     50   bool dispatch_reply_;
     51 
     52   DISALLOW_COPY_AND_ASSIGN(LoggingDispatchEventImpl);
     53 };
     54 
     55 // Callback invocation logger. Acts as a fileapi end-point.
     56 class CallbackLogger {
     57  public:
     58   class Event {
     59    public:
     60     Event(int chunk_length, bool has_more, base::File::Error result)
     61         : chunk_length_(chunk_length), has_more_(has_more), result_(result) {}
     62     virtual ~Event() {}
     63 
     64     int chunk_length() const { return chunk_length_; }
     65     bool has_more() const { return has_more_; }
     66     base::File::Error result() const { return result_; }
     67 
     68    private:
     69     int chunk_length_;
     70     bool has_more_;
     71     base::File::Error result_;
     72 
     73     DISALLOW_COPY_AND_ASSIGN(Event);
     74   };
     75 
     76   CallbackLogger() : weak_ptr_factory_(this) {}
     77   virtual ~CallbackLogger() {}
     78 
     79   void OnReadFile(int chunk_length, bool has_more, base::File::Error result) {
     80     events_.push_back(new Event(chunk_length, has_more, result));
     81   }
     82 
     83   ScopedVector<Event>& events() { return events_; }
     84 
     85   base::WeakPtr<CallbackLogger> GetWeakPtr() {
     86     return weak_ptr_factory_.GetWeakPtr();
     87   }
     88 
     89  private:
     90   ScopedVector<Event> events_;
     91   bool dispatch_reply_;
     92   base::WeakPtrFactory<CallbackLogger> weak_ptr_factory_;
     93 
     94   DISALLOW_COPY_AND_ASSIGN(CallbackLogger);
     95 };
     96 
     97 }  // namespace
     98 
     99 class FileSystemProviderOperationsReadFileTest : public testing::Test {
    100  protected:
    101   FileSystemProviderOperationsReadFileTest() {}
    102   virtual ~FileSystemProviderOperationsReadFileTest() {}
    103 
    104   virtual void SetUp() OVERRIDE {
    105     file_system_info_ =
    106         ProvidedFileSystemInfo(kExtensionId,
    107                                kFileSystemId,
    108                                "" /* file_system_name */,
    109                                base::FilePath() /* mount_path */);
    110     io_buffer_ = make_scoped_refptr(new net::IOBuffer(kOffset + kLength));
    111   }
    112 
    113   ProvidedFileSystemInfo file_system_info_;
    114   scoped_refptr<net::IOBuffer> io_buffer_;
    115 };
    116 
    117 TEST_F(FileSystemProviderOperationsReadFileTest, Execute) {
    118   LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
    119   CallbackLogger callback_logger;
    120 
    121   ReadFile read_file(
    122       NULL,
    123       file_system_info_,
    124       kFileHandle,
    125       io_buffer_.get(),
    126       kOffset,
    127       kLength,
    128       base::Bind(&CallbackLogger::OnReadFile, callback_logger.GetWeakPtr()));
    129   read_file.SetDispatchEventImplForTesting(
    130       base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
    131                  base::Unretained(&dispatcher)));
    132 
    133   EXPECT_TRUE(read_file.Execute(kRequestId));
    134 
    135   ASSERT_EQ(1u, dispatcher.events().size());
    136   extensions::Event* event = dispatcher.events()[0];
    137   EXPECT_EQ(
    138       extensions::api::file_system_provider::OnReadFileRequested::kEventName,
    139       event->event_name);
    140   base::ListValue* event_args = event->event_args.get();
    141   ASSERT_EQ(1u, event_args->GetSize());
    142 
    143   base::DictionaryValue* options = NULL;
    144   ASSERT_TRUE(event_args->GetDictionary(0, &options));
    145 
    146   std::string event_file_system_id;
    147   EXPECT_TRUE(options->GetString("fileSystemId", &event_file_system_id));
    148   EXPECT_EQ(kFileSystemId, event_file_system_id);
    149 
    150   int event_request_id = -1;
    151   EXPECT_TRUE(options->GetInteger("requestId", &event_request_id));
    152   EXPECT_EQ(kRequestId, event_request_id);
    153 
    154   int event_file_handle = -1;
    155   EXPECT_TRUE(options->GetInteger("openRequestId", &event_file_handle));
    156   EXPECT_EQ(kFileHandle, event_file_handle);
    157 
    158   double event_offset = -1;
    159   EXPECT_TRUE(options->GetDouble("offset", &event_offset));
    160   EXPECT_EQ(kOffset, static_cast<double>(event_offset));
    161 
    162   int event_length = -1;
    163   EXPECT_TRUE(options->GetInteger("length", &event_length));
    164   EXPECT_EQ(kLength, event_length);
    165 }
    166 
    167 TEST_F(FileSystemProviderOperationsReadFileTest, Execute_NoListener) {
    168   LoggingDispatchEventImpl dispatcher(false /* dispatch_reply */);
    169   CallbackLogger callback_logger;
    170 
    171   ReadFile read_file(
    172       NULL,
    173       file_system_info_,
    174       kFileHandle,
    175       io_buffer_.get(),
    176       kOffset,
    177       kLength,
    178       base::Bind(&CallbackLogger::OnReadFile, callback_logger.GetWeakPtr()));
    179   read_file.SetDispatchEventImplForTesting(
    180       base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
    181                  base::Unretained(&dispatcher)));
    182 
    183   EXPECT_FALSE(read_file.Execute(kRequestId));
    184 }
    185 
    186 TEST_F(FileSystemProviderOperationsReadFileTest, OnSuccess) {
    187   using extensions::api::file_system_provider_internal::
    188       ReadFileRequestedSuccess::Params;
    189 
    190   LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
    191   CallbackLogger callback_logger;
    192 
    193   ReadFile read_file(
    194       NULL,
    195       file_system_info_,
    196       kFileHandle,
    197       io_buffer_.get(),
    198       kOffset,
    199       kLength,
    200       base::Bind(&CallbackLogger::OnReadFile, callback_logger.GetWeakPtr()));
    201   read_file.SetDispatchEventImplForTesting(
    202       base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
    203                  base::Unretained(&dispatcher)));
    204 
    205   EXPECT_TRUE(read_file.Execute(kRequestId));
    206 
    207   const std::string data = "ABCDE";
    208   const bool has_more = false;
    209 
    210   base::ListValue value_as_list;
    211   value_as_list.Set(0, new base::StringValue(kFileSystemId));
    212   value_as_list.Set(1, new base::FundamentalValue(kRequestId));
    213   value_as_list.Set(
    214       2, base::BinaryValue::CreateWithCopiedBuffer(data.c_str(), data.size()));
    215   value_as_list.Set(3, new base::FundamentalValue(has_more));
    216 
    217   scoped_ptr<Params> params(Params::Create(value_as_list));
    218   ASSERT_TRUE(params.get());
    219   scoped_ptr<RequestValue> request_value(
    220       RequestValue::CreateForReadFileSuccess(params.Pass()));
    221   ASSERT_TRUE(request_value.get());
    222 
    223   read_file.OnSuccess(kRequestId, request_value.Pass(), has_more);
    224 
    225   ASSERT_EQ(1u, callback_logger.events().size());
    226   CallbackLogger::Event* event = callback_logger.events()[0];
    227   EXPECT_EQ(kLength, event->chunk_length());
    228   EXPECT_FALSE(event->has_more());
    229   EXPECT_EQ(data, std::string(io_buffer_->data(), kLength));
    230   EXPECT_EQ(base::File::FILE_OK, event->result());
    231 }
    232 
    233 TEST_F(FileSystemProviderOperationsReadFileTest, OnError) {
    234   using extensions::api::file_system_provider_internal::ReadFileRequestedError::
    235       Params;
    236 
    237   LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
    238   CallbackLogger callback_logger;
    239 
    240   ReadFile read_file(
    241       NULL,
    242       file_system_info_,
    243       kFileHandle,
    244       io_buffer_.get(),
    245       kOffset,
    246       kLength,
    247       base::Bind(&CallbackLogger::OnReadFile, callback_logger.GetWeakPtr()));
    248   read_file.SetDispatchEventImplForTesting(
    249       base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
    250                  base::Unretained(&dispatcher)));
    251 
    252   EXPECT_TRUE(read_file.Execute(kRequestId));
    253 
    254   read_file.OnError(kRequestId, base::File::FILE_ERROR_TOO_MANY_OPENED);
    255 
    256   ASSERT_EQ(1u, callback_logger.events().size());
    257   CallbackLogger::Event* event = callback_logger.events()[0];
    258   EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, event->result());
    259 }
    260 
    261 }  // namespace operations
    262 }  // namespace file_system_provider
    263 }  // namespace chromeos
    264