### Question:
RetryingFunction implements Function<U, V> { @SuppressWarnings("squid:S1181") @Override public V apply(U input) { int retryAttempts = 0; while (true) { try { return baseFunction.apply(input); } catch (Throwable t) { if (!exceptionClass.isAssignableFrom(t.getClass()) || retryAttempts == maxRetries) { throwIfUnchecked(t); throw new RuntimeException(t); } Retries.randomDelay(maxDelayBetweenRetries); retryAttempts++; } } } RetryingFunction(Function<U, V> baseFunction,
      Class<? extends Throwable> exceptionClass,
      int maxRetries,
      int maxDelayBetweenRetries); @SuppressWarnings("squid:S1181") // Yes we really do want to catch Throwable @Override V apply(U input);  }### Answer:
@Test(expected = RetryableException.class) public void testNoRetries() { new RetryingFunction<>(this::succeedAfterOneFailure, RetryableException.class, 0, 10).apply(null); }
@Test public void testSuccessAfterOneRetry() { new RetryingFunction<>(this::succeedAfterOneFailure, RetryableException.class, 1, 10).apply(null); }
@Test(expected = RetryableException.class) public void testFailureAfterOneRetry() { new RetryingFunction<>(this::succeedAfterTwoFailures, RetryableException.class, 1, 10).apply(null); }
@Test public void testFailureAfterTwoRetries() { new RetryingFunction<>(this::succeedAfterTwoFailures, RetryableException.class, 2, 10).apply(null); }
@Test(expected = NonRetryableException.class) public void testFailureWithNonRetryableFailure() { new RetryingFunction<>(this::failCompletely, RetryableException.class, 2, 10).apply(null); }