// Copyright 2019 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 <memory>
#include <set>
#include <string>

#include <gmock/gmock.h>
#include <grpcpp/impl/call.h>
#include <grpcpp/grpcpp.h>
#include <gtest/gtest.h>
#include <chromeos/dbus/service_constants.h>
#include <vm_applications/proto_bindings/apps.pb.h>

#include "base/strings/string_number_conversions.h"
#include "vm_tools/cicerone/container_listener_impl.h"
#include "vm_tools/cicerone/dbus_message_testing_helper.h"
#include "vm_tools/cicerone/service.h"
#include "vm_tools/cicerone/service_testing_helper.h"

#include "container_host.grpc.pb.h"  // NOLINT(build/include)

namespace vm_tools {
namespace cicerone {

namespace {

using ::testing::_;
using ::testing::AllOf;
using ::testing::Invoke;
using ::testing::Matches;
using ::testing::UnorderedElementsAreArray;
using ::testing::Unused;

constexpr char kDefaultPluginVmContainerName[] = "penguin";

// Helper for testing proto-based MethodCalls sent to the dbus. Extracts the
// proto in from the MethodCall to |protobuf| so that it can be tested further.
// Returns an empty (but not NULL) dbus::Response.
//
// Does not confirm method name (a.k.a. GetMethod) or interface name; use
// HasMethodName and HasInterfaceName for that.
dbus::Response* ProtoMethodCallHelper(dbus::MethodCall* method_call,
                                      google::protobuf::MessageLite* protobuf) {
  dbus::MessageReader reader(method_call);
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(protobuf));
  EXPECT_FALSE(reader.HasMoreData());

  // MockObjectProxy will take ownership of the created Response object. See
  // comments in MockObjectProxy.
  return dbus::Response::CreateEmpty().release();
}

// Same, but for method calls that just have a string.
dbus::Response* StringMethodCallHelper(dbus::MethodCall* method_call,
                                       std::string* s) {
  dbus::MessageReader reader(method_call);
  EXPECT_TRUE(reader.PopString(s));
  EXPECT_FALSE(reader.HasMoreData());
  return dbus::Response::CreateEmpty().release();
}

// Same but for signals
void ProtoSignalHelper(dbus::Signal* signal,
                       google::protobuf::MessageLite* protobuf) {
  dbus::MessageReader reader(signal);
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(protobuf));
  EXPECT_FALSE(reader.HasMoreData());
}

TEST(ContainerListenerImplTest,
     ValidContainerShutdownCallShouldProduceDBusMessage) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::ContainerShutdownInfo request;
  vm_tools::EmptyMessage response;
  request.set_token(ServiceTestingHelper::kDefaultContainerToken);

  ContainerShutdownSignal shutdown_result;
  EXPECT_CALL(test_framework.get_mock_exported_object(),
              SendSignal(AllOf(HasInterfaceName(kVmCiceroneInterface),
                               HasMethodName(kContainerShutdownSignal))))
      .WillOnce(Invoke([&shutdown_result](dbus::Signal* signal) {
        ProtoSignalHelper(signal, &shutdown_result);
      }));
  std::string unregister_hostname;
  EXPECT_CALL(test_framework.get_mock_crosdns_service_proxy(),
              MockCallMethodAndBlock(
                  AllOf(HasInterfaceName(crosdns::kCrosDnsInterfaceName),
                        HasMethodName(crosdns::kRemoveHostnameIpMappingMethod)),
                  _))
      .WillOnce(
          Invoke([&unregister_hostname](dbus::MethodCall* method_call, Unused) {
            return StringMethodCallHelper(method_call, &unregister_hostname);
          }));

  grpc::ServerContext ctx;
  grpc::Status status = test_framework.get_service()
                            .GetContainerListenerImpl()
                            ->ContainerShutdown(&ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(shutdown_result.vm_name(), ServiceTestingHelper::kDefaultVmName);
  EXPECT_EQ(shutdown_result.container_name(),
            ServiceTestingHelper::kDefaultContainerName);
  EXPECT_EQ(shutdown_result.owner_id(), ServiceTestingHelper::kDefaultOwnerId);

  EXPECT_EQ(unregister_hostname,
            ServiceTestingHelper::kDefaultContainerHostname);
}

void ValidUpdateApplicationListCallShouldProduceDBusMessageGeneric(
    bool plugin_vm, const char* container_name) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  if (plugin_vm)
    test_framework.SetUpPluginVm();
  else
    test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::UpdateApplicationListRequest request;
  vm_tools::EmptyMessage response;

