diff options
author | Alex Vakulenko <avakulenko@google.com> | 2015-10-12 15:21:28 -0700 |
---|---|---|
committer | Alex Vakulenko <avakulenko@google.com> | 2015-10-13 16:10:03 -0700 |
commit | 9ed0cab99f18acb3570a35e9408f24355f6b8324 (patch) | |
tree | 60e3b4c2822b812b3218489a9a6d835df1e8ca6e /brillo/dbus/dbus_object_test_helpers.h | |
parent | eabfe23a51c91a103042793ac2d5c28170994e1f (diff) | |
download | platform_external_libbrillo-9ed0cab99f18acb3570a35e9408f24355f6b8324.tar.gz platform_external_libbrillo-9ed0cab99f18acb3570a35e9408f24355f6b8324.tar.bz2 platform_external_libbrillo-9ed0cab99f18acb3570a35e9408f24355f6b8324.zip |
Move chromeos symbols into brillo namespace
And move the include files into "brillo" directory instead of "chromeos"
BUG: 24872993
TEST=built aosp and brillo and unit tests pass on dragonoboard
Change-Id: Ieb979d1ebd3152921d36cd15acbd6247f02aae69
Diffstat (limited to 'brillo/dbus/dbus_object_test_helpers.h')
-rw-r--r-- | brillo/dbus/dbus_object_test_helpers.h | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/brillo/dbus/dbus_object_test_helpers.h b/brillo/dbus/dbus_object_test_helpers.h new file mode 100644 index 0000000..6b90c5a --- /dev/null +++ b/brillo/dbus/dbus_object_test_helpers.h @@ -0,0 +1,143 @@ +// 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. + +// Helper utilities to simplify testing of D-Bus object implementations. +// Since the method handlers could now be asynchronous, they use callbacks to +// provide method return values. This makes it really difficult to invoke +// such handlers in unit tests (even if they are actually synchronous but +// still use DBusMethodResponse to send back the method results). +// This file provide testing-only helpers to make calling D-Bus method handlers +// easier. +#ifndef LIBCHROMEOS_BRILLO_DBUS_DBUS_OBJECT_TEST_HELPERS_H_ +#define LIBCHROMEOS_BRILLO_DBUS_DBUS_OBJECT_TEST_HELPERS_H_ + +#include <base/bind.h> +#include <base/memory/weak_ptr.h> +#include <brillo/dbus/dbus_method_invoker.h> +#include <brillo/dbus/dbus_object.h> + +namespace brillo { +namespace dbus_utils { + +// Helper friend class to call DBusInterface::HandleMethodCall() since it is +// a private method of the class and we don't want to make it public. +class DBusInterfaceTestHelper final { + public: + static void HandleMethodCall(DBusInterface* itf, + dbus::MethodCall* method_call, + ResponseSender sender) { + itf->HandleMethodCall(method_call, sender); + } +}; + +namespace testing { + +// This is a simple class that has weak pointer semantics and holds an +// instance of D-Bus method call response message. We use this in tests +// to get the response in case the handler processes a method call request +// synchronously. Otherwise the ResponseHolder object will be destroyed and +// ResponseHolder::ReceiveResponse() will not be called since we bind the +// callback to the object instance via a weak pointer. +struct ResponseHolder final : public base::SupportsWeakPtr<ResponseHolder> { + void ReceiveResponse(scoped_ptr<dbus::Response> response) { + response_.reset(response.release()); + } + + std::unique_ptr<dbus::Response> response_; +}; + +// Dispatches a D-Bus method call to the corresponding handler. +// Used mostly for testing purposes. This method is inlined so that it is +// not included in the shipping code of libchromeos, and included at the +// call sites. Returns a response from the method handler or nullptr if the +// method hasn't provided the response message immediately +// (i.e. it is asynchronous). +inline std::unique_ptr<dbus::Response> CallMethod( + const DBusObject& object, dbus::MethodCall* method_call) { + DBusInterface* itf = object.FindInterface(method_call->GetInterface()); + std::unique_ptr<dbus::Response> response; + if (!itf) { + response = CreateDBusErrorResponse( + method_call, + DBUS_ERROR_UNKNOWN_INTERFACE, + "Interface you invoked a method on isn't known by the object."); + } else { + ResponseHolder response_holder; + DBusInterfaceTestHelper::HandleMethodCall( + itf, method_call, base::Bind(&ResponseHolder::ReceiveResponse, + response_holder.AsWeakPtr())); + response = std::move(response_holder.response_); + } + return response; +} + +// MethodHandlerInvoker is similar to CallMethod() function above, except +// it allows the callers to invoke the method handlers directly bypassing +// the DBusObject/DBusInterface infrastructure. +// This works only on synchronous methods though. The handler must reply +// before the handler exits. +template<typename RetType> +struct MethodHandlerInvoker { + // MethodHandlerInvoker<RetType>::Call() calls a member |method| of a class + // |instance| and passes the |args| to it. The method's return value provided + // via handler's DBusMethodResponse is then extracted and returned. + // If the method handler returns an error, the error information is passed + // to the caller via the |error| object (and the method returns a default + // value of type RetType as a placeholder). + // If the method handler asynchronous and did not provide a reply (success or + // error) before the handler exits, this method aborts with a CHECK(). + template<class Class, typename... Params, typename... Args> + static RetType Call( + ErrorPtr* error, + Class* instance, + void(Class::*method)(std::unique_ptr<DBusMethodResponse<RetType>>, + Params...), + Args... args) { + ResponseHolder response_holder; + dbus::MethodCall method_call("test.interface", "TestMethod"); + method_call.SetSerial(123); + std::unique_ptr<DBusMethodResponse<RetType>> method_response{ + new DBusMethodResponse<RetType>( + &method_call, base::Bind(&ResponseHolder::ReceiveResponse, + response_holder.AsWeakPtr())) + }; + (instance->*method)(std::move(method_response), args...); + CHECK(response_holder.response_.get()) + << "No response received. Asynchronous methods are not supported."; + RetType ret_val; + ExtractMethodCallResults(response_holder.response_.get(), error, &ret_val); + return ret_val; + } +}; + +// Specialization of MethodHandlerInvoker for methods that do not return +// values (void methods). +template<> +struct MethodHandlerInvoker<void> { + template<class Class, typename... Params, typename... Args> + static void Call( + ErrorPtr* error, + Class* instance, + void(Class::*method)(std::unique_ptr<DBusMethodResponse<>>, Params...), + Args... args) { + ResponseHolder response_holder; + dbus::MethodCall method_call("test.interface", "TestMethod"); + method_call.SetSerial(123); + std::unique_ptr<DBusMethodResponse<>> method_response{ + new DBusMethodResponse<>(&method_call, + base::Bind(&ResponseHolder::ReceiveResponse, + response_holder.AsWeakPtr())) + }; + (instance->*method)(std::move(method_response), args...); + CHECK(response_holder.response_.get()) + << "No response received. Asynchronous methods are not supported."; + ExtractMethodCallResults(response_holder.response_.get(), error); + } +}; + +} // namespace testing +} // namespace dbus_utils +} // namespace brillo + +#endif // LIBCHROMEOS_BRILLO_DBUS_DBUS_OBJECT_TEST_HELPERS_H_ |