Moves metadata-related tests to a separate test file.

PiperOrigin-RevId: 565185742
diff --git a/build/source_list.bzl b/build/source_list.bzl
index 10603ec..b008e48 100644
--- a/build/source_list.bzl
+++ b/build/source_list.bzl
@@ -1077,6 +1077,7 @@
     "http2/adapter/event_forwarder_test.cc",
     "http2/adapter/header_validator_test.cc",
     "http2/adapter/noop_header_validator_test.cc",
+    "http2/adapter/oghttp2_adapter_metadata_test.cc",
     "http2/adapter/oghttp2_adapter_test.cc",
     "http2/adapter/oghttp2_session_test.cc",
     "http2/adapter/oghttp2_util_test.cc",
diff --git a/build/source_list.gni b/build/source_list.gni
index 2cd0ddd..23b3066 100644
--- a/build/source_list.gni
+++ b/build/source_list.gni
@@ -1078,6 +1078,7 @@
     "src/quiche/http2/adapter/event_forwarder_test.cc",
     "src/quiche/http2/adapter/header_validator_test.cc",
     "src/quiche/http2/adapter/noop_header_validator_test.cc",
+    "src/quiche/http2/adapter/oghttp2_adapter_metadata_test.cc",
     "src/quiche/http2/adapter/oghttp2_adapter_test.cc",
     "src/quiche/http2/adapter/oghttp2_session_test.cc",
     "src/quiche/http2/adapter/oghttp2_util_test.cc",
diff --git a/build/source_list.json b/build/source_list.json
index f41f490..ef16ce6 100644
--- a/build/source_list.json
+++ b/build/source_list.json
@@ -1077,6 +1077,7 @@
     "quiche/http2/adapter/event_forwarder_test.cc",
     "quiche/http2/adapter/header_validator_test.cc",
     "quiche/http2/adapter/noop_header_validator_test.cc",
+    "quiche/http2/adapter/oghttp2_adapter_metadata_test.cc",
     "quiche/http2/adapter/oghttp2_adapter_test.cc",
     "quiche/http2/adapter/oghttp2_session_test.cc",
     "quiche/http2/adapter/oghttp2_util_test.cc",
