You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2026/10/08 18:24:35 UTC
(httpcomponents-core) branch master updated (f4764775f -> 07d959031)
This is an automated email from the ASF dual-hosted git repository.
ok2c pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
from f4764775f Removed testing framework unused and unmaintained since its contribution in 2016 (binary compatibility breakage)
new 711ef4f5c IOSession: added session initiation time
new 4ca20a40a Use Mockito JUnit extension to wire tests with Mockito mocks
new 07d959031 AbstractIOSessionPool: improved available sessions enumeration; added method to evict expired sessions
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
httpcore5-h2/pom.xml | 5 +
.../apache/hc/core5/http2/nio/pool/H2ConnPool.java | 13 +--
.../impl/nio/TestAbstractH2StreamMultiplexer.java | 7 +-
.../http2/impl/nio/TestClientH2StreamHandler.java | 15 +--
.../impl/nio/TestClientPushH2StreamHandler.java | 15 +--
.../http2/impl/nio/TestServerH2StreamHandler.java | 17 +---
.../http2/ssl/ConscryptClientTlsStrategyTest.java | 12 ---
.../apache/hc/core5/benchmark/HttpBenchmark.java | 5 +
.../hc/core5/testing/nio/LoggingIOSession.java | 5 +
httpcore5/pom.xml | 5 +
.../hc/core5/reactor/AbstractIOSessionPool.java | 65 +++++++++++--
.../org/apache/hc/core5/reactor/IOSession.java | 8 ++
.../org/apache/hc/core5/reactor/IOSessionImpl.java | 7 ++
.../hc/core5/reactor/InternalDataChannel.java | 5 +
.../apache/hc/core5/reactor/ssl/SSLIOSession.java | 5 +
.../http/impl/io/TestBHttpConnectionBase.java | 15 +--
.../impl/io/TestDefaultBHttpClientConnection.java | 15 +--
.../impl/io/TestDefaultBHttpServerConnection.java | 15 +--
.../hc/core5/http/impl/io/TestHttpService.java | 15 +--
...tAbstractHttp1StreamDuplexerCapacityWindow.java | 15 +--
.../io/support/ClassicResponseBuilderTest.java | 15 +--
.../http/nio/ssl/BasicClientTlsStrategyTest.java | 15 +--
.../http/nio/ssl/BasicServerTlsStrategyTest.java | 15 +--
.../core5/reactor/TestAbstractIOSessionPool.java | 102 ++++++++++++++++-----
.../reactor/TestSocksProxyProtocolHandler.java | 11 ++-
pom.xml | 8 +-
26 files changed, 233 insertions(+), 197 deletions(-)
(httpcomponents-core) 01/03: IOSession: added session initiation time
Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ok2c pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
commit 711ef4f5c3837c1a6833d0312f180cfa08ffcf2f
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Thu Oct 8 09:37:42 2026 +0200
IOSession: added session initiation time
---
.../java/org/apache/hc/core5/benchmark/HttpBenchmark.java | 5 +++++
.../org/apache/hc/core5/testing/nio/LoggingIOSession.java | 5 +++++
.../src/main/java/org/apache/hc/core5/reactor/IOSession.java | 8 ++++++++
.../main/java/org/apache/hc/core5/reactor/IOSessionImpl.java | 7 +++++++
.../java/org/apache/hc/core5/reactor/InternalDataChannel.java | 5 +++++
.../java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java | 5 +++++
.../hc/core5/reactor/TestSocksProxyProtocolHandler.java | 11 +++++++++--
7 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/benchmark/HttpBenchmark.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/benchmark/HttpBenchmark.java
index fd110531a..d8d5e17aa 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/benchmark/HttpBenchmark.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/benchmark/HttpBenchmark.java
@@ -272,6 +272,11 @@ public void setSocketTimeout(final Timeout timeout) {
ioSession.setSocketTimeout(timeout);
}
+ @Override
+ public long getInitiationTime() {
+ return ioSession.getInitiationTime();
+ }
+
@Override
public long getLastReadTime() {
return ioSession.getLastReadTime();
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
index fbb53a4d9..0d7125e51 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
@@ -261,6 +261,11 @@ private void logData(final ByteBuffer data, final String prefix) throws IOExcept
}
}
+ @Override
+ public long getInitiationTime() {
+ return this.session.getInitiationTime();
+ }
+
@Override
public void updateReadTime() {
this.session.updateReadTime();
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
index 4c2421cc4..6171571f4 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
@@ -207,6 +207,14 @@ enum Status {
@Override
void setSocketTimeout(Timeout timeout);
+ /**
+ * Returns the absolute millisecond timestamp of the session initiation.
+ * @since 5.5
+ */
+ default long getInitiationTime() {
+ return -1;
+ }
+
/**
* Returns the absolute millisecond timestamp of the last read event.
*
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
index d1421dc8c..76217bcee 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
@@ -72,6 +72,7 @@ class IOSessionImpl implements IOSession {
private final AtomicReference<IOSession.Status> status;
private volatile Timeout socketTimeout;
+ private volatile long initiationTime;
private volatile long lastReadTime;
private volatile long lastWriteTime;
private volatile long lastEventTime;
@@ -89,6 +90,7 @@ public IOSessionImpl(final String type, final SelectionKey key, final SocketChan
this.handlerRef = new AtomicReference<>();
this.status = new AtomicReference<>(Status.ACTIVE);
final long currentTimeMillis = System.currentTimeMillis();
+ this.initiationTime = currentTimeMillis;
this.lastReadTime = currentTimeMillis;
this.lastWriteTime = currentTimeMillis;
this.lastEventTime = currentTimeMillis;
@@ -253,6 +255,11 @@ public int write(final ByteBuffer src) throws IOException {
return totalBytesWritten;
}
+ @Override
+ public long getInitiationTime() {
+ return initiationTime;
+ }
+
@Override
public void updateReadTime() {
lastReadTime = System.currentTimeMillis();
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
index 96b661bbf..2e39ecc93 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
@@ -360,6 +360,11 @@ public int write(final ByteBuffer src) throws IOException {
return currentSession.write(src);
}
+ @Override
+ public long getInitiationTime() {
+ return ioSession.getInitiationTime();
+ }
+
@Override
public void updateReadTime() {
ioSession.updateReadTime();
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
index 5800cb671..98a345961 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
@@ -854,6 +854,11 @@ public void setSocketTimeout(final Timeout timeout) {
}
}
+ @Override
+ public long getInitiationTime() {
+ return this.session.getInitiationTime();
+ }
+
@Override
public void updateReadTime() {
this.session.updateReadTime();
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestSocksProxyProtocolHandler.java b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestSocksProxyProtocolHandler.java
index 9b6b1a182..67e362078 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestSocksProxyProtocolHandler.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestSocksProxyProtocolHandler.java
@@ -125,6 +125,7 @@ private static final class TestIOSession implements IOSession {
private volatile int eventMask;
private volatile IOEventHandler handler;
private volatile Timeout socketTimeout;
+ private volatile long initiationTime;
private volatile long lastReadTime;
private volatile long lastWriteTime;
private volatile long lastEventTime;
@@ -137,8 +138,9 @@ private static final class TestIOSession implements IOSession {
this.eventMask = 0;
this.socketTimeout = Timeout.DISABLED;
this.lastReadTime = System.currentTimeMillis();
- this.lastWriteTime = this.lastReadTime;
- this.lastEventTime = this.lastReadTime;
+ this.lastReadTime = this.initiationTime;
+ this.lastWriteTime = this.initiationTime;
+ this.lastEventTime = this.initiationTime;
}
CloseMode getLastCloseMode() {
@@ -223,6 +225,11 @@ public void setSocketTimeout(final Timeout timeout) {
this.lastEventTime = System.currentTimeMillis();
}
+ @Override
+ public long getInitiationTime() {
+ return this.initiationTime;
+ }
+
@Override
public long getLastReadTime() {
return this.lastReadTime;
(httpcomponents-core) 02/03: Use Mockito JUnit extension to wire tests with Mockito mocks
Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ok2c pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
commit 4ca20a40ab2480136fbc62a4ce19e04ea0606604
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Thu Oct 8 14:52:33 2026 +0200
Use Mockito JUnit extension to wire tests with Mockito mocks
---
httpcore5-h2/pom.xml | 5 +++++
.../impl/nio/TestAbstractH2StreamMultiplexer.java | 7 ++++---
.../http2/impl/nio/TestClientH2StreamHandler.java | 15 +++------------
.../impl/nio/TestClientPushH2StreamHandler.java | 15 +++------------
.../http2/impl/nio/TestServerH2StreamHandler.java | 17 +++--------------
.../http2/ssl/ConscryptClientTlsStrategyTest.java | 12 ------------
httpcore5/pom.xml | 5 +++++
.../core5/http/impl/io/TestBHttpConnectionBase.java | 15 +++------------
.../impl/io/TestDefaultBHttpClientConnection.java | 15 +++------------
.../impl/io/TestDefaultBHttpServerConnection.java | 15 +++------------
.../hc/core5/http/impl/io/TestHttpService.java | 15 +++------------
...estAbstractHttp1StreamDuplexerCapacityWindow.java | 15 +++------------
.../http/io/support/ClassicResponseBuilderTest.java | 15 +++------------
.../http/nio/ssl/BasicClientTlsStrategyTest.java | 15 +++------------
.../http/nio/ssl/BasicServerTlsStrategyTest.java | 15 +++------------
.../hc/core5/reactor/TestAbstractIOSessionPool.java | 20 +++-----------------
pom.xml | 8 +++++---
17 files changed, 55 insertions(+), 169 deletions(-)
diff --git a/httpcore5-h2/pom.xml b/httpcore5-h2/pom.xml
index 2aaead9b2..068694215 100644
--- a/httpcore5-h2/pom.xml
+++ b/httpcore5-h2/pom.xml
@@ -58,6 +58,11 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-junit-jupiter</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java
index d3eaf8d70..5ec17cd97 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java
@@ -76,18 +76,20 @@
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestAbstractH2StreamMultiplexer {
private static final FrameFactory FRAME_FACTORY = DefaultFrameFactory.INSTANCE;
- @Mock
+ @Mock(strictness = Mock.Strictness.LENIENT)
ProtocolIOSession protocolIOSession;
@Mock
Lock lock;
@@ -104,7 +106,6 @@ class TestAbstractH2StreamMultiplexer {
@BeforeEach
void prepareMocks() {
- MockitoAnnotations.openMocks(this);
Mockito.when(protocolIOSession.getLock()).thenReturn(lock);
}
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestClientH2StreamHandler.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestClientH2StreamHandler.java
index e6a944b63..17ef4fb80 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestClientH2StreamHandler.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestClientH2StreamHandler.java
@@ -43,14 +43,15 @@
import org.apache.hc.core5.http.nio.HandlerFactory;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestClientH2StreamHandler {
@Mock
@@ -62,13 +63,10 @@ class TestClientH2StreamHandler {
@Mock
HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
- AutoCloseable closeable;
-
ClientH2StreamHandler handler;
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
handler = new ClientH2StreamHandler(
channel, httpProcessor,
new BasicHttpConnectionMetrics(
@@ -78,13 +76,6 @@ void prepareMocks() {
HttpCoreContext.create());
}
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
- }
-
@Test
void defaults() {
Assertions.assertNotNull(handler.getPushHandlerFactory());
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestClientPushH2StreamHandler.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestClientPushH2StreamHandler.java
index 02516e5d8..aa0dc947c 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestClientPushH2StreamHandler.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestClientPushH2StreamHandler.java
@@ -41,14 +41,15 @@
import org.apache.hc.core5.http.protocol.HttpProcessor;
import org.apache.hc.core5.http2.H2Error;
import org.apache.hc.core5.http2.H2StreamResetException;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestClientPushH2StreamHandler {
@Mock
@@ -60,13 +61,10 @@ class TestClientPushH2StreamHandler {
@Mock
HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
- AutoCloseable closeable;
-
ClientPushH2StreamHandler handler;
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
handler = new ClientPushH2StreamHandler(
channel, httpProcessor,
new BasicHttpConnectionMetrics(
@@ -75,13 +73,6 @@ void prepareMocks() {
HttpCoreContext.create());
}
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
- }
-
@Test
void consumePromiseRefusedWhenFactoryReturnsNull() throws Exception {
final H2StreamResetException ex = Assertions.assertThrows(H2StreamResetException.class, () ->
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestServerH2StreamHandler.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestServerH2StreamHandler.java
index 42b720246..c3aea6f56 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestServerH2StreamHandler.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestServerH2StreamHandler.java
@@ -42,15 +42,16 @@
import org.apache.hc.core5.http.protocol.HttpProcessor;
import org.apache.hc.core5.http2.H2Error;
import org.apache.hc.core5.http2.H2StreamResetException;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestServerH2StreamHandler {
@Mock
@@ -62,13 +63,10 @@ class TestServerH2StreamHandler {
@Mock
HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
- AutoCloseable closeable;
-
ServerH2StreamHandler handler;
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
handler = new ServerH2StreamHandler(
channel,
httpProcessor,
@@ -78,13 +76,6 @@ void prepareMocks() {
HttpCoreContext.create());
}
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
- }
-
@Test
void defaults() {
Assertions.assertNull(handler.getPushHandlerFactory());
@@ -179,8 +170,6 @@ void contentLengthInvalid() throws Exception {
@Test
void contentLengthInvalidNoBody() throws Exception {
- Mockito.when(exchangeHandlerFactory.create(ArgumentMatchers.any(), ArgumentMatchers.any()))
- .thenReturn(exchangeHandler);
final List<Header> requestHeaders = Arrays.asList(
new BasicHeader(":method", "POST"),
new BasicHeader(":scheme", "https"),
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/ssl/ConscryptClientTlsStrategyTest.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/ssl/ConscryptClientTlsStrategyTest.java
index 1a09d017c..2f186d78d 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/ssl/ConscryptClientTlsStrategyTest.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/ssl/ConscryptClientTlsStrategyTest.java
@@ -30,29 +30,17 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
class ConscryptClientTlsStrategyTest {
@Mock
SSLSessionVerifier sslSessionVerifier;
- AutoCloseable closeable;
-
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
- }
-
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
}
@Test
diff --git a/httpcore5/pom.xml b/httpcore5/pom.xml
index c5293a9cd..249a598eb 100644
--- a/httpcore5/pom.xml
+++ b/httpcore5/pom.xml
@@ -55,6 +55,11 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-junit-jupiter</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestBHttpConnectionBase.java b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestBHttpConnectionBase.java
index dc7f57399..85150aa4e 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestBHttpConnectionBase.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestBHttpConnectionBase.java
@@ -42,37 +42,28 @@
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.util.Timeout;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestBHttpConnectionBase {
@Mock
Socket socket;
- AutoCloseable closeable;
-
BHttpConnectionBase conn;
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
conn = new BHttpConnectionBase(Http1Config.DEFAULT, null, null);
}
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
- }
-
@Test
void testBasics() {
Assertions.assertFalse(conn.isOpen());
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpClientConnection.java b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpClientConnection.java
index b0dd3b5e1..f967b7f91 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpClientConnection.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpClientConnection.java
@@ -44,26 +44,24 @@
import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestDefaultBHttpClientConnection {
@Mock
Socket socket;
- AutoCloseable closeable;
-
DefaultBHttpClientConnection conn;
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
conn = new DefaultBHttpClientConnection(Http1Config.DEFAULT,
null, null,
DefaultContentLengthStrategy.INSTANCE,
@@ -72,13 +70,6 @@ void prepareMocks() {
DefaultHttpResponseParserFactory.INSTANCE);
}
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
- }
-
@Test
void testBasics() {
Assertions.assertFalse(conn.isOpen());
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpServerConnection.java b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpServerConnection.java
index dc1f62b77..7080c8bc0 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpServerConnection.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpServerConnection.java
@@ -44,26 +44,24 @@
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.util.Timeout;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestDefaultBHttpServerConnection {
@Mock
Socket socket;
- AutoCloseable closeable;
-
DefaultBHttpServerConnection conn;
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
conn = new DefaultBHttpServerConnection("http", Http1Config.DEFAULT,
null, null,
DefaultContentLengthStrategy.INSTANCE,
@@ -72,13 +70,6 @@ void prepareMocks() {
DefaultHttpResponseWriterFactory.INSTANCE);
}
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
- }
-
@Test
void testBasics() {
Assertions.assertFalse(conn.isOpen());
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestHttpService.java b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestHttpService.java
index 948ae4e9c..c910a0699 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestHttpService.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestHttpService.java
@@ -49,17 +49,18 @@
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestHttpService {
@Mock
@@ -77,13 +78,10 @@ class TestHttpService {
@Mock
HttpServerConnection conn;
- AutoCloseable closeable;
-
private HttpService httpservice;
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
httpservice = new HttpService(
httprocessor,
handlerResolver,
@@ -91,13 +89,6 @@ void prepareMocks() {
responseFactory);
}
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
- }
-
@Test
void testInvalidInitialization() {
Assertions.assertThrows(NullPointerException.class, () ->
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestAbstractHttp1StreamDuplexerCapacityWindow.java b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestAbstractHttp1StreamDuplexerCapacityWindow.java
index a152aaa79..f17f3db66 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestAbstractHttp1StreamDuplexerCapacityWindow.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestAbstractHttp1StreamDuplexerCapacityWindow.java
@@ -32,32 +32,23 @@
import org.apache.hc.core5.http.impl.nio.AbstractHttp1StreamDuplexer.CapacityWindow;
import org.apache.hc.core5.reactor.IOSession;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestAbstractHttp1StreamDuplexerCapacityWindow {
@Mock
IOSession ioSession;
- AutoCloseable closeable;
-
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
- }
-
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
}
@Test
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/io/support/ClassicResponseBuilderTest.java b/httpcore5/src/test/java/org/apache/hc/core5/http/io/support/ClassicResponseBuilderTest.java
index a97993923..e29b67465 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/io/support/ClassicResponseBuilderTest.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/io/support/ClassicResponseBuilderTest.java
@@ -43,28 +43,26 @@
import org.apache.hc.core5.http.impl.io.DefaultHttpResponseWriterFactory;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicHeader;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class ClassicResponseBuilderTest {
@Mock
Socket socket;
- AutoCloseable closeable;
-
DefaultBHttpServerConnection conn;
ByteArrayOutputStream outStream;
@BeforeEach
void prepareMocks() throws IOException {
- closeable = MockitoAnnotations.openMocks(this);
conn = new DefaultBHttpServerConnection("http", Http1Config.DEFAULT,
null, null,
DefaultContentLengthStrategy.INSTANCE,
@@ -77,13 +75,6 @@ void prepareMocks() throws IOException {
Assertions.assertEquals(0, conn.getEndpointDetails().getResponseCount());
}
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
- }
-
@Test
void create() throws IOException, HttpException {
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/nio/ssl/BasicClientTlsStrategyTest.java b/httpcore5/src/test/java/org/apache/hc/core5/http/nio/ssl/BasicClientTlsStrategyTest.java
index 7013d8d15..c789672d5 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/nio/ssl/BasicClientTlsStrategyTest.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/nio/ssl/BasicClientTlsStrategyTest.java
@@ -30,29 +30,20 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class BasicClientTlsStrategyTest {
@Mock
SSLSessionVerifier sslSessionVerifier;
- AutoCloseable closeable;
-
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
- }
-
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
}
@Test
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/nio/ssl/BasicServerTlsStrategyTest.java b/httpcore5/src/test/java/org/apache/hc/core5/http/nio/ssl/BasicServerTlsStrategyTest.java
index bfb35afcf..4a400dc14 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/nio/ssl/BasicServerTlsStrategyTest.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/nio/ssl/BasicServerTlsStrategyTest.java
@@ -30,29 +30,20 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class BasicServerTlsStrategyTest {
@Mock
SSLSessionVerifier sslSessionVerifier;
- AutoCloseable closeable;
-
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
- }
-
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
}
@Test
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestAbstractIOSessionPool.java b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestAbstractIOSessionPool.java
index a61e62cc8..f877da817 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestAbstractIOSessionPool.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestAbstractIOSessionPool.java
@@ -41,18 +41,19 @@
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+@ExtendWith(MockitoExtension.class)
class TestAbstractIOSessionPool {
@Mock
@@ -68,16 +69,12 @@ class TestAbstractIOSessionPool {
@Captor
ArgumentCaptor<FutureCallback<IOSession>> connectCallbackCaptor;
- AutoCloseable closeable;
-
Clock clock;
AbstractIOSessionPool<String> impl;
@BeforeEach
void prepareMocks() {
- closeable = MockitoAnnotations.openMocks(this);
-
clock = Clock.fixed(
LocalDateTime.of(2026, Month.SEPTEMBER, 30, 13, 30).toInstant(ZoneOffset.UTC),
ZoneId.of("UTC"));
@@ -87,13 +84,6 @@ void prepareMocks() {
.useConstructor(clock));
}
- @AfterEach
- void releaseMocks() throws Exception {
- if (closeable != null) {
- closeable.close();
- }
- }
-
@Test
void testGetSessions() throws Exception {
@@ -265,8 +255,6 @@ void testGetSessionReconnectIfClosed() {
@Test
void testGetSessionConnectUnknownHost() {
-
- Mockito.when(connectFuture.isDone()).thenReturn(true);
Mockito.when(impl.connectSession(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(),
@@ -298,8 +286,6 @@ void testCloseIdleOnly() {
Mockito.doReturn(Instant.now(clock).minusSeconds(1).toEpochMilli())
.when(ioSession1).getLastEventTime();
Mockito.doReturn(false).when(impl).isIdle(ioSession2);
- Mockito.doReturn(Instant.now(clock).minusSeconds(2).toEpochMilli())
- .when(ioSession2).getLastEventTime();
impl.closeIdle(null);
diff --git a/pom.xml b/pom.xml
index 6340fc527..c96fe1eb0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -140,7 +140,11 @@
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
- <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-junit-jupiter</artifactId>
+ <version>${mockito.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
@@ -176,13 +180,11 @@
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh.version}</version>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
- <scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
(httpcomponents-core) 03/03: AbstractIOSessionPool: improved available sessions enumeration; added method to evict expired sessions
Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ok2c pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
commit 07d95903168a5fb06e20321ff927204a8cfedda6
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Wed Oct 7 13:06:24 2026 +0200
AbstractIOSessionPool: improved available sessions enumeration; added method to evict expired sessions
---
.../apache/hc/core5/http2/nio/pool/H2ConnPool.java | 13 +---
.../hc/core5/reactor/AbstractIOSessionPool.java | 65 ++++++++++++++---
.../core5/reactor/TestAbstractIOSessionPool.java | 82 ++++++++++++++++++++--
3 files changed, 134 insertions(+), 26 deletions(-)
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/pool/H2ConnPool.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/pool/H2ConnPool.java
index fd6362ffe..36e2247a8 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/pool/H2ConnPool.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/pool/H2ConnPool.java
@@ -157,7 +157,7 @@ protected void validateSession(
final TimeValue inactivityTime = validateAfterInactivity;
if (TimeValue.isNonNegative(inactivityTime)) {
// Last tolerable point of inactivity
- final long deadline = inactivityDeadline(inactivityTime);
+ final long deadline = clockMillis() - inactivityTime.toMilliseconds();
if (ioSession.getLastEventTime() <= deadline) {
ioSession.enqueue(new StaleCheckCommand(callback::execute), Command.Priority.NORMAL);
return;
@@ -178,15 +178,4 @@ protected boolean isIdle(final IOSession session) {
return false;
}
- /**
- * Evict expired (closed) sessions.
- * @since 5.5
- */
- public void evictExpired() {
- // This will cause closed sessions to get removed from the pool
- enumAvailable(e -> {
- // no op
- });
- }
-
}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractIOSessionPool.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractIOSessionPool.java
index e3acd9d52..00912a8a8 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractIOSessionPool.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractIOSessionPool.java
@@ -29,6 +29,8 @@
import java.time.Clock;
import java.util.ArrayDeque;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -36,6 +38,7 @@
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.BiConsumer;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
@@ -88,6 +91,13 @@ protected abstract void closeSession(
IOSession ioSession,
CloseMode closeMode);
+ /**
+ * @since 5.5
+ */
+ protected long clockMillis() {
+ return clock.millis();
+ }
+
/**
* Tests if the given session is idle. This method is expected to be communication protocol
* aware.
@@ -98,6 +108,16 @@ protected boolean isIdle(final IOSession session) {
return false;
}
+ /**
+ * Tests if the given session has expired. This method is expected to be communication protocol
+ * aware.
+ *
+ * @since 5.5
+ */
+ protected boolean isExpired(final T endpoint, final IOSession session) {
+ return false;
+ }
+
@Override
public final void close(final CloseMode closeMode) {
if (closed.compareAndSet(false, true)) {
@@ -265,13 +285,31 @@ public void cancelled() {
}
}
+ /**
+ * @deprecated Use {@link #enumAvailable(BiConsumer)}.
+ */
+ @Deprecated
public final void enumAvailable(final Callback<IOSession> callback) {
- for (final PoolEntry poolEntry: sessionPool.values()) {
+ Args.notNull(callback, "Callback");
+ enumAvailable((endpoint, session) -> callback.execute(session));
+ }
+
+ /**
+ * @since 5.5
+ */
+ public final void enumAvailable(final BiConsumer<T, IOSession> consumer) {
+ Args.notNull(consumer, "consumer");
+ for (final Iterator<Map.Entry<T, PoolEntry>> it = sessionPool.entrySet().iterator(); it.hasNext(); ) {
+ final Map.Entry<T, PoolEntry> entry = it.next();
+ final PoolEntry poolEntry = entry.getValue();
if (poolEntry.session != null) {
poolEntry.lock.lock();
try {
if (poolEntry.session != null) {
- callback.execute(poolEntry.session);
+ if (poolEntry.session.isOpen()) {
+ final T endpoint = entry.getKey();
+ consumer.accept(endpoint, poolEntry.session);
+ }
if (!poolEntry.session.isOpen()) {
poolEntry.session = null;
}
@@ -283,25 +321,32 @@ public final void enumAvailable(final Callback<IOSession> callback) {
}
}
- protected long inactivityDeadline(final TimeValue inactivityTime) {
- return this.clock.millis() - (TimeValue.isPositive(inactivityTime) ? inactivityTime.toMilliseconds() : 0);
- }
-
/**
* Close sessions idle longer than the given period of inactivity. This method will also
* Evict closed sessions.
*/
public final void closeIdle(final TimeValue inactivityTime) {
- // Last tolerable point of inactivity
- // Millisecond precision is good enough
- final long deadline = inactivityDeadline(inactivityTime);
- enumAvailable(session -> {
+ final long deadline = clockMillis() - (TimeValue.isPositive(inactivityTime) ? inactivityTime.toMilliseconds() : 0);
+ enumAvailable((endpoint, session) -> {
if (isIdle(session) && session.getLastEventTime() <= deadline) {
closeSession(session, CloseMode.GRACEFUL);
}
});
}
+ /**
+ * Evict expired (closed) sessions.
+ * @since 5.5
+ */
+ public final void evictExpired() {
+ // This method also causes closed sessions to get removed from the pool
+ enumAvailable((endpoint, session) -> {
+ if (isIdle(session) && isExpired(endpoint, session)) {
+ closeSession(session, CloseMode.GRACEFUL);
+ }
+ });
+ }
+
public final Set<T> getRoutes() {
return new HashSet<>(sessionPool.keySet());
}
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestAbstractIOSessionPool.java b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestAbstractIOSessionPool.java
index f877da817..01851a637 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestAbstractIOSessionPool.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestAbstractIOSessionPool.java
@@ -26,7 +26,6 @@
*/
package org.apache.hc.core5.reactor;
-
import java.net.UnknownHostException;
import java.time.Clock;
import java.time.Instant;
@@ -34,6 +33,10 @@
import java.time.Month;
import java.time.ZoneId;
import java.time.ZoneOffset;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.concurrent.Future;
import org.apache.hc.core5.concurrent.FutureCallback;
@@ -211,9 +214,32 @@ void testEnumSessions() {
Assertions.assertNotNull(entry2);
entry2.session = ioSession2;
- impl.enumAvailable(ioSession -> ioSession.close(CloseMode.GRACEFUL));
- Mockito.verify(ioSession1).close(CloseMode.GRACEFUL);
- Mockito.verify(ioSession2).close(CloseMode.GRACEFUL);
+ Mockito.doReturn(true).when(ioSession1).isOpen();
+ Mockito.doReturn(true).when(ioSession2).isOpen();
+
+ final Map<String, IOSession> sessionMap = new LinkedHashMap<>();
+ impl.enumAvailable(sessionMap::put);
+
+ Assertions.assertEquals(sessionMap.keySet(), new HashSet<>(Arrays.asList("host1", "host2")));
+ }
+
+ @Test
+ void testEnumSessionsWithClosedSession() {
+ final AbstractIOSessionPool.PoolEntry entry1 = impl.getPoolEntry("host1");
+ Assertions.assertNotNull(entry1);
+ entry1.session = ioSession1;
+
+ final AbstractIOSessionPool.PoolEntry entry2 = impl.getPoolEntry("host2");
+ Assertions.assertNotNull(entry2);
+ entry2.session = ioSession2;
+
+ Mockito.doReturn(false).when(ioSession1).isOpen();
+ Mockito.doReturn(true).when(ioSession2).isOpen();
+
+ final Map<String, IOSession> sessionMap = new LinkedHashMap<>();
+ impl.enumAvailable(sessionMap::put);
+
+ Assertions.assertEquals(sessionMap.keySet(), new HashSet<>(Arrays.asList("host2")));
}
@Test
@@ -282,9 +308,11 @@ void testCloseIdleOnly() {
Assertions.assertNotNull(entry2);
entry2.session = ioSession2;
+ Mockito.doReturn(true).when(ioSession1).isOpen();
Mockito.doReturn(true).when(impl).isIdle(ioSession1);
Mockito.doReturn(Instant.now(clock).minusSeconds(1).toEpochMilli())
.when(ioSession1).getLastEventTime();
+ Mockito.doReturn(true).when(ioSession2).isOpen();
Mockito.doReturn(false).when(impl).isIdle(ioSession2);
impl.closeIdle(null);
@@ -303,9 +331,11 @@ void testCloseIdlePastDeadline() {
Assertions.assertNotNull(entry2);
entry2.session = ioSession2;
+ Mockito.doReturn(true).when(ioSession1).isOpen();
Mockito.doReturn(true).when(impl).isIdle(ioSession1);
Mockito.doReturn(Instant.now(clock).minusSeconds(1).toEpochMilli())
.when(ioSession1).getLastEventTime();
+ Mockito.doReturn(true).when(ioSession2).isOpen();
Mockito.doReturn(true).when(impl).isIdle(ioSession2);
Mockito.doReturn(Instant.now(clock).toEpochMilli())
.when(ioSession2).getLastEventTime();
@@ -316,4 +346,48 @@ void testCloseIdlePastDeadline() {
Mockito.verify(impl, Mockito.never()).closeSession(Mockito.same(ioSession2), Mockito.any());
}
+ @Test
+ void testEvictExpired() {
+ final AbstractIOSessionPool.PoolEntry entry1 = impl.getPoolEntry("host1");
+ Assertions.assertNotNull(entry1);
+ entry1.session = ioSession1;
+
+ final AbstractIOSessionPool.PoolEntry entry2 = impl.getPoolEntry("host2");
+ Assertions.assertNotNull(entry2);
+ entry2.session = ioSession2;
+
+ Mockito.doReturn(true).when(ioSession1).isOpen();
+ Mockito.doReturn(true).when(impl).isIdle(ioSession1);
+ Mockito.doReturn(true).when(impl).isExpired("host1", ioSession1);
+ Mockito.doReturn(true).when(ioSession2).isOpen();
+ Mockito.doReturn(true).when(impl).isIdle(ioSession2);
+ Mockito.doReturn(false).when(impl).isExpired("host2", ioSession2);
+
+ impl.evictExpired();
+
+ Mockito.verify(impl).closeSession(ioSession1, CloseMode.GRACEFUL);
+ Mockito.verify(impl, Mockito.never()).closeSession(Mockito.same(ioSession2), Mockito.any());
+ }
+
+ @Test
+ void testEvictExpiredNonIdleDoNotGetEvicted() {
+ final AbstractIOSessionPool.PoolEntry entry1 = impl.getPoolEntry("host1");
+ Assertions.assertNotNull(entry1);
+ entry1.session = ioSession1;
+
+ final AbstractIOSessionPool.PoolEntry entry2 = impl.getPoolEntry("host2");
+ Assertions.assertNotNull(entry2);
+ entry2.session = ioSession2;
+
+ Mockito.doReturn(true).when(ioSession1).isOpen();
+ Mockito.doReturn(false).when(impl).isIdle(ioSession1);
+ Mockito.doReturn(true).when(ioSession2).isOpen();
+ Mockito.doReturn(false).when(impl).isIdle(ioSession2);
+
+ impl.evictExpired();
+
+ Mockito.verify(impl, Mockito.never()).closeSession(Mockito.same(ioSession1), Mockito.any());
+ Mockito.verify(impl, Mockito.never()).closeSession(Mockito.same(ioSession2), Mockito.any());
+ }
+
}