// Copyright 2020 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 "inspect-manager.h"

#include <fcntl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/namespace.h>
#include <lib/fpromise/single_threaded_executor.h>
#include <lib/inspect/cpp/reader.h>
#include <sys/stat.h>

#include <fbl/unique_fd.h>
#include <zxtest/zxtest.h>

#include "src/lib/fxl/strings/substitute.h"
#include "src/lib/storage/vfs/cpp/remote_dir.h"
#include "src/storage/memfs/scoped_memfs.h"

namespace {

constexpr char kTmpfsPath[] = "/fshost-inspect-tmp";

inspect::Hierarchy ReadInspect(const inspect::Inspector& inspector) {
  // take_value() will assert if the promise result is an error.
  return fpromise::run_single_threaded(inspect::ReadFromInspector(inspector)).take_value();
}

class InspectManagerTest : public zxtest::Test {
 public:
  InspectManagerTest() : memfs_loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {}

  void SetUp() override {
    ASSERT_EQ(memfs_loop_.StartThread(), ZX_OK);
    zx::status<ScopedMemfs> memfs =
        ScopedMemfs::CreateMountedAt(memfs_loop_.dispatcher(), kTmpfsPath);
    ASSERT_TRUE(memfs.is_ok());
    memfs_ = std::make_unique<ScopedMemfs>(std::move(*memfs));
  }

  void TearDown() override { memfs_.reset(); }

 protected:
  fidl::ClientEnd<fuchsia_io::Directory> GetDir() {
    auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
    EXPECT_TRUE(endpoints.is_ok());
    auto [client, server] = *std::move(endpoints);
    EXPECT_EQ(ZX_OK, fdio_open(kTmpfsPath,
                               static_cast<uint32_t>(fuchsia_io::wire::OpenFlags::kRightReadable |
                                                     fuchsia_io::wire::OpenFlags::kRightExecutable),
                               server.TakeChannel().release()));
    return std::move(client);
  }

  void AddFile(const std::string& path, size_t content_size) {
    std::string contents(content_size, 'X');
    fbl::unique_fd fd(open(fxl::Substitute("$0/$1", kTmpfsPath, path).c_str(), O_RDWR | O_CREAT,
                           S_IRUSR | S_IWUSR));
    ASSERT_TRUE(fd.is_valid());
    ASSERT_EQ(write(fd.get(), contents.c_str(), content_size), content_size);
  }

  void MakeDir(const std::string& path) {
    ASSERT_EQ(0, mkdir(fxl::Substitute("$0/$1", kTmpfsPath, path).c_str(), 0666));
  }

  void AssertValue(const inspect::Hierarchy& hierarchy, const std::vector<std::string>& path,
                   size_t expected, size_t other_children = 0) {
    auto file_node = hierarchy.GetByPath(path);
    EXPECT_NOT_NULL(file_node);
    ASSERT_EQ(1, file_node->node().properties().size());
    ASSERT_EQ(other_children, file_node->children().size());
    auto& size_property = file_node->node().properties()[0];
    EXPECT_EQ("size", size_property.name());
    EXPECT_EQ(expected, size_property.Get<inspect::UintPropertyValue>().value());
  }

