src/net/quic/quic_network_transaction_unittest.cc
// Make two HTTP/1.1 requests to the same host over a QUIC proxy tunnel and
// check that the proxy socket is reused for the second request.
Make two HTTP/1.1 requests to the same host over a QUIC proxy tunnel and
check that the proxy socket is reused for the second request.
Make two HTTP / 1 . 1 requests to the same host over a QUIC proxy tunnel and check that the proxy socket is reused for the second request .
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectReuseTransportSocket) {
  session_params_.enable_quic = true;
  session_params_.enable_quic_proxies_for_https_urls = true;
  proxy_resolution_service_ =
      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
          "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  MockQuicData mock_quic_data(version_);
  int write_packet_index = 1;
  if (VersionUsesHttp3(version_.transport_version)) {
    mock_quic_data.AddWrite(
        SYNCHRONOUS, ConstructInitialSettingsPacket(write_packet_index++));
    mock_quic_data.AddWrite(
        SYNCHRONOUS, client_maker_->MakePriorityPacket(
                         write_packet_index++, true,
                         GetNthClientInitiatedBidirectionalStreamId(0), 0,
                         ConvertRequestPriorityToQuicPriority(
                             HttpProxyConnectJob::kH2QuicTunnelPriority)));
  }
  mock_quic_data.AddWrite(
      SYNCHRONOUS,
      ConstructClientRequestHeadersPacket(
          write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
          true, false,
          VersionUsesHttp3(version_.transport_version)
              ? MEDIUM
              : HttpProxyConnectJob::kH2QuicTunnelPriority,
          ConnectRequestHeaders("mail.example.org:443"), 0));
  mock_quic_data.AddRead(
      ASYNC, ConstructServerResponseHeadersPacket(
                 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
                 GetResponseHeaders("200 OK")));
  quic::QuicStreamOffset server_data_offset = 0;
  const char get_request_1[] =
      "GET / HTTP/1.1\r\n"
      "Host: mail.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  std::string header = ConstructDataHeader(strlen(get_request_1));
  if (!version_.HasIetfQuicFrames()) {
    mock_quic_data.AddWrite(
        SYNCHRONOUS, ConstructClientAckAndDataPacket(
                         write_packet_index++, false,
                         GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
                         false, quiche::QuicheStringPiece(get_request_1)));
  } else {
    mock_quic_data.AddWrite(
        SYNCHRONOUS, ConstructClientAckAndDataPacket(
                         write_packet_index++, false,
                         GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
                         false, {header + std::string(get_request_1)}));
  }
  const char get_response_1[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  std::string header2 = ConstructDataHeader(strlen(get_response_1));
  mock_quic_data.AddRead(
      ASYNC, ConstructServerDataPacket(
                 2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
                 header2 + std::string(get_response_1)));
  server_data_offset += strlen(get_response_1) + header2.length();
  std::string header3 = ConstructDataHeader(10);
  mock_quic_data.AddRead(
      SYNCHRONOUS, ConstructServerDataPacket(
                       3, GetNthClientInitiatedBidirectionalStreamId(0), false,
                       false, header3 + std::string("0123456789")));
  server_data_offset += 10 + header3.length();
  mock_quic_data.AddWrite(
      SYNCHRONOUS, ConstructClientAckPacket(write_packet_index++, 3, 2, 1));
  const char get_request_2[] =
      "GET /2 HTTP/1.1\r\n"
      "Host: mail.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  std::string header4 = ConstructDataHeader(strlen(get_request_2));
  if (version_.HasIetfQuicFrames()) {
    mock_quic_data.AddWrite(
        SYNCHRONOUS,
        ConstructClientDataPacket(
            write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
            false, false, {header4 + std::string(get_request_2)}));
  } else {
    mock_quic_data.AddWrite(
        SYNCHRONOUS,
        ConstructClientDataPacket(
            write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
            false, false, quiche::QuicheStringPiece(get_request_2)));
  }
  const char get_response_2[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 7\r\n\r\n";
  std::string header5 = ConstructDataHeader(strlen(get_response_2));
  mock_quic_data.AddRead(
      ASYNC, ConstructServerDataPacket(
                 4, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
                 header5 + std::string(get_response_2)));
  server_data_offset += strlen(get_response_2) + header5.length();
  std::string header6 = ConstructDataHeader(7);
  mock_quic_data.AddRead(
      SYNCHRONOUS, ConstructServerDataPacket(
                       5, GetNthClientInitiatedBidirectionalStreamId(0), false,
                       false, header6 + std::string("0123456")));
  server_data_offset += 7 + header6.length();
  mock_quic_data.AddWrite(
      SYNCHRONOUS, ConstructClientAckPacket(write_packet_index++, 5, 4, 1));
  mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  
  if (VersionUsesHttp3(version_.transport_version)) {
    mock_quic_data.AddWrite(
        SYNCHRONOUS, ConstructClientDataPacket(
                         write_packet_index++, GetQpackDecoderStreamId(), true,
                         false, StreamCancellationQpackDecoderInstruction(0)));
  }
  mock_quic_data.AddWrite(
      SYNCHRONOUS,
      ConstructClientRstPacket(write_packet_index++,
                               GetNthClientInitiatedBidirectionalStreamId(0),
                               quic::QUIC_STREAM_CANCELLED));
  mock_quic_data.AddSocketDataToFactory(&socket_factory_);
  socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
  CreateSession();
  request_.url = GURL("https://mail.example.org/");
  HttpNetworkTransaction trans_1(DEFAULT_PRIORITY, session_.get());
  RunTransaction(&trans_1);
  CheckWasHttpResponse(&trans_1);
  CheckResponsePort(&trans_1, 70);
  CheckResponseData(&trans_1, "0123456789");
  EXPECT_TRUE(trans_1.GetResponseInfo()->proxy_server.is_quic());
  request_.url = GURL("https://mail.example.org/2");
  HttpNetworkTransaction trans_2(DEFAULT_PRIORITY, session_.get());
  RunTransaction(&trans_2);
  CheckWasHttpResponse(&trans_2);
  CheckResponsePort(&trans_2, 70);
  CheckResponseData(&trans_2, "0123456");
  EXPECT_TRUE(trans_2.GetResponseInfo()->proxy_server.is_quic());
  NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(mock_quic_data.AllReadDataConsumed());
  EXPECT_TRUE(mock_quic_data.AllWriteDataConsumed());
}
TEST_P ( QuicNetworkTransactionTest , QuicProxyConnectReuseTransportSocket ) { session_params_ . enable_quic = true ; session_params_ . enable_quic_proxies_for_https_urls = true ; proxy_resolution_service_ = ConfiguredProxyResolutionService :: CreateFixedFromPacResult ( " " , TRAFFIC_ANNOTATION_FOR_TESTS ) ; MockQuicData mock_quic_data ( version_ ) ; int write_packet_index = 1 ; if ( VersionUsesHttp3 ( version_ . transport_version ) ) { mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructInitialSettingsPacket ( write_packet_index ++ ) ) ; mock_quic_data . AddWrite ( SYNCHRONOUS , client_maker_ -> MakePriorityPacket ( write_packet_index ++ , true , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , 0 , ConvertRequestPriorityToQuicPriority ( HttpProxyConnectJob :: kH2QuicTunnelPriority ) ) ) ; } mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructClientRequestHeadersPacket ( write_packet_index ++ , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , true , false , VersionUsesHttp3 ( version_ . transport_version ) ? MEDIUM : HttpProxyConnectJob :: kH2QuicTunnelPriority , ConnectRequestHeaders ( " " ) , 0 ) ) ; mock_quic_data . AddRead ( ASYNC , ConstructServerResponseHeadersPacket ( 1 , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , false , false , GetResponseHeaders ( " " ) ) ) ; quic :: QuicStreamOffset server_data_offset = 0 ; const char get_request_1 [ ] = " \r \n " " \r \n " " \r \n \r \n " ; std :: string header = ConstructDataHeader ( strlen ( get_request_1 ) ) ; if ( ! version_ . HasIetfQuicFrames ( ) ) { mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructClientAckAndDataPacket ( write_packet_index ++ , false , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , 1 , 1 , 1 , false , quiche :: QuicheStringPiece ( get_request_1 ) ) ) ; } else { mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructClientAckAndDataPacket ( write_packet_index ++ , false , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , 1 , 1 , 1 , false , { header + std :: string ( get_request_1 ) } ) ) ; } const char get_response_1 [ ] = " \r \n " " \r \n \r \n " ; std :: string header2 = ConstructDataHeader ( strlen ( get_response_1 ) ) ; mock_quic_data . AddRead ( ASYNC , ConstructServerDataPacket ( 2 , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , false , false , header2 + std :: string ( get_response_1 ) ) ) ; server_data_offset += strlen ( get_response_1 ) + header2 . length ( ) ; std :: string header3 = ConstructDataHeader ( 10 ) ; mock_quic_data . AddRead ( SYNCHRONOUS , ConstructServerDataPacket ( 3 , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , false , false , header3 + std :: string ( " " ) ) ) ; server_data_offset += 10 + header3 . length ( ) ; mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructClientAckPacket ( write_packet_index ++ , 3 , 2 , 1 ) ) ; const char get_request_2 [ ] = " \r \n " " \r \n " " \r \n \r \n " ; std :: string header4 = ConstructDataHeader ( strlen ( get_request_2 ) ) ; if ( version_ . HasIetfQuicFrames ( ) ) { mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructClientDataPacket ( write_packet_index ++ , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , false , false , { header4 + std :: string ( get_request_2 ) } ) ) ; } else { mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructClientDataPacket ( write_packet_index ++ , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , false , false , quiche :: QuicheStringPiece ( get_request_2 ) ) ) ; } const char get_response_2 [ ] = " \r \n " " \r \n \r \n " ; std :: string header5 = ConstructDataHeader ( strlen ( get_response_2 ) ) ; mock_quic_data . AddRead ( ASYNC , ConstructServerDataPacket ( 4 , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , false , false , header5 + std :: string ( get_response_2 ) ) ) ; server_data_offset += strlen ( get_response_2 ) + header5 . length ( ) ; std :: string header6 = ConstructDataHeader ( 7 ) ; mock_quic_data . AddRead ( SYNCHRONOUS , ConstructServerDataPacket ( 5 , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , false , false , header6 + std :: string ( " " ) ) ) ; server_data_offset += 7 + header6 . length ( ) ; mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructClientAckPacket ( write_packet_index ++ , 5 , 4 , 1 ) ) ; mock_quic_data . AddRead ( SYNCHRONOUS , ERR_IO_PENDING ) ; if ( VersionUsesHttp3 ( version_ . transport_version ) ) { mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructClientDataPacket ( write_packet_index ++ , GetQpackDecoderStreamId ( ) , true , false , StreamCancellationQpackDecoderInstruction ( 0 ) ) ) ; } mock_quic_data . AddWrite ( SYNCHRONOUS , ConstructClientRstPacket ( write_packet_index ++ , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , quic :: QUIC_STREAM_CANCELLED ) ) ; mock_quic_data . AddSocketDataToFactory ( & socket_factory_ ) ; socket_factory_ . AddSSLSocketDataProvider ( & ssl_data_ ) ; CreateSession ( ) ; request_ . url = GURL ( " " ) ; HttpNetworkTransaction trans_1 ( DEFAULT_PRIORITY , session_ . get ( ) ) ; RunTransaction ( & trans_1 ) ; CheckWasHttpResponse ( & trans_1 ) ; CheckResponsePort ( & trans_1 , 70 ) ; CheckResponseData ( & trans_1 , " " ) ; EXPECT_TRUE ( trans_1 . GetResponseInfo ( ) -> proxy_server . is_quic ( ) ) ; request_ . url = GURL ( " " ) ; HttpNetworkTransaction trans_2 ( DEFAULT_PRIORITY , session_ . get ( ) ) ; RunTransaction ( & trans_2 ) ; CheckWasHttpResponse ( & trans_2 ) ; CheckResponsePort ( & trans_2 , 70 ) ; CheckResponseData ( & trans_2 , " " ) ; EXPECT_TRUE ( trans_2 . GetResponseInfo ( ) -> proxy_server . is_quic ( ) ) ; NetworkChangeNotifier :: NotifyObserversOfIPAddressChangeForTests ( ) ; base :: RunLoop ( ) . RunUntilIdle ( ) ; EXPECT_TRUE ( mock_quic_data . AllReadDataConsumed ( ) ) ; EXPECT_TRUE ( mock_quic_data . AllWriteDataConsumed ( ) ) ; }
Make two HTTP/1.1 requests to the same host over a QUIC proxy tunnel and
check that the proxy socket is reused for the second request.
Make two HTTP / 1 . 1 requests to the same host over a QUIC proxy tunnel and check that the proxy socket is reused for the second request .
// No more data to read // Causes MockSSLClientSocket to disconnect, which causes the underlying QUIC // proxy socket to disconnect.