// 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.

#ifndef SRC_STORAGE_FS_TEST_FS_TEST_H_
#define SRC_STORAGE_FS_TEST_FS_TEST_H_

#include <fcntl.h>
#include <lib/zx/status.h>
#include <lib/zx/time.h>
#include <stdint.h>
#include <zircon/compiler.h>

#include <functional>
#include <iostream>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include <fbl/unique_fd.h>
#include <fs-management/admin.h>
#include <fs-management/format.h>
#include <fs-management/mount.h>
#include <ramdevice-client/ramnand.h>

#include "src/storage/blobfs/blob_layout.h"
#include "src/storage/testing/ram_disk.h"

namespace fs_test {

class Filesystem;

using RamDevice = std::variant<storage::RamDisk, ramdevice_client::RamNand>;

struct TestFilesystemOptions {
  static TestFilesystemOptions DefaultBlobfs();
  static TestFilesystemOptions BlobfsWithoutFvm();

  std::string description;
  bool use_ram_nand = false;
  // If set specifies a VMO to be used to back the device.  If used for ram-nand, Its size must
  // match the device size (if device_block_count is non-zero), including the extra required for
  // OOB.
  zx::unowned_vmo vmo;
  bool use_fvm = false;

  // If non-zero, create a dummy FVM partition which has the effect of moving the location of the
  // partition under test to be at a different offset on the underlying device.
  uint64_t dummy_fvm_partition_size = 0;

  uint64_t device_block_size = 0;
  uint64_t device_block_count = 0;
  uint64_t fvm_slice_size = 0;
  uint64_t initial_fvm_slice_count = 1;
  // Only supported for blobfs for now.
  uint64_t num_inodes = 0;
  const Filesystem* filesystem = nullptr;
  // By default the ram-disk we create is filled with a non-zero value (so that we don't
  // inadvertently depend on it), but that won't work for very large ram-disks (they will trigger
  // OOMs), in which case they can be zero filled.
  bool zero_fill = false;

  // The format blobfs should store blobs in.
  std::optional<blobfs::BlobLayoutFormat> blob_layout_format;

  // If using ram_nand, the number of writes after which writes should fail.
  uint32_t fail_after;

  // If true, when the ram-disk is disconnected it will discard random writes performed since the
  // last flush (which is all that any device will guarantee).
  bool ram_disk_discard_random_after_last_flush = false;
};

std::ostream& operator<<(std::ostream& out, const TestFilesystemOptions& options);

std::vector<TestFilesystemOptions> AllTestFilesystems();
// Provides the ability to map and filter all test file systems, using the supplied function.
std::vector<TestFilesystemOptions> MapAndFilterAllTestFilesystems(
    std::function<std::optional<TestFilesystemOptions>(const TestFilesystemOptions&)>);
TestFilesystemOptions OptionsWithDescription(std::string_view description);

// Returns device and device path.
zx::status<std::pair<RamDevice, std::string>> CreateRamDevice(const TestFilesystemOptions& options);

// A file system instance is a specific instance created for test purposes.
class FilesystemInstance {
 public:
  FilesystemInstance() = default;
  FilesystemInstance(const FilesystemInstance&) = delete;
  FilesystemInstance& operator=(const FilesystemInstance&) = delete;
  virtual ~FilesystemInstance() = default;

  virtual zx::status<> Format(const TestFilesystemOptions&) = 0;
  virtual zx::status<> Mount(const std::string& mount_path, const mount_options_t& options) = 0;
  virtual zx::status<> Unmount(const std::string& mount_path);
  virtual zx::status<> Fsck() = 0;

  // Returns path of the device on which the filesystem is created. For filesystem that are not
  // block device based, like memfs, the function returns an error.
  virtual zx::status<std::string> DevicePath() const = 0;
  virtual storage::RamDisk* GetRamDisk() { return nullptr; }
  virtual ramdevice_client::RamNand* GetRamNand() { return nullptr; }
  virtual zx::unowned_channel GetOutgoingDirectory() const { return {}; }
};

// Base class for all supported file systems. It is a factory class that generates
// instances of FilesystemInstance subclasses.
class Filesystem {
 public:
  struct Traits {
    std::string name;
    zx::duration timestamp_granularity = zx::nsec(1);
    bool supports_hard_links = true;
    bool supports_mmap = false;
    bool supports_resize = false;
    off_t max_file_size = std::numeric_limits<off_t>::max();
    bool in_memory = false;
    bool is_case_sensitive = true;
    bool supports_sparse_files = true;
    bool is_slow = false;
    bool supports_fsck_after_every_transaction = false;
    bool has_directory_size_limit = false;
    bool is_journaled = true;
    bool supports_fs_query = true;
    bool supports_watch_event_deleted = true;
  };

  virtual ~Filesystem() = default;
  virtual zx::status<std::unique_ptr<FilesystemInstance>> Make(
      const TestFilesystemOptions& options) const = 0;
  virtual zx::status<std::unique_ptr<FilesystemInstance>> Open(
      const TestFilesystemOptions& options) const {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }
  virtual const Traits& GetTraits() const = 0;
};

// Template that implementations can use to gain the SharedInstance method.
template <typename T>
class FilesystemImpl : public Filesystem {
 public:
  static const T& SharedInstance() {
    static const auto* const kInstance = new T();
    return *kInstance;
  }
};

template <typename T>
class FilesystemImplWithDefaultMake : public FilesystemImpl<T> {
 public:
  virtual std::unique_ptr<FilesystemInstance> Create(RamDevice device,
                                                     std::string device_path) const = 0;

  zx::status<std::unique_ptr<FilesystemInstance>> Make(
      const TestFilesystemOptions& options) const override {
    auto result = CreateRamDevice(options);
    if (result.is_error()) {
      return result.take_error();
    }
    auto [device, device_path] = std::move(result).value();
    auto instance = Create(std::move(device), std::move(device_path));
    zx::status<> status = instance->Format(options);
    if (status.is_error()) {
      return status.take_error();
    }
    return zx::ok(std::move(instance));
  }
};

// -- Default implementations that use fs-management --

zx::status<> FsFormat(const std::string& device_path, disk_format_t format,
                      const mkfs_options_t& options);

zx::status<> FsMount(const std::string& device_path, const std::string& mount_path,
                     disk_format_t format, const mount_options_t& mount_options,
                     zx::channel* outgoing_directory = nullptr);

// Unmounts using fs/Admin.Shutdown.
zx::status<> FsAdminUnmount(const std::string& mount_path, const zx::channel& outgoing_directory);

zx::status<std::pair<RamDevice, std::string>> OpenRamDevice(const TestFilesystemOptions& options);

std::string StripTrailingSlash(const std::string& in);

// Removes `mount_path` from the namespace.
zx::status<> FsUnbind(const std::string& mount_path);

}  // namespace fs_test

#endif  // SRC_STORAGE_FS_TEST_FS_TEST_H_