  const std::string kDesktopFileId = "nethack-x11";
  const std::string kName = "Nethack";
  const std::string kComment = "Get the amulet!";
  request.set_token(ServiceTestingHelper::kDefaultContainerToken);
  vm_tools::container::Application* application = request.add_application();
  application->set_desktop_file_id(kDesktopFileId);
  application->mutable_name()->add_values()->set_value(kName);
  application->mutable_comment()->add_values()->set_value(kComment);
  application->set_no_display(false);

  vm_tools::apps::ApplicationList dbus_result;
  EXPECT_CALL(
      test_framework.get_mock_vm_applications_service_proxy(),
      MockCallMethodAndBlock(
          AllOf(
              HasInterfaceName(vm_tools::apps::kVmApplicationsServiceInterface),
              HasMethodName(
                  vm_tools::apps::
                      kVmApplicationsServiceUpdateApplicationListMethod)),
          _))
      .WillOnce(Invoke([&dbus_result](dbus::MethodCall* method_call, Unused) {
        return ProtoMethodCallHelper(method_call, &dbus_result);
      }));

  grpc::ServerContext ctx;
  grpc::Status status = test_framework.get_service()
                            .GetContainerListenerImpl()
                            ->UpdateApplicationList(&ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(dbus_result.vm_name(), ServiceTestingHelper::kDefaultVmName);
  EXPECT_EQ(dbus_result.container_name(), container_name);
  EXPECT_EQ(dbus_result.owner_id(), ServiceTestingHelper::kDefaultOwnerId);
  ASSERT_EQ(dbus_result.apps_size(), 1);
  const vm_tools::apps::App& dbus_app = dbus_result.apps(0);
  EXPECT_EQ(dbus_app.desktop_file_id(), kDesktopFileId);
  const vm_tools::apps::App::LocaleString& dbus_name = dbus_app.name();
  ASSERT_EQ(dbus_name.values_size(), 1);
  EXPECT_EQ(dbus_name.values(0).value(), kName);
  EXPECT_EQ(dbus_name.values(0).locale(), "");
  const vm_tools::apps::App::LocaleString& dbus_comment = dbus_app.comment();
  ASSERT_EQ(dbus_comment.values_size(), 1);
  EXPECT_EQ(dbus_comment.values(0).value(), kComment);
  EXPECT_EQ(dbus_comment.values(0).locale(), "");
  EXPECT_FALSE(dbus_app.no_display());
  EXPECT_EQ(dbus_app.mime_types_size(), 0);
  EXPECT_EQ(dbus_app.startup_wm_class(), "");
  EXPECT_FALSE(dbus_app.startup_notify());
  EXPECT_EQ(dbus_app.keywords().values_size(), 0);
  EXPECT_EQ(dbus_app.package_id(), "");
}

TEST(ContainerListenerImplTest,
     ValidUpdateApplicationListCallShouldProduceDBusMessageForDefaultVm) {
  ValidUpdateApplicationListCallShouldProduceDBusMessageGeneric(
      false /* plugin_vm */, ServiceTestingHelper::kDefaultContainerName);
}

TEST(ContainerListenerImplTest,
     ValidUpdateApplicationListCallShouldProduceDBusMessageForPluginVm) {
  ValidUpdateApplicationListCallShouldProduceDBusMessageGeneric(
      true /* plugin_vm */, kDefaultPluginVmContainerName);
}

vm_tools::container::Application::LocalizedString MakeLocalizedString(
    const std::string& field_name, int seed) {
  vm_tools::container::Application::LocalizedString result;
  for (int value = 0; value < seed; ++value) {
    vm_tools::container::Application::LocalizedString::StringWithLocale*
        locale = result.add_values();

    if ((value % 5) != 0) {
      locale->set_value(field_name +
                        ":value:" + base::IntToString(seed * 1000 + value));
    }
    if ((value % 4) != 0) {
      locale->set_locale(field_name +
                         ":locale:" + base::IntToString(seed * 1000 + value));
    }
  }

  return result;
}

vm_tools::container::Application::LocaleStrings MakeLocaleStrings(
    const std::string& field_name, int seed) {
  vm_tools::container::Application::LocaleStrings result;
  for (int value = 0; value < seed; ++value) {
    vm_tools::container::Application::LocaleStrings::StringsWithLocale* locale =
        result.add_values();

    for (int sub_value = 0; sub_value < value; ++sub_value) {
      locale->add_value(
          field_name +
          ":value:" + base::IntToString(seed * 1000 + value * 10 + sub_value));
    }
    if ((value % 4) != 0) {
      locale->set_locale(field_name +
                         ":locale:" + base::IntToString(seed * 1000 + value));
    }
  }

  return result;
}

// Make an UpdateApplicationListRequest with every field filled in and multiple
// entries in every repeated field.
vm_tools::container::UpdateApplicationListRequest
MakeComplexUpdateApplicationListRequest() {
  vm_tools::container::UpdateApplicationListRequest request;
  request.set_token(ServiceTestingHelper::kDefaultContainerToken);

  for (int app_num = 0; app_num < 10; ++app_num) {
    vm_tools::container::Application* application = request.add_application();

    // Non-repeated fields:
    application->set_desktop_file_id("desktop:" + base::IntToString(app_num));
    application->set_no_display((app_num % 2) == 0);
    application->set_startup_wm_class("startup_wm_class:" +
                                      base::IntToString(app_num));
    application->set_startup_notify((app_num % 3) == 0);
    application->set_package_id("package_id:" + base::IntToString(app_num));

    // Repeated fields:
    *application->mutable_name() = MakeLocalizedString("name", app_num);
    *application->mutable_comment() =
        MakeLocalizedString("comment", 10 - app_num);
    for (int mime_type = 0; mime_type < 5; ++mime_type) {
      application->add_mime_types(
          "mime:" + base::IntToString(app_num * 1000 + mime_type));
    }
    *application->mutable_keywords() = MakeLocaleStrings("keyword", app_num);
  }
  return request;
}

void CompareLocaleString(
    const vm_tools::container::Application::LocalizedString& expected,
    const vm_tools::apps::App::LocaleString& actual) {
  // Order is not important, only existence.
  EXPECT_EQ(expected.values_size(), actual.values_size());
  std::set<int> expected_indexes_seen;
  for (const vm_tools::apps::App::LocaleString::Entry& actual_entry :
       actual.values()) {
    bool found = false;
    int expected_index = 0;
    while (!found && expected_index < expected.values_size()) {
      if (expected.values(expected_index).locale() == actual_entry.locale() &&
          expected.values(expected_index).value() == actual_entry.value() &&
          expected_indexes_seen.find(expected_index) ==
              expected_indexes_seen.end()) {
        found = true;
      } else {
        ++expected_index;
      }
    }

    EXPECT_TRUE(found) << "Could not find expected.values() with locale "
                       << actual_entry.locale() << " and value "
                       << actual_entry.value();
    expected_indexes_seen.insert(expected_index);
  }
  EXPECT_EQ(expected_indexes_seen.size(), actual.values_size());
}

void CompareLocaleStrings(
    const vm_tools::container::Application::LocaleStrings& expected,
    const vm_tools::apps::App::LocaleStrings& actual) {
  // Order is not important, only existence.
  EXPECT_EQ(expected.values_size(), actual.values_size());
  std::set<int> expected_indexes_seen;
  for (const vm_tools::apps::App::LocaleStrings::StringsWithLocale&
           actual_entry : actual.values()) {
    bool found = false;
    int expected_index = 0;
    while (!found && expected_index < expected.values_size()) {
      if (expected.values(expected_index).locale() == actual_entry.locale() &&
          Matches(UnorderedElementsAreArray(
              expected.values(expected_index).value()))(actual_entry.value()) &&
          expected_indexes_seen.find(expected_index) ==
              expected_indexes_seen.end()) {
        found = true;
      } else {
        ++expected_index;
      }
    }

    EXPECT_TRUE(found) << "Could not find expected.values() with locale "
                       << actual_entry.locale() << " and "
                       << actual_entry.value_size() << " values";
    expected_indexes_seen.insert(expected_index);
  }
  EXPECT_EQ(expected_indexes_seen.size(), actual.values_size());
}

void CompareInputApplicationToOutputApp(
    const vm_tools::container::Application& expected,
    const vm_tools::apps::App& actual) {
  // Compare non-repeated fields.
  EXPECT_EQ(expected.desktop_file_id(), actual.desktop_file_id());
  EXPECT_EQ(expected.no_display(), actual.no_display());
  EXPECT_EQ(expected.startup_wm_class(), actual.startup_wm_class());
  EXPECT_EQ(expected.startup_notify(), actual.startup_notify());
  EXPECT_EQ(expected.package_id(), actual.package_id());

  EXPECT_THAT(actual.mime_types(),
              UnorderedElementsAreArray(expected.mime_types()));

  CompareLocaleString(expected.name(), actual.name());
  CompareLocaleString(expected.comment(), actual.comment());
  CompareLocaleStrings(expected.keywords(), actual.keywords());
}

// Ensures that all the entries in expected match the entries in actual. Allows
// different order of the applications and sub-fields. EXPECT fails if
// differences are found.
void CompareUpdateApplicationListRequestToApplicationList(
    const vm_tools::container::UpdateApplicationListRequest& expected,
    const vm_tools::apps::ApplicationList& actual) {
  EXPECT_EQ(actual.apps_size(), expected.application_size());
  std::set<int> expected_indexes_seen;
  for (const vm_tools::apps::App& actual_app : actual.apps()) {
    // Don't assume input & output order are the same, because that's not part
    // of the API contract. Assume desktop_file_id is unique, though, since
    // MakeComplexUpdateApplicationListRequest will do that.
    bool found = false;
    int expected_index = 0;
    while (!found && expected_index < expected.application_size()) {
      if (expected.application(expected_index).desktop_file_id() ==
          actual_app.desktop_file_id()) {
        found = true;
      } else {
        ++expected_index;
      }
    }

    ASSERT_TRUE(found)
        << "Could not find expected.application() with desktop_file_id "
        << actual_app.desktop_file_id();
    EXPECT_TRUE(expected_indexes_seen.find(expected_index) ==
                expected_indexes_seen.end())
        << "desktop_file_id " << actual_app.desktop_file_id()
        << " appears twice in actual";
    expected_indexes_seen.insert(expected_index);

    CompareInputApplicationToOutputApp(expected.application(expected_index),
                                       actual_app);
  }
  EXPECT_EQ(expected_indexes_seen.size(), actual.apps_size());
}

void LongerUpdateApplicationListCallShouldProduceDBusMessageGeneric(
    bool plugin_vm, const char* container_name) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  if (plugin_vm)
    test_framework.SetUpPluginVm();
  else
    test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::UpdateApplicationListRequest request(
      MakeComplexUpdateApplicationListRequest());
  vm_tools::EmptyMessage response;