diff --git a/quiche/http2/adapter/oghttp2_adapter_metadata_test.cc b/quiche/http2/adapter/oghttp2_adapter_metadata_test.cc
new file mode 100644
index 0000000..d131daf
--- /dev/null
+++ b/quiche/http2/adapter/oghttp2_adapter_metadata_test.cc
@@ -0,0 +1,636 @@
+#include "quiche/http2/adapter/oghttp2_adapter.h"
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/str_join.h"
+#include "quiche/http2/adapter/http2_protocol.h"
+#include "quiche/http2/adapter/http2_visitor_interface.h"
+#include "quiche/http2/adapter/mock_http2_visitor.h"
+#include "quiche/http2/adapter/oghttp2_util.h"
+#include "quiche/http2/adapter/test_frame_sequence.h"
+#include "quiche/http2/adapter/test_utils.h"
+#include "quiche/common/platform/api/quiche_expect_bug.h"
+#include "quiche/common/platform/api/quiche_test.h"
+#include "quiche/spdy/core/http2_header_block.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using ConnectionError = Http2VisitorInterface::ConnectionError;
+
+using spdy::SpdyFrameType;
+using testing::_;
+
+enum FrameType {
+  DATA,
+  HEADERS,
+  PRIORITY,
+  RST_STREAM,
+  SETTINGS,
+  PUSH_PROMISE,
+  PING,
+  GOAWAY,
+  WINDOW_UPDATE,
+  CONTINUATION,
+};
+
+TEST(OgHttp2AdapterTest, ClientHandlesMetadata) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kClient;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+  testing::InSequence s;
+
+  const std::vector<Header> headers1 =
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "http"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}});
+
+  const char* kSentinel1 = "arbitrary pointer 1";
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  ASSERT_GT(stream_id1, 0);
+  QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _,
+                                         END_STREAM_FLAG | END_HEADERS_FLAG));
+  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _,
+                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
+
+  int result = adapter->Send();
+  EXPECT_EQ(0, result);
+  absl::string_view data = visitor.data();
+  EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+  data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+  EXPECT_THAT(data,
+              EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
+  visitor.Clear();
+
+  const std::string stream_frames =
+      TestFrameSequence()
+          .ServerPreface()
+          .Metadata(0, "Example connection metadata")
+          .Headers(1,
+                   {{":status", "200"},
+                    {"server", "my-fake-server"},
+                    {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+                   /*fin=*/false)
+          .Metadata(1, "Example stream metadata")
+          .Data(1, "This is the response body.", true)
+          .Serialize();
+
+  // Server preface (empty SETTINGS)
+  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+  EXPECT_CALL(visitor, OnSettingsStart());
+  EXPECT_CALL(visitor, OnSettingsEnd());
+
+  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnMetadataEndForStream(0));
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+  EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+  EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+  EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+  EXPECT_CALL(visitor,
+              OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+  EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(1, _));
+  EXPECT_CALL(visitor, OnMetadataEndForStream(1));
+  EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 1));
+  EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
+  EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+  EXPECT_CALL(visitor, OnEndStream(1));
+  EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
+
+  const int64_t stream_result = adapter->ProcessBytes(stream_frames);
+  EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, ACK_FLAG));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, ACK_FLAG, 0));
+
+  EXPECT_TRUE(adapter->want_write());
+  result = adapter->Send();
+  EXPECT_EQ(0, result);
+  EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
+}
+
+TEST(OgHttp2AdapterTest, ClientHandlesMetadataWithEmptyPayload) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kClient;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+  testing::InSequence s;
+
+  const std::vector<Header> headers1 =
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "http"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}});
+
+  const int32_t stream_id = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  ASSERT_GT(stream_id, 0);
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
+                                         END_STREAM_FLAG | END_HEADERS_FLAG));
+  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _,
+                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
+
+  int result = adapter->Send();
+  EXPECT_EQ(0, result);
+  absl::string_view data = visitor.data();
+  EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+  data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+  EXPECT_THAT(data,
+              EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
+  visitor.Clear();
+
+  const std::string stream_frames =
+      TestFrameSequence()
+          .ServerPreface()
+          .Headers(1,
+                   {{":status", "200"},
+                    {"server", "my-fake-server"},
+                    {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+                   /*fin=*/false)
+          .Metadata(1, "")
+          .Data(1, "This is the response body.", true)
+          .Serialize();
+
+  // Server preface (empty SETTINGS)
+  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+  EXPECT_CALL(visitor, OnSettingsStart());
+  EXPECT_CALL(visitor, OnSettingsEnd());
+
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+  EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+  EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(3);
+  EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+  EXPECT_CALL(visitor, OnMetadataEndForStream(1));
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 1));
+  EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
+  EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+  EXPECT_CALL(visitor, OnEndStream(1));
+  EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
+
+  const int64_t stream_result = adapter->ProcessBytes(stream_frames);
+  EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
+}
+
+TEST(OgHttp2AdapterTest, ClientHandlesMetadataWithPayloadError) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kClient;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+  testing::InSequence s;
+
+  const std::vector<Header> headers =
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "http"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}});
+
+  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  ASSERT_GT(stream_id, 0);
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
+                                         END_STREAM_FLAG | END_HEADERS_FLAG));
+  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _,
+                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
+
+  int result = adapter->Send();
+  EXPECT_EQ(0, result);
+  visitor.Clear();
+
+  const std::string stream_frames =
+      TestFrameSequence()
+          .ServerPreface()
+          .Metadata(0, "Example connection metadata")
+          .Headers(stream_id,
+                   {{":status", "200"},
+                    {"server", "my-fake-server"},
+                    {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+                   /*fin=*/false)
+          .Metadata(stream_id, "Example stream metadata")
+          .Data(stream_id, "This is the response body.", true)
+          .Serialize();
+
+  // Server preface (empty SETTINGS)
+  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+  EXPECT_CALL(visitor, OnSettingsStart());
+  EXPECT_CALL(visitor, OnSettingsEnd());
+
+  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnMetadataEndForStream(0));
+  EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 4));
+  EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
+  EXPECT_CALL(visitor, OnHeaderForStream(stream_id, _, _)).Times(3);
+  EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
+  EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, kMetadataFrameType, 4));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(stream_id, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(stream_id, _))
+      .WillOnce(testing::Return(false));
+  // Remaining frames are not processed due to the error.
+  EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
+
+  const int64_t stream_result = adapter->ProcessBytes(stream_frames);
+  // Negative integer returned to indicate an error.
+  EXPECT_LT(stream_result, 0);
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
+  EXPECT_CALL(visitor,
+              OnFrameSent(GOAWAY, 0, _, 0x0,
+                          static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
+
+  EXPECT_FALSE(adapter->want_read());
+  EXPECT_TRUE(adapter->want_write());
+  result = adapter->Send();
+  EXPECT_EQ(0, result);
+  EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
+}
+
+TEST(OgHttp2AdapterTest, ClientHandlesMetadataWithCompletionError) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kClient;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+  testing::InSequence s;
+
+  const std::vector<Header> headers =
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "http"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}});
+
+  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  ASSERT_GT(stream_id, 0);
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
+                                         END_STREAM_FLAG | END_HEADERS_FLAG));
+  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _,
+                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
+
+  int result = adapter->Send();
+  EXPECT_EQ(0, result);
+  visitor.Clear();
+
+  const std::string stream_frames =
+      TestFrameSequence()
+          .ServerPreface()
+          .Metadata(0, "Example connection metadata")
+          .Headers(stream_id,
+                   {{":status", "200"},
+                    {"server", "my-fake-server"},
+                    {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+                   /*fin=*/false)
+          .Metadata(stream_id, "Example stream metadata")
+          .Data(stream_id, "This is the response body.", true)
+          .Serialize();
+
+  // Server preface (empty SETTINGS)
+  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+  EXPECT_CALL(visitor, OnSettingsStart());
+  EXPECT_CALL(visitor, OnSettingsEnd());
+
+  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnMetadataEndForStream(0));
+  EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 4));
+  EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
+  EXPECT_CALL(visitor, OnHeaderForStream(stream_id, _, _)).Times(3);
+  EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
+  EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, kMetadataFrameType, 4));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(stream_id, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(stream_id, _));
+  EXPECT_CALL(visitor, OnMetadataEndForStream(stream_id))
+      .WillOnce(testing::Return(false));
+  // Remaining frames are not processed due to the error.
+  EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
+
+  const int64_t stream_result = adapter->ProcessBytes(stream_frames);
+  // Negative integer returned to indicate an error.
+  EXPECT_LT(stream_result, 0);
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
+  EXPECT_CALL(visitor,
+              OnFrameSent(GOAWAY, 0, _, 0x0,
+                          static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
+
+  EXPECT_FALSE(adapter->want_read());
+  EXPECT_TRUE(adapter->want_write());
+  result = adapter->Send();
+  EXPECT_EQ(0, result);
+  EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
+}
+
+TEST(OgHttp2AdapterTest, ClientSendsMetadataAfterFlowControlBlock) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kClient;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+  testing::InSequence s;
+
+  const std::vector<Header> headers1 =
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "http"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}});
+
+  const std::string kBody = std::string(100 * 1024, 'a');
+  auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
+  body1->AppendPayload(kBody);
+  body1->EndData();
+
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, std::move(body1), nullptr);
+  ASSERT_GT(stream_id1, 0);
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x4));
+  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x4, 0));
+  // 4 DATA frames should saturate the default 64kB stream/connection flow
+  // control window.
+  EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id1, _, 0x0, 0)).Times(4);
+
+  int result = adapter->Send();
+  EXPECT_EQ(0, result);
+  EXPECT_FALSE(adapter->want_write());
+  EXPECT_EQ(0, adapter->GetSendWindowSize());
+
+  auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
+      {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
+  adapter->SubmitMetadata(1, 16384u, std::move(source));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
+  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
+
+  result = adapter->Send();
+  EXPECT_EQ(0, result);
+}
+
+TEST(OgHttp2AdapterTest, ClientSendsMetadataWithContinuation) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kServer;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+  EXPECT_FALSE(adapter->want_write());
+
+  const std::string frames =
+      TestFrameSequence()
+          .ClientPreface()
+          .Metadata(0, "Example connection metadata in multiple frames", true)
+          .Headers(1,
+                   {{":method", "GET"},
+                    {":scheme", "https"},
+                    {":authority", "example.com"},
+                    {":path", "/this/is/request/one"}},
+                   /*fin=*/false,
+                   /*add_continuation=*/true)
+          .Metadata(1,
+                    "Some stream metadata that's also sent in multiple frames",
+                    true)
+          .Serialize();
+  testing::InSequence s;
+
+  // Client preface (empty SETTINGS)
+  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+  EXPECT_CALL(visitor, OnSettingsStart());
+  EXPECT_CALL(visitor, OnSettingsEnd());
+  // Metadata on stream 0
+  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 0));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+  EXPECT_CALL(visitor, OnMetadataEndForStream(0));
+
+  // Stream 1
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0));
+  EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+  EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+  EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, CONTINUATION, 4));
+  EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+  EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+  EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+  // Metadata on stream 1
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 0));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(1, _));
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
+  EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+  EXPECT_CALL(visitor, OnMetadataForStream(1, _));
+  EXPECT_CALL(visitor, OnMetadataEndForStream(1));
+
+  const int64_t result = adapter->ProcessBytes(frames);
+  EXPECT_EQ(frames.size(), static_cast<size_t>(result));
+  EXPECT_EQ("Example connection metadata in multiple frames",
+            absl::StrJoin(visitor.GetMetadata(0), ""));
+  EXPECT_EQ("Some stream metadata that's also sent in multiple frames",
+            absl::StrJoin(visitor.GetMetadata(1), ""));
+}
+
+TEST(OgHttp2AdapterTest, SubmitMetadata) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kServer;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+  auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
+      {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
+  adapter->SubmitMetadata(1, 16384u, std::move(source));
+  EXPECT_TRUE(adapter->want_write());
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
+  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
+
+  int result = adapter->Send();
+  EXPECT_EQ(0, result);
+  EXPECT_THAT(visitor.data(),
+              EqualsFrames({SpdyFrameType::SETTINGS,
+                            static_cast<SpdyFrameType>(kMetadataFrameType)}));
+  EXPECT_FALSE(adapter->want_write());
+}
+
+TEST(OgHttp2AdapterTest, SubmitMetadataMultipleFrames) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kServer;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+  const auto kLargeValue = std::string(63 * 1024, 'a');
+  auto source = std::make_unique<TestMetadataSource>(
+      ToHeaderBlock(ToHeaders({{"large-value", kLargeValue}})));
+  adapter->SubmitMetadata(1, 16384u, std::move(source));
+  EXPECT_TRUE(adapter->want_write());
+
+  testing::InSequence seq;
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
+  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
+
+  int result = adapter->Send();
+  EXPECT_EQ(0, result);
+  absl::string_view serialized = visitor.data();
+  EXPECT_THAT(serialized,
+              EqualsFrames({SpdyFrameType::SETTINGS,
+                            static_cast<SpdyFrameType>(kMetadataFrameType),
+                            static_cast<SpdyFrameType>(kMetadataFrameType),
+                            static_cast<SpdyFrameType>(kMetadataFrameType),
+                            static_cast<SpdyFrameType>(kMetadataFrameType)}));
+  EXPECT_FALSE(adapter->want_write());
+}
+
+TEST(OgHttp2AdapterTest, SubmitConnectionMetadata) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kServer;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+  auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
+      {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
+  adapter->SubmitMetadata(0, 16384u, std::move(source));
+  EXPECT_TRUE(adapter->want_write());
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 0, _, 0x4));
+  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 0, _, 0x4, 0));
+
+  int result = adapter->Send();
+  EXPECT_EQ(0, result);
+  EXPECT_THAT(visitor.data(),
+              EqualsFrames({SpdyFrameType::SETTINGS,
+                            static_cast<SpdyFrameType>(kMetadataFrameType)}));
+  EXPECT_FALSE(adapter->want_write());
+}
+
+TEST(OgHttp2AdapterTest, ServerQueuesMetadataThenTrailers) {
+  DataSavingVisitor visitor;
+  OgHttp2Adapter::Options options;
+  options.perspective = Perspective::kServer;
+  auto adapter = OgHttp2Adapter::Create(visitor, options);
+  EXPECT_FALSE(adapter->want_write());
+
+  const std::string frames = TestFrameSequence()
+                                 .ClientPreface()
+                                 .Headers(1,
+                                          {{":method", "GET"},
+                                           {":scheme", "https"},
+                                           {":authority", "example.com"},
+                                           {":path", "/"}},
+                                          /*fin=*/true)
+                                 .Serialize();
+  testing::InSequence s;
+
+  // Client preface (empty SETTINGS)
+  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+  EXPECT_CALL(visitor, OnSettingsStart());
+  EXPECT_CALL(visitor, OnSettingsEnd());
+  // Stream 1
+  EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+  EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+  EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
+  EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+  EXPECT_CALL(visitor, OnEndStream(1));
+
+  const int64_t result = adapter->ProcessBytes(frames);
+  EXPECT_EQ(frames.size(), static_cast<size_t>(result));
+
+  const absl::string_view kBody = "This is an example response body.";
+
+  // The body source must indicate that the end of the body is not the end of
+  // the stream.
+  auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
+  body1->AppendPayload(kBody);
+  body1->EndData();
+  int submit_result = adapter->SubmitResponse(
+      1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
+      std::move(body1));
+  EXPECT_EQ(submit_result, 0);
+  EXPECT_TRUE(adapter->want_write());
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, ACK_FLAG));
+  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, ACK_FLAG, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
+  EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
+  EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
+
+  int send_result = adapter->Send();
+  EXPECT_EQ(0, send_result);
+  EXPECT_THAT(visitor.data(),
+              EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS,
+                            SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
+  EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
+  visitor.Clear();
+  EXPECT_FALSE(adapter->want_write());
+
+  spdy::Http2HeaderBlock block;
+  block["key"] = "wild value!";
+  adapter->SubmitMetadata(
+      1, 16384u, std::make_unique<TestMetadataSource>(std::move(block)));
+
+  int trailer_result =
+      adapter->SubmitTrailer(1, ToHeaders({{":final-status", "a-ok"}}));
+  ASSERT_EQ(trailer_result, 0);
+  EXPECT_TRUE(adapter->want_write());
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
+  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
+
+  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _,
+                                         END_STREAM_FLAG | END_HEADERS_FLAG));
+  EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _,
+                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
+
+  EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
+
+  send_result = adapter->Send();
+  EXPECT_EQ(0, send_result);
+  EXPECT_THAT(visitor.data(),
+              EqualsFrames({static_cast<SpdyFrameType>(kMetadataFrameType),
+                            SpdyFrameType::HEADERS}));
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace adapter
+}  // namespace http2
diff --git a/quiche/http2/adapter/oghttp2_adapter_test.cc b/quiche/http2/adapter/oghttp2_adapter_test.cc
index 4c9ba14..1d52d28 100644
--- a/quiche/http2/adapter/oghttp2_adapter_test.cc
+++ b/quiche/http2/adapter/oghttp2_adapter_test.cc
@@ -1441,315 +1441,6 @@
   EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
 }
 
