Adds a test-only utility for building HTTP/2 frame sequences.

PiperOrigin-RevId: 367066221
Change-Id: Ifde8250b615aeb35bb1f66e2db46e6da59347424
diff --git a/http2/adapter/test_frame_sequence.cc b/http2/adapter/test_frame_sequence.cc
new file mode 100644
index 0000000..46d33b6
--- /dev/null
+++ b/http2/adapter/test_frame_sequence.cc
@@ -0,0 +1,129 @@
+#include "http2/adapter/test_frame_sequence.h"
+
+#include "http2/adapter/http2_util.h"
+#include "spdy/core/spdy_framer.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+TestFrameSequence& TestFrameSequence::ClientPreface() {
+  preface_ = spdy::kHttp2ConnectionHeaderPrefix;
+  frames_.push_back(absl::make_unique<spdy::SpdySettingsIR>());
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::ServerPreface() {
+  frames_.push_back(absl::make_unique<spdy::SpdySettingsIR>());
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Data(Http2StreamId stream_id,
+                                           absl::string_view payload,
+                                           bool fin,
+                                           absl::optional<int> padding_length) {
+  auto data = absl::make_unique<spdy::SpdyDataIR>(stream_id, payload);
+  data->set_fin(fin);
+  if (padding_length) {
+    data->set_padding_len(padding_length.value());
+  }
+  frames_.push_back(std::move(data));
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::RstStream(Http2StreamId stream_id,
+                                                Http2ErrorCode error) {
+  frames_.push_back(absl::make_unique<spdy::SpdyRstStreamIR>(
+      stream_id, TranslateErrorCode(error)));
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Settings(
+    absl::Span<Http2Setting> values) {
+  auto settings = absl::make_unique<spdy::SpdySettingsIR>();
+  for (const Http2Setting& setting : values) {
+    settings->AddSetting(setting.id, setting.value);
+  }
+  frames_.push_back(std::move(settings));
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::SettingsAck() {
+  auto settings = absl::make_unique<spdy::SpdySettingsIR>();
+  settings->set_is_ack(true);
+  frames_.push_back(std::move(settings));
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Ping(Http2PingId id) {
+  frames_.push_back(absl::make_unique<spdy::SpdyPingIR>(id));
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::PingAck(Http2PingId id) {
+  auto ping = absl::make_unique<spdy::SpdyPingIR>(id);
+  ping->set_is_ack(true);
+  frames_.push_back(std::move(ping));
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::GoAway(Http2StreamId last_good_stream_id,
+                                             Http2ErrorCode error,
+                                             absl::string_view payload) {
+  frames_.push_back(absl::make_unique<spdy::SpdyGoAwayIR>(
+      last_good_stream_id, TranslateErrorCode(error), std::string(payload)));
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Headers(Http2StreamId stream_id,
+                                              spdy::Http2HeaderBlock block,
+                                              bool fin) {
+  auto headers =
+      absl::make_unique<spdy::SpdyHeadersIR>(stream_id, std::move(block));
+  headers->set_fin(fin);
+  frames_.push_back(std::move(headers));
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Headers(Http2StreamId stream_id,
+                                              absl::Span<const Header> headers,
+                                              bool fin) {
+  spdy::SpdyHeaderBlock block;
+  for (const Header& header : headers) {
+    block[header.first] = header.second;
+  }
+  return Headers(stream_id, std::move(block), fin);
+}
+
+TestFrameSequence& TestFrameSequence::WindowUpdate(Http2StreamId stream_id,
+                                                   int32_t delta) {
+  frames_.push_back(
+      absl::make_unique<spdy::SpdyWindowUpdateIR>(stream_id, delta));
+  return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Priority(Http2StreamId stream_id,
+                                               Http2StreamId parent_stream_id,
+                                               int weight,
+                                               bool exclusive) {
+  frames_.push_back(absl::make_unique<spdy::SpdyPriorityIR>(
+      stream_id, parent_stream_id, weight, exclusive));
+  return *this;
+}
+
+std::string TestFrameSequence::Serialize() {
+  std::string result;
+  if (!preface_.empty()) {
+    result = preface_;
+  }
+  spdy::SpdyFramer framer(spdy::SpdyFramer::ENABLE_COMPRESSION);
+  for (const auto& frame : frames_) {
+    spdy::SpdySerializedFrame f = framer.SerializeFrame(*frame);
+    absl::StrAppend(&result, absl::string_view(f));
+  }
+  return result;
+}
+
+}  // namespace test
+}  // namespace adapter
+}  // namespace http2