  vm_tools::apps::ApplicationList dbus_result;
  EXPECT_CALL(
      test_framework.get_mock_vm_applications_service_proxy(),
      MockCallMethodAndBlock(
          AllOf(
              HasInterfaceName(vm_tools::apps::kVmApplicationsServiceInterface),
              HasMethodName(
                  vm_tools::apps::
                      kVmApplicationsServiceUpdateApplicationListMethod)),
          _))
      .WillOnce(Invoke([&dbus_result](dbus::MethodCall* method_call, Unused) {
        return ProtoMethodCallHelper(method_call, &dbus_result);
      }));

  grpc::ServerContext ctx;
  grpc::Status status = test_framework.get_service()
                            .GetContainerListenerImpl()
                            ->UpdateApplicationList(&ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(dbus_result.vm_name(), ServiceTestingHelper::kDefaultVmName);
  EXPECT_EQ(dbus_result.container_name(), container_name);
  EXPECT_EQ(dbus_result.owner_id(), ServiceTestingHelper::kDefaultOwnerId);

  CompareUpdateApplicationListRequestToApplicationList(request, dbus_result);
}

TEST(ContainerListenerImplTest,
     LongerUpdateApplicationListCallShouldProduceDBusMessageForDefaultVm) {
  LongerUpdateApplicationListCallShouldProduceDBusMessageGeneric(
      false /* plugin_vm */, ServiceTestingHelper::kDefaultContainerName);
}

TEST(ContainerListenerImplTest,
     LongerUpdateApplicationListCallShouldProduceDBusMessageForPluginVm) {
  LongerUpdateApplicationListCallShouldProduceDBusMessageGeneric(
      true /* plugin_vm */, kDefaultPluginVmContainerName);
}

void ValidOpenUrlCallShouldProduceDBusMessageGeneric(bool plugin_vm) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  if (plugin_vm)
    test_framework.SetUpPluginVm();
  else
    test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::OpenUrlRequest request;
  vm_tools::EmptyMessage response;

