### Question:
RetryExecutor { public void retry(Runnable action) throws Exception { try { retryAttempts--; action.run(); } catch (Exception e) { if (retryOnException(e) && retryAttempts > 0) { sleep(timeout); retry(action); } throw e; } } RetryExecutor();  RetryExecutor(int retryAttempts, long timeout, List<Class> exceptions); T retryResult(Callable<T> callable); void retry(Runnable action); void retryChecked(CheckedRunnable action); void retrySilent(Runnable action);  }### Answer:
@Test public void test() throws Exception { RetryExecutor retryExecutor = new RetryExecutor(attempts, 3, new ArrayList<>()); retryExecutor.retry(() -> System.out.println("Test")); }
@Test(expected = Exception.class) public void testRetryWithSecondTrySuccess() throws Exception { RetryExecutor retryExecutor = new RetryExecutor(attempts, 3, new ArrayList<>()); retryExecutor.retry(this::success); System.out.println("Successful attempt"); }
@Test(expected = Exception.class) public void testRetry() throws Exception { RetryExecutor retryExecutor = new RetryExecutor(attempts, 3, Arrays.asList(RuntimeException.class)); retryExecutor.retry(this::failure); Assert.fail("The executor should throw exception"); Assert.assertTrue(attempts == 0); }
@Test(expected = Exception.class) public void testNoRetryAttempts() throws Exception { RetryExecutor retryExecutor = new RetryExecutor(attempts, 3, Arrays.asList(Exception.class)); retryExecutor.retry(this::failure); Assert.fail("The executor should throw exception"); Assert.assertTrue(attempts == 2); }