read_file_unittest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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
21namespace chromeos {
22namespace file_system_provider {
23namespace operations {
24namespace {
25
26const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
27const char kFileSystemId[] = "testing-file-system";
28const int kRequestId = 2;
29const int kFileHandle = 3;
30const int kOffset = 10;
31const int kLength = 5;
32
33// Fake event dispatcher implementation with extra logging capability. Acts as
34// a providing extension end-point.
35class 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.
56class 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
99class 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
117TEST_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(5u, event_args->GetSize());
142
143  std::string event_file_system_id;
144  EXPECT_TRUE(event_args->GetString(0, &event_file_system_id));
145  EXPECT_EQ(kFileSystemId, event_file_system_id);
146
147  int event_request_id = -1;
148  EXPECT_TRUE(event_args->GetInteger(1, &event_request_id));
149  EXPECT_EQ(kRequestId, event_request_id);
150
151  int event_file_handle = -1;
152  EXPECT_TRUE(event_args->GetInteger(2, &event_file_handle));
153  EXPECT_EQ(kFileHandle, event_file_handle);
154
155  double event_offset = -1;
156  EXPECT_TRUE(event_args->GetDouble(3, &event_offset));
157  EXPECT_EQ(kOffset, static_cast<double>(event_offset));
158
159  int event_length = -1;
160  EXPECT_TRUE(event_args->GetInteger(4, &event_length));
161  EXPECT_EQ(kLength, event_length);
162}
163
164TEST_F(FileSystemProviderOperationsReadFileTest, Execute_NoListener) {
165  LoggingDispatchEventImpl dispatcher(false /* dispatch_reply */);
166  CallbackLogger callback_logger;
167
168  ReadFile read_file(
169      NULL,
170      file_system_info_,
171      kFileHandle,
172      io_buffer_.get(),
173      kOffset,
174      kLength,
175      base::Bind(&CallbackLogger::OnReadFile, callback_logger.GetWeakPtr()));
176  read_file.SetDispatchEventImplForTesting(
177      base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
178                 base::Unretained(&dispatcher)));
179
180  EXPECT_FALSE(read_file.Execute(kRequestId));
181}
182
183TEST_F(FileSystemProviderOperationsReadFileTest, OnSuccess) {
184  using extensions::api::file_system_provider_internal::
185      ReadFileRequestedSuccess::Params;
186
187  LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
188  CallbackLogger callback_logger;
189
190  ReadFile read_file(
191      NULL,
192      file_system_info_,
193      kFileHandle,
194      io_buffer_.get(),
195      kOffset,
196      kLength,
197      base::Bind(&CallbackLogger::OnReadFile, callback_logger.GetWeakPtr()));
198  read_file.SetDispatchEventImplForTesting(
199      base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
200                 base::Unretained(&dispatcher)));
201
202  EXPECT_TRUE(read_file.Execute(kRequestId));
203
204  const std::string data = "ABCDE";
205  const bool has_more = false;
206
207  base::ListValue value_as_list;
208  value_as_list.Set(0, new base::StringValue(kFileSystemId));
209  value_as_list.Set(1, new base::FundamentalValue(kRequestId));
210  value_as_list.Set(
211      2, base::BinaryValue::CreateWithCopiedBuffer(data.c_str(), data.size()));
212  value_as_list.Set(3, new base::FundamentalValue(has_more));
213
214  scoped_ptr<Params> params(Params::Create(value_as_list));
215  ASSERT_TRUE(params.get());
216  scoped_ptr<RequestValue> request_value(
217      RequestValue::CreateForReadFileSuccess(params.Pass()));
218  ASSERT_TRUE(request_value.get());
219
220  read_file.OnSuccess(kRequestId, request_value.Pass(), has_more);
221
222  ASSERT_EQ(1u, callback_logger.events().size());
223  CallbackLogger::Event* event = callback_logger.events()[0];
224  EXPECT_EQ(kLength, event->chunk_length());
225  EXPECT_FALSE(event->has_more());
226  EXPECT_EQ(data, std::string(io_buffer_->data(), kLength));
227  EXPECT_EQ(base::File::FILE_OK, event->result());
228}
229
230TEST_F(FileSystemProviderOperationsReadFileTest, OnError) {
231  using extensions::api::file_system_provider_internal::ReadFileRequestedError::
232      Params;
233
234  LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
235  CallbackLogger callback_logger;
236
237  ReadFile read_file(
238      NULL,
239      file_system_info_,
240      kFileHandle,
241      io_buffer_.get(),
242      kOffset,
243      kLength,
244      base::Bind(&CallbackLogger::OnReadFile, callback_logger.GetWeakPtr()));
245  read_file.SetDispatchEventImplForTesting(
246      base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
247                 base::Unretained(&dispatcher)));
248
249  EXPECT_TRUE(read_file.Execute(kRequestId));
250
251  read_file.OnError(kRequestId, base::File::FILE_ERROR_TOO_MANY_OPENED);
252
253  ASSERT_EQ(1u, callback_logger.events().size());
254  CallbackLogger::Event* event = callback_logger.events()[0];
255  EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, event->result());
256}
257
258}  // namespace operations
259}  // namespace file_system_provider
260}  // namespace chromeos
261