  const std::string kUrl = "whycrostiniisgreat.com";
  request.set_token(ServiceTestingHelper::kDefaultContainerToken);
  request.set_url(kUrl);

  std::string resulting_url;
  EXPECT_CALL(
      test_framework.get_mock_url_handler_service_proxy(),
      MockCallMethodAndBlock(
          AllOf(HasInterfaceName(chromeos::kUrlHandlerServiceInterface),
                HasMethodName(chromeos::kUrlHandlerServiceOpenUrlMethod)),
          _))
      .WillOnce(Invoke([&resulting_url](dbus::MethodCall* method_call, Unused) {
        return StringMethodCallHelper(method_call, &resulting_url);
      }));

  grpc::ServerContext ctx;
  grpc::Status status =
      test_framework.get_service().GetContainerListenerImpl()->OpenUrl(
          &ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(resulting_url, kUrl);
}

TEST(ContainerListenerImplTest,
     ValidOpenUrlCallShouldProduceDBusMessageForDefaultVm) {
  ValidOpenUrlCallShouldProduceDBusMessageGeneric(false);
}

TEST(ContainerListenerImplTest,
     ValidOpenUrlCallShouldProduceDBusMessageForPluginVm) {
  ValidOpenUrlCallShouldProduceDBusMessageGeneric(true);
}

TEST(ContainerListenerImplTest,
     ValidInstallLinuxPackageProgressCallShouldProduceDBusMessage) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::InstallLinuxPackageProgressInfo request;
  vm_tools::EmptyMessage response;

