@Test public void cancelBetweenOnFailureAndExecutorRunDoesNothing()
    throws InterruptedException {

  RetryableCalls retryableCalls = new RetryableCalls();
  MockWebServer server = new MockWebServer();
  Retrofit retrofit = new Retrofit.Builder()
      .baseUrl(server.url("/"))
      .callbackExecutor(new Executor() {
        @Override public void execute(Runnable command) {
          try {
            Thread.sleep(SECONDS.toMillis(2));
          } catch (InterruptedException e) {
            throw new AssertionError(e);
          }
          command.run();
        }
      })
      .addCallAdapterFactory(retryableCalls.getFactory())
      .addConverterFactory(new Converter.Factory() {
        @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type,
            Annotation[] annotations, Retrofit retrofit) {
          return new Converter<ResponseBody, Object>() {
            @Override public Object convert(ResponseBody value) throws IOException {
              throw new RuntimeException("Broken!");
            }
          };
        }
      })
      .build();
  Service service = retrofit.create(Service.class);
  final CountDownLatch failureLatch = new CountDownLatch(1);
  server.enqueue(new MockResponse().setBody("Hi"));
  RetryableCall<String> call = service.getString();
  call.enqueue(new RetryableCallback<String>() {
    @Override public void onResponse(RetryableCall<String> call, Response<String> response) {
      throw new AssertionError();
    }
    @Override public void onFailure(RetryableCall<String> call, Throwable t) {
      RuntimeException runtimeException = (RuntimeException) t;
      assertThat(runtimeException).hasMessageThat().isEqualTo("Broken!");
      assertThat(call.isCanceled()).isTrue();
      failureLatch.countDown();
    }
    @Override public void onFailureButCanRetry(RetryableCall<String> call, IOException e) {
      throw new AssertionError();
    }
  });
  Thread.sleep(SECONDS.toMillis(1));
  call.cancel();
  assertThat(failureLatch.await(10, SECONDS)).isTrue();
}