@Test
  public void testRetrySuccess() throws DbxException, IOException {
    HttpRequestor mockRequestor = mock(HttpRequestor.class);
    DbxRequestConfig config =
        createRequestConfig().withAutoRetryEnabled(3).withHttpRequestor(mockRequestor).build();

    DbxClientV2 client = new DbxClientV2(config, "fakeAccessToken");
    FileMetadata expected =
        new FileMetadata(
            "bar.txt",
            "id:1HkLjqifwMAAAAAAAAAAAQ",
            new Date(1456169040985L),
            new Date(1456169040985L),
            "2e0c38735597",
            2091603);

    // 503 twice, then return result
    HttpRequestor.Uploader mockUploader = mockUploader();
    when(mockUploader.finish())
        .thenReturn(createEmptyResponse(503))
        .thenReturn(createEmptyResponse(503))
        .thenReturn(createSuccessResponse(serialize(expected)));

    when(mockRequestor.startPost(anyString(), anyHeaders())).thenReturn(mockUploader);

    Metadata actual = client.files().getMetadata(expected.getId());

    // should have only been called 3 times: initial call + 2 retries
    verify(mockRequestor, times(3)).startPost(anyString(), anyHeaders());

    assertEquals(actual.getName(), expected.getName());
    assertTrue(actual instanceof FileMetadata, actual.getClass().toString());
    assertEquals(((FileMetadata) actual).getId(), expected.getId());
  }
  private static byte[] serialize(Metadata metadata) {
    assertNotNull(metadata);

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
      serializer(Metadata.class).serialize(metadata, out);
    } catch (Exception ex) {
      fail("unserializable type: " + metadata.getClass(), ex);
      return null;
    }
    return out.toByteArray();
  }
  @Test
  public void testRetrySuccessWithBackoff() throws DbxException, IOException {
    HttpRequestor mockRequestor = mock(HttpRequestor.class);
    DbxRequestConfig config =
        createRequestConfig().withAutoRetryEnabled(3).withHttpRequestor(mockRequestor).build();

    DbxClientV2 client = new DbxClientV2(config, "fakeAccessToken");
    FileMetadata expected =
        new FileMetadata(
            "banana.png",
            "id:eRsVsAya9YAAAAAAAAAAAQ",
            new Date(1456173312172L),
            new Date(1456173312172L),
            "89df885732c38",
            12345L);

    // 503 twice, then return result
    HttpRequestor.Uploader mockUploader = mockUploader();
    when(mockUploader.finish())
        .thenReturn(createEmptyResponse(503)) // no backoff
        .thenReturn(createRateLimitResponse(1)) // backoff 1 sec
        .thenReturn(createRateLimitResponse(2)) // backoff 2 sec
        .thenReturn(createSuccessResponse(serialize(expected)));

    when(mockRequestor.startPost(anyString(), anyHeaders())).thenReturn(mockUploader);

    long start = System.currentTimeMillis();
    Metadata actual = client.files().getMetadata(expected.getId());
    long end = System.currentTimeMillis();

    // no way easy way to properly test this, but request should
    // have taken AT LEAST 3 seconds due to backoff.
    assertTrue((end - start) >= 3000L, "duration: " + (end - start) + " millis");

    // should have been called 4 times: initial call + 3 retries
    verify(mockRequestor, times(4)).startPost(anyString(), anyHeaders());

    assertEquals(actual.getName(), expected.getName());
    assertTrue(actual instanceof FileMetadata, actual.getClass().toString());
  }