-TEST(OgHttp2AdapterTest, ClientHandlesMetadata) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kClient;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-
-  testing::InSequence s;
-
-  const std::vector<Header> headers1 =
-      ToHeaders({{":method", "GET"},
-                 {":scheme", "http"},
-                 {":authority", "example.com"},
-                 {":path", "/this/is/request/one"}});
-
-  const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
-  ASSERT_GT(stream_id1, 0);
-  QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _,
-                                         END_STREAM_FLAG | END_HEADERS_FLAG));
-  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _,
-                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
-
-  int result = adapter->Send();
-  EXPECT_EQ(0, result);
-  absl::string_view data = visitor.data();
-  EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
-  data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
-  EXPECT_THAT(data,
-              EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
-  visitor.Clear();
-
-  const std::string stream_frames =
-      TestFrameSequence()
-          .ServerPreface()
-          .Metadata(0, "Example connection metadata")
-          .Headers(1,
-                   {{":status", "200"},
-                    {"server", "my-fake-server"},
-                    {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
-                   /*fin=*/false)
-          .Metadata(1, "Example stream metadata")
-          .Data(1, "This is the response body.", true)
-          .Serialize();
-
-  // Server preface (empty SETTINGS)
-  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
-  EXPECT_CALL(visitor, OnSettingsStart());
-  EXPECT_CALL(visitor, OnSettingsEnd());
-
-  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnMetadataEndForStream(0));
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
-  EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
-  EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
-  EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
-  EXPECT_CALL(visitor,
-              OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
-  EXPECT_CALL(visitor, OnEndHeadersForStream(1));
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(1, _));
-  EXPECT_CALL(visitor, OnMetadataEndForStream(1));
-  EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 1));
-  EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
-  EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
-  EXPECT_CALL(visitor, OnEndStream(1));
-  EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
-
-  const int64_t stream_result = adapter->ProcessBytes(stream_frames);
-  EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, ACK_FLAG));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, ACK_FLAG, 0));
-
-  EXPECT_TRUE(adapter->want_write());
-  result = adapter->Send();
-  EXPECT_EQ(0, result);
-  EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
-}
-
-TEST(OgHttp2AdapterTest, ClientHandlesMetadataWithEmptyPayload) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kClient;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-
-  testing::InSequence s;
-
-  const std::vector<Header> headers1 =
-      ToHeaders({{":method", "GET"},
-                 {":scheme", "http"},
-                 {":authority", "example.com"},
-                 {":path", "/this/is/request/one"}});
-
-  const int32_t stream_id = adapter->SubmitRequest(headers1, nullptr, nullptr);
-  ASSERT_GT(stream_id, 0);
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
-                                         END_STREAM_FLAG | END_HEADERS_FLAG));
-  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _,
-                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
-
-  int result = adapter->Send();
-  EXPECT_EQ(0, result);
-  absl::string_view data = visitor.data();
-  EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
-  data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
-  EXPECT_THAT(data,
-              EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
-  visitor.Clear();
-
-  const std::string stream_frames =
-      TestFrameSequence()
-          .ServerPreface()
-          .Headers(1,
-                   {{":status", "200"},
-                    {"server", "my-fake-server"},
-                    {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
-                   /*fin=*/false)
-          .Metadata(1, "")
-          .Data(1, "This is the response body.", true)
-          .Serialize();
-
-  // Server preface (empty SETTINGS)
-  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
-  EXPECT_CALL(visitor, OnSettingsStart());
-  EXPECT_CALL(visitor, OnSettingsEnd());
-
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
-  EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
-  EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(3);
-  EXPECT_CALL(visitor, OnEndHeadersForStream(1));
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
-  EXPECT_CALL(visitor, OnMetadataEndForStream(1));
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 1));
-  EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
-  EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
-  EXPECT_CALL(visitor, OnEndStream(1));
-  EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
-
-  const int64_t stream_result = adapter->ProcessBytes(stream_frames);
-  EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
-}
-
-TEST(OgHttp2AdapterTest, ClientHandlesMetadataWithPayloadError) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kClient;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-
-  testing::InSequence s;
-
-  const std::vector<Header> headers =
-      ToHeaders({{":method", "GET"},
-                 {":scheme", "http"},
-                 {":authority", "example.com"},
-                 {":path", "/this/is/request/one"}});
-
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
-  ASSERT_GT(stream_id, 0);
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
-                                         END_STREAM_FLAG | END_HEADERS_FLAG));
-  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _,
-                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
-
-  int result = adapter->Send();
-  EXPECT_EQ(0, result);
-  visitor.Clear();
-
-  const std::string stream_frames =
-      TestFrameSequence()
-          .ServerPreface()
-          .Metadata(0, "Example connection metadata")
-          .Headers(stream_id,
-                   {{":status", "200"},
-                    {"server", "my-fake-server"},
-                    {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
-                   /*fin=*/false)
-          .Metadata(stream_id, "Example stream metadata")
-          .Data(stream_id, "This is the response body.", true)
-          .Serialize();
-
-  // Server preface (empty SETTINGS)
-  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
-  EXPECT_CALL(visitor, OnSettingsStart());
-  EXPECT_CALL(visitor, OnSettingsEnd());
-
-  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnMetadataEndForStream(0));
-  EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 4));
-  EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
-  EXPECT_CALL(visitor, OnHeaderForStream(stream_id, _, _)).Times(3);
-  EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
-  EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, kMetadataFrameType, 4));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(stream_id, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(stream_id, _))
-      .WillOnce(testing::Return(false));
-  // Remaining frames are not processed due to the error.
-  EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
-
-  const int64_t stream_result = adapter->ProcessBytes(stream_frames);
-  // Negative integer returned to indicate an error.
-  EXPECT_LT(stream_result, 0);
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
-  EXPECT_CALL(visitor,
-              OnFrameSent(GOAWAY, 0, _, 0x0,
-                          static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
-
-  EXPECT_FALSE(adapter->want_read());
-  EXPECT_TRUE(adapter->want_write());
-  result = adapter->Send();
-  EXPECT_EQ(0, result);
-  EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
-}
-
-TEST(OgHttp2AdapterTest, ClientHandlesMetadataWithCompletionError) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kClient;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-
-  testing::InSequence s;
-
-  const std::vector<Header> headers =
-      ToHeaders({{":method", "GET"},
-                 {":scheme", "http"},
-                 {":authority", "example.com"},
-                 {":path", "/this/is/request/one"}});
-
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
-  ASSERT_GT(stream_id, 0);
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
-                                         END_STREAM_FLAG | END_HEADERS_FLAG));
-  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _,
-                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
-
-  int result = adapter->Send();
-  EXPECT_EQ(0, result);
-  visitor.Clear();
-
-  const std::string stream_frames =
-      TestFrameSequence()
-          .ServerPreface()
-          .Metadata(0, "Example connection metadata")
-          .Headers(stream_id,
-                   {{":status", "200"},
-                    {"server", "my-fake-server"},
-                    {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
-                   /*fin=*/false)
-          .Metadata(stream_id, "Example stream metadata")
-          .Data(stream_id, "This is the response body.", true)
-          .Serialize();
-
-  // Server preface (empty SETTINGS)
-  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
-  EXPECT_CALL(visitor, OnSettingsStart());
-  EXPECT_CALL(visitor, OnSettingsEnd());
-
-  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnMetadataEndForStream(0));
-  EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 4));
-  EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
-  EXPECT_CALL(visitor, OnHeaderForStream(stream_id, _, _)).Times(3);
-  EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
-  EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, kMetadataFrameType, 4));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(stream_id, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(stream_id, _));
-  EXPECT_CALL(visitor, OnMetadataEndForStream(stream_id))
-      .WillOnce(testing::Return(false));
-  // Remaining frames are not processed due to the error.
-  EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
-
-  const int64_t stream_result = adapter->ProcessBytes(stream_frames);
-  // Negative integer returned to indicate an error.
-  EXPECT_LT(stream_result, 0);
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
-  EXPECT_CALL(visitor,
-              OnFrameSent(GOAWAY, 0, _, 0x0,
-                          static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
-
-  EXPECT_FALSE(adapter->want_read());
-  EXPECT_TRUE(adapter->want_write());
-  result = adapter->Send();
-  EXPECT_EQ(0, result);
-  EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
-}
-
 TEST(OgHttp2AdapterTest, ClientRstStreamWhileHandlingHeaders) {
   DataSavingVisitor visitor;
   OgHttp2Adapter::Options options;
@@ -3877,52 +3568,6 @@
   EXPECT_EQ(0, result);
 }
 
-TEST(OgHttp2AdapterTest, ClientSendsMetadataAfterFlowControlBlock) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kClient;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-
-  testing::InSequence s;
-
-  const std::vector<Header> headers1 =
-      ToHeaders({{":method", "GET"},
-                 {":scheme", "http"},
-                 {":authority", "example.com"},
-                 {":path", "/this/is/request/one"}});
-
-  const std::string kBody = std::string(100 * 1024, 'a');
-  auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
-  body1->AppendPayload(kBody);
-  body1->EndData();
-
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, std::move(body1), nullptr);
-  ASSERT_GT(stream_id1, 0);
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x4));
-  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x4, 0));
-  // 4 DATA frames should saturate the default 64kB stream/connection flow
-  // control window.
-  EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id1, _, 0x0, 0)).Times(4);
-
-  int result = adapter->Send();
-  EXPECT_EQ(0, result);
-  EXPECT_FALSE(adapter->want_write());
-  EXPECT_EQ(0, adapter->GetSendWindowSize());
-
-  auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
-      {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
-  adapter->SubmitMetadata(1, 16384u, std::move(source));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
-  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
-
-  result = adapter->Send();
-  EXPECT_EQ(0, result);
-}
-
 TEST(OgHttp2AdapterTest, ClientQueuesRequests) {
   DataSavingVisitor visitor;
   OgHttp2Adapter::Options options;
@@ -4067,90 +3712,6 @@
   adapter->Send();
 }
 
