// Copyright 2021 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 <fuchsia/inspect/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/inspect/cpp/hierarchy.h>
#include <lib/inspect/testing/cpp/inspect.h>

#include <algorithm>
#include <string>
#include <string_view>
#include <vector>

#include "src/lib/storage/vfs/cpp/inspect/inspect_tree.h"
#include "src/storage/fs_test/fs_test_fixture.h"

namespace fs_test {
namespace {

using namespace ::testing;
using namespace inspect::testing;

using inspect::StringPropertyValue;
using inspect::UintPropertyValue;

// All properties we require the fs.info node to contain, excluding optional fields.
constexpr std::string_view kRequiredInfoProperties[] = {
    fs_inspect::InfoData::kPropId,
    fs_inspect::InfoData::kPropType,
    fs_inspect::InfoData::kPropName,
    fs_inspect::InfoData::kPropVersionMajor,
    fs_inspect::InfoData::kPropVersionMinor,
    fs_inspect::InfoData::kPropBlockSize,
    fs_inspect::InfoData::kPropMaxFilenameLength,
};

// All properties we expect the fs.usage node to contain.
constexpr std::string_view kAllUsageProperties[] = {
    fs_inspect::UsageData::kPropTotalBytes,
    fs_inspect::UsageData::kPropUsedBytes,
    fs_inspect::UsageData::kPropTotalNodes,
    fs_inspect::UsageData::kPropUsedNodes,
};

// All properties we expect the fs.volume node to contain.
constexpr std::string_view kAllVolumeProperties[] = {
    fs_inspect::VolumeData::kPropSizeBytes,
    fs_inspect::VolumeData::kPropSizeLimitBytes,
    fs_inspect::VolumeData::kPropAvailableSpaceBytes,
    fs_inspect::VolumeData::kPropOutOfSpaceEvents,
};

// Create a vector of all property names found in the given node.
std::vector<std::string> GetPropertyNames(const inspect::NodeValue& node) {
  std::vector<std::string> properties;
  for (const auto& property : node.properties()) {
    properties.push_back(property.name());
  }
  return properties;
}

// Validates that the snapshot's hierarchy is compliant so that the test case invariants can be
// ensured. Use with ASSERT_NO_FATAL_FAILURE.
void ValidateHierarchy(const inspect::Hierarchy& root) {
  // Validate that the expected nodes in the hierarchy exist.
  ASSERT_THAT(root,
              ChildrenMatch(IsSupersetOf({NodeMatches(NameMatches(fs_inspect::kInfoNodeName)),
                                          NodeMatches(NameMatches(fs_inspect::kUsageNodeName)),
                                          NodeMatches(NameMatches(fs_inspect::kVolumeNodeName))})));

  // Ensure the expected properties under each node exist so that the invariants the getters above
  // rely on are valid (namely, that these specific nodes and their properties exist).

  // Validate that the required fs.info node properties are present.
  const inspect::Hierarchy* info = root.GetByPath({fs_inspect::kInfoNodeName});
  ASSERT_NE(info, nullptr) << "Could not find node " << fs_inspect::kInfoNodeName;
  EXPECT_THAT(GetPropertyNames(info->node()), IsSupersetOf(kRequiredInfoProperties));

  // Validate fs.usage node properties.
  const inspect::Hierarchy* usage = root.GetByPath({fs_inspect::kUsageNodeName});
  ASSERT_NE(usage, nullptr) << "Could not find node " << fs_inspect::kUsageNodeName;
  EXPECT_THAT(GetPropertyNames(usage->node()), UnorderedElementsAreArray(kAllUsageProperties));

  // Validate fs.volume node properties.
  const inspect::Hierarchy* volume = root.GetByPath({fs_inspect::kVolumeNodeName});
  ASSERT_NE(volume, nullptr) << "Could not find node " << fs_inspect::kVolumeNodeName;
  EXPECT_THAT(GetPropertyNames(volume->node()), UnorderedElementsAreArray(kAllVolumeProperties));
}

// Parse the given fs.info node properties into a corresponding InfoData struct.
// Properties within the given node must both exist and be the correct type.
fs_inspect::InfoData GetInfoProperties(const inspect::NodeValue& info_node) {
  using fs_inspect::InfoData;

  // oldest_version is optional.
  std::optional<std::string> oldest_version = std::nullopt;
  if (info_node.get_property<StringPropertyValue>(InfoData::kPropOldestVersion)) {
    oldest_version =
        info_node.get_property<StringPropertyValue>(InfoData::kPropOldestVersion)->value();
  }

  return InfoData{
      .id = info_node.get_property<UintPropertyValue>(InfoData::kPropId)->value(),
      .type = info_node.get_property<UintPropertyValue>(InfoData::kPropType)->value(),
      .name = info_node.get_property<StringPropertyValue>(InfoData::kPropName)->value(),
      .version_major =
          info_node.get_property<UintPropertyValue>(InfoData::kPropVersionMajor)->value(),
      .version_minor =
          info_node.get_property<UintPropertyValue>(InfoData::kPropVersionMinor)->value(),
      .block_size = info_node.get_property<UintPropertyValue>(InfoData::kPropBlockSize)->value(),
      .max_filename_length =
          info_node.get_property<UintPropertyValue>(InfoData::kPropMaxFilenameLength)->value(),
      .oldest_version = std::move(oldest_version),
  };
}

// Parse the given fs.usage node properties into a corresponding UsageData struct.
// Properties within the given node must both exist and be the correct type.
fs_inspect::UsageData GetUsageProperties(const inspect::NodeValue& usage_node) {
  using fs_inspect::UsageData;
  return UsageData{
      .total_bytes =
          usage_node.get_property<UintPropertyValue>(UsageData::kPropTotalBytes)->value(),
      .used_bytes = usage_node.get_property<UintPropertyValue>(UsageData::kPropUsedBytes)->value(),
      .total_nodes =
          usage_node.get_property<UintPropertyValue>(UsageData::kPropTotalNodes)->value(),
      .used_nodes = usage_node.get_property<UintPropertyValue>(UsageData::kPropUsedNodes)->value(),
  };
}

// Parse the given fs.volume node properties into a corresponding VolumeData struct.
// Properties within the given node must both exist and be the correct type.
fs_inspect::VolumeData GetVolumeProperties(const inspect::NodeValue& volume_node) {
  using fs_inspect::VolumeData;
  return VolumeData{
      .size_info =
          {
              .size_bytes =
                  volume_node.get_property<UintPropertyValue>(VolumeData::kPropSizeBytes)->value(),
              .size_limit_bytes =
                  volume_node.get_property<UintPropertyValue>(VolumeData::kPropSizeLimitBytes)
                      ->value(),
              .available_space_bytes =
                  volume_node.get_property<UintPropertyValue>(VolumeData::kPropAvailableSpaceBytes)
                      ->value(),
          },
      .out_of_space_events =
          volume_node.get_property<UintPropertyValue>(VolumeData::kPropOutOfSpaceEvents)->value(),
  };
}

class InspectTest : public FilesystemTest {
 protected:
  // Initializes the test case by taking an initial snapshot of the inspect tree, and validates
  // the overall node hierarchy/layout.
  void SetUp() override {
    // Take an initial snapshot.
    ASSERT_NO_FATAL_FAILURE(UpdateAndValidateSnapshot());
  }

