// Copyright 2017 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 "vm_tools/concierge/termina_vm.h"

#include <arpa/inet.h>
#include <stdint.h>
#include <sys/mount.h>

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

#include <base/bind.h>
#include <base/callback.h>
#include <base/callback_helpers.h>
#include <base/check.h>
#include <base/files/file_descriptor_watcher_posix.h>
#include <base/files/scoped_temp_dir.h>
#include <base/guid.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/run_loop.h>
#include <base/single_thread_task_runner.h>
#include <base/strings/stringprintf.h>
#include <base/test/task_environment.h>
#include <base/threading/thread.h>
#include <base/threading/thread_task_runner_handle.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/util/message_differencer.h>
#include <grpcpp/grpcpp.h>
#include <gtest/gtest.h>
#include <chromeos/patchpanel/address_manager.h>
#include <chromeos/patchpanel/mac_address_generator.h>
#include <chromeos/patchpanel/subnet.h>
#include <vm_protos/proto_bindings/vm_guest.grpc.pb.h>

#include "vm_tools/concierge/vsock_cid_pool.h"

using std::string;

namespace pb = google::protobuf;

namespace vm_tools {
namespace concierge {
namespace {

// Converts an IPv4 address in network byte order into a string.
bool IPv4AddressToString(uint32_t addr, string* address) {
  CHECK(address);

  char buf[INET_ADDRSTRLEN];
  struct in_addr in = {
      .s_addr = addr,
  };
  if (inet_ntop(AF_INET, &in, buf, sizeof(buf)) == nullptr) {
    PLOG(ERROR) << "Failed to convert " << addr << " into a string";
    return false;
  }

  *address = buf;
  return true;
}

// Name of the unix domain socket for the grpc server.
constexpr char kServerSocket[] = "server";

// Sample Termina kernel version.
constexpr char kKernelVersion[] = "some kernel version";

// Test fixture for actually testing the TerminaVm functionality.
class TerminaVmTest : public ::testing::Test {
 public:
  TerminaVmTest() = default;
  TerminaVmTest(const TerminaVmTest&) = delete;
  TerminaVmTest& operator=(const TerminaVmTest&) = delete;

  ~TerminaVmTest() override = default;

  // Called by FakeMaitredService to indicate a test failure.
  void TestFailed(string reason);

  // Called by FakeMaitredService for checking the ConfigureNetwork RPC.
  const string& address() const { return address_; }
  const string& netmask() const { return netmask_; }
  const string& gateway() const { return gateway_; }

  // Called by FakeMaitredService the first time it receives a LaunchProcess
  // RPC.
  std::deque<vm_tools::LaunchProcessRequest> launch_requests() {
    return std::move(launch_requests_);
  }

  // Called by FakeMaitredService the first time it receives a Mount RPC.
  std::deque<vm_tools::MountRequest> mount_requests() {
    return std::move(mount_requests_);
  }

 protected:
  // ::testing::Test overrides.
  void SetUp() override;
  void TearDown() override;

 private:
  // Posted back to the main thread by the grpc thread after starting the
  // server.
  void ServerStartCallback(base::Closure quit,
                           std::shared_ptr<grpc::Server> server);

  // The message loop for the current thread.  Declared here because it must be
  // the last thing to be cleaned up.
  base::test::TaskEnvironment task_environment_;
  base::FileDescriptorWatcher watcher_{
      task_environment_.GetMainThreadTaskRunner()};

 protected:
  // Actual virtual machine being tested.
  std::unique_ptr<TerminaVm> vm_;

  // Expected LaunchProcessRequests. Tests should fill this with all the
  // LaunchProcessRequests that it expects the TerminaVm to receive. These
  // will be moved into the FakeMaitredService the first time it receives a
  // LaunchProcess RPC.
  std::deque<vm_tools::LaunchProcessRequest> launch_requests_;

  // Expected MountRequests.  Tests should fill this with all the MountRequests
  // that they expect a TerminaVm to receive.  These will be moved to the
  // FakeMaitredService the firest time it receives a Mount RPC.
  std::deque<vm_tools::MountRequest> mount_requests_;

  // Set when a failure occurs.
  bool failed_{false};
  string failure_reason_;

 private:
  // Temporary directory where we will store our socket.
  base::ScopedTempDir temp_dir_;

  // Resource allocators for the VM.
  std::unique_ptr<patchpanel::AddressManager> network_address_manager_;
  patchpanel::MacAddressGenerator mac_address_generator_;
  VsockCidPool vsock_cid_pool_;

