#include "quiche/http2/adapter/chunked_buffer.h"

#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "quiche/common/platform/api/quiche_test.h"

namespace http2 {
namespace adapter {
namespace {

constexpr absl::string_view kLoremIpsum =
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
    "tempor incididunt ut labore et dolore magna aliqua.";

struct DataAndSize {
  std::unique_ptr<char[]> data;
  size_t size;
};

DataAndSize MakeDataAndSize(absl::string_view source) {
  auto data = std::unique_ptr<char[]>(new char[source.size()]);
  std::copy(source.begin(), source.end(), data.get());
  return {std::move(data), source.size()};
}

TEST(ChunkedBufferTest, Empty) {
  ChunkedBuffer buffer;
  EXPECT_TRUE(buffer.Empty());

  buffer.Append("some data");
  EXPECT_FALSE(buffer.Empty());

  buffer.RemovePrefix(9);
  EXPECT_TRUE(buffer.Empty());
}

TEST(ChunkedBufferTest, ReusedAfterEmptied) {
  ChunkedBuffer buffer;
  buffer.Append("some data");
  buffer.RemovePrefix(9);
  buffer.Append("different data");
  EXPECT_EQ("different data", buffer.GetPrefix());
}

TEST(ChunkedBufferTest, LargeAppendAfterEmptied) {
  ChunkedBuffer buffer;
  buffer.Append("some data");
  EXPECT_THAT(buffer.GetPrefix(), testing::StartsWith("some data"));
  buffer.RemovePrefix(9);
  auto more_data =
      MakeDataAndSize(absl::StrCat("different data", std::string(2048, 'x')));
  buffer.Append(std::move(more_data.data), more_data.size);
  EXPECT_THAT(buffer.GetPrefix(), testing::StartsWith("different data"));
}

TEST(ChunkedBufferTest, LargeAppends) {
  ChunkedBuffer buffer;
  buffer.Append(std::string(500, 'a'));
  buffer.Append(std::string(2000, 'b'));
  buffer.Append(std::string(10, 'c'));
  auto more_data = MakeDataAndSize(std::string(4490, 'd'));
  buffer.Append(std::move(more_data.data), more_data.size);

  EXPECT_EQ(500 + 2000 + 10 + 4490, absl::StrJoin(buffer.Read(), "").size());
}

TEST(ChunkedBufferTest, RemovePartialPrefix) {
  ChunkedBuffer buffer;
  auto data_and_size = MakeDataAndSize(kLoremIpsum);
  buffer.Append(std::move(data_and_size.data), data_and_size.size);
  buffer.RemovePrefix(6);
  EXPECT_THAT(buffer.GetPrefix(), testing::StartsWith("ipsum"));
  buffer.RemovePrefix(20);
  EXPECT_THAT(buffer.GetPrefix(), testing::StartsWith(", consectetur"));
  buffer.Append(" Anday igpay atinlay!");
  const std::initializer_list<absl::string_view> parts = {
      kLoremIpsum.substr(26), " Anday igpay atinlay!"};
  EXPECT_EQ(absl::StrJoin(parts, ""), absl::StrJoin(buffer.Read(), ""));
}

TEST(ChunkedBufferTest, DifferentAppends) {
  ChunkedBuffer buffer;
  buffer.Append("Lorem ipsum");

  auto more_data = MakeDataAndSize(" dolor sit amet, ");
  buffer.Append(std::move(more_data.data), more_data.size);

  buffer.Append("consectetur adipiscing elit, ");

  more_data = MakeDataAndSize("sed do eiusmod tempor incididunt ut ");
  buffer.Append(std::move(more_data.data), more_data.size);

  buffer.Append("labore et dolore magna aliqua.");

  EXPECT_EQ(kLoremIpsum, absl::StrJoin(buffer.Read(), ""));

  buffer.RemovePrefix(kLoremIpsum.size());
  EXPECT_TRUE(buffer.Empty());
}

}  // namespace
}  // namespace adapter
}  // namespace http2
