public static <U> Task<U> withRetryPolicy(String name, RetryPolicy policy, Function1<Integer, Task<U>> taskFunction) {
    RetriableTask<U> retriableTask = new RetriableTask<>(name, policy, taskFunction);
    Task<U> retryTaskWrapper = Task.async(name + " retriableTask", retriableTask::run);
    retryTaskWrapper.getShallowTraceBuilder().setTaskType(TaskType.WITH_RETRY.getName());
    return retryTaskWrapper;
  }
@Test
  public void testErrorClassification()
  {
    Function<Throwable, ErrorClassification> errorClassifier = error -> error instanceof TimeoutException ? ErrorClassification.RECOVERABLE : ErrorClassification.UNRECOVERABLE;

    RetryPolicy retryPolicy = new RetryPolicyBuilder().
        setTerminationPolicy(TerminationPolicy.limitAttempts(3)).
        setErrorClassifier(errorClassifier).
        build();
    assertEquals(retryPolicy.getName(), "RetryPolicy.LimitAttempts");

    Task<Void> task1 = withRetryPolicy("testErrorClassification", retryPolicy, attempt -> Task.failure(new TimeoutException("current attempt: " + attempt)));
    runAndWaitException(task1, TimeoutException.class);
    assertTrue(task1.isDone());
    assertEquals(task1.getError().getMessage(), "current attempt: 2");

    Task<Void> task2 = withRetryPolicy("testErrorClassification", retryPolicy, attempt -> Task.failure(new IllegalArgumentException("current attempt: " + attempt)));
    runAndWaitException(task2, IllegalArgumentException.class);
    assertTrue(task2.isDone());
    assertEquals(task2.getError().getMessage(), "current attempt: 0");
  }