-TEST(OgHttp2AdapterTest, SubmitMetadata) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kServer;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-
-  auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
-      {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
-  adapter->SubmitMetadata(1, 16384u, std::move(source));
-  EXPECT_TRUE(adapter->want_write());
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
-  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
-
-  int result = adapter->Send();
-  EXPECT_EQ(0, result);
-  EXPECT_THAT(visitor.data(),
-              EqualsFrames({SpdyFrameType::SETTINGS,
-                            static_cast<SpdyFrameType>(kMetadataFrameType)}));
-  EXPECT_FALSE(adapter->want_write());
-}
-
-TEST(OgHttp2AdapterTest, SubmitMetadataMultipleFrames) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kServer;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-
-  const auto kLargeValue = std::string(63 * 1024, 'a');
-  auto source = std::make_unique<TestMetadataSource>(
-      ToHeaderBlock(ToHeaders({{"large-value", kLargeValue}})));
-  adapter->SubmitMetadata(1, 16384u, std::move(source));
-  EXPECT_TRUE(adapter->want_write());
-
-  testing::InSequence seq;
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
-  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
-
-  int result = adapter->Send();
-  EXPECT_EQ(0, result);
-  absl::string_view serialized = visitor.data();
-  EXPECT_THAT(serialized,
-              EqualsFrames({SpdyFrameType::SETTINGS,
-                            static_cast<SpdyFrameType>(kMetadataFrameType),
-                            static_cast<SpdyFrameType>(kMetadataFrameType),
-                            static_cast<SpdyFrameType>(kMetadataFrameType),
-                            static_cast<SpdyFrameType>(kMetadataFrameType)}));
-  EXPECT_FALSE(adapter->want_write());
-}
-
-TEST(OgHttp2AdapterTest, SubmitConnectionMetadata) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kServer;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-
-  auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
-      {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
-  adapter->SubmitMetadata(0, 16384u, std::move(source));
-  EXPECT_TRUE(adapter->want_write());
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 0, _, 0x4));
-  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 0, _, 0x4, 0));
-
-  int result = adapter->Send();
-  EXPECT_EQ(0, result);
-  EXPECT_THAT(visitor.data(),
-              EqualsFrames({SpdyFrameType::SETTINGS,
-                            static_cast<SpdyFrameType>(kMetadataFrameType)}));
-  EXPECT_FALSE(adapter->want_write());
-}
-
 TEST(OgHttp2AdapterTest, GetSendWindowSize) {
   DataSavingVisitor visitor;
   OgHttp2Adapter::Options options;
@@ -4704,69 +4265,6 @@
   EXPECT_EQ(frames.size(), static_cast<size_t>(result));
 }
 
