gfe-relnote: Do not include QPACK encoder stream data size in WriteHeaders() return value.  Protected by gfe2_reloadable_flag_quic_writeheaders_excludes_encoder_stream_data.

This is necessary in order to enable QPACK dynamic table in QuicTestClient and QuicTestServer, see cl/306230335.

PiperOrigin-RevId: 308657464
Change-Id: I18098d3600fb9bcdcb5a65f269a96e09e4927d8a
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc
index 6d708d4..b0e2c66 100644
--- a/quic/core/http/quic_spdy_stream_test.cc
+++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -39,6 +39,7 @@
 using spdy::SpdyHeaderBlock;
 using spdy::SpdyPriority;
 using testing::_;
+using testing::AnyNumber;
 using testing::AtLeast;
 using testing::ElementsAre;
 using testing::Invoke;
@@ -46,6 +47,7 @@
 using testing::MatchesRegex;
 using testing::Pair;
 using testing::Return;
+using testing::SaveArg;
 using testing::StrictMock;
 
 namespace quic {
@@ -175,7 +177,8 @@
     if (VersionUsesHttp3(transport_version())) {
       // In this case, call QuicSpdyStream::WriteHeadersImpl() that does the
       // actual work of closing the stream.
-      QuicSpdyStream::WriteHeadersImpl(saved_headers_.Clone(), fin, nullptr);
+      return QuicSpdyStream::WriteHeadersImpl(saved_headers_.Clone(), fin,
+                                              nullptr);
     }
     return 0;
   }
@@ -351,8 +354,7 @@
           .Times(num_control_stream_writes);
     }
     TestCryptoStream* crypto_stream = session_->GetMutableCryptoStream();
-    EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
-        .Times(testing::AnyNumber());
+    EXPECT_CALL(*crypto_stream, HasPendingRetransmission()).Times(AnyNumber());
 
     if (connection_->version().HasHandshakeDone() &&
         session_->perspective() == Perspective::IS_SERVER) {
@@ -2895,6 +2897,50 @@
       kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 0));
 }
 
+TEST_P(QuicSpdyStreamTest, WriteHeadersReturnValue) {
+  if (!UsesHttp3()) {
+    return;
+  }
+
+  Initialize(kShouldProcessData);
+  testing::InSequence s;
+
+  // Enable QPACK dynamic table.
+  session_->OnSetting(SETTINGS_QPACK_MAX_TABLE_CAPACITY, 1024);
+  session_->OnSetting(SETTINGS_QPACK_BLOCKED_STREAMS, 1);
+
+  EXPECT_CALL(*stream_, WriteHeadersMock(true));
+
+  QpackSendStream* encoder_stream =
+      QuicSpdySessionPeer::GetQpackEncoderSendStream(session_.get());
+  EXPECT_CALL(*session_, WritevData(encoder_stream->id(), _, _, _, _, _))
+      .Times(AnyNumber());
+
+  // HEADERS frame header.
+  EXPECT_CALL(*session_,
+              WritevData(stream_->id(), _, /* offset = */ 0, _, _, _));
+  // HEADERS frame payload.
+  size_t headers_frame_payload_length = 0;
+  EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _))
+      .WillOnce(
+          DoAll(SaveArg<1>(&headers_frame_payload_length),
+                Invoke(session_.get(), &MockQuicSpdySession::ConsumeData)));
+
+  SpdyHeaderBlock request_headers;
+  request_headers["foo"] = "bar";
+  size_t write_headers_return_value =
+      stream_->WriteHeaders(std::move(request_headers), /*fin=*/true, nullptr);
+  EXPECT_TRUE(stream_->fin_sent());
+
+  if (GetQuicReloadableFlag(quic_writeheaders_excludes_encoder_stream_data)) {
+    EXPECT_EQ(headers_frame_payload_length, write_headers_return_value);
+  } else {
+    // Return value of WriteHeaders includes length of dynamic table insertions
+    // written on encoder stream.
+    EXPECT_LT(headers_frame_payload_length, write_headers_return_value);
+  }
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic