Merge pull request #1559 from k9mail/deferred-file-body-fix

Fix DeferredFileBody
This commit is contained in:
cketti 2016-08-16 00:07:41 +02:00 committed by GitHub
commit 77f9e82b41
2 changed files with 159 additions and 2 deletions

View file

@ -11,6 +11,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.fsck.k9.K9;
@ -26,11 +27,12 @@ import org.apache.commons.io.IOUtils;
* @see FileFactory
*/
public class DeferredFileBody implements RawDataBody, SizeAware {
public static final int MEMORY_BACKED_THRESHOLD = 1024 * 8;
public static final int DEFAULT_MEMORY_BACKED_THRESHOLD = 1024 * 8;
private final FileFactory fileFactory;
private final String encoding;
private final int memoryBackedThreshold;
@Nullable
private byte[] data;
@ -38,12 +40,19 @@ public class DeferredFileBody implements RawDataBody, SizeAware {
public DeferredFileBody(FileFactory fileFactory, String transferEncoding) {
this(DEFAULT_MEMORY_BACKED_THRESHOLD, fileFactory, transferEncoding);
}
@VisibleForTesting
DeferredFileBody(int memoryBackedThreshold, FileFactory fileFactory,
String transferEncoding) {
this.fileFactory = fileFactory;
this.memoryBackedThreshold = memoryBackedThreshold;
this.encoding = transferEncoding;
}
public OutputStream getOutputStream() throws IOException {
return new DeferredFileOutputStream(MEMORY_BACKED_THRESHOLD, fileFactory) {
return new DeferredFileOutputStream(memoryBackedThreshold, fileFactory) {
@Override
public void close() throws IOException {
super.close();
@ -104,6 +113,7 @@ public class DeferredFileBody implements RawDataBody, SizeAware {
Log.d(K9.LOG_TAG, "Writing body to file for attachment access");
file = fileFactory.createFile();
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);
fos.close();

View file

@ -0,0 +1,147 @@
package com.fsck.k9.mailstore;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.fsck.k9.mailstore.util.FileFactory;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE, sdk = 21)
public class DeferredFileBodyTest {
public static final String TEST_ENCODING = "test-encoding";
public static final byte[] TEST_DATA_SHORT = "test data".getBytes();
public static final byte[] TEST_DATA_LONG = "test data long enough to be file backed".getBytes();
public static final int TEST_THRESHOLD = 15;
private File createdFile;
private DeferredFileBody deferredFileBody;
@Before
public void setUp() throws Exception {
FileFactory fileFactory = new FileFactory() {
@Override
public File createFile() throws IOException {
assertNull("only a single file should be created", createdFile);
createdFile = File.createTempFile("test", "tmp");
createdFile.deleteOnExit();
return createdFile;
}
};
deferredFileBody = new DeferredFileBody(TEST_THRESHOLD, fileFactory, TEST_ENCODING);
}
@Test
public void withShortData__getLength__shouldReturnWrittenLength() throws Exception {
writeShortTestData();
assertNull(createdFile);
assertEquals(TEST_DATA_SHORT.length, deferredFileBody.getSize());
}
@Test
public void withLongData__getLength__shouldReturnWrittenLength() throws Exception {
writeLongTestData();
assertNotNull(createdFile);
assertEquals(TEST_DATA_LONG.length, deferredFileBody.getSize());
}
@Test
public void withShortData__shouldReturnData() throws Exception {
writeShortTestData();
InputStream inputStream = deferredFileBody.getInputStream();
byte[] data = IOUtils.toByteArray(inputStream);
assertNull(createdFile);
assertArrayEquals(TEST_DATA_SHORT, data);
}
@Test
public void withLongData__shouldReturnData() throws Exception {
writeLongTestData();
InputStream inputStream = deferredFileBody.getInputStream();
byte[] data = IOUtils.toByteArray(inputStream);
InputStream fileInputStream = new FileInputStream(createdFile);
byte[] dataFromFile = IOUtils.toByteArray(fileInputStream);
assertArrayEquals(TEST_DATA_LONG, data);
assertArrayEquals(TEST_DATA_LONG, dataFromFile);
}
@Test
public void withShortData__getFile__shouldWriteDataToFile() throws Exception {
writeShortTestData();
File returnedFile = deferredFileBody.getFile();
InputStream fileInputStream = new FileInputStream(returnedFile);
byte[] dataFromFile = IOUtils.toByteArray(fileInputStream);
assertSame(createdFile, returnedFile);
assertArrayEquals(TEST_DATA_SHORT, dataFromFile);
}
@Test
public void withLongData__getFile__shouldReturnCreatedFile() throws Exception {
writeLongTestData();
File returnedFile = deferredFileBody.getFile();
assertSame(createdFile, returnedFile);
}
@Test
public void withShortData__writeTo__shouldWriteData() throws Exception {
writeShortTestData();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
deferredFileBody.writeTo(baos);
assertArrayEquals(TEST_DATA_SHORT, baos.toByteArray());
}
@Test(expected = UnsupportedOperationException.class)
public void setEncoding__shouldThrow() throws Exception {
deferredFileBody.setEncoding("anything");
}
@Test
public void getEncoding__shouldReturnEncoding() throws Exception {
assertEquals(TEST_ENCODING, deferredFileBody.getEncoding());
}
private void writeShortTestData() throws IOException {
OutputStream outputStream = deferredFileBody.getOutputStream();
outputStream.write(TEST_DATA_SHORT);
outputStream.close();
}
private void writeLongTestData() throws IOException {
OutputStream outputStream = deferredFileBody.getOutputStream();
outputStream.write(TEST_DATA_LONG);
outputStream.close();
}
}