// 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 <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_span/span.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(as_bytes(span(kTestData))), OkStatus());
  writer.Close();

  StdFileReader reader(TempFilename());
  ASSERT_EQ(reader.ConservativeReadLimit(), kTestData.size());

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

  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());
  ASSERT_EQ(reader.ConservativeReadLimit(), read_buffer.size());
  result = reader.Read(as_writable_bytes(span(read_buffer)));
  EXPECT_EQ(result.status(), OkStatus());

  reader.Close();
}

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