// Copyright 2018 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 <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#include <random>
#include <string_view>

#include <fbl/unique_fd.h>

#include "src/storage/fs_test/fs_test_fixture.h"

namespace fs_test {
namespace {

using RwTest = FilesystemTest;

// Test that zero length read and write operations are valid.
TEST_P(RwTest, ZeroLengthOperations) {
  const std::string filename = GetPath("zero_length_ops");
  fbl::unique_fd fd(open(filename.c_str(), O_RDWR | O_CREAT, 0644));
  ASSERT_TRUE(fd);

  // Zero-length write.
  ASSERT_EQ(write(fd.get(), nullptr, 0), 0);
  ASSERT_EQ(pwrite(fd.get(), nullptr, 0, 0), 0);

  // Zero-length read.
  ASSERT_EQ(read(fd.get(), nullptr, 0), 0);
  ASSERT_EQ(pread(fd.get(), nullptr, 0, 0), 0);

  // Seek pointer unchanged.
  ASSERT_EQ(lseek(fd.get(), 0, SEEK_CUR), 0);

  ASSERT_EQ(close(fd.release()), 0);
  ASSERT_EQ(unlink(filename.c_str()), 0);
}

// Test that zero length write interleaved with non-zero length writes
// works as expected.
TEST_P(RwTest, ZeroLengthOperationWithNonZeroLengthWrites) {
  const std::string filename = GetPath("zero_length_after_large_offset_ops");
  fbl::unique_fd fd(open(filename.c_str(), O_RDWR | O_CREAT, 0644));
  ASSERT_TRUE(fd);

  constexpr size_t kBufferSize = 65374;
  std::unique_ptr<uint8_t[]> buffer(new uint8_t[kBufferSize]());

  memset(buffer.get(), 0, kBufferSize);
  uint64_t kLargeOffset = 50ull * 1024ull * 1024ull;
  uint64_t kOffset = 11ull * 1024ull * 1024ull;

  ASSERT_EQ(pwrite(fd.get(), buffer.get(), kBufferSize, kLargeOffset),
            static_cast<ssize_t>(kBufferSize));
  ASSERT_EQ(pwrite(fd.get(), nullptr, 0, kOffset), 0);
  ASSERT_EQ(pwrite(fd.get(), buffer.get(), kBufferSize, kLargeOffset - 8192),
            static_cast<ssize_t>(kBufferSize));

  ASSERT_EQ(close(fd.release()), 0);
}

// Test that non-zero length read_at and write_at operations are valid.
TEST_P(RwTest, OffsetOperations) {
  srand(0xDEADBEEF);

  constexpr size_t kBufferSize = PAGE_SIZE;
  uint8_t expected[kBufferSize];
  for (size_t i = 0; i < std::size(expected); i++) {
    expected[i] = static_cast<uint8_t>(rand());
  }

  struct TestOption {
    size_t write_start;
    size_t read_start;
    size_t expected_read_length;
  };

  TestOption options[] = {
      {0, 0, kBufferSize},
      {0, 1, kBufferSize - 1},
      {1, 0, kBufferSize},
      {1, 1, kBufferSize},
  };

  for (const auto& opt : options) {
    const std::string filename = GetPath("offset_ops");
    fbl::unique_fd fd(open(filename.c_str(), O_RDWR | O_CREAT, 0644));
    ASSERT_TRUE(fd);

    uint8_t buf[kBufferSize];
    memset(buf, 0, sizeof(buf));

    // 1) Write "kBufferSize" bytes at opt.write_start
    ASSERT_EQ(pwrite(fd.get(), expected, sizeof(expected), opt.write_start),
              static_cast<ssize_t>(sizeof(expected)));

    // 2) Read "kBufferSize" bytes at opt.read_start;
    //    actually read opt.expected_read_length bytes.
    ASSERT_EQ(pread(fd.get(), buf, sizeof(expected), opt.read_start),
              static_cast<ssize_t>(opt.expected_read_length));

    // 3) Verify the contents of the read matched, the seek
    //    pointer is unchanged, and the file size is correct.
    if (opt.write_start <= opt.read_start) {
      size_t read_skip = opt.read_start - opt.write_start;
      ASSERT_EQ(memcmp(buf, expected + read_skip, opt.expected_read_length), 0);
    } else {
      size_t write_skip = opt.write_start - opt.read_start;
      uint8_t zeroes[write_skip];
      memset(zeroes, 0, sizeof(zeroes));
      ASSERT_EQ(memcmp(buf, zeroes, write_skip), 0);
    }
    ASSERT_EQ(lseek(fd.get(), 0, SEEK_CUR), 0);
    struct stat st;
    ASSERT_EQ(fstat(fd.get(), &st), 0);
    ASSERT_EQ(st.st_size, static_cast<ssize_t>(opt.write_start + sizeof(expected)));

    ASSERT_EQ(close(fd.release()), 0);
    ASSERT_EQ(unlink(filename.c_str()), 0);
  }
}

using RwFullDiskTest = FilesystemTest;

TEST_P(RwFullDiskTest, PartialWriteSucceedsForFullDisk) {
  fbl::unique_fd fd(open(GetPath("bigfile").c_str(), O_CREAT | O_RDWR, 0644));
  ASSERT_TRUE(fd);
  constexpr int kBufSize = 131072;
  std::vector<uint64_t> data(kBufSize / sizeof(uint64_t));
  std::random_device random_device;
  std::default_random_engine random(random_device());
  std::uniform_int_distribution<uint64_t> distribution;
  std::generate(data.begin(), data.end(), [&]() { return distribution(random); });
  off_t done = 0;
  for (;;) {
    const int offset = done % kBufSize;
    int len = kBufSize - offset;
    // We should always hit ENOSPC on a power of 2; make sure that we'll always have a short write
    // at the end.
    if (done + len % 2 == 0) {
      --len;
    }
    ssize_t r = write(fd.get(), reinterpret_cast<uint8_t*>(data.data()) + offset, len);
    if (r < 0) {
      EXPECT_EQ(errno, ENOSPC);
      break;
    }
    EXPECT_LE(r, len);
    done += r;
  }
  struct stat stat_buf;
  ASSERT_EQ(fstat(fd.get(), &stat_buf), 0) << errno;
  EXPECT_EQ(stat_buf.st_size, done);
  ASSERT_EQ(lseek(fd.get(), 0, SEEK_SET), 0) << errno;
  std::vector<uint8_t> read_buf(kBufSize);
  off_t verified = 0;
  for (;;) {
    const int offset = verified % kBufSize;
    int len = kBufSize - offset;
    ssize_t r = read(fd.get(), read_buf.data(), len);
    ASSERT_GE(r, 0) << errno;
    if (r == 0) {
      EXPECT_EQ(verified, done);
      break;
    }
    ASSERT_LE(r, len);
    EXPECT_EQ(memcmp(read_buf.data(), reinterpret_cast<uint8_t*>(data.data()) + offset, r), 0);
    verified += r;
  }
}

using RwSparseTest = FilesystemTest;

TEST_P(RwSparseTest, MaxFileSize) {
  constexpr std::string_view kTestData = "hello";
  off_t offset = fs().GetTraits().max_file_size - kTestData.size();
  const std::string foo = GetPath("foo");
  {
    fbl::unique_fd fd(open(foo.c_str(), O_RDWR | O_CREAT, 0644));
    ASSERT_TRUE(fd);
    ASSERT_EQ(pwrite(fd.get(), kTestData.data(), kTestData.size(), offset),
              static_cast<ssize_t>(kTestData.size()));
    ASSERT_EQ(fsync(fd.get()), 0);  // Deliberate sync so that close is likely to unload the vnode.
    ASSERT_EQ(close(fd.release()), 0);
  }
  {
    fbl::unique_fd fd(open(foo.c_str(), O_RDONLY));
    ASSERT_TRUE(fd);
    uint8_t buf[kTestData.size()];
    ASSERT_EQ(pread(fd.get(), buf, kTestData.size(), offset),
              static_cast<ssize_t>(kTestData.size()));
    ASSERT_EQ(memcmp(buf, kTestData.data(), kTestData.size()), 0);
  }
}

INSTANTIATE_TEST_SUITE_P(/*no prefix*/, RwTest, testing::ValuesIn(AllTestFilesystems()),
                         testing::PrintToStringParamName());

INSTANTIATE_TEST_SUITE_P(
    /*no prefix*/, RwFullDiskTest,
    testing::ValuesIn(MapAndFilterAllTestFilesystems(
        [](TestFilesystemOptions options) -> std::optional<TestFilesystemOptions> {
          if (options.filesystem->GetTraits().in_memory) {
            return std::nullopt;
          }
          // Run on a smaller ram-disk to keep run-time reasonable.
          options.device_block_count = 8192;
          options.fvm_slice_size = 32768;
          return options;
        })),
    testing::PrintToStringParamName());

// These tests will only work on a file system that supports sparse files.
INSTANTIATE_TEST_SUITE_P(
    /*no prefix*/, RwSparseTest,
    testing::ValuesIn(MapAndFilterAllTestFilesystems(
        [](const TestFilesystemOptions& options) -> std::optional<TestFilesystemOptions> {
          if (options.filesystem->GetTraits().supports_sparse_files) {
            return options;
          } else {
            return std::nullopt;
          }
        })),
    testing::PrintToStringParamName());

}  // namespace
}  // namespace fs_test