  // Take a new snapshot of the filesystem's inspect tree and validate the layout for compliance.
  // Invalidates the previous hierarchy obtained by calling Root().
  //
  // All calls to this function *must* be wrapped with ASSERT_NO_FATAL_FAILURE. Failure to do so
  // can result in some test fixture methods segfaulting.
  void UpdateAndValidateSnapshot() {
    snapshot_ = fs().TakeSnapshot();
    // Validate the inspect hierarchy. Ensures all nodes/properties exist and are the correct types.
    ASSERT_NO_FATAL_FAILURE(ValidateHierarchy(Root()));
  }

  // Reference to root hierarchy from last snapshot. After calling UpdateAndValidateSnapshot(),
  // existing references are invalidated and *must not* be used.
  const inspect::Hierarchy& Root() const {
    // All inspect properties are attached under a unique name based on the filesystem type.
    // This allows a unique path to query the properties which is important for lapis sampling.
    const inspect::Hierarchy* root = snapshot_.GetByPath({fs().GetTraits().name});
    ZX_ASSERT_MSG(
        root != nullptr,
        "Could not find named root node in filesystem hierarchy (expected node name = %s).",
        fs().GetTraits().name.c_str());
    return *root;
  }

  // Obtains InfoData containing values from the latest snapshot's fs.info node.
  // All calls to UpdateAndValidateSnapshot() must be wrapped by ASSERT_NO_FATAL_FAILURE,
  // otherwise this function can dereference a nullptr causing a segfault.
  fs_inspect::InfoData GetInfoData() const {
    return GetInfoProperties(Root().GetByPath({fs_inspect::kInfoNodeName})->node());
  }

  // Obtains UsageData containing values from the latest snapshot's fs.usage node.
  // All calls to UpdateAndValidateSnapshot() must be wrapped by ASSERT_NO_FATAL_FAILURE,
  // otherwise this function can dereference a nullptr causing a segfault.
  fs_inspect::UsageData GetUsageData() const {
    return GetUsageProperties(Root().GetByPath({fs_inspect::kUsageNodeName})->node());
  }

  // Obtains VolumeData containing values from the latest snapshot's fs.volume node.
  // All calls to UpdateAndValidateSnapshot() must be wrapped by ASSERT_NO_FATAL_FAILURE,
  // otherwise this function can dereference a nullptr causing a segfault.
  fs_inspect::VolumeData GetVolumeData() const {
    return GetVolumeProperties(Root().GetByPath({fs_inspect::kVolumeNodeName})->node());
  }

