// Copyright (c) 2012 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 <memory>

#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/scoped_task_environment.h"
#include "dbus/message.h"
#include "dbus/mock_bus.h"
#include "dbus/mock_exported_object.h"
#include "dbus/mock_object_proxy.h"
#include "dbus/object_path.h"
#include "dbus/scoped_dbus_error.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::Unused;

namespace dbus {

class MockTest : public testing::Test {
 public:
  MockTest() = default;

  void SetUp() override {
    // Create a mock bus.
    Bus::Options options;
    options.bus_type = Bus::SYSTEM;
    mock_bus_ = new MockBus(options);

    // Create a mock proxy.
    mock_proxy_ = new MockObjectProxy(
        mock_bus_.get(),
        "org.chromium.TestService",
        ObjectPath("/org/chromium/TestObject"));

    // Set an expectation so mock_proxy's CallMethodAndBlock() will use
    // CreateMockProxyResponse() to return responses.
    EXPECT_CALL(*mock_proxy_.get(), CallMethodAndBlock(_, _))
        .WillRepeatedly(Invoke(this, &MockTest::CreateMockProxyResponse));
    EXPECT_CALL(*mock_proxy_.get(),
                CallMethodAndBlockWithErrorDetails(_, _, _))
        .WillRepeatedly(
            Invoke(this, &MockTest::CreateMockProxyResponseWithErrorDetails));

    // Set an expectation so mock_proxy's CallMethod() will use
    // HandleMockProxyResponseWithMessageLoop() to return responses.
    EXPECT_CALL(*mock_proxy_.get(), DoCallMethod(_, _, _))
        .WillRepeatedly(
            Invoke(this, &MockTest::HandleMockProxyResponseWithMessageLoop));

    // Set an expectation so mock_bus's GetObjectProxy() for the given
    // service name and the object path will return mock_proxy_.
    EXPECT_CALL(*mock_bus_.get(),
                GetObjectProxy("org.chromium.TestService",
                               ObjectPath("/org/chromium/TestObject")))
        .WillOnce(Return(mock_proxy_.get()));

    // ShutdownAndBlock() will be called in TearDown().
    EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
  }

  void TearDown() override { mock_bus_->ShutdownAndBlock(); }

  // Called when the response is received.
  void OnResponse(Response* response) {
    // |response| will be deleted on exit of the function. Copy the
    // payload to |response_string_|.
    if (response) {
      MessageReader reader(response);
      ASSERT_TRUE(reader.PopString(&response_string_));
    }
    run_loop_->Quit();
  }

 protected:
  std::string response_string_;
  base::test::ScopedTaskEnvironment scoped_task_environment_;
  std::unique_ptr<base::RunLoop> run_loop_;
  scoped_refptr<MockBus> mock_bus_;
  scoped_refptr<MockObjectProxy> mock_proxy_;

 private:
  // Returns a response for the given method call. Used to implement
  // CallMethodAndBlock() for |mock_proxy_|.
  std::unique_ptr<Response> CreateMockProxyResponse(MethodCall* method_call,
                                                    int timeout_ms) {
    if (method_call->GetInterface() == "org.chromium.TestInterface" &&
        method_call->GetMember() == "Echo") {
      MessageReader reader(method_call);
      std::string text_message;
      if (reader.PopString(&text_message)) {
        std::unique_ptr<Response> response = Response::CreateEmpty();
        MessageWriter writer(response.get());
        writer.AppendString(text_message);
        return response;
      }
    }

    LOG(ERROR) << "Unexpected method call: " << method_call->ToString();
    return nullptr;
  }

  std::unique_ptr<Response> CreateMockProxyResponseWithErrorDetails(
      MethodCall* method_call, int timeout_ms, ScopedDBusError* error) {
    dbus_set_error(error->get(), DBUS_ERROR_NOT_SUPPORTED, "Not implemented");
    return nullptr;
  }

  // Creates a response and posts the given response callback with the
  // response. Used to implement for |mock_proxy_|.
  void HandleMockProxyResponseWithMessageLoop(
      MethodCall* method_call,
      int timeout_ms,
      ObjectProxy::ResponseCallback* response_callback) {
    std::unique_ptr<Response> response =
        CreateMockProxyResponse(method_call, timeout_ms);
    scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
        FROM_HERE,
        base::BindOnce(&MockTest::RunResponseCallback, base::Unretained(this),
                       std::move(*response_callback), std::move(response)));
  }

  // Runs the given response callback with the given response.
  void RunResponseCallback(
      ObjectProxy::ResponseCallback response_callback,
      std::unique_ptr<Response> response) {
    std::move(response_callback).Run(response.get());
  }
};

// This test demonstrates how to mock a synchronous method call using the
// mock classes.
TEST_F(MockTest, CallMethodAndBlock) {
  const char kHello[] = "Hello";
  // Get an object proxy from the mock bus.
  ObjectProxy* proxy = mock_bus_->GetObjectProxy(
      "org.chromium.TestService",
      ObjectPath("/org/chromium/TestObject"));

  // Create a method call.
  MethodCall method_call("org.chromium.TestInterface", "Echo");
  MessageWriter writer(&method_call);
  writer.AppendString(kHello);

  // Call the method.
  std::unique_ptr<Response> response(proxy->CallMethodAndBlock(
      &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));

  // Check the response.
  ASSERT_TRUE(response.get());
  MessageReader reader(response.get());
  std::string text_message;
  ASSERT_TRUE(reader.PopString(&text_message));
  // The text message should be echo'ed back.
  EXPECT_EQ(kHello, text_message);
}

TEST_F(MockTest, CallMethodAndBlockWithErrorDetails) {
  // Get an object proxy from the mock bus.
  ObjectProxy* proxy = mock_bus_->GetObjectProxy(
      "org.chromium.TestService",
      ObjectPath("/org/chromium/TestObject"));

  // Create a method call.
  MethodCall method_call("org.chromium.TestInterface", "Echo");

  ScopedDBusError error;
  // Call the method.
  std::unique_ptr<Response> response(proxy->CallMethodAndBlockWithErrorDetails(
      &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT, &error));

  // Check the response.
  ASSERT_FALSE(response.get());
  ASSERT_TRUE(error.is_set());
  EXPECT_STREQ(DBUS_ERROR_NOT_SUPPORTED, error.name());
  EXPECT_STREQ("Not implemented", error.message());
}

// This test demonstrates how to mock an asynchronous method call using the
// mock classes.
TEST_F(MockTest, CallMethod) {
  const char kHello[] = "hello";

  // Get an object proxy from the mock bus.
  ObjectProxy* proxy = mock_bus_->GetObjectProxy(
      "org.chromium.TestService",
      ObjectPath("/org/chromium/TestObject"));

  // Create a method call.
  MethodCall method_call("org.chromium.TestInterface", "Echo");
  MessageWriter writer(&method_call);
  writer.AppendString(kHello);

  // Call the method.
  run_loop_.reset(new base::RunLoop);
  proxy->CallMethod(&method_call,
                    ObjectProxy::TIMEOUT_USE_DEFAULT,
                    base::Bind(&MockTest::OnResponse,
                               base::Unretained(this)));
  // Run the message loop to let OnResponse be called.
  run_loop_->Run();

  EXPECT_EQ(kHello, response_string_);
}

}  // namespace dbus