-TEST(OgHttp2AdapterTest, ClientSendsMetadataWithContinuation) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kServer;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-  EXPECT_FALSE(adapter->want_write());
-
-  const std::string frames =
-      TestFrameSequence()
-          .ClientPreface()
-          .Metadata(0, "Example connection metadata in multiple frames", true)
-          .Headers(1,
-                   {{":method", "GET"},
-                    {":scheme", "https"},
-                    {":authority", "example.com"},
-                    {":path", "/this/is/request/one"}},
-                   /*fin=*/false,
-                   /*add_continuation=*/true)
-          .Metadata(1,
-                    "Some stream metadata that's also sent in multiple frames",
-                    true)
-          .Serialize();
-  testing::InSequence s;
-
-  // Client preface (empty SETTINGS)
-  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
-  EXPECT_CALL(visitor, OnSettingsStart());
-  EXPECT_CALL(visitor, OnSettingsEnd());
-  // Metadata on stream 0
-  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 0));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(0, _));
-  EXPECT_CALL(visitor, OnMetadataEndForStream(0));
-
-  // Stream 1
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0));
-  EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
-  EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
-  EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, CONTINUATION, 4));
-  EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
-  EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
-  EXPECT_CALL(visitor, OnEndHeadersForStream(1));
-  // Metadata on stream 1
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 0));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(1, _));
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
-  EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
-  EXPECT_CALL(visitor, OnMetadataForStream(1, _));
-  EXPECT_CALL(visitor, OnMetadataEndForStream(1));
-
-  const int64_t result = adapter->ProcessBytes(frames);
-  EXPECT_EQ(frames.size(), static_cast<size_t>(result));
-  EXPECT_EQ("Example connection metadata in multiple frames",
-            absl::StrJoin(visitor.GetMetadata(0), ""));
-  EXPECT_EQ("Some stream metadata that's also sent in multiple frames",
-            absl::StrJoin(visitor.GetMetadata(1), ""));
-}
-
 TEST(OgHttp2AdapterTest, RepeatedHeaderNames) {
   DataSavingVisitor visitor;
   OgHttp2Adapter::Options options;
@@ -5351,95 +4849,6 @@
   EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
 }
 