  request.set_token(ServiceTestingHelper::kDefaultContainerToken);
  request.set_status(
      vm_tools::container::InstallLinuxPackageProgressInfo::DOWNLOADING);
  request.set_progress_percent(52);

  InstallLinuxPackageProgressSignal dbus_result;
  EXPECT_CALL(
      test_framework.get_mock_exported_object(),
      SendSignal(AllOf(HasInterfaceName(kVmCiceroneInterface),
                       HasMethodName(kInstallLinuxPackageProgressSignal))))
      .WillOnce(Invoke([&dbus_result](dbus::Signal* signal) {
        ProtoSignalHelper(signal, &dbus_result);
      }));

  grpc::ServerContext ctx;
  grpc::Status status =
      test_framework.get_service()
          .GetContainerListenerImpl()
          ->InstallLinuxPackageProgress(&ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(dbus_result.vm_name(), ServiceTestingHelper::kDefaultVmName);
  EXPECT_EQ(dbus_result.container_name(),
            ServiceTestingHelper::kDefaultContainerName);
  EXPECT_EQ(dbus_result.owner_id(), ServiceTestingHelper::kDefaultOwnerId);
  EXPECT_EQ(dbus_result.status(),
            InstallLinuxPackageProgressSignal::DOWNLOADING);
  EXPECT_EQ(dbus_result.progress_percent(), 52);
  EXPECT_EQ(dbus_result.failure_details(), "");
}

TEST(ContainerListenerImplTest,
     FailureInstallLinuxPackageProgressCallShouldProduceDBusMessage) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::InstallLinuxPackageProgressInfo request;
  vm_tools::EmptyMessage response;

  const std::string kFailureDetails = "I prefer not to.";
  request.set_token(ServiceTestingHelper::kDefaultContainerToken);
  request.set_status(
      vm_tools::container::InstallLinuxPackageProgressInfo::FAILED);
  request.set_failure_details(kFailureDetails);

  InstallLinuxPackageProgressSignal dbus_result;
  EXPECT_CALL(
      test_framework.get_mock_exported_object(),
      SendSignal(AllOf(HasInterfaceName(kVmCiceroneInterface),
                       HasMethodName(kInstallLinuxPackageProgressSignal))))
      .WillOnce(Invoke([&dbus_result](dbus::Signal* signal) {
        ProtoSignalHelper(signal, &dbus_result);
      }));