  // Addresses assigned to the VM.
  string address_;
  string netmask_;
  string gateway_;

  // The thread on which the server will run.
  base::Thread server_thread_{"gRPC maitre'd thread"};

  // grpc::Server that will handle the requests.
  std::shared_ptr<grpc::Server> server_;

  base::WeakPtrFactory<TerminaVmTest> weak_factory_{this};
};

// Test server that verifies the RPCs it receives with the expected RPCs.
class FakeMaitredService final : public vm_tools::Maitred::Service {
 public:
  explicit FakeMaitredService(TerminaVmTest* vm_test);
  FakeMaitredService(const FakeMaitredService&) = delete;
  FakeMaitredService& operator=(const FakeMaitredService&) = delete;

  ~FakeMaitredService() override = default;

  // Maitred::Service overrides.
  grpc::Status LaunchProcess(
      grpc::ServerContext* ctx,
      const vm_tools::LaunchProcessRequest* request,
      vm_tools::LaunchProcessResponse* response) override;
  grpc::Status ConfigureNetwork(grpc::ServerContext* ctx,
                                const vm_tools::NetworkConfigRequest* request,
                                vm_tools::EmptyMessage* response) override;
  grpc::Status Mount(grpc::ServerContext* ctx,
                     const vm_tools::MountRequest* request,
                     vm_tools::MountResponse* response) override;
  grpc::Status Shutdown(grpc::ServerContext* ctx,
                        const vm_tools::EmptyMessage* request,
                        vm_tools::EmptyMessage* response) override;
  grpc::Status SetTime(grpc::ServerContext* ctx,
                       const vm_tools::SetTimeRequest* request,
                       vm_tools::EmptyMessage* response) override;
  grpc::Status SetResolvConfig(grpc::ServerContext* ctx,
                               const vm_tools::SetResolvConfigRequest* request,
                               vm_tools::EmptyMessage* response) override;

 private:
  // Populated the first time this class receives a LaunchProcess RPC.
  std::deque<vm_tools::LaunchProcessRequest> launch_requests_;

  // Set to true when launch_requests_ has been populated.
  bool launch_requests_initialized_;

  // Populated the first time this class receives a MountProcess RPC.
  std::deque<vm_tools::MountRequest> mount_requests_;

  // Set to true when mount_requests_ has been populated.
  bool mount_requests_initialized_;