-TEST(OgHttp2AdapterTest, ServerQueuesMetadataThenTrailers) {
-  DataSavingVisitor visitor;
-  OgHttp2Adapter::Options options;
-  options.perspective = Perspective::kServer;
-  auto adapter = OgHttp2Adapter::Create(visitor, options);
-  EXPECT_FALSE(adapter->want_write());
-
-  const std::string frames = TestFrameSequence()
-                                 .ClientPreface()
-                                 .Headers(1,
-                                          {{":method", "GET"},
-                                           {":scheme", "https"},
-                                           {":authority", "example.com"},
-                                           {":path", "/"}},
-                                          /*fin=*/true)
-                                 .Serialize();
-  testing::InSequence s;
-
-  // Client preface (empty SETTINGS)
-  EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
-  EXPECT_CALL(visitor, OnSettingsStart());
-  EXPECT_CALL(visitor, OnSettingsEnd());
-  // Stream 1
-  EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
-  EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
-  EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
-  EXPECT_CALL(visitor, OnEndHeadersForStream(1));
-  EXPECT_CALL(visitor, OnEndStream(1));
-
-  const int64_t result = adapter->ProcessBytes(frames);
-  EXPECT_EQ(frames.size(), static_cast<size_t>(result));
-
-  const absl::string_view kBody = "This is an example response body.";
-
-  // The body source must indicate that the end of the body is not the end of
-  // the stream.
-  auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
-  body1->AppendPayload(kBody);
-  body1->EndData();
-  int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-      std::move(body1));
-  EXPECT_EQ(submit_result, 0);
-  EXPECT_TRUE(adapter->want_write());
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, ACK_FLAG));
-  EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, ACK_FLAG, 0));
-  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
-  EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
-  EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
-
-  int send_result = adapter->Send();
-  EXPECT_EQ(0, send_result);
-  EXPECT_THAT(visitor.data(),
-              EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS,
-                            SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
-  EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
-  visitor.Clear();
-  EXPECT_FALSE(adapter->want_write());
-
-  spdy::Http2HeaderBlock block;
-  block["key"] = "wild value!";
-  adapter->SubmitMetadata(
-      1, 16384u, std::make_unique<TestMetadataSource>(std::move(block)));
-
-  int trailer_result =
-      adapter->SubmitTrailer(1, ToHeaders({{":final-status", "a-ok"}}));
-  ASSERT_EQ(trailer_result, 0);
-  EXPECT_TRUE(adapter->want_write());
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
-  EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
-
-  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _,
-                                         END_STREAM_FLAG | END_HEADERS_FLAG));
-  EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _,
-                                   END_STREAM_FLAG | END_HEADERS_FLAG, 0));
-
-  EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
-
-  send_result = adapter->Send();
-  EXPECT_EQ(0, send_result);
-  EXPECT_THAT(visitor.data(),
-              EqualsFrames({static_cast<SpdyFrameType>(kMetadataFrameType),
-                            SpdyFrameType::HEADERS}));
-}
-
 TEST(OgHttp2AdapterTest, ServerHandlesDataWithPadding) {
   DataSavingVisitor visitor;
   OgHttp2Adapter::Options options;