request_manager_unittest.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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/bind.h"
8#include "base/callback.h"
9#include "base/files/file.h"
10#include "base/files/file_path.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/memory/scoped_vector.h"
13#include "base/memory/weak_ptr.h"
14#include "base/run_loop.h"
15#include "base/values.h"
16#include "chrome/browser/chromeos/file_system_provider/request_manager.h"
17#include "content/public/test/test_browser_thread_bundle.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20namespace chromeos {
21namespace file_system_provider {
22namespace {
23
24// Logs calls of the success and error callbacks on requests.
25class EventLogger {
26 public:
27  class SuccessEvent {
28   public:
29    SuccessEvent(scoped_ptr<base::DictionaryValue> result, bool has_next)
30        : result_(result.Pass()), has_next_(has_next) {}
31    ~SuccessEvent() {}
32
33    base::DictionaryValue* result() { return result_.get(); }
34    bool has_next() { return has_next_; }
35
36   private:
37    scoped_ptr<base::DictionaryValue> result_;
38    bool has_next_;
39  };
40
41  class ErrorEvent {
42   public:
43    explicit ErrorEvent(base::File::Error error) : error_(error) {}
44    ~ErrorEvent() {}
45
46    base::File::Error error() { return error_; }
47
48   private:
49    base::File::Error error_;
50  };
51
52  EventLogger() : weak_ptr_factory_(this) {}
53  virtual ~EventLogger() {}
54
55  void OnSuccess(scoped_ptr<base::DictionaryValue> result, bool has_next) {
56    success_events_.push_back(new SuccessEvent(result.Pass(), has_next));
57  }
58
59  void OnError(base::File::Error error) {
60    error_events_.push_back(new ErrorEvent(error));
61  }
62
63  ScopedVector<SuccessEvent>& success_events() { return success_events_; }
64  ScopedVector<ErrorEvent>& error_events() { return error_events_; }
65
66  base::WeakPtr<EventLogger> GetWeakPtr() {
67    return weak_ptr_factory_.GetWeakPtr();
68  }
69
70 private:
71  ScopedVector<SuccessEvent> success_events_;
72  ScopedVector<ErrorEvent> error_events_;
73  base::WeakPtrFactory<EventLogger> weak_ptr_factory_;
74};
75
76}  // namespace
77
78class FileSystemProviderRequestManagerTest : public testing::Test {
79 protected:
80  FileSystemProviderRequestManagerTest() {}
81  virtual ~FileSystemProviderRequestManagerTest() {}
82
83  virtual void SetUp() OVERRIDE {
84    request_manager_.reset(new RequestManager());
85  }
86
87  content::TestBrowserThreadBundle thread_bundle_;
88  scoped_ptr<RequestManager> request_manager_;
89};
90
91TEST_F(FileSystemProviderRequestManagerTest, CreateAndFulFill) {
92  EventLogger logger;
93
94  int request_id = request_manager_->CreateRequest(
95      base::Bind(&EventLogger::OnSuccess, logger.GetWeakPtr()),
96      base::Bind(&EventLogger::OnError, logger.GetWeakPtr()));
97
98  EXPECT_EQ(1, request_id);
99  EXPECT_EQ(0u, logger.success_events().size());
100  EXPECT_EQ(0u, logger.error_events().size());
101
102  scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue());
103  const bool has_next = false;
104  response->SetString("path", "i-like-vanilla");
105
106  bool result =
107      request_manager_->FulfillRequest(request_id, response.Pass(), has_next);
108  EXPECT_TRUE(result);
109
110  // Validate if the callback has correct arguments.
111  ASSERT_EQ(1u, logger.success_events().size());
112  EXPECT_EQ(0u, logger.error_events().size());
113  EventLogger::SuccessEvent* event = logger.success_events()[0];
114  ASSERT_TRUE(event->result());
115  std::string response_test_string;
116  EXPECT_TRUE(event->result()->GetString("path", &response_test_string));
117  EXPECT_EQ("i-like-vanilla", response_test_string);
118  EXPECT_FALSE(event->has_next());
119
120  // Confirm, that the request is removed. Basically, fulfilling again for the
121  // same request, should fail.
122  {
123    scoped_ptr<base::DictionaryValue> response;
124    bool retry =
125        request_manager_->FulfillRequest(request_id, response.Pass(), has_next);
126    EXPECT_FALSE(retry);
127  }
128
129  // Rejecting should also fail.
130  {
131    bool retry = request_manager_->RejectRequest(request_id,
132                                                 base::File::FILE_ERROR_FAILED);
133    EXPECT_FALSE(retry);
134  }
135}
136
137TEST_F(FileSystemProviderRequestManagerTest, CreateAndFulFill_WithHasNext) {
138  EventLogger logger;
139
140  int request_id = request_manager_->CreateRequest(
141      base::Bind(&EventLogger::OnSuccess, logger.GetWeakPtr()),
142      base::Bind(&EventLogger::OnError, logger.GetWeakPtr()));
143
144  EXPECT_EQ(1, request_id);
145  EXPECT_EQ(0u, logger.success_events().size());
146  EXPECT_EQ(0u, logger.error_events().size());
147
148  scoped_ptr<base::DictionaryValue> response;
149  const bool has_next = true;
150
151  bool result =
152      request_manager_->FulfillRequest(request_id, response.Pass(), has_next);
153  EXPECT_TRUE(result);
154
155  // Validate if the callback has correct arguments.
156  ASSERT_EQ(1u, logger.success_events().size());
157  EXPECT_EQ(0u, logger.error_events().size());
158  EventLogger::SuccessEvent* event = logger.success_events()[0];
159  EXPECT_FALSE(event->result());
160  EXPECT_TRUE(event->has_next());
161
162  // Confirm, that the request is not removed (since it has has_next == true).
163  // Basically, fulfilling again for the same request, should not fail.
164  {
165    bool new_has_next = false;
166    bool retry = request_manager_->FulfillRequest(
167        request_id, response.Pass(), new_has_next);
168    EXPECT_TRUE(retry);
169  }
170
171  // Since |new_has_next| is false, then the request should be removed. To check
172  // it, try to fulfill again, what should fail.
173  {
174    bool new_has_next = false;
175    bool retry = request_manager_->FulfillRequest(
176        request_id, response.Pass(), new_has_next);
177    EXPECT_FALSE(retry);
178  }
179}
180
181TEST_F(FileSystemProviderRequestManagerTest, CreateAndReject) {
182  EventLogger logger;
183
184  int request_id = request_manager_->CreateRequest(
185      base::Bind(&EventLogger::OnSuccess, logger.GetWeakPtr()),
186      base::Bind(&EventLogger::OnError, logger.GetWeakPtr()));
187
188  EXPECT_EQ(1, request_id);
189  EXPECT_EQ(0u, logger.success_events().size());
190  EXPECT_EQ(0u, logger.error_events().size());
191
192  base::File::Error error = base::File::FILE_ERROR_NO_MEMORY;
193  bool result = request_manager_->RejectRequest(request_id, error);
194  EXPECT_TRUE(result);
195
196  // Validate if the callback has correct arguments.
197  ASSERT_EQ(1u, logger.error_events().size());
198  EXPECT_EQ(0u, logger.success_events().size());
199  EventLogger::ErrorEvent* event = logger.error_events()[0];
200  EXPECT_EQ(error, event->error());
201
202  // Confirm, that the request is removed. Basically, fulfilling again for the
203  // same request, should fail.
204  {
205    scoped_ptr<base::DictionaryValue> response;
206    bool has_next = false;
207    bool retry =
208        request_manager_->FulfillRequest(request_id, response.Pass(), has_next);
209    EXPECT_FALSE(retry);
210  }
211
212  // Rejecting should also fail.
213  {
214    bool retry = request_manager_->RejectRequest(request_id, error);
215    EXPECT_FALSE(retry);
216  }
217}
218
219TEST_F(FileSystemProviderRequestManagerTest,
220       CreateAndFulfillWithWrongRequestId) {
221  EventLogger logger;
222
223  int request_id = request_manager_->CreateRequest(
224      base::Bind(&EventLogger::OnSuccess, logger.GetWeakPtr()),
225      base::Bind(&EventLogger::OnError, logger.GetWeakPtr()));
226
227  EXPECT_EQ(1, request_id);
228  EXPECT_EQ(0u, logger.success_events().size());
229  EXPECT_EQ(0u, logger.error_events().size());
230
231  base::File::Error error = base::File::FILE_ERROR_NO_MEMORY;
232  bool result = request_manager_->RejectRequest(request_id + 1, error);
233  EXPECT_FALSE(result);
234
235  // Callbacks should not be called.
236  EXPECT_EQ(0u, logger.error_events().size());
237  EXPECT_EQ(0u, logger.success_events().size());
238
239  // Confirm, that the request hasn't been removed, by rejecting it correctly.
240  {
241    bool retry = request_manager_->RejectRequest(request_id, error);
242    EXPECT_TRUE(retry);
243  }
244}
245
246TEST_F(FileSystemProviderRequestManagerTest,
247       CreateAndRejectWithWrongRequestId) {
248  EventLogger logger;
249
250  int request_id = request_manager_->CreateRequest(
251      base::Bind(&EventLogger::OnSuccess, logger.GetWeakPtr()),
252      base::Bind(&EventLogger::OnError, logger.GetWeakPtr()));
253
254  EXPECT_EQ(1, request_id);
255  EXPECT_EQ(0u, logger.success_events().size());
256  EXPECT_EQ(0u, logger.error_events().size());
257
258  base::File::Error error = base::File::FILE_ERROR_NO_MEMORY;
259  bool result = request_manager_->RejectRequest(request_id + 1, error);
260  EXPECT_FALSE(result);
261
262  // Callbacks should not be called.
263  EXPECT_EQ(0u, logger.error_events().size());
264  EXPECT_EQ(0u, logger.success_events().size());
265
266  // Confirm, that the request hasn't been removed, by rejecting it correctly.
267  {
268    bool retry = request_manager_->RejectRequest(request_id, error);
269    EXPECT_TRUE(retry);
270  }
271}
272
273TEST_F(FileSystemProviderRequestManagerTest, UniqueIds) {
274  EventLogger logger;
275
276  int first_request_id = request_manager_->CreateRequest(
277      base::Bind(&EventLogger::OnSuccess, logger.GetWeakPtr()),
278      base::Bind(&EventLogger::OnError, logger.GetWeakPtr()));
279
280  int second_request_id = request_manager_->CreateRequest(
281      base::Bind(&EventLogger::OnSuccess, logger.GetWeakPtr()),
282      base::Bind(&EventLogger::OnError, logger.GetWeakPtr()));
283
284  EXPECT_EQ(1, first_request_id);
285  EXPECT_EQ(2, second_request_id);
286}
287
288TEST_F(FileSystemProviderRequestManagerTest, AbortOnDestroy) {
289  EventLogger logger;
290
291  {
292    RequestManager request_manager;
293    int request_id = request_manager.CreateRequest(
294        base::Bind(&EventLogger::OnSuccess, logger.GetWeakPtr()),
295        base::Bind(&EventLogger::OnError, logger.GetWeakPtr()));
296
297    EXPECT_EQ(1, request_id);
298    EXPECT_EQ(0u, logger.success_events().size());
299    EXPECT_EQ(0u, logger.error_events().size());
300  }
301
302  // All active requests should be aborted in the destructor of RequestManager.
303  EventLogger::ErrorEvent* event = logger.error_events()[0];
304  ASSERT_EQ(1u, logger.error_events().size());
305  EXPECT_EQ(base::File::FILE_ERROR_ABORT, event->error());
306
307  EXPECT_EQ(0u, logger.success_events().size());
308}
309
310TEST_F(FileSystemProviderRequestManagerTest, AbortOnTimeout) {
311  EventLogger logger;
312  base::RunLoop run_loop;
313
314  request_manager_->SetTimeoutForTests(base::TimeDelta::FromSeconds(0));
315  int request_id = request_manager_->CreateRequest(
316      base::Bind(&EventLogger::OnSuccess, logger.GetWeakPtr()),
317      base::Bind(&EventLogger::OnError, logger.GetWeakPtr()));
318  EXPECT_LT(0, request_id);
319
320  // Wait until the request is timeouted.
321  run_loop.RunUntilIdle();
322
323  ASSERT_EQ(1u, logger.error_events().size());
324  EventLogger::ErrorEvent* event = logger.error_events()[0];
325  EXPECT_EQ(base::File::FILE_ERROR_ABORT, event->error());
326}
327
328}  // namespace file_system_provider
329}  // namespace chromeos
330