// Copyright 2019 The Fuchsia 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 <chrono>
#include <cstdlib>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <re2/re2.h>

#include "src/lib/json_parser/json_parser.h"
#include "src/virtualization/tests/guest_test.h"

namespace {

using testing::HasSubstr;
using namespace std::chrono_literals;

constexpr size_t kVirtioBalloonPageCount = 256;
constexpr size_t kVirtioConsoleMessageCount = 100;
constexpr char kVirtioRngUtil[] = "virtio_rng_test_util";

constexpr uint64_t kOneKibibyte = 1ul << 10;
constexpr uint64_t kOneMebibyte = 1ul << 20;
constexpr uint64_t kOneGibibyte = 1ul << 30;

// Memory tests moderately increase the VM's guest memory above the default so that they can
// validate that the guest memory is configurable.
#if __aarch64__
constexpr uint64_t kGuestMemoryForMemoryTests = kOneGibibyte + 512 * kOneMebibyte;
#else
constexpr uint64_t kGuestMemoryForMemoryTests = 4 * kOneGibibyte + 512 * kOneMebibyte;
#endif

template <class T>
using CoreGuestTest = GuestTest<T>;

// This test suite contains all guest tests that don't require a specific configuration of devices.
// They are grouped together so that they share guests and reduce the number of times guests are
// started, which is time consuming. Note that this means that some tests need to dynamically check
// the guest type in order to skip under certain conditions.
TYPED_TEST_SUITE(CoreGuestTest, AllGuestTypes, GuestTestNameGenerator);

TYPED_TEST(CoreGuestTest, VirtioBalloon) {
  // Zircon does not yet have a virtio balloon driver.
  if (this->GetGuestKernel() == GuestKernel::ZIRCON) {
    return;
  }

  std::string result;
  EXPECT_EQ(this->Execute({"echo", "test"}, &result), ZX_OK);
  EXPECT_EQ(result, "test\n");

  fuchsia::virtualization::BalloonControllerSyncPtr balloon_controller;
  this->ConnectToBalloon(balloon_controller.NewRequest());

  uint32_t initial_num_pages;
  zx_status_t status = balloon_controller->GetNumPages(&initial_num_pages);
  ASSERT_EQ(status, ZX_OK);

  // Request an increase to the number of pages in the balloon.
  status = balloon_controller->RequestNumPages(initial_num_pages + kVirtioBalloonPageCount);
  ASSERT_EQ(status, ZX_OK);

  // Verify that the number of pages eventually equals the requested number. The
  // guest may not respond to the request immediately so we call GetNumPages in
  // a loop.
  uint32_t num_pages;
  while (true) {
    status = balloon_controller->GetNumPages(&num_pages);
    ASSERT_EQ(status, ZX_OK);
    if (num_pages == initial_num_pages + kVirtioBalloonPageCount) {
      break;
    }
  }

  // Request a decrease to the number of pages in the balloon back to the
  // initial value.
  status = balloon_controller->RequestNumPages(initial_num_pages);
  ASSERT_EQ(status, ZX_OK);

  while (true) {
    status = balloon_controller->GetNumPages(&num_pages);
    ASSERT_EQ(status, ZX_OK);
    if (num_pages == initial_num_pages) {
      break;
    }
  }
}

TYPED_TEST(CoreGuestTest, VirtioConsole) {
  // Test many small packets.
  std::string result;
  for (size_t i = 0; i != kVirtioConsoleMessageCount; ++i) {
    EXPECT_EQ(this->Execute({"echo", "test"}, &result), ZX_OK);
    EXPECT_EQ(result, "test\n");
  }

  // Test large packets. Note that we must keep the total length below 4096,
  // which is the maximum line length for dash.
  std::string test_data = "";
  for (size_t i = 0; i != kVirtioConsoleMessageCount; ++i) {
    test_data.append("Lorem ipsum dolor sit amet consectetur");
  }
  EXPECT_EQ(this->Execute({"echo", test_data.c_str()}, &result), ZX_OK);
  test_data.append("\n");
  EXPECT_EQ(result, test_data);
}

TYPED_TEST(CoreGuestTest, VirtioRng) {
  std::string result;
  ASSERT_EQ(this->RunUtil(kVirtioRngUtil, {}, &result), ZX_OK);
  EXPECT_THAT(result, HasSubstr("PASS"));
}

TYPED_TEST(CoreGuestTest, RealTimeClock) {
  // Real time clock not functioning in Zircon guest at this time.
  //
  // TODO(fxbug.dev/75440): Fix clock in Zircon guest.
  if (this->GetGuestKernel() == GuestKernel::ZIRCON) {
    return;
  }

  // Print seconds since Unix epoch (1970-01-01), and parse the result.
  std::string result;
  ASSERT_EQ(this->Execute({"/bin/date", "+%s"}, {}, &result), ZX_OK);
  int64_t guest_timestamp = std::stol(result, /*pos=*/nullptr, /*base=*/10);
  ASSERT_TRUE(guest_timestamp > 0) << "Could not parse guest time.";

  // Get the system time.
  std::chrono::time_point now = std::chrono::system_clock::now();
  int64_t host_timestamp =
      std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();

  // Ensure the clock matches the system time, within a few minutes.
  std::cout << "Guest time is " << (host_timestamp - guest_timestamp)
            << " second(s) behind host time.\n";
  EXPECT_LT(std::abs(host_timestamp - guest_timestamp),
            std::chrono::duration_cast<std::chrono::seconds>(5min).count())
      << "Guest time (" << guest_timestamp << ") and host time (" << host_timestamp
      << ") differ by more than 5 minutes.";
}

template <typename T>
class CustomizableMemoryGuest : public T {
 public:
  explicit CustomizableMemoryGuest(async::Loop& loop) : T(loop) {}

