// Copyright 2020 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_kvs/alignment.h"

#include <cstring>
#include <string_view>

#include "gtest/gtest.h"
#include "pw_status/status_with_size.h"

namespace pw::kvs {
namespace {

using namespace std::string_view_literals;
using std::byte;

constexpr size_t kAlignment = 10;

constexpr std::string_view kData =
    "123456789_123456789_123456789_123456789_123456789_"   //  50
    "123456789_123456789_123456789_123456789_123456789_";  // 100

const span<const byte> kBytes = as_bytes(span(kData));

// The output function checks that the data is properly aligned and matches
// the expected value (should always be 123456789_...).
OutputToFunction check_against_data([](span<const byte> data) {
  EXPECT_EQ(data.size() % kAlignment, 0u);
  EXPECT_EQ(kData.substr(0, data.size()),
            std::string_view(reinterpret_cast<const char*>(data.data()),
                             data.size()));
  return StatusWithSize(data.size());
});

TEST(AlignedWriter, Write_VaryingLengths) {
  AlignedWriterBuffer<32> writer(kAlignment, check_against_data);

  // Write values smaller than the alignment.
  EXPECT_EQ(OkStatus(), writer.Write(kBytes.subspan(0, 1)).status());
  EXPECT_EQ(OkStatus(), writer.Write(kBytes.subspan(1, 9)).status());

  // Write values larger than the alignment but smaller than the buffer.
  EXPECT_EQ(OkStatus(), writer.Write(kBytes.subspan(10, 11)).status());

  // Exactly fill the remainder of the buffer.
  EXPECT_EQ(OkStatus(), writer.Write(kBytes.subspan(21, 11)).status());

  // Fill the buffer more than once.
  EXPECT_EQ(OkStatus(), writer.Write(kBytes.subspan(32, 66)).status());

  // Write nothing.
  EXPECT_EQ(OkStatus(), writer.Write(kBytes.subspan(98, 0)).status());

  // Write the remaining data.
  EXPECT_EQ(OkStatus(), writer.Write(kBytes.subspan(98, 2)).status());

  auto result = writer.Flush();
  EXPECT_EQ(OkStatus(), result.status());
  EXPECT_EQ(kData.size(), result.size());
}

TEST(AlignedWriter, DestructorFlushes) {
  static size_t called_with_bytes;
  called_with_bytes = 0;

  OutputToFunction output([](span<const byte> data) {
    called_with_bytes += data.size();
    return StatusWithSize(data.size());
  });

  {
    AlignedWriterBuffer<64> writer(3, output);
    ASSERT_EQ(OkStatus(),
              writer.Write(as_bytes(span("What is this?"))).status());
    EXPECT_EQ(called_with_bytes, 0u);  // Buffer not full; no output yet.
  }

  EXPECT_EQ(called_with_bytes, AlignUp(sizeof("What is this?"), 3));
}

// Output class that can be programmed to fail for testing purposes.
// TODO(hepler): If we create a general pw_io / pw_stream module, this and
// InputWithErrorInjection should be made into generic test utility classes,
// similar to FakeFlashMemory.
struct OutputWithErrorInjection final : public Output {
 public:
  enum { kKeepGoing, kBreakOnNext, kBroken } state = kKeepGoing;

