package com.fsck.k9.message.extractors; import android.content.Context; import android.net.Uri; import android.support.annotation.Nullable; import com.fsck.k9.K9RobolectricTestRunner; import com.fsck.k9.mail.Part; import com.fsck.k9.mail.internet.MimeBodyPart; import com.fsck.k9.mail.internet.MimeHeader; import com.fsck.k9.mail.internet.TextBody; import com.fsck.k9.mailstore.AttachmentViewInfo; import com.fsck.k9.mailstore.LocalBodyPart; import com.fsck.k9.mailstore.DeferredFileBody; import com.fsck.k9.provider.AttachmentProvider; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(K9RobolectricTestRunner.class) @Config(manifest = Config.NONE) public class AttachmentInfoExtractorTest { public static final Uri TEST_URI = Uri.parse("uri://test"); public static final String TEST_MIME_TYPE = "text/plain"; public static final long TEST_SIZE = 123L; public static final String TEST_ACCOUNT_UUID = "uuid"; public static final long TEST_ID = 234L; public static final String TEST_CONTENT_ID = "test-content-id"; private AttachmentInfoExtractor attachmentInfoExtractor; private Context context; @Before public void setUp() throws Exception { context = RuntimeEnvironment.application; attachmentInfoExtractor = new AttachmentInfoExtractor(context); } @Test(expected = IllegalArgumentException.class) public void extractInfo__withGenericPart_shouldThrow() throws Exception { Part part = mock(Part.class); attachmentInfoExtractor.extractAttachmentInfo(part); } @Test public void extractInfo__fromLocalBodyPart__shouldReturnProvidedValues() throws Exception { LocalBodyPart part = new LocalBodyPart(TEST_ACCOUNT_UUID, null, TEST_ID, TEST_SIZE); part.setHeader(MimeHeader.HEADER_CONTENT_TYPE, TEST_MIME_TYPE); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfo(part); assertEquals(AttachmentProvider.getAttachmentUri(TEST_ACCOUNT_UUID, TEST_ID), attachmentViewInfo.internalUri); assertEquals(TEST_SIZE, attachmentViewInfo.size); assertEquals(TEST_MIME_TYPE, attachmentViewInfo.mimeType); } @Test public void extractInfoForDb__withNoHeaders__shouldReturnEmptyValues() throws Exception { MimeBodyPart part = new MimeBodyPart(); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); assertEquals(Uri.EMPTY, attachmentViewInfo.internalUri); assertEquals(AttachmentViewInfo.UNKNOWN_SIZE, attachmentViewInfo.size); assertEquals("noname.txt", attachmentViewInfo.displayName); assertEquals("text/plain", attachmentViewInfo.mimeType); assertFalse(attachmentViewInfo.inlineAttachment); } @Test public void extractInfoForDb__withTextMimeType__shouldReturnTxtExtension() throws Exception { MimeBodyPart part = new MimeBodyPart(); part.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/plain"); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); // MimeUtility.getExtensionByMimeType("text/plain"); -> "txt" assertEquals("noname.txt", attachmentViewInfo.displayName); assertEquals("text/plain", attachmentViewInfo.mimeType); } @Test public void extractInfoForDb__withContentTypeAndName__shouldReturnNamedAttachment() throws Exception { MimeBodyPart part = new MimeBodyPart(); part.setHeader(MimeHeader.HEADER_CONTENT_TYPE, TEST_MIME_TYPE + "; name=\"filename.ext\""); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); assertEquals(Uri.EMPTY, attachmentViewInfo.internalUri); assertEquals(TEST_MIME_TYPE, attachmentViewInfo.mimeType); assertEquals("filename.ext", attachmentViewInfo.displayName); assertFalse(attachmentViewInfo.inlineAttachment); } @Test public void extractInfoForDb__withContentTypeAndEncodedWordName__shouldReturnDecodedName() throws Exception { Part part = new MimeBodyPart(); part.addRawHeader(MimeHeader.HEADER_CONTENT_TYPE, MimeHeader.HEADER_CONTENT_TYPE + ": " +TEST_MIME_TYPE + "; name=\"=?ISO-8859-1?Q?Sm=F8rrebr=F8d?=\""); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); assertEquals("Smørrebrød", attachmentViewInfo.displayName); } @Test public void extractInfoForDb__withDispositionAttach__shouldReturnNamedAttachment() throws Exception { MimeBodyPart part = new MimeBodyPart(); part.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "attachment" + "; filename=\"filename.ext\"; meaningless=\"dummy\""); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); assertEquals(Uri.EMPTY, attachmentViewInfo.internalUri); assertEquals("filename.ext", attachmentViewInfo.displayName); assertFalse(attachmentViewInfo.inlineAttachment); } @Test public void extractInfoForDb__withDispositionInlineAndContentId__shouldReturnInlineAttachment() throws Exception { Part part = new MimeBodyPart(); part.addRawHeader(MimeHeader.HEADER_CONTENT_ID, MimeHeader.HEADER_CONTENT_ID + ": " + TEST_CONTENT_ID); part.addRawHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, MimeHeader.HEADER_CONTENT_DISPOSITION + ": " + "inline" + ";\n filename=\"filename.ext\";\n meaningless=\"dummy\""); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); assertTrue(attachmentViewInfo.inlineAttachment); } @Test public void extractInfoForDb__withDispositionSizeParam__shouldReturnThatSize() throws Exception { MimeBodyPart part = new MimeBodyPart(); part.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "attachment" + "; size=\"" + TEST_SIZE + "\""); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); assertEquals(TEST_SIZE, attachmentViewInfo.size); } @Test public void extractInfoForDb__withDispositionInvalidSizeParam__shouldReturnUnknownSize() throws Exception { MimeBodyPart part = new MimeBodyPart(); part.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "attachment" + "; size=\"notanint\""); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); assertEquals(AttachmentViewInfo.UNKNOWN_SIZE, attachmentViewInfo.size); } @Test public void extractInfoForDb__withNoBody__shouldReturnContentNotAvailable() throws Exception { MimeBodyPart part = new MimeBodyPart(); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); assertFalse(attachmentViewInfo.isContentAvailable()); } @Test public void extractInfoForDb__withNoBody__shouldReturnContentAvailable() throws Exception { MimeBodyPart part = new MimeBodyPart(); part.setBody(new TextBody("data")); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfoForDatabase(part); assertTrue(attachmentViewInfo.isContentAvailable()); } @Test public void extractInfo__withDeferredFileBody() throws Exception { attachmentInfoExtractor = new AttachmentInfoExtractor(context) { @Nullable @Override protected Uri getDecryptedFileProviderUri(DeferredFileBody decryptedTempFileBody, String mimeType) { return TEST_URI; } }; DeferredFileBody body = mock(DeferredFileBody.class); when(body.getSize()).thenReturn(TEST_SIZE); MimeBodyPart part = new MimeBodyPart(); part.setBody(body); part.setHeader(MimeHeader.HEADER_CONTENT_TYPE, TEST_MIME_TYPE); AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfo(part); assertEquals(TEST_URI, attachmentViewInfo.internalUri); assertEquals(TEST_SIZE, attachmentViewInfo.size); assertEquals(TEST_MIME_TYPE, attachmentViewInfo.mimeType); assertFalse(attachmentViewInfo.inlineAttachment); assertTrue(attachmentViewInfo.isContentAvailable()); } }