  grpc::ServerContext ctx;
  grpc::Status status =
      test_framework.get_service()
          .GetContainerListenerImpl()
          ->InstallLinuxPackageProgress(&ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(dbus_result.vm_name(), ServiceTestingHelper::kDefaultVmName);
  EXPECT_EQ(dbus_result.container_name(),
            ServiceTestingHelper::kDefaultContainerName);
  EXPECT_EQ(dbus_result.owner_id(), ServiceTestingHelper::kDefaultOwnerId);
  EXPECT_EQ(dbus_result.status(), InstallLinuxPackageProgressSignal::FAILED);
  EXPECT_EQ(dbus_result.progress_percent(), 0);
  EXPECT_EQ(dbus_result.failure_details(), kFailureDetails);
}

TEST(ContainerListenerImplTest,
     ValidUninstallPackageProgressCallShouldProduceDBusMessage) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::UninstallPackageProgressInfo request;
  vm_tools::EmptyMessage response;

  request.set_token(ServiceTestingHelper::kDefaultContainerToken);
  request.set_status(
      vm_tools::container::UninstallPackageProgressInfo::UNINSTALLING);
  request.set_progress_percent(72);

  UninstallPackageProgressSignal dbus_result;
  EXPECT_CALL(test_framework.get_mock_exported_object(),
              SendSignal(AllOf(HasInterfaceName(kVmCiceroneInterface),
                               HasMethodName(kUninstallPackageProgressSignal))))
      .WillOnce(Invoke([&dbus_result](dbus::Signal* signal) {
        ProtoSignalHelper(signal, &dbus_result);
      }));

  grpc::ServerContext ctx;
  grpc::Status status =
      test_framework.get_service()
          .GetContainerListenerImpl()
          ->UninstallPackageProgress(&ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(dbus_result.vm_name(), ServiceTestingHelper::kDefaultVmName);
  EXPECT_EQ(dbus_result.container_name(),
            ServiceTestingHelper::kDefaultContainerName);
  EXPECT_EQ(dbus_result.owner_id(), ServiceTestingHelper::kDefaultOwnerId);
  EXPECT_EQ(dbus_result.status(), UninstallPackageProgressSignal::UNINSTALLING);
  EXPECT_EQ(dbus_result.progress_percent(), 72);
  EXPECT_EQ(dbus_result.failure_details(), "");
}

TEST(ContainerListenerImplTest,
     FailedUninstallPackageProgressCallShouldProduceDBusMessage) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::UninstallPackageProgressInfo request;
  vm_tools::EmptyMessage response;

  const std::string kFailureDetails = "Hahaha NO";
  request.set_token(ServiceTestingHelper::kDefaultContainerToken);
  request.set_status(vm_tools::container::UninstallPackageProgressInfo::FAILED);
  request.set_failure_details(kFailureDetails);

  UninstallPackageProgressSignal dbus_result;
  EXPECT_CALL(test_framework.get_mock_exported_object(),
              SendSignal(AllOf(HasInterfaceName(kVmCiceroneInterface),
                               HasMethodName(kUninstallPackageProgressSignal))))
      .WillOnce(Invoke([&dbus_result](dbus::Signal* signal) {
        ProtoSignalHelper(signal, &dbus_result);
      }));

  grpc::ServerContext ctx;
  grpc::Status status =
      test_framework.get_service()
          .GetContainerListenerImpl()
          ->UninstallPackageProgress(&ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(dbus_result.vm_name(), ServiceTestingHelper::kDefaultVmName);
  EXPECT_EQ(dbus_result.container_name(),
            ServiceTestingHelper::kDefaultContainerName);
  EXPECT_EQ(dbus_result.owner_id(), ServiceTestingHelper::kDefaultOwnerId);
  EXPECT_EQ(dbus_result.status(), UninstallPackageProgressSignal::FAILED);
  EXPECT_EQ(dbus_result.progress_percent(), 0);
  EXPECT_EQ(dbus_result.failure_details(), kFailureDetails);
}

TEST(ContainerListenerImplTest, ValidOpenTerminalCallShouldProduceDBusMessage) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::OpenTerminalRequest request;
  vm_tools::EmptyMessage response;

