|
21 | 21 | import static org.hamcrest.Matchers.is;
|
22 | 22 | import static org.junit.jupiter.api.Assertions.assertEquals;
|
23 | 23 | import static org.junit.jupiter.api.Assertions.assertFalse;
|
| 24 | +import static org.junit.jupiter.api.Assertions.assertInstanceOf; |
| 25 | +import static org.junit.jupiter.api.Assertions.assertNotNull; |
| 26 | +import static org.junit.jupiter.api.Assertions.assertNull; |
24 | 27 | import static org.junit.jupiter.api.Assertions.assertTrue;
|
25 | 28 | import static org.mockito.BDDMockito.given;
|
26 | 29 | import static org.mockito.BDDMockito.then;
|
|
29 | 32 | import static org.mockito.Mockito.times;
|
30 | 33 | import static org.neo4j.driver.internal.async.connection.ChannelAttributes.authContext;
|
31 | 34 | import static org.neo4j.driver.internal.async.connection.ChannelAttributes.setAuthContext;
|
| 35 | +import static org.neo4j.driver.internal.async.connection.ChannelAttributes.setConnectionReadTimeout; |
32 | 36 | import static org.neo4j.driver.internal.async.connection.ChannelAttributes.setCreationTimestamp;
|
33 | 37 | import static org.neo4j.driver.internal.async.connection.ChannelAttributes.setLastUsedTimestamp;
|
34 | 38 | import static org.neo4j.driver.internal.async.connection.ChannelAttributes.setMessageDispatcher;
|
|
54 | 58 | import org.junit.jupiter.params.provider.MethodSource;
|
55 | 59 | import org.neo4j.driver.AuthTokenManager;
|
56 | 60 | import org.neo4j.driver.AuthTokens;
|
| 61 | +import org.neo4j.driver.internal.async.inbound.ConnectionReadTimeoutHandler; |
57 | 62 | import org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher;
|
58 | 63 | import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
|
59 | 64 | import org.neo4j.driver.internal.messaging.request.ResetMessage;
|
@@ -248,6 +253,65 @@ void shouldKeepIdleConnectionWhenPingSucceeds() {
|
248 | 253 | testPing(true);
|
249 | 254 | }
|
250 | 255 |
|
| 256 | + @Test |
| 257 | + void shouldHandlePingWithConnectionReceiveTimeout() { |
| 258 | + var idleTimeBeforeConnectionTest = 1000; |
| 259 | + var connectionReadTimeout = 60L; |
| 260 | + var settings = new PoolSettings( |
| 261 | + DEFAULT_MAX_CONNECTION_POOL_SIZE, |
| 262 | + DEFAULT_CONNECTION_ACQUISITION_TIMEOUT, |
| 263 | + NOT_CONFIGURED, |
| 264 | + idleTimeBeforeConnectionTest); |
| 265 | + var clock = Clock.systemUTC(); |
| 266 | + var healthChecker = newHealthChecker(settings, clock); |
| 267 | + |
| 268 | + setCreationTimestamp(channel, clock.millis()); |
| 269 | + setConnectionReadTimeout(channel, connectionReadTimeout); |
| 270 | + setLastUsedTimestamp(channel, clock.millis() - idleTimeBeforeConnectionTest * 2); |
| 271 | + |
| 272 | + var healthy = healthChecker.isHealthy(channel); |
| 273 | + channel.runPendingTasks(); |
| 274 | + |
| 275 | + var firstElementOnPipeline = channel.pipeline().first(); |
| 276 | + assertInstanceOf(ConnectionReadTimeoutHandler.class, firstElementOnPipeline); |
| 277 | + assertNotNull(dispatcher.getBeforeLastHandlerHook()); |
| 278 | + var readTimeoutHandler = (ConnectionReadTimeoutHandler) firstElementOnPipeline; |
| 279 | + assertEquals(connectionReadTimeout * 1000L, readTimeoutHandler.getReaderIdleTimeInMillis()); |
| 280 | + assertEquals(ResetMessage.RESET, single(channel.outboundMessages())); |
| 281 | + assertFalse(healthy.isDone()); |
| 282 | + |
| 283 | + dispatcher.handleSuccessMessage(Collections.emptyMap()); |
| 284 | + assertThat(await(healthy), is(true)); |
| 285 | + assertNull(channel.pipeline().first()); |
| 286 | + assertNull(dispatcher.getBeforeLastHandlerHook()); |
| 287 | + } |
| 288 | + |
| 289 | + @Test |
| 290 | + void shouldHandlePingWithoutConnectionReceiveTimeout() { |
| 291 | + var idleTimeBeforeConnectionTest = 1000; |
| 292 | + var settings = new PoolSettings( |
| 293 | + DEFAULT_MAX_CONNECTION_POOL_SIZE, |
| 294 | + DEFAULT_CONNECTION_ACQUISITION_TIMEOUT, |
| 295 | + NOT_CONFIGURED, |
| 296 | + idleTimeBeforeConnectionTest); |
| 297 | + var clock = Clock.systemUTC(); |
| 298 | + var healthChecker = newHealthChecker(settings, clock); |
| 299 | + |
| 300 | + setCreationTimestamp(channel, clock.millis()); |
| 301 | + setLastUsedTimestamp(channel, clock.millis() - idleTimeBeforeConnectionTest * 2); |
| 302 | + |
| 303 | + var healthy = healthChecker.isHealthy(channel); |
| 304 | + channel.runPendingTasks(); |
| 305 | + |
| 306 | + assertNull(channel.pipeline().first()); |
| 307 | + assertEquals(ResetMessage.RESET, single(channel.outboundMessages())); |
| 308 | + assertFalse(healthy.isDone()); |
| 309 | + |
| 310 | + dispatcher.handleSuccessMessage(Collections.emptyMap()); |
| 311 | + assertThat(await(healthy), is(true)); |
| 312 | + assertNull(channel.pipeline().first()); |
| 313 | + } |
| 314 | + |
251 | 315 | @Test
|
252 | 316 | void shouldDropIdleConnectionWhenPingFails() {
|
253 | 317 | testPing(false);
|
|
0 commit comments