[android] Split up AttachmentController tests into integration and unit

This commit is contained in:
Torsten Grote
2018-12-24 17:39:40 -02:00
committed by akwizgran
parent 6e83fb7aef
commit ebe6b0d4c0
6 changed files with 256 additions and 99 deletions

View File

@@ -21,7 +21,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class AttachmentControllerTest { public class AttachmentControllerIntegrationTest {
private static final String smallKitten = private static final String smallKitten =
"https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Kitten_in_Rizal_Park%2C_Manila.jpg/160px-Kitten_in_Rizal_Park%2C_Manila.jpg"; "https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Kitten_in_Rizal_Park%2C_Manila.jpg/160px-Kitten_in_Rizal_Park%2C_Manila.jpg";
@@ -51,49 +51,6 @@ public class AttachmentControllerTest {
private final AttachmentController controller = private final AttachmentController controller =
new AttachmentController(null, dimensions); new AttachmentController(null, dimensions);
@Test
public void testNoSizeWrongMimeTypeProducesError() throws Exception {
AttachmentHeader h =
new AttachmentHeader(msgId, "application/octet-stream");
InputStream is = getUrlInputStream(smallKitten);
Attachment a = new Attachment(is);
AttachmentItem item = controller.getAttachmentItem(h, a, false);
assertTrue(item.hasError());
}
@Test
public void testNoSizeJpeg() throws Exception {
AttachmentHeader h = new AttachmentHeader(msgId, "image/jpeg");
InputStream is = getUrlInputStream(smallKitten);
Attachment a = new Attachment(is);
AttachmentItem item = controller.getAttachmentItem(h, a, false);
assertEquals("image/jpeg", item.getMimeType());
assertEquals("jpg", item.getExtension());
assertFalse(item.hasError());
}
@Test
public void testNoSizePng() throws Exception {
AttachmentHeader h = new AttachmentHeader(msgId, "image/png");
InputStream is = getUrlInputStream(smallKitten);
Attachment a = new Attachment(is);
AttachmentItem item = controller.getAttachmentItem(h, a, false);
assertEquals("image/png", item.getMimeType());
assertEquals("png", item.getExtension());
assertFalse(item.hasError());
}
@Test
public void testNoSizeGif() throws Exception {
AttachmentHeader h = new AttachmentHeader(msgId, "image/gif");
InputStream is = getUrlInputStream(smallKitten);
Attachment a = new Attachment(is);
AttachmentItem item = controller.getAttachmentItem(h, a, false);
assertEquals("image/gif", item.getMimeType());
assertEquals("gif", item.getExtension());
assertFalse(item.hasError());
}
@Test @Test
public void testSmallJpegImage() throws Exception { public void testSmallJpegImage() throws Exception {
AttachmentHeader h = new AttachmentHeader(msgId, "image/jpeg"); AttachmentHeader h = new AttachmentHeader(msgId, "image/jpeg");
@@ -110,22 +67,6 @@ public class AttachmentControllerTest {
assertFalse(item.hasError()); assertFalse(item.hasError());
} }
@Test
public void testSmallJpegImageHealsWrongMimeType() throws Exception {
AttachmentHeader h = new AttachmentHeader(msgId, "image/png");
InputStream is = getUrlInputStream(smallKitten);
Attachment a = new Attachment(is);
AttachmentItem item = controller.getAttachmentItem(h, a, true);
assertEquals(msgId, item.getMessageId());
assertEquals(160, item.getWidth());
assertEquals(240, item.getHeight());
assertEquals(160, item.getThumbnailWidth());
assertEquals(240, item.getThumbnailHeight());
assertEquals("image/jpeg", item.getMimeType());
assertEquals("jpg", item.getExtension());
assertFalse(item.hasError());
}
@Test @Test
public void testBigJpegImage() throws Exception { public void testBigJpegImage() throws Exception {
AttachmentHeader h = new AttachmentHeader(msgId, "image/jpeg"); AttachmentHeader h = new AttachmentHeader(msgId, "image/jpeg");
@@ -158,22 +99,6 @@ public class AttachmentControllerTest {
assertFalse(item.hasError()); assertFalse(item.hasError());
} }
@Test
public void testSmallPngImageHealsWrongMimeType() throws Exception {
AttachmentHeader h = new AttachmentHeader(msgId, "image/jpg");
InputStream is = getUrlInputStream(pngKitten);
Attachment a = new Attachment(is);
AttachmentItem item = controller.getAttachmentItem(h, a, true);
assertEquals(msgId, item.getMessageId());
assertEquals(737, item.getWidth());
assertEquals(510, item.getHeight());
assertEquals(dimensions.maxWidth, item.getThumbnailWidth());
assertEquals(138, item.getThumbnailHeight());
assertEquals("image/png", item.getMimeType());
assertEquals("png", item.getExtension());
assertFalse(item.hasError());
}
@Test @Test
public void testUberGif() throws Exception { public void testUberGif() throws Exception {
AttachmentHeader h = new AttachmentHeader(msgId, "image/jpg"); AttachmentHeader h = new AttachmentHeader(msgId, "image/jpg");
@@ -333,15 +258,6 @@ public class AttachmentControllerTest {
assertFalse(item.hasError()); assertFalse(item.hasError());
} }
@Test
public void testZeroSizeError() throws Exception {
AttachmentHeader h = new AttachmentHeader(msgId, "image/jpg");
InputStream is = getAssetInputStream("error_zero.jpg");
Attachment a = new Attachment(is);
AttachmentItem item = controller.getAttachmentItem(h, a, true);
assertTrue(item.hasError());
}
private InputStream getUrlInputStream(String url) throws IOException { private InputStream getUrlInputStream(String url) throws IOException {
return new URL(url).openStream(); return new URL(url).openStream();
} }

View File

@@ -1,6 +1,7 @@
package org.briarproject.briar.android.conversation; package org.briarproject.briar.android.conversation;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.media.ExifInterface; import android.support.media.ExifInterface;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
@@ -47,6 +48,7 @@ class AttachmentController {
private static final int READ_LIMIT = 1024 * 8192; private static final int READ_LIMIT = 1024 * 8192;
private final MessagingManager messagingManager; private final MessagingManager messagingManager;
private final ImageManager imageManager;
private final int defaultSize; private final int defaultSize;
private final int minWidth, maxWidth; private final int minWidth, maxWidth;
private final int minHeight, maxHeight; private final int minHeight, maxHeight;
@@ -55,8 +57,9 @@ class AttachmentController {
new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
AttachmentController(MessagingManager messagingManager, AttachmentController(MessagingManager messagingManager,
AttachmentDimensions dimensions) { AttachmentDimensions dimensions, ImageManager imageManager) {
this.messagingManager = messagingManager; this.messagingManager = messagingManager;
this.imageManager = imageManager;
defaultSize = dimensions.defaultSize; defaultSize = dimensions.defaultSize;
minWidth = dimensions.minWidth; minWidth = dimensions.minWidth;
maxWidth = dimensions.maxWidth; maxWidth = dimensions.maxWidth;
@@ -64,6 +67,23 @@ class AttachmentController {
maxHeight = dimensions.maxHeight; maxHeight = dimensions.maxHeight;
} }
AttachmentController(MessagingManager messagingManager,
AttachmentDimensions dimensions) {
this(messagingManager, dimensions, new ImageManager() {
@Override
public void decodeStream(InputStream is, Options options) {
BitmapFactory.decodeStream(is, null, options);
}
@Nullable
@Override
public String getExtensionFromMimeType(String mimeType) {
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
return mimeTypeMap.getExtensionFromMimeType(mimeType);
}
});
}
void put(MessageId messageId, List<AttachmentItem> attachments) { void put(MessageId messageId, List<AttachmentItem> attachments) {
attachmentCache.put(messageId, attachments); attachmentCache.put(messageId, attachments);
} }
@@ -113,7 +133,7 @@ class AttachmentController {
MessageId messageId = h.getMessageId(); MessageId messageId = h.getMessageId();
if (!needsSize) { if (!needsSize) {
String mimeType = h.getContentType(); String mimeType = h.getContentType();
String extension = getExtensionFromMimeType(mimeType); String extension = imageManager.getExtensionFromMimeType(mimeType);
boolean hasError = false; boolean hasError = false;
if (extension == null) { if (extension == null) {
extension = ""; extension = "";
@@ -156,7 +176,7 @@ class AttachmentController {
getThumbnailSize(size.width, size.height, size.mimeType); getThumbnailSize(size.width, size.height, size.mimeType);
} }
// get file extension // get file extension
String extension = getExtensionFromMimeType(size.mimeType); String extension = imageManager.getExtensionFromMimeType(size.mimeType);
boolean hasError = extension == null || size.error; boolean hasError = extension == null || size.error;
if (extension == null) extension = ""; if (extension == null) extension = "";
return new AttachmentItem(messageId, size.width, size.height, return new AttachmentItem(messageId, size.width, size.height,
@@ -164,17 +184,10 @@ class AttachmentController {
thumbnailSize.height, hasError); thumbnailSize.height, hasError);
} }
@Nullable
private String getExtensionFromMimeType(String mimeType) {
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
return mimeTypeMap.getExtensionFromMimeType(mimeType);
}
/** /**
* Gets the size of a JPEG {@link InputStream} if EXIF info is available. * Gets the size of a JPEG {@link InputStream} if EXIF info is available.
*/ */
private static Size getSizeFromExif(InputStream is) private Size getSizeFromExif(InputStream is) throws IOException {
throws IOException {
ExifInterface exif = new ExifInterface(is); ExifInterface exif = new ExifInterface(is);
// these can return 0 independent of default value // these can return 0 independent of default value
int width = exif.getAttributeInt(TAG_IMAGE_WIDTH, 0); int width = exif.getAttributeInt(TAG_IMAGE_WIDTH, 0);
@@ -194,10 +207,10 @@ class AttachmentController {
/** /**
* Gets the size of any image {@link InputStream}. * Gets the size of any image {@link InputStream}.
*/ */
private static Size getSizeFromBitmap(InputStream is) { private Size getSizeFromBitmap(InputStream is) {
BitmapFactory.Options options = new BitmapFactory.Options(); Options options = new Options();
options.inJustDecodeBounds = true; options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, options); imageManager.decodeStream(is, options);
if (options.outWidth < 1 || options.outHeight < 1) if (options.outWidth < 1 || options.outHeight < 1)
return new Size(); return new Size();
return new Size(options.outWidth, options.outHeight, return new Size(options.outWidth, options.outHeight,

View File

@@ -0,0 +1,18 @@
package org.briarproject.briar.android.conversation;
import android.graphics.BitmapFactory;
import android.support.annotation.Nullable;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.InputStream;
@NotNullByDefault
interface ImageManager {
void decodeStream(InputStream is, BitmapFactory.Options options);
@Nullable
String getExtensionFromMimeType(String mimeType);
}

View File

@@ -0,0 +1,162 @@
package org.briarproject.briar.android.conversation;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.briar.api.messaging.Attachment;
import org.briarproject.briar.api.messaging.AttachmentHeader;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.jmock.Expectations;
import org.junit.Test;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class AttachmentControllerTest extends BrambleMockTestCase {
private final AttachmentDimensions dimensions = new AttachmentDimensions(
100, 50, 200, 75, 300
);
private final MessageId msgId = new MessageId(getRandomId());
private final Attachment attachment = new Attachment(
new BufferedInputStream(
new ByteArrayInputStream(getRandomBytes(42))));
private final MessagingManager messagingManager =
context.mock(MessagingManager.class);
private final ImageManager imageManager = context.mock(ImageManager.class);
private final AttachmentController controller =
new AttachmentController(
messagingManager,
dimensions,
imageManager
);
@Test
public void testNoSize() {
String mimeType = "image/jpeg";
AttachmentHeader h = getAttachmentHeader(mimeType);
context.checking(new Expectations() {{
oneOf(imageManager).getExtensionFromMimeType(mimeType);
will(returnValue("jpg"));
}});
AttachmentItem item =
controller.getAttachmentItem(h, attachment, false);
assertEquals(mimeType, item.getMimeType());
assertEquals("jpg", item.getExtension());
assertFalse(item.hasError());
}
@Test
public void testNoSizeWrongMimeTypeProducesError() {
String mimeType = "application/octet-stream";
AttachmentHeader h = getAttachmentHeader(mimeType);
context.checking(new Expectations() {{
oneOf(imageManager).getExtensionFromMimeType(mimeType);
will(returnValue(null));
}});
AttachmentItem item =
controller.getAttachmentItem(h, attachment, false);
assertTrue(item.hasError());
}
@Test
public void testSmallJpegImage() {
String mimeType = "image/jpeg";
AttachmentHeader h = getAttachmentHeader(mimeType);
context.checking(new BitmapDecoderExpectations() {{
withDecodeStream(imageManager, options -> {
options.outWidth = 160;
options.outHeight = 240;
options.outMimeType = mimeType;
});
oneOf(imageManager).getExtensionFromMimeType(mimeType);
will(returnValue("jpg"));
}});
AttachmentItem item = controller.getAttachmentItem(h, attachment, true);
assertEquals(msgId, item.getMessageId());
assertEquals(160, item.getWidth());
assertEquals(240, item.getHeight());
assertEquals(160, item.getThumbnailWidth());
assertEquals(240, item.getThumbnailHeight());
assertEquals(mimeType, item.getMimeType());
assertEquals("jpg", item.getExtension());
assertFalse(item.hasError());
}
@Test
public void testImageHealsWrongMimeType() {
AttachmentHeader h = getAttachmentHeader("image/png");
context.checking(new BitmapDecoderExpectations() {{
withDecodeStream(imageManager, options -> {
options.outWidth = 160;
options.outHeight = 240;
options.outMimeType = "image/jpeg";
});
oneOf(imageManager).getExtensionFromMimeType("image/jpeg");
will(returnValue("jpg"));
}});
AttachmentItem item = controller.getAttachmentItem(h, attachment, true);
assertEquals("image/jpeg", item.getMimeType());
assertEquals("jpg", item.getExtension());
assertFalse(item.hasError());
}
@Test
public void testBigJpegImage() {
String mimeType = "image/jpeg";
AttachmentHeader h = getAttachmentHeader(mimeType);
context.checking(new BitmapDecoderExpectations() {{
withDecodeStream(imageManager, options -> {
options.outWidth = 1728;
options.outHeight = 2592;
options.outMimeType = mimeType;
});
oneOf(imageManager).getExtensionFromMimeType(mimeType);
will(returnValue("jpg"));
}});
AttachmentItem item = controller.getAttachmentItem(h, attachment, true);
assertEquals(1728, item.getWidth());
assertEquals(2592, item.getHeight());
assertEquals(dimensions.maxWidth, item.getThumbnailWidth());
assertEquals(dimensions.maxHeight, item.getThumbnailHeight());
assertFalse(item.hasError());
}
@Test
public void testMalformedError() {
AttachmentHeader h = getAttachmentHeader("image/jpeg");
context.checking(new BitmapDecoderExpectations() {{
withDecodeStream(imageManager, options -> {
options.outWidth = 0;
options.outHeight = 0;
});
oneOf(imageManager).getExtensionFromMimeType("");
will(returnValue(null));
}});
AttachmentItem item = controller.getAttachmentItem(h, attachment, true);
assertTrue(item.hasError());
}
private AttachmentHeader getAttachmentHeader(String contentType) {
return new AttachmentHeader(msgId, contentType);
}
}

View File

@@ -0,0 +1,48 @@
package org.briarproject.briar.android.conversation;
import android.graphics.BitmapFactory.Options;
import android.support.annotation.Nullable;
import org.hamcrest.Description;
import org.jmock.Expectations;
import org.jmock.api.Action;
import org.jmock.api.Invocation;
import java.io.InputStream;
class BitmapDecoderExpectations extends Expectations {
protected void withDecodeStream(ImageManager imageManager,
OptionsModifier optionsModifier) {
oneOf(imageManager).decodeStream(with(any(InputStream.class)),
with(any(Options.class)));
currentBuilder().setAction(new BitmapDecoderAction(optionsModifier));
}
private class BitmapDecoderAction implements Action {
private final OptionsModifier optionsModifier;
private BitmapDecoderAction(OptionsModifier optionsModifier) {
this.optionsModifier = optionsModifier;
}
@Nullable
@Override
public Object invoke(Invocation invocation) {
Options options = (Options) invocation.getParameter(1);
optionsModifier.modifyOptions(options);
return null;
}
@Override
public void describeTo(Description description) {
description.appendText("decodes a Bitmap InputStream");
}
}
interface OptionsModifier {
void modifyOptions(Options options);
}
}