@Test
  public void testBlocking() throws Exception {
    manager = new ConnectionManagerImpl("pool", factory, endpointManager, 1, 0, -1, -1, logger,
        60 * 1000, cancelCriterion, poolStats);
    manager.start(background);

    Connection connection1 = manager.borrowConnection(10);

    long borrowTimeoutMillis1 = 300;

    long elapsedMillis = Timer.measure(() -> {
      Throwable thrown = catchThrowable(() -> {
        manager.borrowConnection(borrowTimeoutMillis1);
      });
      assertThat(thrown).isInstanceOf(AllConnectionsInUseException.class);
    });
    assertThat(elapsedMillis)
        .withFailMessage(
            "Should have blocked for " + borrowTimeoutMillis1 + " millis for a connection")
        .isGreaterThanOrEqualTo(borrowTimeoutMillis1 - ALLOWABLE_ERROR_IN_MILLIS);

    Future<Void> returnConnectionFuture = executorServiceRule.submit(() -> {
      Thread.sleep(50);

      manager.returnConnection(connection1);
    });

    long borrowTimeoutMillis2 = 5000;

    AtomicReference<Connection> connection2 = new AtomicReference<>();
    elapsedMillis = Timer.measure(() -> {
      connection2.set(manager.borrowConnection(borrowTimeoutMillis2));
    });
    assertThat(elapsedMillis)
        .withFailMessage(
            "Should have blocked for less than " + borrowTimeoutMillis2 + " milliseconds")
        .isLessThan(borrowTimeoutMillis2 + ALLOWABLE_ERROR_IN_MILLIS);

    manager.returnConnection(connection2.get());

    Connection connection3 = manager.borrowConnection(10);

    Future<Void> invalidateFuture1 = executorServiceRule.submit(() -> {
      Thread.sleep(50);

      connection3.destroy();
      manager.returnConnection(connection3);
    });

    elapsedMillis = Timer.measure(() -> {
      connection2.set(manager.borrowConnection(borrowTimeoutMillis2));
    });
    assertThat(elapsedMillis)
        .withFailMessage(
            "Should have blocked for less than " + borrowTimeoutMillis2 + " milliseconds")
        .isLessThan(borrowTimeoutMillis2 + ALLOWABLE_ERROR_IN_MILLIS);

    manager.returnConnection(connection2.get());

    Connection connection4 = manager.borrowConnection(10);

    Future<Void> invalidateFuture2 = executorServiceRule.submit(() -> {
      Thread.sleep(50);

      endpointManager.serverCrashed(connection4.getEndpoint());
      manager.returnConnection(connection4);
    });

    elapsedMillis = Timer.measure(() -> {
      connection2.set(manager.borrowConnection(borrowTimeoutMillis2));
    });
    assertThat(elapsedMillis)
        .withFailMessage(
            "Should have blocked for less than " + borrowTimeoutMillis2 + " milliseconds")
        .isLessThan(borrowTimeoutMillis2 + ALLOWABLE_ERROR_IN_MILLIS);

    manager.returnConnection(connection2.get());

    returnConnectionFuture.get(getTimeout().toMillis(), MILLISECONDS);
    invalidateFuture1.get(getTimeout().toMillis(), MILLISECONDS);
    invalidateFuture2.get(getTimeout().toMillis(), MILLISECONDS);
  }
This tests that a deadlock between connection formation and connection pool closing has been
fixed. See GEODE-4615
geode-core/src/integrationTest/java/org/apache/geode/cache/client/internal/pooling/ConnectionManagerJUnitTest.java