@@ -346,6 +346,36 @@ void testReleaseReusableAndClosedInCacheReturnedToPool() throws Exception {
346346 Mockito .eq (true ));
347347 }
348348
349+ /**
350+ * Same connection can only be released once.
351+ * Attempting to release it again will throw: IllegalStateException("Pool entry is not present in the set of leased entries")
352+ *
353+ * @see org.apache.hc.core5.pool.LaxConnPool.PerRoutePool#removeLeased(PoolEntry)
354+ * @see org.apache.hc.core5.pool.StrictConnPool#release(PoolEntry, boolean)
355+ */
356+ @ Test
357+ void testReleaseNonReusableNotInCacheReturnedToPool () throws Exception {
358+ final PoolEntry <String , HttpConnection > poolEntry = new PoolEntry <>(DEFAULT_ROUTE );
359+ poolEntry .assignConnection (connection );
360+ Mockito .when (connection .isOpen ()).thenReturn (false );
361+ final H2SharingConnPool .PerRoutePool <String , HttpConnection > routePool = h2SharingPool .getPerRoutePool (DEFAULT_ROUTE );
362+ routePool .track (poolEntry );
363+ routePool .track (poolEntry );
364+
365+ final AtomicReference <HttpConnection > connRef = new AtomicReference <>(connection );
366+ Mockito .doAnswer (invocation -> {
367+ final PoolEntry <String , HttpConnection > entry = invocation .getArgument (0 );
368+ if (!connRef .compareAndSet (entry .getConnection (), null )) {
369+ throw new IllegalStateException ("Pool entry is not present in the set of leased entries" );
370+ }
371+ return null ;
372+ }).when (connPool ).release (Mockito .eq (poolEntry ), Mockito .anyBoolean ());
373+
374+ h2SharingPool .release (poolEntry , false );
375+ // for reproduce https://issues.apache.org/jira/browse/HTTPCLIENT-2379
376+ Assertions .assertThrows (IllegalStateException .class , () -> h2SharingPool .release (poolEntry , false ));
377+ }
378+
349379 @ Test
350380 void testClose () throws Exception {
351381 h2SharingPool .close ();
0 commit comments