 private:
  StatusWithSize DoWrite(span<const byte> data) override {
    switch (state) {
      case kKeepGoing:
        return StatusWithSize(data.size());
      case kBreakOnNext:
        state = kBroken;
        break;
      case kBroken:
        ADD_FAILURE();
        break;
    }
    return StatusWithSize::Unknown(data.size());
  }
};

TEST(AlignedWriter, Write_NoFurtherWritesOnFailure) {
  OutputWithErrorInjection output;

  {
    AlignedWriterBuffer<4> writer(3, output);
    ASSERT_EQ(OkStatus(),
              writer.Write(as_bytes(span("Everything is fine."))).status());
    output.state = OutputWithErrorInjection::kBreakOnNext;
    EXPECT_EQ(Status::Unknown(),
              writer.Write(as_bytes(span("No more writes, okay?"))).status());
  }
}

TEST(AlignedWriter, Write_ReturnsTotalBytesWritten) {
  static Status return_status;
  return_status = OkStatus();

  OutputToFunction output([](span<const byte> data) {
    return StatusWithSize(return_status, data.size());
  });

  AlignedWriterBuffer<22> writer(10, output);

  StatusWithSize result = writer.Write(as_bytes(span("12345678901"sv)));
  EXPECT_EQ(OkStatus(), result.status());
  EXPECT_EQ(0u, result.size());  // No writes; haven't filled buffer.

  result = writer.Write(as_bytes(span("2345678901"sv)));
  EXPECT_EQ(OkStatus(), result.status());
  EXPECT_EQ(20u, result.size());

  return_status = Status::PermissionDenied();

  result = writer.Write(as_bytes(span("2345678901234567890"sv)));
  EXPECT_EQ(Status::PermissionDenied(), result.status());
  EXPECT_EQ(40u, result.size());
}

TEST(AlignedWriter, Flush_Ok_ReturnsTotalBytesWritten) {
  OutputToFunction output(
      [](span<const byte> data) { return StatusWithSize(data.size()); });

  AlignedWriterBuffer<4> writer(2, output);

  EXPECT_EQ(OkStatus(), writer.Write(as_bytes(span("12345678901"sv))).status());

  StatusWithSize result = writer.Flush();
  EXPECT_EQ(OkStatus(), result.status());
  EXPECT_EQ(12u, result.size());
}

TEST(AlignedWriter, Flush_Error_ReturnsTotalBytesWritten) {
  OutputToFunction output([](span<const byte> data) {
    return StatusWithSize::Aborted(data.size());
  });

  AlignedWriterBuffer<20> writer(10, output);

  EXPECT_EQ(0u, writer.Write(as_bytes(span("12345678901"sv))).size());

  StatusWithSize result = writer.Flush();
  EXPECT_EQ(Status::Aborted(), result.status());
  EXPECT_EQ(20u, result.size());
}

// Input class that can be programmed to fail for testing purposes.
class InputWithErrorInjection final : public Input {
 public:
  void BreakOnIndex(size_t index) { break_on_index_ = index; }

 private:
  StatusWithSize DoRead(span<byte> data) override {
    EXPECT_LE(index_ + data.size(), kBytes.size());

    if (index_ + data.size() > kBytes.size()) {
      return StatusWithSize::Internal();
    }

    // Check if reading from the index that was programmed to cause an error.
    if (index_ <= break_on_index_ && break_on_index_ <= index_ + data.size()) {
      return StatusWithSize::Aborted();
    }

    std::memcpy(data.data(), kBytes.data(), data.size());
    index_ += data.size();
    return StatusWithSize(data.size());
  }

  size_t index_ = 0;
  size_t break_on_index_ = size_t(-1);
};

TEST(AlignedWriter, WriteFromInput_Successful) {
  AlignedWriterBuffer<32> writer(kAlignment, check_against_data);

  InputWithErrorInjection input;
  StatusWithSize result = writer.Write(input, kData.size());
  EXPECT_EQ(OkStatus(), result.status());
  EXPECT_LE(result.size(), kData.size());  // May not have written it all yet.

  result = writer.Flush();
  EXPECT_EQ(OkStatus(), result.status());
  EXPECT_EQ(kData.size(), result.size());
}

TEST(AlignedWriter, WriteFromInput_InputError) {
  AlignedWriterBuffer<kAlignment> writer(kAlignment, check_against_data);

  InputWithErrorInjection input;
  input.BreakOnIndex(kAlignment + 2);

  StatusWithSize result = writer.Write(input, kData.size());
  EXPECT_EQ(Status::Aborted(), result.status());
  EXPECT_LE(result.size(), kAlignment);  // Wrote the first chunk, nothing more.
}

TEST(AlignedWriter, WriteFromInput_OutputError) {
  InputWithErrorInjection input;
  OutputWithErrorInjection output;

  AlignedWriterBuffer<4> writer(3, output);
  output.state = OutputWithErrorInjection::kBreakOnNext;

  StatusWithSize result = writer.Write(input, kData.size());
  EXPECT_EQ(Status::Unknown(), result.status());
  EXPECT_EQ(3u, result.size());  // Attempted to write 3 bytes.
}

}  // namespace
}  // namespace pw::kvs