  // Non-owning pointer to the test fixture.  Valid for the lifetime of this
  // object because this lives on the grpc thread, which is a member of the test
  // fixture.  The cross-thread access is safe because all the TerminaVm
  // RPCs are synchronous, which means the main thread will be blocked while the
  // grpc thread is processing the RPC.
  TerminaVmTest* vm_test_;
};

FakeMaitredService::FakeMaitredService(TerminaVmTest* vm_test)
    : launch_requests_initialized_(false),
      mount_requests_initialized_(false),
      vm_test_(vm_test) {}

grpc::Status FakeMaitredService::LaunchProcess(
    grpc::ServerContext* ctx,
    const vm_tools::LaunchProcessRequest* request,
    vm_tools::LaunchProcessResponse* response) {
  if (!launch_requests_initialized_) {
    launch_requests_ = vm_test_->launch_requests();
    launch_requests_initialized_ = true;
  }

  if (launch_requests_.empty()) {
    vm_test_->TestFailed("Received LaunchProcessRequest with empty deque");
    return grpc::Status::OK;
  }

  vm_tools::LaunchProcessRequest expected = std::move(launch_requests_.front());
  launch_requests_.pop_front();

  string difference;
  pb::util::MessageDifferencer differencer;
  differencer.ReportDifferencesToString(&difference);
  if (!differencer.Compare(expected, *request)) {
    vm_test_->TestFailed("Mismatched LaunchProcessRequests: " + difference);
  }
  return grpc::Status::OK;
}

grpc::Status FakeMaitredService::ConfigureNetwork(
    grpc::ServerContext* ctx,
    const vm_tools::NetworkConfigRequest* request,
    vm_tools::EmptyMessage* response) {
  string address;
  if (!IPv4AddressToString(request->ipv4_config().address(), &address)) {
    vm_test_->TestFailed(
        base::StringPrintf("Failed to parse address %u into a string",
                           request->ipv4_config().address()));
    return grpc::Status::OK;
  }
  if (address != vm_test_->address()) {
    vm_test_->TestFailed(
        base::StringPrintf("Mismatched addresses: expected %s got %s",
                           vm_test_->address().c_str(), address.c_str()));
    return grpc::Status::OK;
  }

  string netmask;
  if (!IPv4AddressToString(request->ipv4_config().netmask(), &netmask)) {
    vm_test_->TestFailed(
        base::StringPrintf("Failed to parse netmask %u into a string",
                           request->ipv4_config().netmask()));
    return grpc::Status::OK;
  }
  if (netmask != vm_test_->netmask()) {
    vm_test_->TestFailed(
        base::StringPrintf("Mismatched netmasks: expected %s got %s",
                           vm_test_->netmask().c_str(), netmask.c_str()));
    return grpc::Status::OK;
  }

  string gateway;
  if (!IPv4AddressToString(request->ipv4_config().gateway(), &gateway)) {
    vm_test_->TestFailed(
        base::StringPrintf("Failed to parse gateway %u into a string",
                           request->ipv4_config().gateway()));
    return grpc::Status::OK;
  }
  if (gateway != vm_test_->gateway()) {
    vm_test_->TestFailed(
        base::StringPrintf("Mismatched gateways: expected %s got %s",
                           vm_test_->gateway().c_str(), gateway.c_str()));
    return grpc::Status::OK;
  }

  return grpc::Status::OK;
}

grpc::Status FakeMaitredService::Mount(grpc::ServerContext* ctx,
                                       const vm_tools::MountRequest* request,
                                       vm_tools::MountResponse* response) {
  if (!mount_requests_initialized_) {
    mount_requests_ = vm_test_->mount_requests();
    mount_requests_initialized_ = true;
  }

  if (mount_requests_.empty()) {
    vm_test_->TestFailed("Received MountRequest with empty deque");
    return grpc::Status::OK;
  }

  vm_tools::MountRequest expected = std::move(mount_requests_.front());
  mount_requests_.pop_front();

  string difference;
  pb::util::MessageDifferencer differencer;
  differencer.ReportDifferencesToString(&difference);
  if (!differencer.Compare(expected, *request)) {
    vm_test_->TestFailed("Mismatched MountRequests: " + difference);
  }
  return grpc::Status::OK;
}

grpc::Status FakeMaitredService::Shutdown(grpc::ServerContext* ctx,
                                          const vm_tools::EmptyMessage* request,
                                          vm_tools::EmptyMessage* response) {
  return grpc::Status::OK;
}

grpc::Status FakeMaitredService::SetTime(
    grpc::ServerContext* ctx,
    const vm_tools::SetTimeRequest* request,
    vm_tools::EmptyMessage* response) {
  return grpc::Status::OK;
}

grpc::Status FakeMaitredService::SetResolvConfig(
    grpc::ServerContext* ctx,
    const vm_tools::SetResolvConfigRequest* request,
    vm_tools::EmptyMessage* response) {
  return grpc::Status::OK;
}

// Runs on the grpc thread and starts the grpc server.
void StartFakeMaitredService(
    TerminaVmTest* vm_test,
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    base::FilePath listen_path,
    base::Callback<void(std::shared_ptr<grpc::Server>)> server_cb) {
  FakeMaitredService maitred(vm_test);

  grpc::ServerBuilder builder;
  builder.AddListeningPort("unix:" + listen_path.value(),
                           grpc::InsecureServerCredentials());
  builder.RegisterService(&maitred);

  std::shared_ptr<grpc::Server> server(builder.BuildAndStart().release());
  main_task_runner->PostTask(FROM_HERE, base::Bind(server_cb, server));

  if (server) {
    // This will not race with shutdown because the grpc server code includes a
    // check to see if the server has already been shut down (or is shutting
    // down) when Wait is called.
    server->Wait();
  }
}

void TerminaVmTest::SetUp() {
  // Create the temporary directory.
  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

  // Start the FakeMaitredService on a different thread.
  base::RunLoop run_loop;

  ASSERT_TRUE(server_thread_.Start());
  server_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(
          &StartFakeMaitredService, this, base::ThreadTaskRunnerHandle::Get(),
          temp_dir_.GetPath().Append(kServerSocket),
          base::Bind(&TerminaVmTest::ServerStartCallback,
                     weak_factory_.GetWeakPtr(), run_loop.QuitClosure())));

  run_loop.Run();

  ASSERT_TRUE(server_);

