| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/chromeos/file_system_provider/request_manager.h" |
| |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/files/file.h" |
| #include "base/files/file_path.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/scoped_vector.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/run_loop.h" |
| #include "chrome/browser/chromeos/file_system_provider/notification_manager_interface.h" |
| #include "chrome/browser/chromeos/file_system_provider/request_value.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace chromeos { |
| namespace file_system_provider { |
| namespace { |
| |
| // Fake implementation for the notification manager. Simulates user action on |
| // a notification. |
| class FakeNotificationManager : public NotificationManagerInterface { |
| public: |
| FakeNotificationManager() {} |
| ~FakeNotificationManager() override {} |
| |
| // NotificationManagerInterface overrides: |
| void ShowUnresponsiveNotification( |
| int id, |
| const NotificationCallback& callback) override { |
| callbacks_[id] = callback; |
| } |
| |
| void HideUnresponsiveNotification(int id) override { callbacks_.erase(id); } |
| |
| // Aborts all of the virtually shown notifications. |
| void Abort() { OnNotificationResult(ABORT); } |
| |
| // Discards all of the virtually shown notifications. |
| void Continue() { OnNotificationResult(CONTINUE); } |
| |
| // Returns number of currently shown notifications. |
| size_t size() { return callbacks_.size(); } |
| |
| private: |
| typedef std::map<int, NotificationCallback> CallbackMap; |
| |
| // Handles a notification result by calling all registered callbacks and |
| // clearing the list. |
| void OnNotificationResult(NotificationResult result) { |
| CallbackMap::iterator it = callbacks_.begin(); |
| while (it != callbacks_.end()) { |
| CallbackMap::iterator current_it = it++; |
| NotificationCallback callback = current_it->second; |
| callbacks_.erase(current_it); |
| callback.Run(result); |
| } |
| } |
| |
| CallbackMap callbacks_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FakeNotificationManager); |
| }; |
| |
| // Logs calls of the success and error callbacks on requests. |
| class EventLogger { |
| public: |
| class ExecuteEvent { |
| public: |
| explicit ExecuteEvent(int request_id) : request_id_(request_id) {} |
| virtual ~ExecuteEvent() {} |
| |
| int request_id() { return request_id_; } |
| |
| private: |
| int request_id_; |
| }; |
| |
| class SuccessEvent { |
| public: |
| SuccessEvent(int request_id, scoped_ptr<RequestValue> result, bool has_more) |
| : request_id_(request_id), |
| result_(result.Pass()), |
| has_more_(has_more) {} |
| virtual ~SuccessEvent() {} |
| |
| int request_id() { return request_id_; } |
| RequestValue* result() { return result_.get(); } |
| bool has_more() { return has_more_; } |
| |
| private: |
| int request_id_; |
| scoped_ptr<RequestValue> result_; |
| bool has_more_; |
| }; |
| |
| class ErrorEvent { |
| public: |
| ErrorEvent(int request_id, |
| scoped_ptr<RequestValue> result, |
| base::File::Error error) |
| : request_id_(request_id), result_(result.Pass()), error_(error) {} |
| virtual ~ErrorEvent() {} |
| |
| int request_id() { return request_id_; } |
| RequestValue* result() { return result_.get(); } |
| base::File::Error error() { return error_; } |
| |
| private: |
| int request_id_; |
| scoped_ptr<RequestValue> result_; |
| base::File::Error error_; |
| }; |
| |
| EventLogger() : weak_ptr_factory_(this) {} |
| virtual ~EventLogger() {} |
| |
| void OnExecute(int request_id) { |
| execute_events_.push_back(new ExecuteEvent(request_id)); |
| } |
| |
| void OnSuccess(int request_id, |
| scoped_ptr<RequestValue> result, |
| bool has_more) { |
| success_events_.push_back( |
| new SuccessEvent(request_id, result.Pass(), has_more)); |
| } |
| |
| void OnError(int request_id, |
| scoped_ptr<RequestValue> result, |
| base::File::Error error) { |
| error_events_.push_back(new ErrorEvent(request_id, result.Pass(), error)); |
| } |
| |
| ScopedVector<ExecuteEvent>& execute_events() { return execute_events_; } |
| ScopedVector<SuccessEvent>& success_events() { return success_events_; } |
| ScopedVector<ErrorEvent>& error_events() { return error_events_; } |
| |
| base::WeakPtr<EventLogger> GetWeakPtr() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| private: |
| ScopedVector<ExecuteEvent> execute_events_; |
| ScopedVector<SuccessEvent> success_events_; |
| ScopedVector<ErrorEvent> error_events_; |
| base::WeakPtrFactory<EventLogger> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(EventLogger); |
| }; |
| |
| // Fake handler, which forwards callbacks to the logger. The handler is owned |
| // by a request manager, however the logger is owned by tests. |
| class FakeHandler : public RequestManager::HandlerInterface { |
| public: |
| // The handler can outlive the passed logger, so using a weak pointer. The |
| // |execute_reply| value will be returned for the Execute() call. |
| FakeHandler(base::WeakPtr<EventLogger> logger, bool execute_reply) |
| : logger_(logger), execute_reply_(execute_reply) {} |
| |
| // RequestManager::Handler overrides. |
| bool Execute(int request_id) override { |
| if (logger_.get()) |
| logger_->OnExecute(request_id); |
| |
| return execute_reply_; |
| } |
| |
| // RequestManager::Handler overrides. |
| void OnSuccess(int request_id, |
| scoped_ptr<RequestValue> result, |
| bool has_more) override { |
| if (logger_.get()) |
| logger_->OnSuccess(request_id, result.Pass(), has_more); |
| } |
| |
| // RequestManager::Handler overrides. |
| void OnError(int request_id, |
| scoped_ptr<RequestValue> result, |
| base::File::Error error) override { |
| if (logger_.get()) |
| logger_->OnError(request_id, result.Pass(), error); |
| } |
| |
| ~FakeHandler() override {} |
| |
| private: |
| base::WeakPtr<EventLogger> logger_; |
| bool execute_reply_; |
| DISALLOW_COPY_AND_ASSIGN(FakeHandler); |
| }; |
| |
| // Observer the request manager for request events. |
| class RequestObserver : public RequestManager::Observer { |
| public: |
| class Event { |
| public: |
| explicit Event(int request_id) : request_id_(request_id) {} |
| virtual ~Event() {} |
| int request_id() const { return request_id_; } |
| |
| private: |
| int request_id_; |
| }; |
| |
| class CreatedEvent : public Event { |
| public: |
| CreatedEvent(int request_id, RequestType type) |
| : Event(request_id), type_(type) {} |
| ~CreatedEvent() override {} |
| |
| RequestType type() const { return type_; } |
| |
| private: |
| RequestType type_; |
| }; |
| |
| class FulfilledEvent : public Event { |
| public: |
| FulfilledEvent(int request_id, bool has_more) |
| : Event(request_id), has_more_(has_more) {} |
| ~FulfilledEvent() override {} |
| |
| bool has_more() const { return has_more_; } |
| |
| private: |
| bool has_more_; |
| }; |
| |
| class RejectedEvent : public Event { |
| public: |
| RejectedEvent(int request_id, base::File::Error error) |
| : Event(request_id), error_(error) {} |
| ~RejectedEvent() override {} |
| |
| base::File::Error error() const { return error_; } |
| |
| private: |
| base::File::Error error_; |
| }; |
| |
| RequestObserver() {} |
| ~RequestObserver() override {} |
| |
| // RequestManager::Observer overrides. |
| void OnRequestCreated(int request_id, RequestType type) override { |
| created_.push_back(CreatedEvent(request_id, type)); |
| } |
| |
| // RequestManager::Observer overrides. |
| void OnRequestDestroyed(int request_id) override { |
| destroyed_.push_back(Event(request_id)); |
| } |
| |
| // RequestManager::Observer overrides. |
| void OnRequestExecuted(int request_id) override { |
| executed_.push_back(Event(request_id)); |
| } |
| |
| // RequestManager::Observer overrides. |
| void OnRequestFulfilled(int request_id, |
| const RequestValue& result, |
| bool has_more) override { |
| fulfilled_.push_back(FulfilledEvent(request_id, has_more)); |
| } |
| |
| // RequestManager::Observer overrides. |
| void OnRequestRejected(int request_id, |
| const RequestValue& result, |
| base::File::Error error) override { |
| rejected_.push_back(RejectedEvent(request_id, error)); |
| } |
| |
| // RequestManager::Observer overrides. |
| void OnRequestTimeouted(int request_id) override { |
| timeouted_.push_back(Event(request_id)); |
| } |
| |
| const std::vector<CreatedEvent>& created() const { return created_; } |
| const std::vector<Event>& destroyed() const { return destroyed_; } |
| const std::vector<Event>& executed() const { return executed_; } |
| const std::vector<FulfilledEvent>& fulfilled() const { return fulfilled_; } |
| const std::vector<RejectedEvent>& rejected() const { return rejected_; } |
| const std::vector<Event>& timeouted() const { return timeouted_; } |
| |
| private: |
| std::vector<CreatedEvent> created_; |
| std::vector<Event> destroyed_; |
| std::vector<Event> executed_; |
| std::vector<FulfilledEvent> fulfilled_; |
| std::vector<RejectedEvent> rejected_; |
| std::vector<Event> timeouted_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RequestObserver); |
| }; |
| |
| } // namespace |
| |
| class FileSystemProviderRequestManagerTest : public testing::Test { |
| protected: |
| FileSystemProviderRequestManagerTest() {} |
| ~FileSystemProviderRequestManagerTest() override {} |
| |
| void SetUp() override { |
| profile_.reset(new TestingProfile); |
| notification_manager_.reset(new FakeNotificationManager); |
| request_manager_.reset(new RequestManager(profile_.get(), |
| std::string() /* extension_id */, |
| notification_manager_.get())); |
| } |
| |
| content::TestBrowserThreadBundle thread_bundle_; |
| scoped_ptr<TestingProfile> profile_; |
| scoped_ptr<FakeNotificationManager> notification_manager_; |
| scoped_ptr<RequestManager> request_manager_; |
| }; |
| |
| TEST_F(FileSystemProviderRequestManagerTest, CreateFailure) { |
| EventLogger logger; |
| RequestObserver observer; |
| request_manager_->AddObserver(&observer); |
| |
| const int request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), false /* execute_reply */))); |
| |
| EXPECT_EQ(0, request_id); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| |
| EXPECT_EQ(1u, observer.created().size()); |
| EXPECT_EQ(TESTING, observer.created()[0].type()); |
| EXPECT_EQ(1u, observer.destroyed().size()); |
| EXPECT_EQ(0u, observer.executed().size()); |
| |
| const std::vector<int> active_request_ids = |
| request_manager_->GetActiveRequestIds(); |
| EXPECT_EQ(0u, active_request_ids.size()); |
| |
| request_manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(FileSystemProviderRequestManagerTest, CreateAndFulFill) { |
| EventLogger logger; |
| RequestObserver observer; |
| request_manager_->AddObserver(&observer); |
| |
| const int request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| |
| EXPECT_EQ(1, request_id); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| |
| ASSERT_EQ(1u, observer.created().size()); |
| EXPECT_EQ(request_id, observer.created()[0].request_id()); |
| EXPECT_EQ(TESTING, observer.created()[0].type()); |
| |
| ASSERT_EQ(1u, observer.executed().size()); |
| EXPECT_EQ(request_id, observer.executed()[0].request_id()); |
| |
| const std::vector<int> active_request_ids = |
| request_manager_->GetActiveRequestIds(); |
| ASSERT_EQ(1u, active_request_ids.size()); |
| EXPECT_EQ(request_id, active_request_ids[0]); |
| |
| scoped_ptr<RequestValue> response( |
| RequestValue::CreateForTesting("i-like-vanilla")); |
| const bool has_more = false; |
| |
| const base::File::Error result = |
| request_manager_->FulfillRequest(request_id, response.Pass(), has_more); |
| EXPECT_EQ(base::File::FILE_OK, result); |
| |
| ASSERT_EQ(1u, observer.fulfilled().size()); |
| EXPECT_EQ(request_id, observer.fulfilled()[0].request_id()); |
| EXPECT_FALSE(observer.fulfilled()[0].has_more()); |
| |
| // Validate if the callback has correct arguments. |
| ASSERT_EQ(1u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| EventLogger::SuccessEvent* event = logger.success_events()[0]; |
| ASSERT_TRUE(event->result()); |
| const std::string* response_test_string = event->result()->testing_params(); |
| ASSERT_TRUE(response_test_string); |
| EXPECT_EQ("i-like-vanilla", *response_test_string); |
| EXPECT_FALSE(event->has_more()); |
| |
| // Confirm, that the request is removed. Basically, fulfilling again for the |
| // same request, should fail. |
| { |
| const std::vector<int> active_request_ids = |
| request_manager_->GetActiveRequestIds(); |
| EXPECT_EQ(0u, active_request_ids.size()); |
| |
| const base::File::Error retry = request_manager_->FulfillRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue), has_more); |
| EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, retry); |
| EXPECT_EQ(1u, observer.fulfilled().size()); |
| } |
| |
| // Rejecting should also fail. |
| { |
| const base::File::Error retry = request_manager_->RejectRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue()), |
| base::File::FILE_ERROR_FAILED); |
| EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, retry); |
| EXPECT_EQ(0u, observer.rejected().size()); |
| } |
| |
| ASSERT_EQ(1u, observer.destroyed().size()); |
| EXPECT_EQ(request_id, observer.destroyed()[0].request_id()); |
| EXPECT_EQ(0u, observer.timeouted().size()); |
| |
| request_manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(FileSystemProviderRequestManagerTest, CreateAndFulFill_WithHasNext) { |
| EventLogger logger; |
| RequestObserver observer; |
| request_manager_->AddObserver(&observer); |
| |
| const int request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| |
| EXPECT_EQ(1, request_id); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| |
| ASSERT_EQ(1u, observer.created().size()); |
| EXPECT_EQ(request_id, observer.created()[0].request_id()); |
| EXPECT_EQ(TESTING, observer.created()[0].type()); |
| |
| ASSERT_EQ(1u, observer.executed().size()); |
| EXPECT_EQ(request_id, observer.executed()[0].request_id()); |
| |
| const bool has_more = true; |
| |
| const base::File::Error result = request_manager_->FulfillRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue), has_more); |
| EXPECT_EQ(base::File::FILE_OK, result); |
| |
| // Validate if the callback has correct arguments. |
| ASSERT_EQ(1u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| EventLogger::SuccessEvent* event = logger.success_events()[0]; |
| EXPECT_TRUE(event->result()); |
| EXPECT_TRUE(event->has_more()); |
| |
| ASSERT_EQ(1u, observer.fulfilled().size()); |
| EXPECT_EQ(request_id, observer.fulfilled()[0].request_id()); |
| EXPECT_TRUE(observer.fulfilled()[0].has_more()); |
| |
| // Confirm, that the request is not removed (since it has has_more == true). |
| // Basically, fulfilling again for the same request, should not fail. |
| { |
| const std::vector<int> active_request_ids = |
| request_manager_->GetActiveRequestIds(); |
| ASSERT_EQ(1u, active_request_ids.size()); |
| EXPECT_EQ(request_id, active_request_ids[0]); |
| |
| const bool new_has_more = false; |
| const base::File::Error retry = request_manager_->FulfillRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue), new_has_more); |
| EXPECT_EQ(base::File::FILE_OK, retry); |
| |
| ASSERT_EQ(2u, observer.fulfilled().size()); |
| EXPECT_EQ(request_id, observer.fulfilled()[1].request_id()); |
| EXPECT_FALSE(observer.fulfilled()[1].has_more()); |
| } |
| |
| // Since |new_has_more| is false, then the request should be removed. To check |
| // it, try to fulfill again, what should fail. |
| { |
| const std::vector<int> active_request_ids = |
| request_manager_->GetActiveRequestIds(); |
| EXPECT_EQ(0u, active_request_ids.size()); |
| |
| const bool new_has_more = false; |
| const base::File::Error retry = request_manager_->FulfillRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue), new_has_more); |
| EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, retry); |
| EXPECT_EQ(0u, observer.rejected().size()); |
| } |
| |
| ASSERT_EQ(1u, observer.destroyed().size()); |
| EXPECT_EQ(request_id, observer.destroyed()[0].request_id()); |
| EXPECT_EQ(0u, observer.timeouted().size()); |
| |
| request_manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(FileSystemProviderRequestManagerTest, CreateAndReject) { |
| EventLogger logger; |
| RequestObserver observer; |
| request_manager_->AddObserver(&observer); |
| |
| const int request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| |
| EXPECT_EQ(1, request_id); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| |
| ASSERT_EQ(1u, observer.created().size()); |
| EXPECT_EQ(request_id, observer.created()[0].request_id()); |
| EXPECT_EQ(TESTING, observer.created()[0].type()); |
| |
| ASSERT_EQ(1u, observer.executed().size()); |
| EXPECT_EQ(request_id, observer.executed()[0].request_id()); |
| |
| const base::File::Error error = base::File::FILE_ERROR_NO_MEMORY; |
| const base::File::Error result = request_manager_->RejectRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue()), error); |
| EXPECT_EQ(base::File::FILE_OK, result); |
| |
| // Validate if the callback has correct arguments. |
| ASSERT_EQ(1u, logger.error_events().size()); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EventLogger::ErrorEvent* event = logger.error_events()[0]; |
| EXPECT_EQ(error, event->error()); |
| |
| ASSERT_EQ(1u, observer.rejected().size()); |
| EXPECT_EQ(request_id, observer.rejected()[0].request_id()); |
| EXPECT_EQ(error, observer.rejected()[0].error()); |
| |
| // Confirm, that the request is removed. Basically, fulfilling again for the |
| // same request, should fail. |
| { |
| const bool has_more = false; |
| const base::File::Error retry = request_manager_->FulfillRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue), has_more); |
| EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, retry); |
| EXPECT_EQ(0u, observer.fulfilled().size()); |
| } |
| |
| // Rejecting should also fail. |
| { |
| const base::File::Error retry = request_manager_->RejectRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue()), error); |
| EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, retry); |
| EXPECT_EQ(1u, observer.rejected().size()); |
| } |
| |
| ASSERT_EQ(1u, observer.destroyed().size()); |
| EXPECT_EQ(request_id, observer.destroyed()[0].request_id()); |
| EXPECT_EQ(0u, observer.timeouted().size()); |
| |
| request_manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(FileSystemProviderRequestManagerTest, |
| CreateAndFulfillWithWrongRequestId) { |
| EventLogger logger; |
| RequestObserver observer; |
| request_manager_->AddObserver(&observer); |
| |
| const int request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| |
| EXPECT_EQ(1, request_id); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| |
| ASSERT_EQ(1u, observer.created().size()); |
| EXPECT_EQ(request_id, observer.created()[0].request_id()); |
| EXPECT_EQ(TESTING, observer.created()[0].type()); |
| |
| ASSERT_EQ(1u, observer.executed().size()); |
| EXPECT_EQ(request_id, observer.executed()[0].request_id()); |
| |
| const bool has_more = true; |
| |
| const base::File::Error result = request_manager_->FulfillRequest( |
| request_id + 1, scoped_ptr<RequestValue>(new RequestValue), has_more); |
| EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, result); |
| |
| // Callbacks should not be called. |
| EXPECT_EQ(0u, logger.error_events().size()); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| |
| EXPECT_EQ(0u, observer.fulfilled().size()); |
| EXPECT_EQ(request_id, observer.executed()[0].request_id()); |
| |
| // Confirm, that the request hasn't been removed, by fulfilling it correctly. |
| { |
| const base::File::Error retry = request_manager_->FulfillRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue), has_more); |
| EXPECT_EQ(base::File::FILE_OK, retry); |
| EXPECT_EQ(1u, observer.fulfilled().size()); |
| } |
| |
| request_manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(FileSystemProviderRequestManagerTest, |
| CreateAndRejectWithWrongRequestId) { |
| EventLogger logger; |
| RequestObserver observer; |
| request_manager_->AddObserver(&observer); |
| |
| const int request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| |
| EXPECT_EQ(1, request_id); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| |
| ASSERT_EQ(1u, observer.created().size()); |
| EXPECT_EQ(request_id, observer.created()[0].request_id()); |
| EXPECT_EQ(TESTING, observer.created()[0].type()); |
| |
| ASSERT_EQ(1u, observer.executed().size()); |
| EXPECT_EQ(request_id, observer.executed()[0].request_id()); |
| |
| const base::File::Error error = base::File::FILE_ERROR_NO_MEMORY; |
| const base::File::Error result = request_manager_->RejectRequest( |
| request_id + 1, scoped_ptr<RequestValue>(new RequestValue()), error); |
| EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, result); |
| |
| // Callbacks should not be called. |
| EXPECT_EQ(0u, logger.error_events().size()); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| |
| EXPECT_EQ(0u, observer.rejected().size()); |
| |
| // Confirm, that the request hasn't been removed, by rejecting it correctly. |
| { |
| const base::File::Error retry = request_manager_->RejectRequest( |
| request_id, scoped_ptr<RequestValue>(new RequestValue()), error); |
| EXPECT_EQ(base::File::FILE_OK, retry); |
| EXPECT_EQ(1u, observer.rejected().size()); |
| } |
| |
| request_manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(FileSystemProviderRequestManagerTest, UniqueIds) { |
| EventLogger logger; |
| |
| const int first_request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| |
| const int second_request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| |
| EXPECT_EQ(1, first_request_id); |
| EXPECT_EQ(2, second_request_id); |
| } |
| |
| TEST_F(FileSystemProviderRequestManagerTest, AbortOnDestroy) { |
| EventLogger logger; |
| RequestObserver observer; |
| int request_id; |
| |
| { |
| RequestManager request_manager(profile_.get(), |
| std::string() /* extension_id */, nullptr); |
| request_manager.AddObserver(&observer); |
| |
| request_id = request_manager.CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| |
| EXPECT_EQ(1, request_id); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| |
| ASSERT_EQ(1u, observer.created().size()); |
| EXPECT_EQ(request_id, observer.created()[0].request_id()); |
| EXPECT_EQ(TESTING, observer.created()[0].type()); |
| |
| ASSERT_EQ(1u, observer.executed().size()); |
| EXPECT_EQ(request_id, observer.executed()[0].request_id()); |
| |
| EXPECT_EQ(0u, observer.fulfilled().size()); |
| EXPECT_EQ(0u, observer.rejected().size()); |
| EXPECT_EQ(0u, observer.destroyed().size()); |
| EXPECT_EQ(0u, observer.timeouted().size()); |
| |
| // Do not remove the observer, to catch events while destructing. |
| } |
| |
| // All active requests should be aborted in the destructor of RequestManager. |
| ASSERT_EQ(1u, logger.error_events().size()); |
| EventLogger::ErrorEvent* event = logger.error_events()[0]; |
| EXPECT_EQ(base::File::FILE_ERROR_ABORT, event->error()); |
| |
| EXPECT_EQ(0u, logger.success_events().size()); |
| |
| EXPECT_EQ(0u, observer.fulfilled().size()); |
| EXPECT_EQ(0u, observer.timeouted().size()); |
| ASSERT_EQ(1u, observer.rejected().size()); |
| EXPECT_EQ(request_id, observer.rejected()[0].request_id()); |
| EXPECT_EQ(base::File::FILE_ERROR_ABORT, observer.rejected()[0].error()); |
| ASSERT_EQ(1u, observer.destroyed().size()); |
| } |
| |
| TEST_F(FileSystemProviderRequestManagerTest, AbortOnTimeout) { |
| EventLogger logger; |
| RequestObserver observer; |
| request_manager_->AddObserver(&observer); |
| |
| request_manager_->SetTimeoutForTesting(base::TimeDelta::FromSeconds(0)); |
| const int request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| EXPECT_EQ(1, request_id); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| EXPECT_EQ(0u, notification_manager_->size()); |
| |
| ASSERT_EQ(1u, observer.created().size()); |
| EXPECT_EQ(request_id, observer.created()[0].request_id()); |
| EXPECT_EQ(TESTING, observer.created()[0].type()); |
| |
| ASSERT_EQ(1u, observer.executed().size()); |
| EXPECT_EQ(request_id, observer.executed()[0].request_id()); |
| |
| // Wait until the request is timeouted. |
| base::RunLoop().RunUntilIdle(); |
| |
| // Abort the request. |
| EXPECT_EQ(1u, notification_manager_->size()); |
| notification_manager_->Abort(); |
| EXPECT_EQ(0u, notification_manager_->size()); |
| |
| ASSERT_EQ(1u, logger.error_events().size()); |
| EventLogger::ErrorEvent* event = logger.error_events()[0]; |
| EXPECT_EQ(base::File::FILE_ERROR_ABORT, event->error()); |
| |
| ASSERT_EQ(1u, observer.rejected().size()); |
| EXPECT_EQ(request_id, observer.rejected()[0].request_id()); |
| EXPECT_EQ(base::File::FILE_ERROR_ABORT, observer.rejected()[0].error()); |
| ASSERT_EQ(1u, observer.timeouted().size()); |
| EXPECT_EQ(request_id, observer.timeouted()[0].request_id()); |
| ASSERT_EQ(1u, observer.destroyed().size()); |
| EXPECT_EQ(request_id, observer.destroyed()[0].request_id()); |
| |
| request_manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(FileSystemProviderRequestManagerTest, ContinueOnTimeout) { |
| EventLogger logger; |
| RequestObserver observer; |
| request_manager_->AddObserver(&observer); |
| |
| request_manager_->SetTimeoutForTesting(base::TimeDelta::FromSeconds(0)); |
| const int request_id = request_manager_->CreateRequest( |
| TESTING, |
| make_scoped_ptr<RequestManager::HandlerInterface>( |
| new FakeHandler(logger.GetWeakPtr(), true /* execute_reply */))); |
| EXPECT_EQ(1, request_id); |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| EXPECT_EQ(0u, notification_manager_->size()); |
| |
| ASSERT_EQ(1u, observer.created().size()); |
| EXPECT_EQ(request_id, observer.created()[0].request_id()); |
| EXPECT_EQ(TESTING, observer.created()[0].type()); |
| |
| ASSERT_EQ(1u, observer.executed().size()); |
| EXPECT_EQ(request_id, observer.executed()[0].request_id()); |
| |
| // Wait until the request is timeouted. |
| base::RunLoop().RunUntilIdle(); |
| |
| // Let the extension more time by closing the notification. |
| EXPECT_EQ(1u, notification_manager_->size()); |
| notification_manager_->Continue(); |
| EXPECT_EQ(0u, notification_manager_->size()); |
| |
| // The request is still active. |
| EXPECT_EQ(0u, logger.success_events().size()); |
| EXPECT_EQ(0u, logger.error_events().size()); |
| |
| // Wait until the request is timeouted again. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1u, notification_manager_->size()); |
| |
| request_manager_->RemoveObserver(&observer); |
| } |
| |
| } // namespace file_system_provider |
| } // namespace chromeos |