// Copyright 2022 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_stream/std_file_stream.h"

#include <algorithm>
#include <array>
#include <cinttypes>
#include <cstdio>
#include <filesystem>
#include <random>
#include <span>
#include <string>
#include <string_view>

#include "gtest/gtest.h"
#include "pw_assert/assert.h"
#include "pw_bytes/span.h"
#include "pw_containers/algorithm.h"
#include "pw_random/xor_shift.h"
#include "pw_status/status.h"
#include "pw_status/status_with_size.h"
#include "pw_string/string_builder.h"

namespace pw::stream {
namespace {

constexpr std::string_view kSmallTestData(
    "This is a test string used to verify correctness!");

// Creates a directory with a specified prefix followed by a random 32-bit hex
// number. Random temporary file handle names can then be requested. When the
// TempDir is destroyed, the entire directory is deleted.
//
// Example created temporary files:
//     /tmp/StdFileStreamTest32B37409/997BDDA2
//     /tmp/StdFileStreamTest32B37409/C181909B
//
// WARNING: This class should ONLY be used for these tests!
//
// These tests need to open and close files by file name, which is incompatible
// with std::tmpfile() (which deletes files on close). Even though std::tmpnam()
// looks like the right tool to use, it's not thread safe and doesn't provide
// any guarantees that the provided file name is not in use. std::tmpnam() is
// also marked with a deprecation warning on some systems, warning against using
// it at all.
//
// While on some systems this approach may provide significantly better
// uniqueness since std::random_device may be backed with thread-safe random
// sources, the STL does not explicitly require std::random_device to produce
// non-deterministic random data (instead only recommending it). If
// std::random_device is pseudo-random, this temporary directory will always
// end up with the same naming pattern.
//
// If the STL required std::random_device to be thread-safe and
// cryptographically-secure, this class could be made reasonably production
// ready by increasing use of entropy and making temporary file name selection
// thread-safe (in case a TempDir is static and shared across multiple threads).
//
// Today, this class does not provide much better safety guarantees than
// std::tmpnam(), but thanks to the required directory prefix and typical
// implementations of std::random_device, should see less risk of collisions in
// practice.
class TempDir {
 public:
  TempDir(std::string_view prefix) : rng_(GetSeed()) {
    temp_dir_ = std::filesystem::temp_directory_path();
    temp_dir_ /= std::string(prefix) + GetRandomSuffix();
    PW_ASSERT(std::filesystem::create_directory(temp_dir_));
  }

  ~TempDir() { PW_ASSERT(std::filesystem::remove_all(temp_dir_)); }

  std::filesystem::path GetTempFileName() {
    return temp_dir_ / GetRandomSuffix();
  }

 private:
  std::string GetRandomSuffix() {
    pw::StringBuffer<9> random_suffix_str;
    uint32_t random_suffix_int = 0;
    PW_ASSERT(rng_.GetInt(random_suffix_int).ok());
    PW_ASSERT(random_suffix_str.Format("%08" PRIx32, random_suffix_int).ok());
    return std::string(random_suffix_str.view());
  }

  // Generate a 64-bit random from system entropy pool. This is used to seed a
  // pseudo-random number generator for individual file names.
  static uint64_t GetSeed() {
    std::random_device sys_rand;
    uint64_t seed = 0;
    for (size_t seed_bytes = 0; seed_bytes < sizeof(seed);
         seed_bytes += sizeof(std::random_device::result_type)) {
      std::random_device::result_type val = sys_rand();
      seed = seed << 8 * sizeof(std::random_device::result_type);
      seed |= val;
    }
    return seed;
  }

  random::XorShiftStarRng64 rng_;
  std::filesystem::path temp_dir_;
};

class StdFileStreamTest : public ::testing::Test {
 protected:
  StdFileStreamTest() = default;

  void SetUp() override {
    temp_file_path_ = temp_dir_.GetTempFileName().generic_string();
  }
  void TearDown() override {
    PW_ASSERT(std::filesystem::remove(TempFilename()));
  }

  const char* TempFilename() { return temp_file_path_.c_str(); }

 private:
  // Only construct one temporary directory to reduce waste of system entropy.
  static TempDir temp_dir_;

  std::string temp_file_path_;
};

TempDir StdFileStreamTest::temp_dir_{"StdFileStreamTest"};

TEST_F(StdFileStreamTest, SeekAtEnd) {
  // Write some data to the temporary file.
  const std::string_view kTestData = kSmallTestData;
  StdFileWriter writer(TempFilename());
  ASSERT_EQ(writer.Write(std::as_bytes(std::span(kTestData))), OkStatus());
  writer.Close();

  StdFileReader reader(TempFilename());
  std::array<char, 3> read_buffer;
  size_t read_offset = 0;
  while (read_offset < kTestData.size()) {
    Result<ConstByteSpan> result =
        reader.Read(std::as_writable_bytes(std::span(read_buffer)));
    ASSERT_EQ(result.status(), OkStatus());
    ASSERT_GT(result.value().size(), 0u);
    ASSERT_LE(result.value().size(), read_buffer.size());
    ASSERT_LE(result.value().size(), kTestData.size() - read_offset);
    ConstByteSpan expect_window =
        std::as_bytes(std::span(kTestData))
            .subspan(read_offset, result.value().size());
    EXPECT_TRUE(pw::containers::Equal(result.value(), expect_window));
    read_offset += result.value().size();
  }
  // After data has been read, do a final read to trigger EOF.
  Result<ConstByteSpan> result =
      reader.Read(std::as_writable_bytes(std::span(read_buffer)));
  EXPECT_EQ(result.status(), Status::OutOfRange());

  EXPECT_EQ(read_offset, kTestData.size());

  // Seek backwards and read again to ensure seek at EOF works.
  ASSERT_EQ(reader.Seek(-1 * read_buffer.size(), Stream::Whence::kEnd),
            OkStatus());
  result = reader.Read(std::as_writable_bytes(std::span(read_buffer)));
  EXPECT_EQ(result.status(), OkStatus());

  reader.Close();
}

}  // namespace
}  // namespace pw::stream