  // Create the stub to the FakeMaitredService.
  std::unique_ptr<vm_tools::Maitred::Stub> stub =
      vm_tools::Maitred::NewStub(grpc::CreateChannel(
          "unix:" + temp_dir_.GetPath().Append(kServerSocket).value(),
          grpc::InsecureChannelCredentials()));
  ASSERT_TRUE(stub);

  // Allocate resources for the VM.
  network_address_manager_.reset(new patchpanel::AddressManager());
  uint32_t vsock_cid = vsock_cid_pool_.Allocate();
  std::unique_ptr<patchpanel::Subnet> subnet =
      network_address_manager_->AllocateIPv4Subnet(
          patchpanel::AddressManager::Guest::VM_TERMINA);

  ASSERT_TRUE(subnet);

  ASSERT_TRUE(IPv4AddressToString(subnet->AddressAtOffset(1), &address_));
  ASSERT_TRUE(IPv4AddressToString(subnet->Netmask(), &netmask_));
  ASSERT_TRUE(IPv4AddressToString(subnet->AddressAtOffset(0), &gateway_));

  std::string stateful_device = "/dev/vdb";
  uint64_t stateful_size = (uint64_t)20 * 1024 * 1024 * 1024;

  // Create the TerminaVm.
  VmBuilder vm_builder;
  vm_builder.SetRootfs({.device = "/dev/vda", .path = base::FilePath("dummy")});
  vm_ = TerminaVm::CreateForTesting(
      std::move(subnet), vsock_cid, temp_dir_.GetPath(), base::FilePath(),
      base::FilePath(), std::move(stateful_device), stateful_size,
      kKernelVersion, std::move(stub), true /* is_termina */,
      std::move(vm_builder));
  ASSERT_TRUE(vm_);
}

void TerminaVmTest::TearDown() {
  // Do the opposite of SetUp to make sure things get cleaned up in the right
  // order.
  vm_.reset();
  server_->Shutdown();
  server_.reset();
  server_thread_.Stop();
}

void TerminaVmTest::ServerStartCallback(base::Closure quit,
                                        std::shared_ptr<grpc::Server> server) {
  server_.swap(server);
  quit.Run();
}

void TerminaVmTest::TestFailed(string reason) {
  failed_ = true;
  failure_reason_ = std::move(reason);
}

}  // namespace

TEST_F(TerminaVmTest, ConfigureNetwork) {
  ASSERT_TRUE(vm_->ConfigureNetwork({"8.8.8.8"}, {}));

  EXPECT_FALSE(failed_) << "Failure reason: " << failure_reason_;
}

TEST_F(TerminaVmTest, SetTime) {
  string reason;
  bool success = vm_->SetTime(&reason);
  EXPECT_TRUE(success) << reason;

  EXPECT_FALSE(failed_) << "Failure reason: " << failure_reason_;
}

TEST_F(TerminaVmTest, Mount) {
  struct {
    const char* source;
    const char* target;
    const char* fstype;
    uint64_t flags;
    const char* opts;
  } mounts[] = {
      {
          .source = "100.115.92.25:/my/home/directory",
          .target = "/mnt/shared",
          .fstype = "nfs",
          .flags = 0,
          .opts = "nolock,vers=3,addr=100.115.92.25",
      },
      {
          .source = "/dev/vdb",
          .target = "/mnt/container_rootfs",
          .fstype = "ext4",
          .flags = MS_RDONLY,
          .opts = "",
      },
  };

  // Build the expected protobufs.
  for (const auto& mt : mounts) {
    vm_tools::MountRequest request;

    request.set_source(mt.source);
    request.set_target(mt.target);
    request.set_fstype(mt.fstype);
    request.set_mountflags(mt.flags);
    request.set_options(mt.opts);

    mount_requests_.emplace_back(std::move(request));
  }

  // Make the requests.
  for (const auto& mt : mounts) {
    ASSERT_TRUE(vm_->Mount(mt.source, mt.target, mt.fstype, mt.flags, mt.opts));

    EXPECT_FALSE(failed_) << "Failure reason: " << failure_reason_;
  }
}

TEST_F(TerminaVmTest, GetVmEnterpriseReportingInfo) {
  GetVmEnterpriseReportingInfoResponse response;
  bool result = vm_->GetVmEnterpriseReportingInfo(&response);
  EXPECT_TRUE(result);
  EXPECT_EQ(kKernelVersion, response.vm_kernel_version());
}

}  // namespace concierge
}  // namespace vm_tools
