• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/quic/quic_chromium_client_stream.h"
6 
7 #include <string>
8 #include <string_view>
9 
10 #include "base/functional/bind.h"
11 #include "base/functional/callback_helpers.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/run_loop.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/test/metrics/histogram_tester.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/quic/quic_chromium_client_session.h"
21 #include "net/quic/quic_context.h"
22 #include "net/test/gtest_util.h"
23 #include "net/test/test_with_task_environment.h"
24 #include "net/third_party/quiche/src/quiche/common/http/http_header_block.h"
25 #include "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h"
26 #include "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.h"
27 #include "net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h"
28 #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h"
29 #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
30 #include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
31 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_config_peer.h"
32 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h"
33 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h"
34 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
35 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 
38 using testing::_;
39 using testing::Return;
40 
41 namespace net::test {
42 namespace {
43 
44 class EstablishedCryptoStream : public quic::test::MockQuicCryptoStream {
45  public:
46   using quic::test::MockQuicCryptoStream::MockQuicCryptoStream;
47 
encryption_established() const48   bool encryption_established() const override { return true; }
49 };
50 
51 class MockQuicClientSessionBase : public quic::QuicSpdyClientSessionBase {
52  public:
53   explicit MockQuicClientSessionBase(quic::QuicConnection* connection);
54 
55   MockQuicClientSessionBase(const MockQuicClientSessionBase&) = delete;
56   MockQuicClientSessionBase& operator=(const MockQuicClientSessionBase&) =
57       delete;
58 
59   ~MockQuicClientSessionBase() override;
60 
GetCryptoStream() const61   const quic::QuicCryptoStream* GetCryptoStream() const override {
62     return crypto_stream_.get();
63   }
64 
GetMutableCryptoStream()65   quic::QuicCryptoStream* GetMutableCryptoStream() override {
66     return crypto_stream_.get();
67   }
68 
SetCryptoStream(quic::QuicCryptoStream * crypto_stream)69   void SetCryptoStream(quic::QuicCryptoStream* crypto_stream) {
70     crypto_stream_.reset(crypto_stream);
71   }
72 
73   // From quic::QuicSession.
74   MOCK_METHOD2(OnConnectionClosed,
75                void(const quic::QuicConnectionCloseFrame& frame,
76                     quic::ConnectionCloseSource source));
77   MOCK_METHOD1(CreateIncomingStream,
78                quic::QuicSpdyStream*(quic::QuicStreamId id));
79   MOCK_METHOD1(CreateIncomingStream,
80                quic::QuicSpdyStream*(quic::PendingStream* pending));
81   MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicChromiumClientStream*());
82   MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicChromiumClientStream*());
83   MOCK_METHOD6(WritevData,
84                quic::QuicConsumedData(quic::QuicStreamId id,
85                                       size_t write_length,
86                                       quic::QuicStreamOffset offset,
87                                       quic::StreamSendingState state,
88                                       quic::TransmissionType type,
89                                       quic::EncryptionLevel level));
90   MOCK_METHOD2(WriteControlFrame,
91                bool(const quic::QuicFrame&, quic::TransmissionType));
92   MOCK_METHOD4(SendRstStream,
93                void(quic::QuicStreamId stream_id,
94                     quic::QuicRstStreamErrorCode error,
95                     quic::QuicStreamOffset bytes_written,
96                     bool send_rst_only));
97 
98   MOCK_METHOD2(OnStreamHeaders,
99                void(quic::QuicStreamId stream_id,
100                     std::string_view headers_data));
101   MOCK_METHOD2(OnStreamHeadersPriority,
102                void(quic::QuicStreamId stream_id,
103                     const spdy::SpdyStreamPrecedence& precedence));
104   MOCK_METHOD3(OnStreamHeadersComplete,
105                void(quic::QuicStreamId stream_id, bool fin, size_t frame_len));
106   MOCK_CONST_METHOD0(OneRttKeysAvailable, bool());
107   // Methods taking non-copyable types like quiche::HttpHeaderBlock by value
108   // cannot be mocked directly.
WriteHeadersOnHeadersStream(quic::QuicStreamId id,quiche::HttpHeaderBlock headers,bool fin,const spdy::SpdyStreamPrecedence & precedence,quiche::QuicheReferenceCountedPointer<quic::QuicAckListenerInterface> ack_listener)109   size_t WriteHeadersOnHeadersStream(
110       quic::QuicStreamId id,
111       quiche::HttpHeaderBlock headers,
112       bool fin,
113       const spdy::SpdyStreamPrecedence& precedence,
114       quiche::QuicheReferenceCountedPointer<quic::QuicAckListenerInterface>
115           ack_listener) override {
116     return WriteHeadersOnHeadersStreamMock(id, headers, fin, precedence,
117                                            std::move(ack_listener));
118   }
119   MOCK_METHOD5(WriteHeadersOnHeadersStreamMock,
120                size_t(quic::QuicStreamId id,
121                       const quiche::HttpHeaderBlock& headers,
122                       bool fin,
123                       const spdy::SpdyStreamPrecedence& precedence,
124                       const quiche::QuicheReferenceCountedPointer<
125                           quic::QuicAckListenerInterface>& ack_listener));
126   MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(quic::QuicTime::Delta delta));
127 
128   using quic::QuicSession::ActivateStream;
129 
130   // Returns a quic::QuicConsumedData that indicates all of |write_length| (and
131   // |fin| if set) has been consumed.
132   static quic::QuicConsumedData ConsumeAllData(
133       quic::QuicStreamId id,
134       size_t write_length,
135       quic::QuicStreamOffset offset,
136       bool fin,
137       quic::QuicAckListenerInterface* ack_listener);
138 
OnProofValid(const quic::QuicCryptoClientConfig::CachedState & cached)139   void OnProofValid(
140       const quic::QuicCryptoClientConfig::CachedState& cached) override {}
OnProofVerifyDetailsAvailable(const quic::ProofVerifyDetails & verify_details)141   void OnProofVerifyDetailsAvailable(
142       const quic::ProofVerifyDetails& verify_details) override {}
143 
144  protected:
145   MOCK_METHOD1(ShouldCreateIncomingStream, bool(quic::QuicStreamId id));
146   MOCK_METHOD0(ShouldCreateOutgoingBidirectionalStream, bool());
147   MOCK_METHOD0(ShouldCreateOutgoingUnidirectionalStream, bool());
148 
149  private:
150   std::unique_ptr<quic::QuicCryptoStream> crypto_stream_;
151 };
152 
MockQuicClientSessionBase(quic::QuicConnection * connection)153 MockQuicClientSessionBase::MockQuicClientSessionBase(
154     quic::QuicConnection* connection)
155     : quic::QuicSpdyClientSessionBase(connection,
156                                       /*visitor=*/nullptr,
157                                       quic::test::DefaultQuicConfig(),
158                                       connection->supported_versions()) {
159   crypto_stream_ = std::make_unique<quic::test::MockQuicCryptoStream>(this);
160   Initialize();
161   ON_CALL(*this, WritevData(_, _, _, _, _, _))
162       .WillByDefault(testing::Return(quic::QuicConsumedData(0, false)));
163 }
164 
165 MockQuicClientSessionBase::~MockQuicClientSessionBase() = default;
166 
167 class QuicChromiumClientStreamTest
168     : public ::testing::TestWithParam<quic::ParsedQuicVersion>,
169       public WithTaskEnvironment {
170  public:
QuicChromiumClientStreamTest()171   QuicChromiumClientStreamTest()
172       : version_(GetParam()),
173         crypto_config_(
174             quic::test::crypto_test_utils::ProofVerifierForTesting()),
175         session_(new quic::test::MockQuicConnection(
176             &helper_,
177             &alarm_factory_,
178             quic::Perspective::IS_CLIENT,
179             quic::test::SupportedVersions(version_))) {
180     quic::test::QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
181         session_.config(), quic::kMinimumFlowControlSendWindow);
182     quic::test::QuicConfigPeer::
183         SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
184             session_.config(), quic::kMinimumFlowControlSendWindow);
185     quic::test::QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
186         session_.config(), 10);
187     session_.OnConfigNegotiated();
188     stream_ = new QuicChromiumClientStream(
189         quic::test::GetNthClientInitiatedBidirectionalStreamId(
190             version_.transport_version, 0),
191         &session_, quic::QuicServerId(), quic::BIDIRECTIONAL,
192         NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS);
193     session_.ActivateStream(base::WrapUnique(stream_.get()));
194     handle_ = stream_->CreateHandle();
195     helper_.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1));
196     session_.SetCryptoStream(new EstablishedCryptoStream(&session_));
197     session_.connection()->SetEncrypter(
198         quic::ENCRYPTION_FORWARD_SECURE,
199         std::make_unique<quic::test::TaggingEncrypter>(
200             quic::ENCRYPTION_FORWARD_SECURE));
201   }
202 
InitializeHeaders()203   void InitializeHeaders() {
204     headers_[":host"] = "www.google.com";
205     headers_[":path"] = "/index.hml";
206     headers_[":scheme"] = "https";
207     headers_[":status"] = "200";
208     headers_["cookie"] =
209         "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
210         "__utmc=160408618; "
211         "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
212         "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
213         "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
214         "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
215         "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
216         "1zFMi5vzcns38-8_Sns; "
217         "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
218         "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
219         "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
220         "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
221         "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
222         "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
223         "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
224         "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
225         "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
226         "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
227         "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
228         "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
229         "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
230         "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
231         "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
232   }
233 
CreateResponseHeaders(const std::string & status_code)234   quiche::HttpHeaderBlock CreateResponseHeaders(
235       const std::string& status_code) {
236     quiche::HttpHeaderBlock headers;
237     headers[":status"] = status_code;
238     return headers;
239   }
240 
ReadData(std::string_view expected_data)241   void ReadData(std::string_view expected_data) {
242     auto buffer =
243         base::MakeRefCounted<IOBufferWithSize>(expected_data.length() + 1);
244     EXPECT_EQ(static_cast<int>(expected_data.length()),
245               stream_->Read(buffer.get(), expected_data.length() + 1));
246     EXPECT_EQ(expected_data,
247               std::string_view(buffer->data(), expected_data.length()));
248   }
249 
ProcessHeaders(const quiche::HttpHeaderBlock & headers)250   quic::QuicHeaderList ProcessHeaders(const quiche::HttpHeaderBlock& headers) {
251     quic::QuicHeaderList h = quic::test::AsHeaderList(headers);
252     stream_->OnStreamHeaderList(false, h.uncompressed_header_bytes(), h);
253     return h;
254   }
255 
ProcessTrailers(const quiche::HttpHeaderBlock & headers)256   quic::QuicHeaderList ProcessTrailers(const quiche::HttpHeaderBlock& headers) {
257     quic::QuicHeaderList h = quic::test::AsHeaderList(headers);
258     stream_->OnStreamHeaderList(true, h.uncompressed_header_bytes(), h);
259     return h;
260   }
261 
ProcessHeadersFull(const quiche::HttpHeaderBlock & headers)262   quic::QuicHeaderList ProcessHeadersFull(
263       const quiche::HttpHeaderBlock& headers) {
264     quic::QuicHeaderList h = ProcessHeaders(headers);
265     TestCompletionCallback callback;
266     EXPECT_EQ(static_cast<int>(h.uncompressed_header_bytes()),
267               handle_->ReadInitialHeaders(&headers_, callback.callback()));
268     EXPECT_EQ(headers, headers_);
269     EXPECT_TRUE(stream_->header_list().empty());
270     return h;
271   }
272 
GetNthClientInitiatedBidirectionalStreamId(int n)273   quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
274     return quic::test::GetNthClientInitiatedBidirectionalStreamId(
275         session_.connection()->transport_version(), n);
276   }
277 
GetNthServerInitiatedUnidirectionalStreamId(int n)278   quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
279     return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
280         session_.connection()->transport_version(), n);
281   }
282 
ResetStreamCallback(QuicChromiumClientStream * stream,int)283   void ResetStreamCallback(QuicChromiumClientStream* stream, int /*rv*/) {
284     stream->Reset(quic::QUIC_STREAM_CANCELLED);
285   }
286 
ConstructDataHeader(size_t body_len)287   std::string ConstructDataHeader(size_t body_len) {
288     quiche::QuicheBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
289         body_len, quiche::SimpleBufferAllocator::Get());
290     return std::string(buffer.data(), buffer.size());
291   }
292 
293   const quic::ParsedQuicVersion version_;
294   quic::QuicCryptoClientConfig crypto_config_;
295   std::unique_ptr<QuicChromiumClientStream::Handle> handle_;
296   std::unique_ptr<QuicChromiumClientStream::Handle> handle2_;
297   quic::test::MockQuicConnectionHelper helper_;
298   quic::test::MockAlarmFactory alarm_factory_;
299   MockQuicClientSessionBase session_;
300   raw_ptr<QuicChromiumClientStream> stream_;
301   quiche::HttpHeaderBlock headers_;
302   quiche::HttpHeaderBlock trailers_;
303   base::HistogramTester histogram_tester_;
304 };
305 
306 INSTANTIATE_TEST_SUITE_P(Version,
307                          QuicChromiumClientStreamTest,
308                          ::testing::ValuesIn(AllSupportedQuicVersions()),
309                          ::testing::PrintToStringParamName());
310 
TEST_P(QuicChromiumClientStreamTest,Handle)311 TEST_P(QuicChromiumClientStreamTest, Handle) {
312   testing::InSequence seq;
313   EXPECT_TRUE(handle_->IsOpen());
314   EXPECT_EQ(quic::test::GetNthClientInitiatedBidirectionalStreamId(
315                 version_.transport_version, 0),
316             handle_->id());
317   EXPECT_EQ(quic::QUIC_NO_ERROR, handle_->connection_error());
318   EXPECT_EQ(quic::QUIC_STREAM_NO_ERROR, handle_->stream_error());
319   EXPECT_TRUE(handle_->IsFirstStream());
320   EXPECT_FALSE(handle_->IsDoneReading());
321   EXPECT_FALSE(handle_->fin_sent());
322   EXPECT_FALSE(handle_->fin_received());
323   EXPECT_EQ(0u, handle_->stream_bytes_read());
324   EXPECT_EQ(0u, handle_->stream_bytes_written());
325   EXPECT_EQ(0u, handle_->NumBytesConsumed());
326 
327   InitializeHeaders();
328   quic::QuicStreamOffset offset = 0;
329   ProcessHeadersFull(headers_);
330   quic::QuicStreamFrame frame2(
331       quic::test::GetNthClientInitiatedBidirectionalStreamId(
332           version_.transport_version, 0),
333       true, offset, std::string_view());
334   stream_->OnStreamFrame(frame2);
335   EXPECT_TRUE(handle_->fin_received());
336   handle_->OnFinRead();
337 
338   const char kData1[] = "hello world";
339   const size_t kDataLen = std::size(kData1);
340 
341   // All data written.
342   std::string header = ConstructDataHeader(kDataLen);
343   EXPECT_CALL(session_,
344               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
345       .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
346   EXPECT_CALL(session_,
347               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
348       .WillOnce(Return(quic::QuicConsumedData(kDataLen, true)));
349   TestCompletionCallback callback;
350   EXPECT_EQ(OK, handle_->WriteStreamData(std::string_view(kData1, kDataLen),
351                                          true, callback.callback()));
352 
353   EXPECT_FALSE(handle_->IsOpen());
354   EXPECT_EQ(quic::test::GetNthClientInitiatedBidirectionalStreamId(
355                 version_.transport_version, 0),
356             handle_->id());
357   EXPECT_EQ(quic::QUIC_NO_ERROR, handle_->connection_error());
358   EXPECT_EQ(quic::QUIC_STREAM_NO_ERROR, handle_->stream_error());
359   EXPECT_TRUE(handle_->IsFirstStream());
360   EXPECT_TRUE(handle_->IsDoneReading());
361   EXPECT_TRUE(handle_->fin_sent());
362   EXPECT_TRUE(handle_->fin_received());
363   EXPECT_EQ(0u, handle_->stream_bytes_read());
364   EXPECT_EQ(header.length() + kDataLen, handle_->stream_bytes_written());
365   EXPECT_EQ(0u, handle_->NumBytesConsumed());
366 
367   EXPECT_EQ(ERR_CONNECTION_CLOSED,
368             handle_->WriteStreamData(std::string_view(kData1, kDataLen), true,
369                                      callback.callback()));
370 
371   std::vector<scoped_refptr<IOBuffer>> buffers = {
372       base::MakeRefCounted<IOBufferWithSize>(10)};
373   std::vector<int> lengths = {10};
374   EXPECT_EQ(
375       ERR_CONNECTION_CLOSED,
376       handle_->WritevStreamData(buffers, lengths, true, callback.callback()));
377 
378   quiche::HttpHeaderBlock headers;
379   EXPECT_EQ(0, handle_->WriteHeaders(std::move(headers), true, nullptr));
380 }
381 
TEST_P(QuicChromiumClientStreamTest,HandleAfterConnectionClose)382 TEST_P(QuicChromiumClientStreamTest, HandleAfterConnectionClose) {
383   quic::test::QuicConnectionPeer::TearDownLocalConnectionState(
384       session_.connection());
385   quic::QuicConnectionCloseFrame frame;
386   frame.quic_error_code = quic::QUIC_INVALID_FRAME_DATA;
387   stream_->OnConnectionClosed(frame, quic::ConnectionCloseSource::FROM_PEER);
388 
389   EXPECT_FALSE(handle_->IsOpen());
390   EXPECT_EQ(quic::QUIC_INVALID_FRAME_DATA, handle_->connection_error());
391 }
392 
TEST_P(QuicChromiumClientStreamTest,HandleAfterStreamReset)393 TEST_P(QuicChromiumClientStreamTest, HandleAfterStreamReset) {
394   // Make a STOP_SENDING frame and pass it to QUIC. We need both a REST_STREAM
395   // and a STOP_SENDING to effect a closed stream.
396   quic::QuicStopSendingFrame stop_sending_frame(
397       quic::kInvalidControlFrameId,
398       quic::test::GetNthClientInitiatedBidirectionalStreamId(
399           version_.transport_version, 0),
400       quic::QUIC_STREAM_CANCELLED);
401   session_.OnStopSendingFrame(stop_sending_frame);
402 
403   // Verify that the Handle still behaves correctly after the stream is reset.
404   quic::QuicRstStreamFrame rst(
405       quic::kInvalidControlFrameId,
406       quic::test::GetNthClientInitiatedBidirectionalStreamId(
407           version_.transport_version, 0),
408       quic::QUIC_STREAM_CANCELLED, 0);
409 
410   stream_->OnStreamReset(rst);
411   EXPECT_FALSE(handle_->IsOpen());
412   EXPECT_EQ(quic::QUIC_STREAM_CANCELLED, handle_->stream_error());
413 }
414 
TEST_P(QuicChromiumClientStreamTest,OnFinRead)415 TEST_P(QuicChromiumClientStreamTest, OnFinRead) {
416   InitializeHeaders();
417   quic::QuicStreamOffset offset = 0;
418   ProcessHeadersFull(headers_);
419   quic::QuicStreamFrame frame2(
420       quic::test::GetNthClientInitiatedBidirectionalStreamId(
421           version_.transport_version, 0),
422       true, offset, std::string_view());
423   stream_->OnStreamFrame(frame2);
424 }
425 
TEST_P(QuicChromiumClientStreamTest,OnDataAvailable)426 TEST_P(QuicChromiumClientStreamTest, OnDataAvailable) {
427   InitializeHeaders();
428   ProcessHeadersFull(headers_);
429 
430   const char data[] = "hello world!";
431   int data_len = strlen(data);
432   size_t offset = 0;
433   std::string header = ConstructDataHeader(data_len);
434   stream_->OnStreamFrame(quic::QuicStreamFrame(
435       quic::test::GetNthClientInitiatedBidirectionalStreamId(
436           version_.transport_version, 0),
437       /*fin=*/false,
438       /*offset=*/offset, header));
439   offset += header.length();
440   stream_->OnStreamFrame(quic::QuicStreamFrame(
441       quic::test::GetNthClientInitiatedBidirectionalStreamId(
442           version_.transport_version, 0),
443       /*fin=*/false,
444       /*offset=*/offset, data));
445 
446   // Read the body and verify that it arrives correctly.
447   TestCompletionCallback callback;
448   auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
449   EXPECT_EQ(data_len,
450             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
451   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
452 }
453 
TEST_P(QuicChromiumClientStreamTest,OnDataAvailableAfterReadBody)454 TEST_P(QuicChromiumClientStreamTest, OnDataAvailableAfterReadBody) {
455   InitializeHeaders();
456   ProcessHeadersFull(headers_);
457 
458   const char data[] = "hello world!";
459   int data_len = strlen(data);
460 
461   // Start to read the body.
462   TestCompletionCallback callback;
463   auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
464   EXPECT_EQ(ERR_IO_PENDING,
465             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
466 
467   size_t offset = 0;
468   std::string header = ConstructDataHeader(data_len);
469   stream_->OnStreamFrame(quic::QuicStreamFrame(
470       quic::test::GetNthClientInitiatedBidirectionalStreamId(
471           version_.transport_version, 0),
472       /*fin=*/false,
473       /*offset=*/offset, header));
474   offset += header.length();
475 
476   stream_->OnStreamFrame(quic::QuicStreamFrame(
477       quic::test::GetNthClientInitiatedBidirectionalStreamId(
478           version_.transport_version, 0),
479       /*fin=*/false,
480       /*offset=*/offset, data));
481 
482   EXPECT_EQ(data_len, callback.WaitForResult());
483   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
484   base::RunLoop().RunUntilIdle();
485 }
486 
TEST_P(QuicChromiumClientStreamTest,ProcessHeadersWithError)487 TEST_P(QuicChromiumClientStreamTest, ProcessHeadersWithError) {
488   quiche::HttpHeaderBlock bad_headers;
489   bad_headers["NAME"] = "...";
490 
491   EXPECT_CALL(
492       *static_cast<quic::test::MockQuicConnection*>(session_.connection()),
493       OnStreamReset(quic::test::GetNthClientInitiatedBidirectionalStreamId(
494                         version_.transport_version, 0),
495                     quic::QUIC_BAD_APPLICATION_PAYLOAD));
496 
497   auto headers = quic::test::AsHeaderList(bad_headers);
498   stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
499                               headers);
500 
501   base::RunLoop().RunUntilIdle();
502 }
503 
TEST_P(QuicChromiumClientStreamTest,OnDataAvailableWithError)504 TEST_P(QuicChromiumClientStreamTest, OnDataAvailableWithError) {
505   InitializeHeaders();
506   auto headers = quic::test::AsHeaderList(headers_);
507   ProcessHeadersFull(headers_);
508 
509   const char data[] = "hello world!";
510   int data_len = strlen(data);
511 
512   // Start to read the body.
513   TestCompletionCallback callback;
514   auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
515   EXPECT_EQ(
516       ERR_IO_PENDING,
517       handle_->ReadBody(
518           buffer.get(), 2 * data_len,
519           base::BindOnce(&QuicChromiumClientStreamTest::ResetStreamCallback,
520                          base::Unretained(this), stream_)));
521 
522   EXPECT_CALL(
523       *static_cast<quic::test::MockQuicConnection*>(session_.connection()),
524       OnStreamReset(quic::test::GetNthClientInitiatedBidirectionalStreamId(
525                         version_.transport_version, 0),
526                     quic::QUIC_STREAM_CANCELLED));
527 
528   // Receive the data and close the stream during the callback.
529   size_t offset = 0;
530   std::string header = ConstructDataHeader(data_len);
531   stream_->OnStreamFrame(quic::QuicStreamFrame(
532       quic::test::GetNthClientInitiatedBidirectionalStreamId(
533           version_.transport_version, 0),
534       /*fin=*/false,
535       /*offset=*/offset, header));
536   offset += header.length();
537   stream_->OnStreamFrame(quic::QuicStreamFrame(
538       quic::test::GetNthClientInitiatedBidirectionalStreamId(
539           version_.transport_version, 0),
540       /*fin=*/false,
541       /*offset=*/0, data));
542 
543   base::RunLoop().RunUntilIdle();
544 }
545 
TEST_P(QuicChromiumClientStreamTest,OnError)546 TEST_P(QuicChromiumClientStreamTest, OnError) {
547   //  EXPECT_CALL(delegate_, OnError(ERR_INTERNET_DISCONNECTED)).Times(1);
548 
549   stream_->OnError(ERR_INTERNET_DISCONNECTED);
550   stream_->OnError(ERR_INTERNET_DISCONNECTED);
551 }
552 
TEST_P(QuicChromiumClientStreamTest,OnTrailers)553 TEST_P(QuicChromiumClientStreamTest, OnTrailers) {
554   InitializeHeaders();
555   ProcessHeadersFull(headers_);
556 
557   const char data[] = "hello world!";
558   int data_len = strlen(data);
559   size_t offset = 0;
560   std::string header = ConstructDataHeader(data_len);
561   stream_->OnStreamFrame(quic::QuicStreamFrame(
562       quic::test::GetNthClientInitiatedBidirectionalStreamId(
563           version_.transport_version, 0),
564       /*fin=*/false,
565       /*offset=*/offset, header));
566   offset += header.length();
567   stream_->OnStreamFrame(quic::QuicStreamFrame(
568       quic::test::GetNthClientInitiatedBidirectionalStreamId(
569           version_.transport_version, 0),
570       /*fin=*/false,
571       /*offset=*/offset, data));
572 
573   // Read the body and verify that it arrives correctly.
574   TestCompletionCallback callback;
575   auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
576   EXPECT_EQ(data_len,
577             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
578   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
579 
580   quiche::HttpHeaderBlock trailers;
581   trailers["bar"] = "foo";
582 
583   auto t = ProcessTrailers(trailers);
584 
585   TestCompletionCallback trailers_callback;
586   EXPECT_EQ(
587       static_cast<int>(t.uncompressed_header_bytes()),
588       handle_->ReadTrailingHeaders(&trailers_, trailers_callback.callback()));
589 
590   // Read the body and verify that it arrives correctly.
591   EXPECT_EQ(0,
592             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
593 
594   EXPECT_EQ(trailers, trailers_);
595   base::RunLoop().RunUntilIdle();
596 }
597 
598 // Tests that trailers are marked as consumed only before delegate is to be
599 // immediately notified about trailers.
TEST_P(QuicChromiumClientStreamTest,MarkTrailersConsumedWhenNotifyDelegate)600 TEST_P(QuicChromiumClientStreamTest, MarkTrailersConsumedWhenNotifyDelegate) {
601   InitializeHeaders();
602   ProcessHeadersFull(headers_);
603 
604   const char data[] = "hello world!";
605   int data_len = strlen(data);
606   size_t offset = 0;
607   std::string header = ConstructDataHeader(data_len);
608   stream_->OnStreamFrame(quic::QuicStreamFrame(
609       quic::test::GetNthClientInitiatedBidirectionalStreamId(
610           version_.transport_version, 0),
611       /*fin=*/false,
612       /*offset=*/offset, header));
613   offset += header.length();
614   stream_->OnStreamFrame(quic::QuicStreamFrame(
615       quic::test::GetNthClientInitiatedBidirectionalStreamId(
616           version_.transport_version, 0),
617       /*fin=*/false,
618       /*offset=*/offset, data));
619 
620   // Read the body and verify that it arrives correctly.
621   TestCompletionCallback callback;
622   auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
623   EXPECT_EQ(data_len,
624             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
625   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
626 
627   // Read again, and it will be pending.
628   EXPECT_THAT(
629       handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()),
630       IsError(ERR_IO_PENDING));
631 
632   quiche::HttpHeaderBlock trailers;
633   trailers["bar"] = "foo";
634   quic::QuicHeaderList t = ProcessTrailers(trailers);
635   EXPECT_FALSE(stream_->IsDoneReading());
636 
637   EXPECT_EQ(static_cast<int>(t.uncompressed_header_bytes()),
638             handle_->ReadTrailingHeaders(&trailers_, callback.callback()));
639 
640   // Read the body and verify that it arrives correctly.
641   EXPECT_EQ(0, callback.WaitForResult());
642 
643   // Make sure the stream is properly closed since trailers and data are all
644   // consumed.
645   EXPECT_TRUE(stream_->IsDoneReading());
646   EXPECT_EQ(trailers, trailers_);
647 
648   base::RunLoop().RunUntilIdle();
649 }
650 
651 // Test that if Read() is called after response body is read and after trailers
652 // are received but not yet delivered, Read() will return ERR_IO_PENDING instead
653 // of 0 (EOF).
TEST_P(QuicChromiumClientStreamTest,ReadAfterTrailersReceivedButNotDelivered)654 TEST_P(QuicChromiumClientStreamTest, ReadAfterTrailersReceivedButNotDelivered) {
655   InitializeHeaders();
656   ProcessHeadersFull(headers_);
657 
658   const char data[] = "hello world!";
659   int data_len = strlen(data);
660   size_t offset = 0;
661   std::string header = ConstructDataHeader(data_len);
662   stream_->OnStreamFrame(quic::QuicStreamFrame(
663       quic::test::GetNthClientInitiatedBidirectionalStreamId(
664           version_.transport_version, 0),
665       /*fin=*/false,
666       /*offset=*/offset, header));
667   offset += header.length();
668   stream_->OnStreamFrame(quic::QuicStreamFrame(
669       quic::test::GetNthClientInitiatedBidirectionalStreamId(
670           version_.transport_version, 0),
671       /*fin=*/false,
672       /*offset=*/offset, data));
673 
674   // Read the body and verify that it arrives correctly.
675   TestCompletionCallback callback;
676   auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
677   EXPECT_EQ(data_len,
678             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
679   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
680 
681   // Deliver trailers. Delegate notification is posted asynchronously.
682   quiche::HttpHeaderBlock trailers;
683   trailers["bar"] = "foo";
684 
685   quic::QuicHeaderList t = ProcessTrailers(trailers);
686 
687   EXPECT_FALSE(stream_->IsDoneReading());
688   // Read again, it return ERR_IO_PENDING.
689   EXPECT_THAT(
690       handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()),
691       IsError(ERR_IO_PENDING));
692 
693   // Trailers are not delivered
694   EXPECT_FALSE(stream_->IsDoneReading());
695 
696   TestCompletionCallback callback2;
697   EXPECT_EQ(static_cast<int>(t.uncompressed_header_bytes()),
698             handle_->ReadTrailingHeaders(&trailers_, callback2.callback()));
699 
700   // Read the body and verify that it arrives correctly.
701   // OnDataAvailable() should follow right after and Read() will return 0.
702   EXPECT_EQ(0, callback.WaitForResult());
703 
704   // Make sure the stream is properly closed since trailers and data are all
705   // consumed.
706   EXPECT_TRUE(stream_->IsDoneReading());
707 
708   EXPECT_EQ(trailers, trailers_);
709 
710   base::RunLoop().RunUntilIdle();
711 }
712 
TEST_P(QuicChromiumClientStreamTest,WriteStreamData)713 TEST_P(QuicChromiumClientStreamTest, WriteStreamData) {
714   testing::InSequence seq;
715   const char kData1[] = "hello world";
716   const size_t kDataLen = std::size(kData1);
717 
718   // All data written.
719   std::string header = ConstructDataHeader(kDataLen);
720   EXPECT_CALL(session_,
721               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
722       .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
723   EXPECT_CALL(session_,
724               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
725       .WillOnce(Return(quic::QuicConsumedData(kDataLen, true)));
726   TestCompletionCallback callback;
727   EXPECT_EQ(OK, handle_->WriteStreamData(std::string_view(kData1, kDataLen),
728                                          true, callback.callback()));
729 }
730 
TEST_P(QuicChromiumClientStreamTest,WriteStreamDataAsync)731 TEST_P(QuicChromiumClientStreamTest, WriteStreamDataAsync) {
732   testing::InSequence seq;
733   const char kData1[] = "hello world";
734   const size_t kDataLen = std::size(kData1);
735 
736   // No data written.
737   EXPECT_CALL(session_,
738               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
739       .WillOnce(Return(quic::QuicConsumedData(0, false)));
740   TestCompletionCallback callback;
741   EXPECT_EQ(ERR_IO_PENDING,
742             handle_->WriteStreamData(std::string_view(kData1, kDataLen), true,
743                                      callback.callback()));
744   ASSERT_FALSE(callback.have_result());
745 
746   // All data written.
747   std::string header = ConstructDataHeader(kDataLen);
748   EXPECT_CALL(session_,
749               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
750       .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
751   EXPECT_CALL(session_,
752               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
753       .WillOnce(Return(quic::QuicConsumedData(kDataLen, true)));
754   stream_->OnCanWrite();
755   // Do 2 writes in version 99.
756   stream_->OnCanWrite();
757   ASSERT_TRUE(callback.have_result());
758   EXPECT_THAT(callback.WaitForResult(), IsOk());
759 }
760 
TEST_P(QuicChromiumClientStreamTest,WritevStreamData)761 TEST_P(QuicChromiumClientStreamTest, WritevStreamData) {
762   testing::InSequence seq;
763   scoped_refptr<StringIOBuffer> buf1 =
764       base::MakeRefCounted<StringIOBuffer>("hello world!");
765   scoped_refptr<StringIOBuffer> buf2 =
766       base::MakeRefCounted<StringIOBuffer>("Just a small payload");
767 
768   // All data written.
769   std::string header = ConstructDataHeader(buf1->size());
770   EXPECT_CALL(session_,
771               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
772       .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
773   EXPECT_CALL(session_,
774               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
775       .WillOnce(Return(quic::QuicConsumedData(buf1->size(), false)));
776   header = ConstructDataHeader(buf2->size());
777   EXPECT_CALL(session_,
778               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
779       .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
780   EXPECT_CALL(session_,
781               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
782       .WillOnce(Return(quic::QuicConsumedData(buf2->size(), true)));
783   TestCompletionCallback callback;
784   EXPECT_EQ(
785       OK, handle_->WritevStreamData({buf1, buf2}, {buf1->size(), buf2->size()},
786                                     true, callback.callback()));
787 }
788 
TEST_P(QuicChromiumClientStreamTest,WritevStreamDataAsync)789 TEST_P(QuicChromiumClientStreamTest, WritevStreamDataAsync) {
790   testing::InSequence seq;
791   scoped_refptr<StringIOBuffer> buf1 =
792       base::MakeRefCounted<StringIOBuffer>("hello world!");
793   scoped_refptr<StringIOBuffer> buf2 =
794       base::MakeRefCounted<StringIOBuffer>("Just a small payload");
795 
796   // Only a part of the data is written.
797   std::string header = ConstructDataHeader(buf1->size());
798   EXPECT_CALL(session_,
799               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
800       .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
801   EXPECT_CALL(session_,
802               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
803       // First piece of data is written.
804       .WillOnce(Return(quic::QuicConsumedData(buf1->size(), false)));
805   // Second piece of data is queued.
806   EXPECT_CALL(session_,
807               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
808       .WillOnce(Return(quic::QuicConsumedData(0, false)));
809   TestCompletionCallback callback;
810   EXPECT_EQ(ERR_IO_PENDING,
811             handle_->WritevStreamData({buf1.get(), buf2.get()},
812                                       {buf1->size(), buf2->size()}, true,
813                                       callback.callback()));
814   ASSERT_FALSE(callback.have_result());
815 
816   // The second piece of data is written.
817   header = ConstructDataHeader(buf2->size());
818   EXPECT_CALL(session_,
819               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
820       .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
821   EXPECT_CALL(session_,
822               WritevData(stream_->id(), _, _, _, quic::NOT_RETRANSMISSION, _))
823       .WillOnce(Return(quic::QuicConsumedData(buf2->size(), true)));
824   stream_->OnCanWrite();
825   stream_->OnCanWrite();
826   ASSERT_TRUE(callback.have_result());
827   EXPECT_THAT(callback.WaitForResult(), IsOk());
828 }
829 
TEST_P(QuicChromiumClientStreamTest,WriteConnectUdpPayload)830 TEST_P(QuicChromiumClientStreamTest, WriteConnectUdpPayload) {
831   testing::InSequence seq;
832   std::string packet = {1, 2, 3, 4, 5, 6};
833 
834   quic::test::QuicSpdySessionPeer::SetHttpDatagramSupport(
835       &session_, quic::HttpDatagramSupport::kRfc);
836   EXPECT_CALL(
837       *static_cast<quic::test::MockQuicConnection*>(session_.connection()),
838       SendMessage(1, _, false))
839       .WillOnce(Return(quic::MESSAGE_STATUS_SUCCESS));
840   EXPECT_EQ(OK, handle_->WriteConnectUdpPayload(packet));
841   histogram_tester_.ExpectBucketCount(
842       QuicChromiumClientStream::kHttp3DatagramDroppedHistogram, false, 1);
843 
844   // Packet is dropped if session does not have HTTP3 Datagram support.
845   quic::test::QuicSpdySessionPeer::SetHttpDatagramSupport(
846       &session_, quic::HttpDatagramSupport::kNone);
847   EXPECT_EQ(OK, handle_->WriteConnectUdpPayload(packet));
848   histogram_tester_.ExpectBucketCount(
849       QuicChromiumClientStream::kHttp3DatagramDroppedHistogram, true, 1);
850   histogram_tester_.ExpectTotalCount(
851       QuicChromiumClientStream::kHttp3DatagramDroppedHistogram, 2);
852 }
853 
TEST_P(QuicChromiumClientStreamTest,HeadersBeforeHandle)854 TEST_P(QuicChromiumClientStreamTest, HeadersBeforeHandle) {
855   // We don't use stream_ because we want an incoming server push
856   // stream.
857   quic::QuicStreamId stream_id = GetNthServerInitiatedUnidirectionalStreamId(0);
858   QuicChromiumClientStream* stream2 = new QuicChromiumClientStream(
859       stream_id, &session_, quic::QuicServerId(), quic::READ_UNIDIRECTIONAL,
860       NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS);
861   session_.ActivateStream(base::WrapUnique(stream2));
862 
863   InitializeHeaders();
864 
865   // Receive the headers before the delegate is set.
866   quic::QuicHeaderList header_list = quic::test::AsHeaderList(headers_);
867   stream2->OnStreamHeaderList(true, header_list.uncompressed_header_bytes(),
868                               header_list);
869 
870   // Now set the delegate and verify that the headers are delivered.
871   handle2_ = stream2->CreateHandle();
872   TestCompletionCallback callback;
873   EXPECT_EQ(static_cast<int>(header_list.uncompressed_header_bytes()),
874             handle2_->ReadInitialHeaders(&headers_, callback.callback()));
875   EXPECT_EQ(headers_, headers_);
876 }
877 
TEST_P(QuicChromiumClientStreamTest,HeadersAndDataBeforeHandle)878 TEST_P(QuicChromiumClientStreamTest, HeadersAndDataBeforeHandle) {
879   // We don't use stream_ because we want an incoming server push
880   // stream.
881   quic::QuicStreamId stream_id = GetNthServerInitiatedUnidirectionalStreamId(0);
882   QuicChromiumClientStream* stream2 = new QuicChromiumClientStream(
883       stream_id, &session_, quic::QuicServerId(), quic::READ_UNIDIRECTIONAL,
884       NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS);
885   session_.ActivateStream(base::WrapUnique(stream2));
886 
887   InitializeHeaders();
888 
889   // Receive the headers and data before the delegate is set.
890   quic::QuicHeaderList header_list = quic::test::AsHeaderList(headers_);
891   stream2->OnStreamHeaderList(false, header_list.uncompressed_header_bytes(),
892                               header_list);
893   const char data[] = "hello world!";
894 
895   size_t offset = 0;
896   std::string header = ConstructDataHeader(strlen(data));
897   stream2->OnStreamFrame(quic::QuicStreamFrame(stream_id,
898                                                /*fin=*/false,
899                                                /*offset=*/offset, header));
900   offset += header.length();
901   stream2->OnStreamFrame(quic::QuicStreamFrame(stream_id, /*fin=*/false,
902                                                /*offset=*/offset, data));
903 
904   // Now set the delegate and verify that the headers are delivered, but
905   // not the data, which needs to be read explicitly.
906   handle2_ = stream2->CreateHandle();
907   TestCompletionCallback callback;
908   EXPECT_EQ(static_cast<int>(header_list.uncompressed_header_bytes()),
909             handle2_->ReadInitialHeaders(&headers_, callback.callback()));
910   EXPECT_EQ(headers_, headers_);
911   base::RunLoop().RunUntilIdle();
912 
913   // Now explicitly read the data.
914   int data_len = std::size(data) - 1;
915   auto buffer = base::MakeRefCounted<IOBufferWithSize>(data_len + 1);
916   ASSERT_EQ(data_len, stream2->Read(buffer.get(), data_len + 1));
917   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
918 }
919 
920 // Regression test for https://crbug.com/1043531.
TEST_P(QuicChromiumClientStreamTest,ResetOnEmptyResponseHeaders)921 TEST_P(QuicChromiumClientStreamTest, ResetOnEmptyResponseHeaders) {
922   const quiche::HttpHeaderBlock empty_response_headers;
923   ProcessHeaders(empty_response_headers);
924 
925   // Empty headers are allowed by QuicSpdyStream,
926   // but an error is generated by QuicChromiumClientStream.
927   int rv = handle_->ReadInitialHeaders(&headers_, CompletionOnceCallback());
928   EXPECT_THAT(rv, IsError(net::ERR_QUIC_PROTOCOL_ERROR));
929 }
930 
931 // Tests that the stream resets when it receives an invalid ":status"
932 // pseudo-header value.
TEST_P(QuicChromiumClientStreamTest,InvalidStatus)933 TEST_P(QuicChromiumClientStreamTest, InvalidStatus) {
934   quiche::HttpHeaderBlock headers = CreateResponseHeaders("xxx");
935 
936   EXPECT_CALL(
937       *static_cast<quic::test::MockQuicConnection*>(session_.connection()),
938       OnStreamReset(quic::test::GetNthClientInitiatedBidirectionalStreamId(
939                         version_.transport_version, 0),
940                     quic::QUIC_BAD_APPLICATION_PAYLOAD));
941 
942   ProcessHeaders(headers);
943   EXPECT_FALSE(handle_->IsOpen());
944   EXPECT_EQ(quic::QUIC_BAD_APPLICATION_PAYLOAD, handle_->stream_error());
945 }
946 
947 // Tests that the stream resets when it receives 101 Switching Protocols.
TEST_P(QuicChromiumClientStreamTest,SwitchingProtocolsResponse)948 TEST_P(QuicChromiumClientStreamTest, SwitchingProtocolsResponse) {
949   quiche::HttpHeaderBlock informational_headers = CreateResponseHeaders("101");
950 
951   EXPECT_CALL(
952       *static_cast<quic::test::MockQuicConnection*>(session_.connection()),
953       OnStreamReset(quic::test::GetNthClientInitiatedBidirectionalStreamId(
954                         version_.transport_version, 0),
955                     quic::QUIC_BAD_APPLICATION_PAYLOAD));
956 
957   ProcessHeaders(informational_headers);
958   EXPECT_FALSE(handle_->IsOpen());
959   EXPECT_EQ(quic::QUIC_BAD_APPLICATION_PAYLOAD, handle_->stream_error());
960 }
961 
962 // Tests that the stream ignores 100 Continue response.
TEST_P(QuicChromiumClientStreamTest,ContinueResponse)963 TEST_P(QuicChromiumClientStreamTest, ContinueResponse) {
964   quiche::HttpHeaderBlock informational_headers = CreateResponseHeaders("100");
965 
966   // This informational headers should be ignored.
967   ProcessHeaders(informational_headers);
968 
969   // Pass the initial headers.
970   InitializeHeaders();
971   quic::QuicHeaderList header_list = ProcessHeaders(headers_);
972 
973   // Read the initial headers.
974   quiche::HttpHeaderBlock response_headers;
975   // Pass DoNothing because the initial headers is already available and the
976   // callback won't be called.
977   EXPECT_EQ(static_cast<int>(header_list.uncompressed_header_bytes()),
978             handle_->ReadInitialHeaders(&response_headers, base::DoNothing()));
979   base::RunLoop().RunUntilIdle();
980 
981   EXPECT_EQ(response_headers, headers_);
982 }
983 
984 // Tests that the stream handles 103 Early Hints responses.
TEST_P(QuicChromiumClientStreamTest,EarlyHintsResponses)985 TEST_P(QuicChromiumClientStreamTest, EarlyHintsResponses) {
986   // Pass Two Early Hints responses to the stream.
987   quiche::HttpHeaderBlock hints1_headers = CreateResponseHeaders("103");
988   hints1_headers["x-header1"] = "foo";
989   quic::QuicHeaderList header_list = ProcessHeaders(hints1_headers);
990   const size_t hints1_bytes = header_list.uncompressed_header_bytes();
991 
992   quiche::HttpHeaderBlock hints2_headers = CreateResponseHeaders("103");
993   hints2_headers["x-header2"] = "foobarbaz";
994   header_list = ProcessHeaders(hints2_headers);
995   const size_t hints2_bytes = header_list.uncompressed_header_bytes();
996 
997   // Pass the initial headers to the stream.
998   InitializeHeaders();
999   header_list = ProcessHeaders(headers_);
1000   const size_t initial_headers_bytes = header_list.uncompressed_header_bytes();
1001 
1002   quiche::HttpHeaderBlock headers;
1003 
1004   // Read headers. The first two reads should return Early Hints.
1005   EXPECT_EQ(static_cast<int>(hints1_bytes),
1006             handle_->ReadInitialHeaders(&headers, base::DoNothing()));
1007   base::RunLoop().RunUntilIdle();
1008   EXPECT_EQ(headers, hints1_headers);
1009   base::TimeTicks first_early_hints_time = handle_->first_early_hints_time();
1010   EXPECT_FALSE(first_early_hints_time.is_null());
1011 
1012   EXPECT_EQ(static_cast<int>(hints2_bytes),
1013             handle_->ReadInitialHeaders(&headers, base::DoNothing()));
1014   base::RunLoop().RunUntilIdle();
1015   EXPECT_EQ(headers, hints2_headers);
1016   EXPECT_EQ(first_early_hints_time, handle_->first_early_hints_time());
1017 
1018   // The third read should return the initial headers.
1019   EXPECT_EQ(static_cast<int>(initial_headers_bytes),
1020             handle_->ReadInitialHeaders(&headers, base::DoNothing()));
1021   base::RunLoop().RunUntilIdle();
1022   EXPECT_EQ(headers, headers_);
1023 }
1024 
1025 // Tests that pending reads for Early Hints work.
TEST_P(QuicChromiumClientStreamTest,EarlyHintsAsync)1026 TEST_P(QuicChromiumClientStreamTest, EarlyHintsAsync) {
1027   quiche::HttpHeaderBlock headers;
1028   TestCompletionCallback hints_callback;
1029 
1030   // Try to read headers. The read should be blocked.
1031   EXPECT_EQ(ERR_IO_PENDING,
1032             handle_->ReadInitialHeaders(&headers, hints_callback.callback()));
1033 
1034   // Pass an Early Hints and the initial headers.
1035   quiche::HttpHeaderBlock hints_headers = CreateResponseHeaders("103");
1036   hints_headers["x-header1"] = "foo";
1037   quic::QuicHeaderList header_list = ProcessHeaders(hints_headers);
1038   const size_t hints_bytes = header_list.uncompressed_header_bytes();
1039   InitializeHeaders();
1040   header_list = ProcessHeaders(headers_);
1041   const size_t initial_headers_bytes = header_list.uncompressed_header_bytes();
1042 
1043   // Wait for the pending headers read. The result should be the Early Hints.
1044   const int hints_result = hints_callback.WaitForResult();
1045   EXPECT_EQ(hints_result, static_cast<int>(hints_bytes));
1046   EXPECT_EQ(headers, hints_headers);
1047 
1048   // Second read should return the initial headers.
1049   EXPECT_EQ(static_cast<int>(initial_headers_bytes),
1050             handle_->ReadInitialHeaders(&headers, base::DoNothing()));
1051   EXPECT_EQ(headers, headers_);
1052 }
1053 
1054 // Tests that Early Hints after the initial headers is treated as an error.
TEST_P(QuicChromiumClientStreamTest,EarlyHintsAfterInitialHeaders)1055 TEST_P(QuicChromiumClientStreamTest, EarlyHintsAfterInitialHeaders) {
1056   InitializeHeaders();
1057   ProcessHeadersFull(headers_);
1058 
1059   // Early Hints after the initial headers are treated as trailers, and it
1060   // should result in an error because trailers must not contain pseudo-headers
1061   // like ":status".
1062   EXPECT_CALL(
1063       *static_cast<quic::test::MockQuicConnection*>(session_.connection()),
1064       CloseConnection(
1065           quic::QUIC_INVALID_HEADERS_STREAM_DATA, _,
1066           quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1067 
1068   quiche::HttpHeaderBlock hints_headers;
1069   hints_headers[":status"] = "103";
1070   ProcessHeaders(hints_headers);
1071   base::RunLoop().RunUntilIdle();
1072 }
1073 
1074 // Similar to the above test but don't read the initial headers.
TEST_P(QuicChromiumClientStreamTest,EarlyHintsAfterInitialHeadersWithoutRead)1075 TEST_P(QuicChromiumClientStreamTest, EarlyHintsAfterInitialHeadersWithoutRead) {
1076   InitializeHeaders();
1077   ProcessHeaders(headers_);
1078 
1079   // Early Hints after the initial headers are treated as trailers, and it
1080   // should result in an error because trailers must not contain pseudo-headers
1081   // like ":status".
1082   EXPECT_CALL(
1083       *static_cast<quic::test::MockQuicConnection*>(session_.connection()),
1084       CloseConnection(
1085           quic::QUIC_INVALID_HEADERS_STREAM_DATA, _,
1086           quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1087 
1088   quiche::HttpHeaderBlock hints_headers;
1089   hints_headers[":status"] = "103";
1090   ProcessHeaders(hints_headers);
1091   base::RunLoop().RunUntilIdle();
1092 }
1093 
1094 // Regression test for https://crbug.com/1248970. Write an Early Hints headers,
1095 // an initial response headers and trailers in succession without reading in
1096 // the middle of writings.
TEST_P(QuicChromiumClientStreamTest,TrailersAfterEarlyHintsWithoutRead)1097 TEST_P(QuicChromiumClientStreamTest, TrailersAfterEarlyHintsWithoutRead) {
1098   // Process an Early Hints response headers on the stream.
1099   quiche::HttpHeaderBlock hints_headers = CreateResponseHeaders("103");
1100   quic::QuicHeaderList hints_header_list = ProcessHeaders(hints_headers);
1101 
1102   // Process an initial response headers on the stream.
1103   InitializeHeaders();
1104   quic::QuicHeaderList header_list = ProcessHeaders(headers_);
1105 
1106   // Process a trailer headers on the stream. This should not hit any DCHECK.
1107   quiche::HttpHeaderBlock trailers;
1108   trailers["bar"] = "foo";
1109   quic::QuicHeaderList trailer_header_list = ProcessTrailers(trailers);
1110   base::RunLoop().RunUntilIdle();
1111 
1112   // Read the Early Hints response from the handle.
1113   {
1114     quiche::HttpHeaderBlock headers;
1115     TestCompletionCallback callback;
1116     EXPECT_EQ(static_cast<int>(hints_header_list.uncompressed_header_bytes()),
1117               handle_->ReadInitialHeaders(&headers, callback.callback()));
1118     EXPECT_EQ(headers, hints_headers);
1119   }
1120 
1121   // Read the initial headers from the handle.
1122   {
1123     quiche::HttpHeaderBlock headers;
1124     TestCompletionCallback callback;
1125     EXPECT_EQ(static_cast<int>(header_list.uncompressed_header_bytes()),
1126               handle_->ReadInitialHeaders(&headers, callback.callback()));
1127     EXPECT_EQ(headers, headers_);
1128   }
1129 
1130   // Read trailers from the handle.
1131   {
1132     quiche::HttpHeaderBlock headers;
1133     TestCompletionCallback callback;
1134     EXPECT_EQ(static_cast<int>(trailer_header_list.uncompressed_header_bytes()),
1135               handle_->ReadTrailingHeaders(&headers, callback.callback()));
1136     EXPECT_EQ(headers, trailers);
1137   }
1138 }
1139 
1140 }  // namespace
1141 }  // namespace net::test
1142