RateLimitedResultSetFuture implements ResultSetFuture { @Override public boolean isDone() { return originalFuture.isDone() && safeGet().isDone(); } RateLimitedResultSetFuture(Session session, AsyncRateLimiter rateLimiter, Statement statement); @Override ResultSet getUninterruptibly(); @Override ResultSet getUninterruptibly(long timeout, TimeUnit unit); @Override boolean cancel(boolean mayInterruptIfRunning); @Override boolean isCancelled(); @Override boolean isDone(); @Override ResultSet get(); @Override ResultSet get(long timeout, TimeUnit unit); @Override void addListener(Runnable listener, Executor executor);  }
@Test public void doNotReleasePermissionIfRateLimitFutureFailed() throws InterruptedException { when(rateLimiter.acquireAsync()).thenReturn(Futures.immediateFailedFuture(new BufferLimitException())); resultSetFuture = new RateLimitedResultSetFuture(session, rateLimiter, statement); Thread.sleep(1000L); verify(rateLimiter).acquireAsync(); try { assertTrue(resultSetFuture.isDone()); fail(); } catch (Exception e) { assertTrue(e instanceof IllegalStateException); Throwable actualCause = e.getCause(); assertTrue(actualCause instanceof ExecutionException); } verifyNoMoreInteractions(session, rateLimiter, statement); }