// 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 LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_TEST_HELPERS_H_
#define LIBBRILLO_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(std::unique_ptr<dbus::Response> response) {
    response_ = std::move(response);
  }

  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 libbrillo, 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  // LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_TEST_HELPERS_H_
