-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Wrong progress reported to
ProgressListener
by `AbstractBoxMul…
- Loading branch information
Showing
4 changed files
with
174 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.box.sdk; | ||
|
||
import java.io.IOException; | ||
import okhttp3.MediaType; | ||
import okhttp3.RequestBody; | ||
import okio.BufferedSink; | ||
|
||
/** | ||
* | ||
*/ | ||
final class RequestBodyFromCallback extends RequestBody { | ||
|
||
private final UploadFileCallback callback; | ||
private final MediaType mediaType; | ||
|
||
RequestBodyFromCallback(UploadFileCallback callback, MediaType mediaType) { | ||
this.callback = callback; | ||
this.mediaType = mediaType; | ||
} | ||
|
||
@Override | ||
public MediaType contentType() { | ||
return mediaType; | ||
} | ||
|
||
@Override | ||
public void writeTo(BufferedSink bufferedSink) throws IOException { | ||
callback.writeToStream(bufferedSink.outputStream()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.box.sdk; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import okhttp3.MediaType; | ||
import okhttp3.RequestBody; | ||
import okio.BufferedSink; | ||
|
||
/** | ||
* Utility class to write body from stream to BufferedSink used by OkHttp. | ||
*/ | ||
final class RequestBodyFromStream extends RequestBody { | ||
private final InputStream inputStream; | ||
private final ProgressListener progressListener; | ||
private final MediaType mediaType; | ||
private final int contentLength; | ||
|
||
RequestBodyFromStream(InputStream inputStream, MediaType mediaType, ProgressListener progressListener) { | ||
this.inputStream = inputStream; | ||
this.progressListener = progressListener; | ||
this.mediaType = mediaType; | ||
try { | ||
this.contentLength = inputStream.available(); | ||
} catch (IOException e) { | ||
throw new RuntimeException("Cannot read input stream for upload", e); | ||
} | ||
} | ||
|
||
@Override | ||
public long contentLength() { | ||
return contentLength; | ||
} | ||
|
||
@Override | ||
public MediaType contentType() { | ||
return mediaType; | ||
} | ||
|
||
@Override | ||
public void writeTo(BufferedSink bufferedSink) throws IOException { | ||
byte[] buffer = new byte[AbstractBoxMultipartRequest.BUFFER_SIZE]; | ||
int n = this.inputStream.read(buffer); | ||
int totalWritten = 0; | ||
while (n != -1) { | ||
bufferedSink.write(buffer, 0, n); | ||
totalWritten += n; | ||
if (progressListener != null) { | ||
progressListener.onProgressChanged(totalWritten, this.contentLength()); | ||
} | ||
n = this.inputStream.read(buffer); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package com.box.sdk; | ||
|
||
import static com.box.sdk.AbstractBoxMultipartRequest.BUFFER_SIZE; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.IOException; | ||
import java.util.Random; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
import okhttp3.MediaType; | ||
import okio.Buffer; | ||
import org.hamcrest.MatcherAssert; | ||
import org.hamcrest.Matchers; | ||
import org.junit.Test; | ||
|
||
public class RequestBodyFromStreamTest { | ||
|
||
@Test | ||
public void reportCorrectProgressWhenFileIsEmpty() throws IOException { | ||
ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[]{}); | ||
ProgressListener progressListener = (numBytes, totalBytes) -> { | ||
MatcherAssert.assertThat(numBytes, Matchers.is((long) 0)); | ||
MatcherAssert.assertThat(totalBytes, Matchers.is((long) 0)); | ||
}; | ||
|
||
RequestBodyFromStream request = new RequestBodyFromStream( | ||
inputStream, MediaType.parse("application/json"), progressListener | ||
); | ||
|
||
request.writeTo(new Buffer()); | ||
} | ||
@Test | ||
public void reportCorrectProgressWhenFileSizeIfLessThanBuffer() throws IOException { | ||
int howManyBytes = 1000; | ||
ByteArrayInputStream inputStream = new ByteArrayInputStream(generateBytes(howManyBytes)); | ||
ProgressListener progressListener = (numBytes, totalBytes) -> { | ||
MatcherAssert.assertThat(numBytes, Matchers.is((long) howManyBytes)); | ||
MatcherAssert.assertThat(totalBytes, Matchers.is((long) howManyBytes)); | ||
}; | ||
|
||
RequestBodyFromStream request = new RequestBodyFromStream( | ||
inputStream, MediaType.parse("application/json"), progressListener | ||
); | ||
|
||
request.writeTo(new Buffer()); | ||
} | ||
|
||
@Test | ||
public void reportCorrectProgressWhenFileSizeIfEqualToBuffer() throws IOException { | ||
int howManyBytes = BUFFER_SIZE; | ||
ByteArrayInputStream inputStream = new ByteArrayInputStream(generateBytes(howManyBytes)); | ||
ProgressListener progressListener = (numBytes, totalBytes) -> { | ||
MatcherAssert.assertThat(numBytes, Matchers.is((long) howManyBytes)); | ||
MatcherAssert.assertThat(totalBytes, Matchers.is((long) howManyBytes)); | ||
}; | ||
|
||
RequestBodyFromStream request = new RequestBodyFromStream( | ||
inputStream, MediaType.parse("application/json"), progressListener | ||
); | ||
|
||
request.writeTo(new Buffer()); | ||
} | ||
|
||
@Test | ||
public void reportCorrectProgressWhenFileSizeIfGreaterThanBuffer() throws IOException { | ||
int howManyBytes = BUFFER_SIZE + 1000; | ||
ByteArrayInputStream inputStream = new ByteArrayInputStream(generateBytes(howManyBytes)); | ||
AtomicInteger counter = new AtomicInteger(0); | ||
ProgressListener progressListener = (numBytes, totalBytes) -> { | ||
if (counter.getAndIncrement() == 0) { | ||
MatcherAssert.assertThat(numBytes, Matchers.is((long) BUFFER_SIZE)); | ||
MatcherAssert.assertThat(totalBytes, Matchers.is((long) howManyBytes)); | ||
} else { | ||
MatcherAssert.assertThat(numBytes, Matchers.is((long) howManyBytes)); | ||
MatcherAssert.assertThat(totalBytes, Matchers.is((long) howManyBytes)); | ||
} | ||
}; | ||
|
||
RequestBodyFromStream request = new RequestBodyFromStream( | ||
inputStream, MediaType.parse("application/json"), progressListener | ||
); | ||
|
||
request.writeTo(new Buffer()); | ||
} | ||
|
||
private byte[] generateBytes(int howManyBytes) { | ||
byte[] bytes = new byte[howManyBytes]; | ||
new Random().nextBytes(bytes); | ||
return bytes; | ||
} | ||
} |