// 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/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::TaskEnvironment 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);
    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
