// Copyright 2018 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.

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/memory/ref_counted.h>
#include <base/run_loop.h>
#include <base/values.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <dbus/values_util.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "vm_tools/notificationd/notification_daemon.h"

using ::testing::_;
using ::testing::Invoke;

namespace {

class MockNotificationDaemon : public vm_tools::notificationd::DBusInterface {
 public:
  MockNotificationDaemon() : dbus_service() {}

  bool GetCapabilities(std::vector<std::string>* out_capabilities) override {
    *out_capabilities = capabilities_;
    return true;
  }

  bool Notify(const NotifyArgument& input, uint32_t* out_id) override {
    received_notify_arg_ = input;
    *out_id = notify_out_id_;
    return true;
  }

  bool GetServerInformation(ServerInformation* output) override {
    *output = server_info_;
    return true;
  }

  bool CloseNotification(uint32_t id) override {
    received_close_notification_id_ = id;
    return true;
  }

  void SetCapabilities(const std::vector<std::string>& capabilities) {
    capabilities_ = capabilities;
  }

  void SetServerInformation(const ServerInformation& server_info) {
    server_info_ = server_info;
  }

  void SetNotifyOutId(uint32_t out_id) { notify_out_id_ = out_id; }

  const NotifyArgument& GetReceivedNotifyArg() const {
    return received_notify_arg_;
  }

  uint32_t received_close_notification_id() const {
    return received_close_notification_id_;
  }

 private:
  std::vector<std::string> capabilities_;
  ServerInformation server_info_;
  NotifyArgument received_notify_arg_;
  uint32_t notify_out_id_;
  uint32_t received_close_notification_id_;

  std::unique_ptr<vm_tools::notificationd::DBusService> dbus_service;

  FRIEND_TEST(DBusServiceTest, GetCapabilities);
  FRIEND_TEST(DBusServiceTest, Notify);
  FRIEND_TEST(DBusServiceTest, GetServerInformation);
  FRIEND_TEST(DBusServiceTest, CloseNotification);
};

}  // namespace

namespace vm_tools {
namespace notificationd {

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

  // Create dummy method call.
  std::unique_ptr<dbus::MethodCall> CreateMockMethodCall(
      const std::string& method_name) {
    const uint32_t kSerial = 123;
    auto method_call = std::make_unique<dbus::MethodCall>(
        "org.freedesktop.Notifications", method_name);
    method_call->SetSerial(kSerial);
    return method_call;
  }

  void AppendStringArray(dbus::MessageWriter* writer,
                         const std::vector<std::string>& array) {
    dbus::MessageWriter array_writer(nullptr);
    writer->OpenArray("s", &array_writer);
    for (const auto& str : array) {
      array_writer.AppendString(str);
    }
    writer->CloseContainer(&array_writer);
  }