  request.set_token(ServiceTestingHelper::kDefaultContainerToken);
  *request.add_params() = "-c";
  *request.add_params() = "/bin/ls";
  *request.add_params() = "/tmp";

  vm_tools::apps::TerminalParams dbus_result;
  EXPECT_CALL(
      test_framework.get_mock_vm_applications_service_proxy(),
      MockCallMethodAndBlock(
          AllOf(
              HasInterfaceName(vm_tools::apps::kVmApplicationsServiceInterface),
              HasMethodName(
                  vm_tools::apps::kVmApplicationsServiceLaunchTerminalMethod)),
          _))
      .WillOnce(Invoke([&dbus_result](dbus::MethodCall* method_call, Unused) {
        return ProtoMethodCallHelper(method_call, &dbus_result);
      }));

  grpc::ServerContext ctx;
  grpc::Status status =
      test_framework.get_service().GetContainerListenerImpl()->OpenTerminal(
          &ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(dbus_result.vm_name(), ServiceTestingHelper::kDefaultVmName);
  EXPECT_EQ(dbus_result.container_name(),
            ServiceTestingHelper::kDefaultContainerName);
  EXPECT_EQ(dbus_result.owner_id(), ServiceTestingHelper::kDefaultOwnerId);
  ASSERT_EQ(dbus_result.params_size(), 3);
  EXPECT_EQ(dbus_result.params(0), "-c");
  EXPECT_EQ(dbus_result.params(1), "/bin/ls");
  EXPECT_EQ(dbus_result.params(2), "/tmp");
}

TEST(ContainerListenerImplTest,
     ValidUpdateMimeTypesCallShouldProduceDBusMessage) {
  ServiceTestingHelper test_framework(ServiceTestingHelper::NORMAL_MOCKS);
  test_framework.SetUpDefaultVmAndContainer();
  test_framework.ExpectNoDBusMessages();

  vm_tools::container::UpdateMimeTypesRequest request;
  vm_tools::EmptyMessage response;

  request.set_token(ServiceTestingHelper::kDefaultContainerToken);
  (*request.mutable_mime_type_mappings())["aiff"] = "audio/x-aiff";
  (*request.mutable_mime_type_mappings())["rar"] = "application/rar";
  (*request.mutable_mime_type_mappings())["png"] = "image/png";

  vm_tools::apps::MimeTypes dbus_result;
  EXPECT_CALL(
      test_framework.get_mock_vm_applications_service_proxy(),
      MockCallMethodAndBlock(
          AllOf(
              HasInterfaceName(vm_tools::apps::kVmApplicationsServiceInterface),
              HasMethodName(
                  vm_tools::apps::kVmApplicationsServiceUpdateMimeTypesMethod)),
          _))
      .WillOnce(Invoke([&dbus_result](dbus::MethodCall* method_call, Unused) {
        return ProtoMethodCallHelper(method_call, &dbus_result);
      }));

  grpc::ServerContext ctx;
  grpc::Status status =
      test_framework.get_service().GetContainerListenerImpl()->UpdateMimeTypes(
          &ctx, &request, &response);
  ASSERT_TRUE(status.ok()) << status.error_message();

  EXPECT_EQ(dbus_result.vm_name(), ServiceTestingHelper::kDefaultVmName);
  EXPECT_EQ(dbus_result.container_name(),
            ServiceTestingHelper::kDefaultContainerName);
  EXPECT_EQ(dbus_result.owner_id(), ServiceTestingHelper::kDefaultOwnerId);
  const auto& mime_type_mappings = dbus_result.mime_type_mappings();
  EXPECT_EQ(mime_type_mappings.size(), 3);
  auto aiff_iter = mime_type_mappings.find("aiff");
  ASSERT_TRUE(aiff_iter != mime_type_mappings.end());
  EXPECT_EQ(aiff_iter->second, "audio/x-aiff");
  auto rar_iter = mime_type_mappings.find("rar");
  ASSERT_TRUE(rar_iter != mime_type_mappings.end());
  EXPECT_EQ(rar_iter->second, "application/rar");
  auto png_iter = mime_type_mappings.find("png");
  ASSERT_TRUE(png_iter != mime_type_mappings.end());
  EXPECT_EQ(png_iter->second, "image/png");
}

}  // namespace

}  // namespace cicerone
}  // namespace vm_tools