 private:
  // Last snapshot taken of the inspect tree.
  inspect::Hierarchy snapshot_ = {};
};

// Validate values in the fs.info node.
TEST_P(InspectTest, ValidateInfoNode) {
  fs_inspect::InfoData info_data = GetInfoData();
  // The filesystem name (type) should match those in the filesystem traits.
  ASSERT_EQ(info_data.name, fs().GetTraits().name);
  // The filesystem instance identifier should be a valid handle (i.e. non-zero).
  ASSERT_NE(info_data.id, ZX_HANDLE_INVALID);
  // The maximum filename length should be set (i.e. > 0).
  ASSERT_GT(info_data.max_filename_length, 0u);
  // If the filesystem reports oldest_version, ensure it is the correct format (oldest maj/min).
  if (info_data.oldest_version.has_value()) {
    ASSERT_THAT(info_data.oldest_version.value(), ::testing::MatchesRegex("^[0-9]+\\/[0-9]+$"));
  }
}

// Validate values in the fs.usage node.
TEST_P(InspectTest, ValidateUsageNode) {
  fs_inspect::UsageData usage_data = GetUsageData();
  EXPECT_GT(usage_data.total_nodes, 0u);
  EXPECT_GT(usage_data.total_bytes, 0u);
  EXPECT_LE(usage_data.total_bytes,
            fs().options().device_block_count * fs().options().device_block_size);
  uint64_t orig_used_bytes = usage_data.used_bytes;
  uint64_t orig_used_nodes = usage_data.used_nodes;

  // Write a file to disk.
  std::string test_filename = GetPath("test_file");
  const size_t kDataWriteSize = 128ul * 1024ul;

  fbl::unique_fd fd(open(test_filename.c_str(), O_CREAT | O_RDWR, 0666));
  ASSERT_TRUE(fd);
  std::vector<uint8_t> data(kDataWriteSize);
  ASSERT_EQ(write(fd.get(), data.data(), data.size()), static_cast<ssize_t>(data.size()));
  ASSERT_EQ(fsync(fd.get()), 0);

  // Take a new inspect snapshot, ensure used_bytes/used_nodes are updated correctly.
  ASSERT_NO_FATAL_FAILURE(UpdateAndValidateSnapshot());
  usage_data = GetUsageData();
  // Used bytes should increase by at least the amount of written data, and we should now use
  // at least one more inode than before.
  EXPECT_GE(usage_data.used_bytes, orig_used_bytes + kDataWriteSize);
  EXPECT_GE(usage_data.used_nodes, orig_used_nodes + 1);
}

// Validate values in the fs.volume node.
TEST_P(InspectTest, ValidateVolumeNode) {
  fs_inspect::VolumeData volume_data = GetVolumeData();
  EXPECT_EQ(volume_data.out_of_space_events, 0u);
  if (fs().options().use_fvm) {
    uint64_t device_size = fs().options().device_block_count * fs().options().device_block_size;
    uint64_t init_fvm_size = fs().options().fvm_slice_size * fs().options().initial_fvm_slice_count;
    ASSERT_GT(device_size, 0u) << "Invalid block device size!";
    ASSERT_GT(init_fvm_size, 0u) << "Invalid FVM volume size!";

    // The reported volume size should be at least the amount of initial FVM slices, but not exceed
    // the size of the block device.
    EXPECT_GE(volume_data.size_info.size_bytes, init_fvm_size);
    EXPECT_LT(volume_data.size_info.size_bytes, device_size);

    // We should have some amount of free space, but not more than the size of the block device.
    EXPECT_GT(volume_data.size_info.available_space_bytes, 0u);
    EXPECT_LT(volume_data.size_info.available_space_bytes, device_size);

    // We do not set a volume size limit in fs_test currently, so this should always be zero.
    EXPECT_EQ(volume_data.size_info.size_limit_bytes, 0u);

  } else {
    // If we aren't using an FVM-backed filesystem, we should fail to query these properties from
    // the volume protocol, so they should all be set to zero.
    EXPECT_EQ(volume_data.size_info.available_space_bytes, 0u);
    EXPECT_EQ(volume_data.size_info.size_bytes, 0u);
    EXPECT_EQ(volume_data.size_info.size_limit_bytes, 0u);
  }
}

std::vector<TestFilesystemOptions> GetTestCombinations() {
  return MapAndFilterAllTestFilesystems(
      [](const TestFilesystemOptions& options) -> std::optional<TestFilesystemOptions> {
        if (options.filesystem->GetTraits().supports_inspect) {
          return options;
        }
        return std::nullopt;
      });
}

INSTANTIATE_TEST_SUITE_P(/*no prefix*/, InspectTest, ::testing::ValuesIn(GetTestCombinations()),
                         ::testing::PrintToStringParamName());

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InspectTest);

}  // namespace
}  // namespace fs_test