  void AppendEmptyVariantDict(dbus::MessageWriter* writer) {
    dbus::MessageWriter array_writer(nullptr);
    writer->OpenArray("{sv}", &array_writer);

    writer->CloseContainer(&array_writer);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(DBusServiceTest);
};

// Test if dbus adaptor can properly call GetCapability method and recieve the
// data from notification daemon.
TEST_F(DBusServiceTest, GetCapabilities) {
  MockNotificationDaemon daemon;
  DBusService dbus_service(&daemon);

  const std::vector<std::string> expected_data = {"body", "actions",
                                                  "action-icons"};
  daemon.SetCapabilities(expected_data);

  auto method_call = CreateMockMethodCall("GetCapabilities");

  auto response = dbus_service.CallGetCapabilities(method_call.get());
  ASSERT_TRUE(response.get() != nullptr);

  // Parse resonse
  dbus::MessageReader reader(response.get());
  std::unique_ptr<base::Value> value(PopDataAsValue(&reader));
  ASSERT_TRUE(value.get() != nullptr);
  ASSERT_FALSE(reader.HasMoreData());
  ASSERT_TRUE(value->is_list());
  std::vector<std::string> received_data;
  auto list = base::ListValue::From(std::move(value));
  ASSERT_TRUE(list.get() != nullptr);
  for (const auto& element : *list) {
    ASSERT_TRUE(element->is_string());
    received_data.push_back(element->GetString());
  }

  EXPECT_EQ(received_data, expected_data);
}

// Test if dbus adaptor can properly call GetServerInformation method and
// recieve the data from notification daemon.
TEST_F(DBusServiceTest, GetServerInformation) {
  MockNotificationDaemon daemon;
  DBusService dbus_service(&daemon);

  const NotificationDaemon::ServerInformation expected_data = {
      .name = "NameTest",
      .vendor = "VendorTest",
      .version = "VersionTest",
      .spec_version = "SpecVersionTest"};
  daemon.SetServerInformation(expected_data);

  auto method_call = CreateMockMethodCall("GetServerInformation");

  auto response = dbus_service.CallGetServerInformation(method_call.get());
  ASSERT_TRUE(response.get() != nullptr);

  // Parse response
  dbus::MessageReader reader(response.get());
  NotificationDaemon::ServerInformation received_data;
  ASSERT_TRUE(reader.PopString(&received_data.name));
  ASSERT_TRUE(reader.PopString(&received_data.vendor));
  ASSERT_TRUE(reader.PopString(&received_data.version));
  ASSERT_TRUE(reader.PopString(&received_data.spec_version));
  ASSERT_FALSE(reader.HasMoreData());

  EXPECT_EQ(received_data.name, expected_data.name);
  EXPECT_EQ(received_data.vendor, expected_data.vendor);
  EXPECT_EQ(received_data.version, expected_data.version);
  EXPECT_EQ(received_data.spec_version, expected_data.spec_version);
}

// Test if dbus adaptor can properly call Notify method and recieve the data
// from notification daemon.
TEST_F(DBusServiceTest, Notify) {
  MockNotificationDaemon daemon;
  DBusService dbus_service(&daemon);

  const NotificationDaemon::NotifyArgument expected_data = {
      .app_name = "AppNameTest",
      .replaces_id = 1,
      .app_icon = "AppIconTest",
      .summary = "SummaryTest",
      .body = "BodyTest",
      .actions = {"ActionTest1", "ActionTest2", "Actiontest3"},
      .hints = {{"KeyTest1", "ValueTest1"}},
      .expire_timeout = 2};
  const uint32_t expected_out_id = 333;
  daemon.SetNotifyOutId(expected_out_id);

  auto method_call = CreateMockMethodCall("Notify");

  // Prepare args for the method call
  dbus::MessageWriter writer(method_call.get());
  writer.AppendString(expected_data.app_name);
  writer.AppendUint32(expected_data.replaces_id);
  writer.AppendString(expected_data.app_icon);
  writer.AppendString(expected_data.summary);
  writer.AppendString(expected_data.body);
  AppendStringArray(&writer, expected_data.actions);
  AppendEmptyVariantDict(&writer);
  writer.AppendInt32(expected_data.expire_timeout);

  auto response = dbus_service.CallNotify(method_call.get());
  ASSERT_TRUE(response.get() != nullptr);

  // Test args
  const auto received_args = daemon.GetReceivedNotifyArg();
  EXPECT_EQ(received_args.app_name, expected_data.app_name);
  EXPECT_EQ(received_args.replaces_id, expected_data.replaces_id);
  EXPECT_EQ(received_args.app_icon, expected_data.app_icon);
  EXPECT_EQ(received_args.summary, expected_data.summary);
  EXPECT_EQ(received_args.body, expected_data.body);
  EXPECT_EQ(received_args.actions, expected_data.actions);
  // parsing hints is not implemented yet.
  EXPECT_NE(received_args.hints, expected_data.hints);
  EXPECT_EQ(received_args.expire_timeout, expected_data.expire_timeout);

  // Parse response
  dbus::MessageReader reader(response.get());
  uint32_t received_out_id = 0;
  ASSERT_TRUE(reader.PopUint32(&received_out_id));
  ASSERT_FALSE(reader.HasMoreData());

  // Test response
  EXPECT_EQ(received_out_id, expected_out_id);
}

// Test if dbus adaptor can properly call CloseNotification method.
TEST_F(DBusServiceTest, CloseNotification) {
  MockNotificationDaemon daemon;
  DBusService dbus_service(&daemon);

  const uint32_t expected_data = 777;
  auto method_call = CreateMockMethodCall("CloseNotification");

  // Prepare args for the method call
  dbus::MessageWriter writer(method_call.get());
  writer.AppendUint32(expected_data);

  auto response = dbus_service.CallCloseNotification(method_call.get());
  ASSERT_TRUE(response.get() != nullptr);

  // Test received data
  EXPECT_EQ(daemon.received_close_notification_id(), expected_data);

  // Parse response (expects no data in response)
  dbus::MessageReader reader(response.get());
  ASSERT_FALSE(reader.HasMoreData());
}

// Test if dbus adaptor can properly send NotificationClosed signal.
TEST_F(DBusServiceTest, NotificationClosedSignal) {
  DBusService dbus_service(nullptr);

  // Prepare mock exported object
  const dbus::ObjectPath kObjectPath("/org/example/TestService");
  auto mock_exported_object =
      make_scoped_refptr(new dbus::MockExportedObject(nullptr, kObjectPath));
  dbus_service.exported_object_ = mock_exported_object.get();

  // Expected data
  const uint32_t expected_id = 456;
  const auto expected_reason = DBusService::ClosedReason::BY_USER;

  // Test if SendSignal is called once with expected args
  EXPECT_CALL(*mock_exported_object.get(), SendSignal(_))
      .WillOnce(Invoke([&](dbus::Signal* signal) {
        dbus::MessageReader reader(signal);

        uint32_t id = -1;
        uint32_t reason = -1;
        ASSERT_TRUE(reader.PopUint32(&id));
        ASSERT_TRUE(reader.PopUint32(&reason));
        ASSERT_FALSE(reader.HasMoreData());

        EXPECT_EQ(id, expected_id);
        EXPECT_EQ(reason, static_cast<uint32_t>(expected_reason));
      }));

  // Send signal
  dbus_service.SendNotificationClosedSignal(expected_id, expected_reason);
}

// Test if dbus adaptor can properly send ActionInvoked signal.
TEST_F(DBusServiceTest, ActionInvokedSignal) {
  DBusService dbus_service(nullptr);

  // Prepare mock exported object
  const dbus::ObjectPath kObjectPath("/org/example/TestService");
  auto mock_exported_object =
      make_scoped_refptr(new dbus::MockExportedObject(nullptr, kObjectPath));
  dbus_service.exported_object_ = mock_exported_object.get();

  // Expected data
  const uint32_t expected_id = 456;
  const std::string expected_action_key = "Test action key";

  // Test if SendSignal is called once with expected args
  EXPECT_CALL(*mock_exported_object.get(), SendSignal(_))
      .WillOnce(Invoke([&](dbus::Signal* signal) {
        dbus::MessageReader reader(signal);

        uint32_t id = -1;
        std::string action_key;
        ASSERT_TRUE(reader.PopUint32(&id));
        ASSERT_TRUE(reader.PopString(&action_key));
        ASSERT_FALSE(reader.HasMoreData());

        EXPECT_EQ(id, expected_id);
        EXPECT_EQ(action_key, expected_action_key);
      }));

  // Send signal
  dbus_service.SendActionInvokedSignal(expected_id, expected_action_key);
}

}  // namespace notificationd
}  // namespace vm_tools
