// 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/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.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() {
  }

  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::MessageLoop message_loop_;
  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 runs the given response callback in the
  // message loop 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);
    message_loop_.task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&MockTest::RunResponseCallback, base::Unretained(this),
                       std::move(*response_callback), base::Passed(&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
