@Test
public void testUploadFile() throws B2Exception {

    final B2UploadListener listener = mock(B2UploadListener.class);
    final B2UploadFileRequest request = B2UploadFileRequest
            .builder(bucketId(1), fileName(1), B2ContentTypes.B2_AUTO, contentSourceWithSha1)
            .setCustomField("color", "gr\u00fcn")
            .setCustomField("number", "six")
            .setListener(listener)
            .build();
    final B2UploadUrlResponse uploadUrl = uploadUrlResponse(bucketId(1), 1);
    webifier.uploadFile(uploadUrl, request);
    webApiClient.check("postJsonReturnJson.\n" +
            "url:\n" +
            "    uploadUrl1\n" +
            "headers:\n" +
            "    Authorization: downloadToken1\n" +
            "    Content-Type: b2/x-auto\n" +
            "    Expect: 100-continue\n" +
            "    User-Agent: SecretAgentMan/3.19.28\n" +
            "    X-Bz-Content-Sha1: 0a0a9f2a6772942557ab5355d76af442f8f65e01\n" +
            "    X-Bz-File-Name: files/%E8%87%AA%E7%94%B1/0001\n" +
            "    X-Bz-Info-color: gr%C3%BCn\n" +
            "    X-Bz-Info-number: six\n" +
            "    X-Bz-Info-src_last_modified_millis: 1234567\n" +
            "    X-Bz-Test-Mode: force_cap_exceeded\n" +
            "inputStream:\n" +
            "    Hello, World!\n" +
            "contentLength:\n" +
            "    13\n" +
            "responseClass:\n" +
            "    B2FileVersion\n"
    );
    verify(listener, times(1)).progress(eq(new B2UploadProgress(0, 1, 0, 13,  0, B2UploadState.WAITING_TO_START)));
    verify(listener, times(1)).progress(eq(new B2UploadProgress(0, 1, 0, 13,  0, B2UploadState.STARTING)));
    // we get two UPLOADING events with bytesSoFar=13:
    //   the first happens when our first read succeeds.
    //   the second happens when we hit eof.
    // that's fine.  (in the real world there will probably be more than one UPLOADING event and the final one might be suppressed by the B2ByteProgressFilteringListener
    //                which is added above this code, in the B2StorageClientImpl, so it's important that send one for reachedEof.  and i don't want to complicate things
    //                enough to filter this case out.)
    verify(listener, times(2)).progress(eq(new B2UploadProgress(0, 1, 0, 13, 13, B2UploadState.UPLOADING)));
    verify(listener, times(1)).progress(eq(new B2UploadProgress(0, 1, 0, 13, 13, B2UploadState.SUCCEEDED)));
    reset(listener); // to clear the counts.
    checkRequestCategory(UPLOADING, w -> w.uploadFile(uploadUrl, request));
    verify(listener, times(1)).progress(eq(new B2UploadProgress(0, 1, 0, 13,  0, B2UploadState.WAITING_TO_START)));
    verify(listener, times(1)).progress(eq(new B2UploadProgress(0, 1, 0, 13,  0, B2UploadState.STARTING)));
    verify(listener, times(1)).progress(eq(new B2UploadProgress(0, 1, 0, 13,  0, B2UploadState.FAILED)));
}