4747import jdk .internal .net .http .quic .QuicClient ;
4848import jdk .internal .net .http .quic .QuicConnectionId ;
4949import jdk .internal .net .http .quic .QuicConnectionImpl ;
50+ import jdk .internal .net .http .quic .QuicTransportParameters ;
5051import jdk .internal .net .http .quic .TerminationCause ;
5152import jdk .internal .net .quic .QuicTLSContext ;
5253import jdk .internal .net .quic .QuicVersion ;
5859import static jdk .internal .net .quic .QuicTransportErrors .NO_VIABLE_PATH ;
5960import static org .junit .jupiter .api .Assertions .assertEquals ;
6061import static org .junit .jupiter .api .Assertions .assertFalse ;
62+ import static org .junit .jupiter .api .Assertions .assertNotEquals ;
6163import static org .junit .jupiter .api .Assertions .assertNotNull ;
6264import static org .junit .jupiter .api .Assertions .assertTrue ;
6365
6466/*
6567 * @test
68+ * @bug 8373877
6669 * @summary verify that when a QUIC (client) connection receives a stateless reset
6770 * from the peer, then the connection is properly terminated
6871 * @library /test/lib /test/jdk/java/net/httpclient/lib
@@ -87,6 +90,10 @@ static void beforeAll() throws Exception {
8790 .availableVersions (new QuicVersion []{QuicVersion .QUIC_V1 })
8891 .sslContext (sslContext )
8992 .build ();
93+ // Use a longer max ack delay to inflate the draining time (3xPTO)
94+ final QuicTransportParameters transportParameters = new QuicTransportParameters ();
95+ transportParameters .setIntParameter (QuicTransportParameters .ParameterId .max_ack_delay ,
96+ (1 << 14 ) - 1 ); // 16 seconds, maximum allowed
9097 server .start ();
9198 System .out .println ("Server started at " + server .getAddress ());
9299 }
@@ -179,6 +186,9 @@ public void testClosingConnection() throws Exception {
179186 conn .close ();
180187 // verify connection is no longer open
181188 assertFalse (conn .underlyingQuicConnection ().isOpen (), "QUIC connection is still open" );
189+ // Check that the (closing) connection is still registered with the endpoint
190+ assertNotEquals (0 , conn .endpoint ().connectionCount (),
191+ "Expected the QUIC connection to be registered" );
182192 // now send a stateless reset from the server connection
183193 sendStatelessResetFrom (serverConn );
184194 // wait for the stateless reset to be processed
@@ -231,12 +241,19 @@ public void testDrainingConnection() throws Exception {
231241 .loggedAs ("intentionally closed by server to initiate draining state" +
232242 " on client connection" );
233243 serverConn .connectionTerminator ().terminate (tc );
244+ // send ping in case the connection_close message gets lost
245+ conn .underlyingQuicConnection ().requestSendPing ();
234246 // wait for client conn to terminate
235247 final TerminationCause clientTC = ((QuicConnectionImpl ) conn .underlyingQuicConnection ())
236248 .futureTerminationCause ().get ();
237249 // verify connection closed for the right reason
238250 assertEquals (NO_VIABLE_PATH .code (), clientTC .getCloseCode (),
239251 "unexpected termination cause" );
252+ // wait for a while to let the connection close completely
253+ Thread .sleep (10 );
254+ // Check that the (draining) connection is still registered with the endpoint
255+ assertNotEquals (0 , conn .endpoint ().connectionCount (),
256+ "Expected the QUIC connection to be registered" );
240257 // now send a stateless reset from the server connection
241258 sendStatelessResetFrom (serverConn );
242259 // wait for the stateless reset to be processed
0 commit comments