  async::Loop memfs_loop_;
  std::unique_ptr<ScopedMemfs> memfs_;
};

TEST_F(InspectManagerTest, ServeStats) {
  // Initialize test directory
  MakeDir("a");
  MakeDir("a/b");
  MakeDir("a/c");
  AddFile("top.txt", 12);
  AddFile("a/a.txt", 13);
  AddFile("a/b/b.txt", 14);
  AddFile("a/c/c.txt", 15);
  AddFile("a/c/d.txt", 16);

  // Serve inspect stats.
  auto inspect_manager = fshost::FshostInspectManager();
  auto test_dir = GetDir();
  inspect_manager.ServeStats("test_dir", std::move(test_dir));

  // Read inspect
  inspect::Hierarchy hierarchy = ReadInspect(inspect_manager.inspector());

  // Assert root
  ASSERT_EQ(1, hierarchy.children().size());
  ASSERT_EQ(0, hierarchy.node().properties().size());

  // Assert all size values.
  AssertValue(hierarchy, {"test_dir_stats", "test_dir"}, 70, 2);
  AssertValue(hierarchy, {"test_dir_stats", "test_dir", "top.txt"}, 12);
  AssertValue(hierarchy, {"test_dir_stats", "test_dir", "a"}, 58, 3);
  AssertValue(hierarchy, {"test_dir_stats", "test_dir", "a", "a.txt"}, 13);
  AssertValue(hierarchy, {"test_dir_stats", "test_dir", "a", "b"}, 14, 1);
  AssertValue(hierarchy, {"test_dir_stats", "test_dir", "a", "b", "b.txt"}, 14);
  AssertValue(hierarchy, {"test_dir_stats", "test_dir", "a", "c"}, 31, 2);
  AssertValue(hierarchy, {"test_dir_stats", "test_dir", "a", "c", "c.txt"}, 15);
  AssertValue(hierarchy, {"test_dir_stats", "test_dir", "a", "c", "d.txt"}, 16);
}

// Validate that using a bad handle to serve a stats node doesn't block indefinitely.
TEST_F(InspectManagerTest, ServeStatsBadHandle) {
  // Serve inspect stats using an invalid channel.
  auto inspect_manager = fshost::FshostInspectManager();
  fidl::ClientEnd<fuchsia_io::Directory> client_end;
  ASSERT_FALSE(client_end.is_valid());
  inspect_manager.ServeStats("test_dir", std::move(client_end));
  inspect::Hierarchy hierarchy = ReadInspect(inspect_manager.inspector());
  // Ensure the node doesn't actually exist since the callback should return an error.
  ASSERT_EQ(hierarchy.GetByPath({"test_dir_stats"}), nullptr);
}

TEST_F(InspectManagerTest, DirectoryEntryIteratorGetNext) {
  MakeDir("iterator-test");
  for (int64_t i = 0; i < 5000; i++) {
    if (i % 2 == 0) {
      MakeDir(fxl::Substitute("/iterator-test/dir$0", std::to_string(i)));
    } else {
      AddFile(fxl::Substitute("/iterator-test/file$0", std::to_string(i)), 10);
    }
  }
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  ASSERT_TRUE(endpoints.is_ok());
  auto [root, server] = *std::move(endpoints);
  ASSERT_EQ(ZX_OK, fdio_open(kTmpfsPath,
                             static_cast<uint32_t>(fuchsia_io::wire::OpenFlags::kRightReadable |
                                                   fuchsia_io::wire::OpenFlags::kRightExecutable),
                             server.TakeChannel().release()));
  fidl::ClientEnd<fuchsia_io::Node> test_dir_chan;
  auto status = fshost::OpenNode(root, "/iterator-test", S_IFDIR, &test_dir_chan);
  ASSERT_EQ(status, ZX_OK);

  // The opened node must be a directory because of the |MakeDir| call above.
  fidl::ClientEnd<fuchsia_io::Directory> test_dir(test_dir_chan.TakeChannel());
  auto iterator = fshost::DirectoryEntriesIterator(std::move(test_dir));
  int64_t found = 0;
  while (auto entry = iterator.GetNext()) {
    if (entry->name.find("dir") == 0) {
      EXPECT_EQ(entry->size, 0);
      EXPECT_TRUE(entry->is_dir);
    } else {
      EXPECT_EQ(entry->name.find("file"), 0);
      EXPECT_EQ(entry->size, 10);
      EXPECT_FALSE(entry->is_dir);
    }
    EXPECT_TRUE(entry->node.is_valid());
    found += 1;
  }
  EXPECT_EQ(found, 5000);
}

TEST_F(InspectManagerTest, CorruptionEvents) {
  fshost::FshostInspectManager inspect_manager;
  // There should be no "corruption_events" node until an event is reported.
  inspect::Hierarchy hierarchy = ReadInspect(inspect_manager.inspector());
  ASSERT_EQ(hierarchy.GetByPath({"corruption_events"}), nullptr);

  // Report some corruption events and make sure they show up where we expect.
  inspect_manager.LogCorruption(fs_management::DiskFormat::kDiskFormatMinfs);
  inspect_manager.LogCorruption(fs_management::DiskFormat::kDiskFormatFxfs);
  inspect_manager.LogCorruption(fs_management::DiskFormat::kDiskFormatFxfs);
  inspect_manager.LogCorruption(fs_management::DiskFormat::kDiskFormatFxfs);

  hierarchy = ReadInspect(inspect_manager.inspector());
  const inspect::Hierarchy* corruption_events = hierarchy.GetByPath({"corruption_events"});
  ASSERT_NE(corruption_events, nullptr);

  const auto* minfs_corruption_events =
      corruption_events->node().get_property<inspect::UintPropertyValue>("minfs");
  ASSERT_NE(minfs_corruption_events, nullptr);
  ASSERT_EQ(minfs_corruption_events->value(), 1u);

  const auto* fxfs_corruption_events =
      corruption_events->node().get_property<inspect::UintPropertyValue>("fxfs");
  ASSERT_NE(fxfs_corruption_events, nullptr);
  ASSERT_EQ(fxfs_corruption_events->value(), 3u);
}

}  // namespace
