libchromeos: Migrate AsyncEventSequencer to libchromeos This enables sharing this functionality between peerd and buffet. BUG=chromium:398626 TEST=libchromeos/buffet unittests Change-Id: Ic38b9bbf491b57d18b0409f0587efedeab6ef988 Reviewed-on: https://chromium-review.googlesource.com/210402 Reviewed-by: Alex Vakulenko <avakulenko@chromium.org> Commit-Queue: Alex Vakulenko <avakulenko@chromium.org> Tested-by: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/async_event_sequencer.cc b/buffet/async_event_sequencer.cc deleted file mode 100644 index b90b552..0000000 --- a/buffet/async_event_sequencer.cc +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2014 The Chromium OS 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 "buffet/async_event_sequencer.h" - -namespace buffet { - -namespace dbus_utils { - -AsyncEventSequencer::AsyncEventSequencer() { } -AsyncEventSequencer::~AsyncEventSequencer() { } - -AsyncEventSequencer::Handler AsyncEventSequencer::GetHandler( - const std::string& descriptive_message, bool failure_is_fatal) { - CHECK(!started_) << "Cannot create handlers after OnAllTasksCompletedCall()"; - int unique_registration_id = ++registration_counter_; - outstanding_registrations_.insert(unique_registration_id); - return base::Bind(&AsyncEventSequencer::HandleFinish, this, - unique_registration_id, descriptive_message, - failure_is_fatal); -} - -AsyncEventSequencer::ExportHandler AsyncEventSequencer::GetExportHandler( - const std::string& interface_name, const std::string& method_name, - const std::string& descriptive_message, bool failure_is_fatal) { - auto finish_handler = GetHandler(descriptive_message, failure_is_fatal); - return base::Bind(&AsyncEventSequencer::HandleDBusMethodExported, this, - finish_handler, - interface_name, - method_name); -} - -void AsyncEventSequencer::OnAllTasksCompletedCall( - std::vector<CompletionAction> actions) { - CHECK(!started_) << "OnAllTasksCompletedCall called twice!"; - started_ = true; - completion_actions_.assign(actions.begin(), actions.end()); - // All of our callbacks might have been called already. - PossiblyRunCompletionActions(); -} - -namespace { -void IgnoreSuccess(const AsyncEventSequencer::CompletionTask& task, - bool /*success*/) { task.Run(); } -} // namespace - -AsyncEventSequencer::CompletionAction AsyncEventSequencer::WrapCompletionTask( - const CompletionTask& task) { - return base::Bind(&IgnoreSuccess, task); -} - -void AsyncEventSequencer::HandleFinish(int registration_number, - const std::string& error_message, - bool failure_is_fatal, bool success) { - RetireRegistration(registration_number); - CheckForFailure(failure_is_fatal, success, error_message); - PossiblyRunCompletionActions(); -} - -void AsyncEventSequencer::HandleDBusMethodExported( - const AsyncEventSequencer::Handler& finish_handler, - const std::string& expected_interface_name, - const std::string& expected_method_name, - const std::string& actual_interface_name, - const std::string& actual_method_name, bool success) { - CHECK_EQ(expected_method_name, actual_method_name) - << "Exported DBus method '" << actual_method_name << "' " - << "but expected '" << expected_method_name << "'"; - CHECK_EQ(expected_interface_name, actual_interface_name) - << "Exported method DBus interface '" << actual_interface_name << "' " - << "but expected '" << expected_interface_name << "'"; - finish_handler.Run(success); -} - - -void AsyncEventSequencer::RetireRegistration(int registration_number) { - const size_t handlers_retired = outstanding_registrations_.erase( - registration_number); - CHECK_EQ(1, handlers_retired) - << "Tried to retire invalid handler " << registration_number << ")"; -} - -void AsyncEventSequencer::CheckForFailure(bool failure_is_fatal, bool success, - const std::string& error_message) { - if (failure_is_fatal) { - CHECK(success) << error_message; - } - if (!success) { - LOG(ERROR) << error_message; - had_failures_ = true; - } -} - -void AsyncEventSequencer::PossiblyRunCompletionActions() { - if (!started_ || !outstanding_registrations_.empty()) { - // Don't run completion actions if we have any outstanding - // Handlers outstanding or if any more handlers might - // be scheduled in the future. - return; - } - for (const auto& completion_action : completion_actions_) { - // Should this be put on the message loop or run directly? - completion_action.Run(!had_failures_); - } - // Discard our references to those actions. - completion_actions_.clear(); -} - -} // namespace dbus_utils - -} // namespace buffet
diff --git a/buffet/async_event_sequencer.h b/buffet/async_event_sequencer.h deleted file mode 100644 index c16325b..0000000 --- a/buffet/async_event_sequencer.h +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2014 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BUFFET_ASYNC_EVENT_SEQUENCER_H_ -#define BUFFET_ASYNC_EVENT_SEQUENCER_H_ - -#include <set> -#include <string> -#include <vector> - -#include <base/bind.h> -#include <base/basictypes.h> -#include <base/memory/ref_counted.h> - -namespace buffet { - -namespace dbus_utils { - -// A helper class for coordinating the multiple async tasks. A consumer -// may grab any number of callbacks via Get*Handler() and schedule a list -// of completion actions to take. When all handlers obtained via Get*Handler() -// have been called, the AsyncEventSequencer will call its CompletionActions. -// -// Usage: -// -// void Init(const base::Callback<void(bool success)> cb) { -// scoped_refptr<AsyncEventSequencer> sequencer( -// new AsyncEventSequencer()); -// one_delegate_needing_init_.Init(sequencer->GetHandler( -// "my delegate failed to init", false)); -// dbus_init_delegate_.Init(sequencer->GetExportHandler( -// "org.test.Interface", "ExposedMethodName", -// "another delegate is flaky", false)); -// sequencer->OnAllTasksCompletedCall({cb}); -// } -class AsyncEventSequencer : public base::RefCounted<AsyncEventSequencer> { - public: - typedef base::Callback<void(bool success)> Handler; - typedef base::Callback<void (const std::string& interface_name, - const std::string& method_name, - bool success)> ExportHandler; - typedef base::Callback<void(bool all_succeeded)> CompletionAction; - typedef base::Callback<void(void)> CompletionTask; - - AsyncEventSequencer(); - - // Get a Finished handler callback. Each callback is "unique" in the sense - // that subsequent calls to GetHandler() will create new handlers - // which will need to be called before completion actions are run. - Handler GetHandler(const std::string& descriptive_message, - bool failure_is_fatal); - - // Like GetHandler except with a signature tailored to - // ExportedObject's ExportMethod callback requirements. Will also assert - // that the passed interface/method names from ExportedObject are correct. - ExportHandler GetExportHandler( - const std::string& interface_name, const std::string& method_name, - const std::string& descriptive_message, bool failure_is_fatal); - - // Once all handlers obtained via GetHandler have run, - // we'll run each CompletionAction, then discard our references. - // No more handlers may be obtained after this call. - void OnAllTasksCompletedCall(std::vector<CompletionAction> actions); - - // Wrap a CompletionTask with a function that discards the result. - // This CompletionTask retains no references to the AsyncEventSequencer. - CompletionAction WrapCompletionTask(const CompletionTask& task); - - private: - // We'll partially bind this function before giving it back via - // GetHandler. Note that the returned callbacks have - // references to *this, which gives us the neat property that we'll - // destroy *this only when all our callbacks have been destroyed. - void HandleFinish(int registration_number, const std::string& error_message, - bool failure_is_fatal, bool success); - // Similar to HandleFinish. - void HandleDBusMethodExported( - const Handler& finish_handler, - const std::string& expected_interface_name, - const std::string& expected_method_name, - const std::string& actual_interface_name, - const std::string& actual_method_name, - bool success); - void RetireRegistration(int registration_number); - void CheckForFailure(bool failure_is_fatal, bool success, - const std::string& error_message); - void PossiblyRunCompletionActions(); - - bool started_{false}; - int registration_counter_{0}; - std::set<int> outstanding_registrations_; - std::vector<CompletionAction> completion_actions_; - bool had_failures_{false}; - // Ref counted objects have private destructors. - ~AsyncEventSequencer(); - friend class base::RefCounted<AsyncEventSequencer>; - DISALLOW_COPY_AND_ASSIGN(AsyncEventSequencer); -}; - -} // namespace dbus_utils - -} // namespace buffet - -#endif // BUFFET_ASYNC_EVENT_SEQUENCER_H_
diff --git a/buffet/async_event_sequencer_unittest.cc b/buffet/async_event_sequencer_unittest.cc deleted file mode 100644 index d95ff56..0000000 --- a/buffet/async_event_sequencer_unittest.cc +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2014 The Chromium OS 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 "buffet/async_event_sequencer.h" - -#include <base/bind_helpers.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -namespace buffet { - -namespace dbus_utils { - -namespace { - -const char kTestInterface[] = "org.test.if"; -const char kTestMethod1[] = "TestMethod1"; -const char kTestMethod2[] = "TestMethod2"; - -} // namespace - -class AsyncEventSequencerTest : public ::testing::Test { - public: - MOCK_METHOD1(HandleCompletion, void(bool all_succeeded)); - - void SetUp() { - aec_ = new AsyncEventSequencer(); - cb_ = base::Bind(&AsyncEventSequencerTest::HandleCompletion, - base::Unretained(this)); - } - - scoped_refptr<AsyncEventSequencer> aec_; - AsyncEventSequencer::CompletionAction cb_; -}; - -TEST_F(AsyncEventSequencerTest, WaitForCompletionActions) { - auto finished_handler = aec_->GetHandler("handler failed", false); - finished_handler.Run(true); - EXPECT_CALL(*this, HandleCompletion(true)).Times(1); - aec_->OnAllTasksCompletedCall({cb_}); -} - -TEST_F(AsyncEventSequencerTest, MultiInitActionsSucceed) { - auto finished_handler1 = aec_->GetHandler("handler failed", false); - auto finished_handler2 = aec_->GetHandler("handler failed", false); - aec_->OnAllTasksCompletedCall({cb_}); - finished_handler1.Run(true); - EXPECT_CALL(*this, HandleCompletion(true)).Times(1); - finished_handler2.Run(true); -} - -TEST_F(AsyncEventSequencerTest, SomeInitActionsFail) { - auto finished_handler1 = aec_->GetHandler("handler failed", false); - auto finished_handler2 = aec_->GetHandler("handler failed", false); - aec_->OnAllTasksCompletedCall({cb_}); - finished_handler1.Run(false); - EXPECT_CALL(*this, HandleCompletion(false)).Times(1); - finished_handler2.Run(true); -} - -TEST_F(AsyncEventSequencerTest, MultiDBusActionsSucceed) { - auto handler1 = aec_->GetExportHandler( - kTestInterface, kTestMethod1, "method export failed", false); - auto handler2 = aec_->GetExportHandler( - kTestInterface, kTestMethod2, "method export failed", false); - aec_->OnAllTasksCompletedCall({cb_}); - handler1.Run(kTestInterface, kTestMethod1, true); - EXPECT_CALL(*this, HandleCompletion(true)).Times(1); - handler2.Run(kTestInterface, kTestMethod2, true); -} - -TEST_F(AsyncEventSequencerTest, SomeDBusActionsFail) { - auto handler1 = aec_->GetExportHandler( - kTestInterface, kTestMethod1, "method export failed", false); - auto handler2 = aec_->GetExportHandler( - kTestInterface, kTestMethod2, "method export failed", false); - aec_->OnAllTasksCompletedCall({cb_}); - handler1.Run(kTestInterface, kTestMethod1, true); - EXPECT_CALL(*this, HandleCompletion(false)).Times(1); - handler2.Run(kTestInterface, kTestMethod2, false); -} - -TEST_F(AsyncEventSequencerTest, MixedActions) { - auto handler1 = aec_->GetExportHandler( - kTestInterface, kTestMethod1, "method export failed", false); - auto handler2 = aec_->GetHandler("handler failed", false); - aec_->OnAllTasksCompletedCall({cb_}); - handler1.Run(kTestInterface, kTestMethod1, true); - EXPECT_CALL(*this, HandleCompletion(true)).Times(1); - handler2.Run(true); -} - -} // namespace dbus_utils - -} // namespace buffet
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp index 001d610..a9300c4 100644 --- a/buffet/buffet.gyp +++ b/buffet/buffet.gyp
@@ -5,6 +5,7 @@ 'dbus-1', 'libchrome-<(libbase_ver)', 'libchrome-test-<(libbase_ver)', + 'libchromeos-<(libbase_ver)', 'libcurl', 'libmetrics-<(libbase_ver)', ], @@ -24,7 +25,6 @@ 'type': 'static_library', 'sources': [ 'any.cc', - 'async_event_sequencer.cc', 'commands/command_definition.cc', 'commands/command_dictionary.cc', 'commands/command_manager.cc', @@ -84,7 +84,6 @@ 'sources': [ 'any_unittest.cc', 'any_internal_impl_unittest.cc', - 'async_event_sequencer_unittest.cc', 'buffet_testrunner.cc', 'commands/command_definition_unittest.cc', 'commands/command_dictionary_unittest.cc',
diff --git a/buffet/exported_object_manager.cc b/buffet/exported_object_manager.cc index c1403ad..d76e067 100644 --- a/buffet/exported_object_manager.cc +++ b/buffet/exported_object_manager.cc
@@ -4,9 +4,11 @@ #include "buffet/exported_object_manager.h" +#include <chromeos/async_event_sequencer.h> #include <dbus/object_manager.h> -#include "buffet/async_event_sequencer.h" + +using chromeos::dbus_utils::AsyncEventSequencer; namespace buffet { @@ -18,8 +20,7 @@ void ExportedObjectManager::Init(const OnInitFinish& cb) { bus_->AssertOnOriginThread(); - scoped_refptr<dbus_utils::AsyncEventSequencer> sequencer( - new dbus_utils::AsyncEventSequencer()); + scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer()); exported_object_->ExportMethod( dbus::kObjectManagerInterface, dbus::kObjectManagerGetManagedObjects,
diff --git a/buffet/exported_property_set.cc b/buffet/exported_property_set.cc index b1b5633..3ab3c2d 100644 --- a/buffet/exported_property_set.cc +++ b/buffet/exported_property_set.cc
@@ -5,12 +5,14 @@ #include "buffet/exported_property_set.h" #include <base/bind.h> +#include <chromeos/async_event_sequencer.h> #include <dbus/bus.h> // For kPropertyInterface #include <dbus/property.h> // For kPropertyInterface -#include "buffet/async_event_sequencer.h" #include "buffet/dbus_utils.h" +using chromeos::dbus_utils::AsyncEventSequencer; + namespace buffet { namespace dbus_utils {
diff --git a/buffet/main.cc b/buffet/main.cc index 358358e..eb25d13 100644 --- a/buffet/main.cc +++ b/buffet/main.cc
@@ -12,15 +12,15 @@ #include <base/message_loop/message_loop.h> #include <base/strings/string_util.h> #include <base/strings/stringprintf.h> +#include <chromeos/async_event_sequencer.h> #include <dbus/bus.h> #include <sysexits.h> -#include "buffet/async_event_sequencer.h" #include "buffet/dbus_constants.h" #include "buffet/exported_object_manager.h" #include "buffet/manager.h" -using buffet::dbus_utils::AsyncEventSequencer; +using chromeos::dbus_utils::AsyncEventSequencer; using buffet::dbus_utils::ExportedObjectManager; namespace {
diff --git a/buffet/manager.cc b/buffet/manager.cc index aa29552..0a6af31 100644 --- a/buffet/manager.cc +++ b/buffet/manager.cc
@@ -10,18 +10,18 @@ #include <base/bind.h> #include <base/bind_helpers.h> #include <base/json/json_writer.h> +#include <chromeos/async_event_sequencer.h> #include <dbus/bus.h> #include <dbus/object_path.h> #include <dbus/values_util.h> -#include "buffet/async_event_sequencer.h" #include "buffet/commands/command_manager.h" #include "buffet/dbus_constants.h" #include "buffet/dbus_utils.h" #include "buffet/error.h" #include "buffet/exported_object_manager.h" -using buffet::dbus_utils::AsyncEventSequencer; +using chromeos::dbus_utils::AsyncEventSequencer; using buffet::dbus_utils::GetBadArgsError; using buffet::dbus_utils::GetDBusError;