  zx_status_t LaunchInfo(GuestLaunchInfo* launch_info) override {
    zx_status_t status = T::LaunchInfo(launch_info);
    if (status != ZX_OK) {
      return status;
    }

    launch_info->config.set_guest_memory(kGuestMemoryForMemoryTests);

    return ZX_OK;
  }
};

using LinuxCustomizableMemoryGuestTypes =
    ::testing::Types<CustomizableMemoryGuest<DebianEnclosedGuest>,
                     CustomizableMemoryGuest<TerminaEnclosedGuest>>;

template <class T>
using CustomizableMemoryLinuxGuestTest = GuestTest<T>;
TYPED_TEST_SUITE(CustomizableMemoryLinuxGuestTest, LinuxCustomizableMemoryGuestTypes,
                 GuestTestNameGenerator);

TYPED_TEST(CustomizableMemoryLinuxGuestTest, LinuxSystemMemoryConfigurable) {
  std::string result;
  ASSERT_EQ(this->Execute({"cat", "/proc/meminfo"}, {}, &result), ZX_OK);

  std::string sizestr;
  RE2::PartialMatch(result, R"(MemTotal:\s+(\d+)\skB)", &sizestr);

  uint64_t system_memory = std::stoull(sizestr) * kOneKibibyte;

  // Linux doesn't report the actual amount of system memory via meminfo, and we don't
  // currently emulate SMBIOS allowing us to use dmidecode. For now, we can just assume
  // that the Linux kernel isn't taking up more than 300 mebibytes giving moderate
  // confidence that this works.
  uint64_t memory_leeway = 300 * kOneMebibyte;
  EXPECT_THAT(system_memory + memory_leeway, ::testing::Gt(kGuestMemoryForMemoryTests));
}

using CustomizableMemoryZirconGuestTest = GuestTest<CustomizableMemoryGuest<ZirconEnclosedGuest>>;
TEST_F(CustomizableMemoryZirconGuestTest, ZirconSystemMemoryConfigurable) {
  std::string result;
  ASSERT_EQ(this->Execute({"memgraph"}, {}, &result), ZX_OK);

  json_parser::JSONParser parser;
  rapidjson::Document memgraph = parser.ParseFromString(result, "memgraph");
  ASSERT_FALSE(parser.HasError()) << parser.error_str();
  ASSERT_TRUE(memgraph.IsArray());

  uint64_t system_memory = 0;
  std::string physmem("physmem");
  for (auto& entry : memgraph.GetArray()) {
    if (entry.HasMember("name") && entry["name"].GetString() == physmem) {
      system_memory = entry["size_bytes"].GetUint64();
    }
  }

  ASSERT_NE(0ul, system_memory) << "Couldn't find physmem entry in memgraph output";

  // Zircon may or may not allow the first MiB to be used for as guest memory, so expect that
  // reported memory is within one MiB of expected memory.
  uint64_t memory_leeway = kOneMebibyte;
  EXPECT_THAT(system_memory + memory_leeway, ::testing::Gt(kGuestMemoryForMemoryTests));
}

}  // namespace
