diff --git a/build.gradle b/build.gradle index d863379b4..8698197a7 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:2.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}" } } diff --git a/gradle.properties b/gradle.properties index b1cc6a840..8f8ddbeb3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,4 @@ +kotlinVersion=1.1.4-3 androidCompileSdkVersion=25 androidBuildToolsVersion=25.0.2 androidSupportLibraryVersion=25.2.0 @@ -7,3 +8,4 @@ robolectricVersion=3.2.2 junitVersion=4.12 mockitoVersion=1.10.19 okioVersion=1.11.0 +truthVersion=0.35 diff --git a/k9mail-library/build.gradle b/k9mail-library/build.gradle index f72e88a4d..ddb71c577 100644 --- a/k9mail-library/build.gradle +++ b/k9mail-library/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' if (!rootProject.optimizeForDevelopment) { apply from: '../gradle/plugins/checkstyle-android.gradle' @@ -25,9 +26,11 @@ dependencies { androidTestCompile 'com.android.support.test:runner:0.4.1' androidTestCompile 'com.madgag.spongycastle:pg:1.51.0.0' + testCompile "org.jetbrains.kotlin:kotlin-stdlib-jre7:${kotlinVersion}" testCompile "com.squareup.okio:okio:${okioVersion}" testCompile "org.robolectric:robolectric:${robolectricVersion}" testCompile "junit:junit:${junitVersion}" + testCompile "com.google.truth:truth:${truthVersion}" testCompile "org.mockito:mockito-core:${mockitoVersion}" } diff --git a/k9mail-library/src/test/java/com/fsck/k9/mail/MessageTest.java b/k9mail-library/src/test/java/com/fsck/k9/mail/MessageTest.java deleted file mode 100644 index 0556703a0..000000000 --- a/k9mail-library/src/test/java/com/fsck/k9/mail/MessageTest.java +++ /dev/null @@ -1,355 +0,0 @@ -package com.fsck.k9.mail; - - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Date; -import java.util.TimeZone; - -import android.content.Context; - -import com.fsck.k9.mail.Message.RecipientType; -import com.fsck.k9.mail.internet.BinaryTempFileBody; -import com.fsck.k9.mail.internet.BinaryTempFileMessageBody; -import com.fsck.k9.mail.internet.CharsetSupport; -import com.fsck.k9.mail.internet.MimeBodyPart; -import com.fsck.k9.mail.internet.MimeHeader; -import com.fsck.k9.mail.internet.MimeMessage; -import com.fsck.k9.mail.internet.MimeMessageHelper; -import com.fsck.k9.mail.internet.MimeMultipart; -import com.fsck.k9.mail.internet.TextBody; -import org.apache.commons.io.IOUtils; -import org.apache.james.mime4j.util.MimeUtil; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - - -@RunWith(K9LibRobolectricTestRunner.class) -public class MessageTest { - - private Context context; - - @Before - public void setUp() throws Exception { - context = RuntimeEnvironment.application; - - TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo")); - BinaryTempFileBody.setTempDirectory(context.getCacheDir()); - } - - private static final String SEVEN_BIT_RESULT = - "From: from@example.com\r\n" - + "To: to@example.com\r\n" - + "Subject: Test Message\r\n" - + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" - + "MIME-Version: 1.0\r\n" - + "Content-Type: multipart/mixed; boundary=\"----Boundary103\"\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "------Boundary103\r\n" - + "Content-Transfer-Encoding: quoted-printable\r\n" - + "Content-Type: text/plain;\r\n" - + " charset=utf-8\r\n" - + "\r\n" - + "Testing=2E\r\n" - + "This is a text body with some greek characters=2E\r\n" - + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" - + "End of test=2E\r\n" - + "\r\n" - + "------Boundary103\r\n" - + "Content-Type: application/octet-stream\r\n" - + "Content-Transfer-Encoding: base64\r\n" - + "\r\n" - + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" - + "\r\n" - + "------Boundary103\r\n" - + "Content-Type: message/rfc822\r\n" - + "Content-Disposition: attachment\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "From: from@example.com\r\n" - + "To: to@example.com\r\n" - + "Subject: Test Message\r\n" - + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" - + "MIME-Version: 1.0\r\n" - + "Content-Type: multipart/mixed; boundary=\"----Boundary102\"\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "------Boundary102\r\n" - + "Content-Transfer-Encoding: quoted-printable\r\n" - + "Content-Type: text/plain;\r\n" - + " charset=utf-8\r\n" - + "\r\n" - + "Testing=2E\r\n" - + "This is a text body with some greek characters=2E\r\n" - + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" - + "End of test=2E\r\n" - + "\r\n" - + "------Boundary102\r\n" - + "Content-Type: application/octet-stream\r\n" - + "Content-Transfer-Encoding: base64\r\n" - + "\r\n" - + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" - + "\r\n" - + "------Boundary102\r\n" - + "Content-Type: message/rfc822\r\n" - + "Content-Disposition: attachment\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "From: from@example.com\r\n" - + "To: to@example.com\r\n" - + "Subject: Test Message\r\n" - + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" - + "MIME-Version: 1.0\r\n" - + "Content-Type: multipart/mixed; boundary=\"----Boundary101\"\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "------Boundary101\r\n" - + "Content-Transfer-Encoding: quoted-printable\r\n" - + "Content-Type: text/plain;\r\n" - + " charset=utf-8\r\n" - + "\r\n" - + "Testing=2E\r\n" - + "This is a text body with some greek characters=2E\r\n" - + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" - + "End of test=2E\r\n" - + "\r\n" - + "------Boundary101\r\n" - + "Content-Type: application/octet-stream\r\n" - + "Content-Transfer-Encoding: base64\r\n" - + "\r\n" - + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" - + "\r\n" - + "------Boundary101--\r\n" - + "\r\n" - + "------Boundary102--\r\n" - + "\r\n" - + "------Boundary103--\r\n"; - - private static final String TO_BODY_PART_RESULT = - "Content-Type: multipart/mixed; boundary=\"----Boundary103\"\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "------Boundary103\r\n" - + "Content-Transfer-Encoding: quoted-printable\r\n" - + "Content-Type: text/plain;\r\n" - + " charset=utf-8\r\n" - + "\r\n" - + "Testing=2E\r\n" - + "This is a text body with some greek characters=2E\r\n" - + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" - + "End of test=2E\r\n" - + "\r\n" - + "------Boundary103\r\n" - + "Content-Type: application/octet-stream\r\n" - + "Content-Transfer-Encoding: base64\r\n" - + "\r\n" - + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" - + "\r\n" - + "------Boundary103\r\n" - + "Content-Type: message/rfc822\r\n" - + "Content-Disposition: attachment\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "From: from@example.com\r\n" - + "To: to@example.com\r\n" - + "Subject: Test Message\r\n" - + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" - + "MIME-Version: 1.0\r\n" - + "Content-Type: multipart/mixed; boundary=\"----Boundary102\"\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "------Boundary102\r\n" - + "Content-Transfer-Encoding: quoted-printable\r\n" - + "Content-Type: text/plain;\r\n" - + " charset=utf-8\r\n" - + "\r\n" - + "Testing=2E\r\n" - + "This is a text body with some greek characters=2E\r\n" - + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" - + "End of test=2E\r\n" - + "\r\n" - + "------Boundary102\r\n" - + "Content-Type: application/octet-stream\r\n" - + "Content-Transfer-Encoding: base64\r\n" - + "\r\n" - + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" - + "\r\n" - + "------Boundary102\r\n" - + "Content-Type: message/rfc822\r\n" - + "Content-Disposition: attachment\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "From: from@example.com\r\n" - + "To: to@example.com\r\n" - + "Subject: Test Message\r\n" - + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" - + "MIME-Version: 1.0\r\n" - + "Content-Type: multipart/mixed; boundary=\"----Boundary101\"\r\n" - + "Content-Transfer-Encoding: 7bit\r\n" - + "\r\n" - + "------Boundary101\r\n" - + "Content-Transfer-Encoding: quoted-printable\r\n" - + "Content-Type: text/plain;\r\n" - + " charset=utf-8\r\n" - + "\r\n" - + "Testing=2E\r\n" - + "This is a text body with some greek characters=2E\r\n" - + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" - + "End of test=2E\r\n" - + "\r\n" - + "------Boundary101\r\n" - + "Content-Type: application/octet-stream\r\n" - + "Content-Transfer-Encoding: base64\r\n" - + "\r\n" - + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" - + "\r\n" - + "------Boundary101--\r\n" - + "\r\n" - + "------Boundary102--\r\n" - + "\r\n" - + "------Boundary103--\r\n"; - - private int mMimeBoundary; - - @Test - public void testSetSendDateSetsSentDate() throws Exception { - Message message = sampleMessage(); - final int milliseconds = 0; - Date date = new Date(milliseconds); - message.setSentDate(date, false); - Date sentDate = message.getSentDate(); - assertNotNull(sentDate); - assertEquals(milliseconds, sentDate.getTime()); - } - - @Test - public void testSetSendDateFormatsHeaderCorrectlyWithCurrentTimeZone() throws Exception { - Message message = sampleMessage(); - message.setSentDate(new Date(0), false); - assertEquals("Thu, 01 Jan 1970 09:00:00 +0900", message.getHeader("Date")[0]); - } - - @Test - public void testSetSendDateFormatsHeaderCorrectlyWithoutTimeZone() throws Exception { - Message message = sampleMessage(); - message.setSentDate(new Date(0), true); - assertEquals("Thu, 01 Jan 1970 00:00:00 +0000", message.getHeader("Date")[0]); - } - - @Test - public void testMessage() throws MessagingException, IOException { - MimeMessage message; - ByteArrayOutputStream out; - - BinaryTempFileBody.setTempDirectory(context.getCacheDir()); - - mMimeBoundary = 101; - message = nestedMessage(nestedMessage(sampleMessage())); - out = new ByteArrayOutputStream(); - message.writeTo(out); - assertEquals(SEVEN_BIT_RESULT, out.toString()); - } - - private MimeMessage nestedMessage(MimeMessage subMessage) - throws MessagingException, IOException { - BinaryTempFileMessageBody tempMessageBody = new BinaryTempFileMessageBody(MimeUtil.ENC_8BIT); - - OutputStream out = tempMessageBody.getOutputStream(); - try { - subMessage.writeTo(out); - } finally { - out.close(); - } - - MimeBodyPart bodyPart = new MimeBodyPart(tempMessageBody, "message/rfc822"); - bodyPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "attachment"); - bodyPart.setEncoding(MimeUtil.ENC_7BIT); - - MimeMessage parentMessage = sampleMessage(); - ((Multipart) parentMessage.getBody()).addBodyPart(bodyPart); - - return parentMessage; - } - - private MimeMessage sampleMessage() throws MessagingException, IOException { - MimeMessage message = new MimeMessage(); - message.setFrom(new Address("from@example.com")); - message.setRecipient(RecipientType.TO, new Address("to@example.com")); - message.setSubject("Test Message"); - message.setHeader("Date", "Wed, 28 Aug 2013 08:51:09 -0400"); - message.setEncoding(MimeUtil.ENC_7BIT); - - MimeMultipart multipartBody = new MimeMultipart("multipart/mixed", generateBoundary()); - multipartBody.addBodyPart(textBodyPart()); - multipartBody.addBodyPart(binaryBodyPart()); - MimeMessageHelper.setBody(message, multipartBody); - - return message; - } - - private MimeBodyPart binaryBodyPart() throws IOException, - MessagingException { - String encodedTestString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - + "abcdefghijklmnopqrstuvwxyz0123456789+/\r\n"; - - BinaryTempFileBody tempFileBody = new BinaryTempFileBody(MimeUtil.ENC_BASE64); - - InputStream in = new ByteArrayInputStream( - encodedTestString.getBytes("UTF-8")); - - OutputStream out = tempFileBody.getOutputStream(); - try { - IOUtils.copy(in, out); - } finally { - out.close(); - } - - MimeBodyPart bodyPart = new MimeBodyPart(tempFileBody, - "application/octet-stream"); - bodyPart.setEncoding(MimeUtil.ENC_BASE64); - - return bodyPart; - } - - private MimeBodyPart textBodyPart() throws MessagingException { - TextBody textBody = new TextBody( - "Testing.\r\n" - + "This is a text body with some greek characters.\r\n" - + "αβγδεζηθ\r\n" - + "End of test.\r\n"); - textBody.setCharset("utf-8"); - - MimeBodyPart bodyPart = new MimeBodyPart(); - MimeMessageHelper.setBody(bodyPart, textBody); - CharsetSupport.setCharset("utf-8", bodyPart); - return bodyPart; - } - - private String generateBoundary() { - return "----Boundary" + Integer.toString(mMimeBoundary++); - } - - @Test - public void testToBodyPart() throws MessagingException, IOException { - MimeMessage message; - ByteArrayOutputStream out; - - BinaryTempFileBody.setTempDirectory(context.getCacheDir()); - - mMimeBoundary = 101; - message = nestedMessage(nestedMessage(sampleMessage())); - out = new ByteArrayOutputStream(); - MimeBodyPart bodyPart = message.toBodyPart(); - bodyPart.writeTo(out); - assertEquals(TO_BODY_PART_RESULT, out.toString()); - } -} diff --git a/k9mail-library/src/test/java/com/fsck/k9/mail/MessageTest.kt b/k9mail-library/src/test/java/com/fsck/k9/mail/MessageTest.kt new file mode 100644 index 000000000..706db42f4 --- /dev/null +++ b/k9mail-library/src/test/java/com/fsck/k9/mail/MessageTest.kt @@ -0,0 +1,324 @@ +package com.fsck.k9.mail + + +import com.fsck.k9.mail.Message.RecipientType +import com.fsck.k9.mail.internet.* +import com.google.common.truth.Truth.assertThat +import okio.Buffer +import org.apache.james.mime4j.util.MimeUtil +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RuntimeEnvironment +import java.io.ByteArrayOutputStream +import java.util.* + + +@RunWith(K9LibRobolectricTestRunner::class) +class MessageTest { + private val context = RuntimeEnvironment.application + private var mimeBoundary: Int = 0 + + @Before + fun setUp() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo")) + BinaryTempFileBody.setTempDirectory(context.cacheDir) + } + + @Test + fun setSendDate_shouldSetSendDate() { + val message = sampleMessage() + val date = Date(0L) + + message.setSentDate(date, false) + + assertThat(message.sentDate).isEqualTo(date) + } + + @Test + fun setSendDate_withoutHidingTimeZone_shouldCreateDateHeaderWithTimezone() { + val message = sampleMessage() + + message.setSentDate(Date(0L), false) + + assertThat(message.getFirstHeader("Date")).isEqualTo("Thu, 01 Jan 1970 09:00:00 +0900") + } + + @Test + fun setSendDate_withHidingTimeZone_shouldCreateDateHeaderWithTimezoneSetToZero() { + val message = sampleMessage() + + message.setSentDate(Date(0L), true) + + assertThat(message.getFirstHeader("Date")).isEqualTo("Thu, 01 Jan 1970 00:00:00 +0000") + } + + @Test + fun writeTo_withNestedMessage() { + mimeBoundary = 101 + val message = nestedMessage(nestedMessage(sampleMessage())) + val out = ByteArrayOutputStream() + + message.writeTo(out) + + assertThat(out.toString()).isEqualTo(""" + From: from@example.com + To: to@example.com + Subject: Test Message + Date: Wed, 28 Aug 2013 08:51:09 -0400 + MIME-Version: 1.0 + Content-Type: multipart/mixed; boundary="----Boundary103" + Content-Transfer-Encoding: 7bit + + ------Boundary103 + Content-Transfer-Encoding: quoted-printable + Content-Type: text/plain; + charset=utf-8 + + Testing=2E + This is a text body with some greek characters=2E + =CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8 + End of test=2E + + ------Boundary103 + Content-Type: application/octet-stream + Content-Transfer-Encoding: base64 + + ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ + + ------Boundary103 + Content-Type: message/rfc822 + Content-Disposition: attachment + Content-Transfer-Encoding: 7bit + + From: from@example.com + To: to@example.com + Subject: Test Message + Date: Wed, 28 Aug 2013 08:51:09 -0400 + MIME-Version: 1.0 + Content-Type: multipart/mixed; boundary="----Boundary102" + Content-Transfer-Encoding: 7bit + + ------Boundary102 + Content-Transfer-Encoding: quoted-printable + Content-Type: text/plain; + charset=utf-8 + + Testing=2E + This is a text body with some greek characters=2E + =CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8 + End of test=2E + + ------Boundary102 + Content-Type: application/octet-stream + Content-Transfer-Encoding: base64 + + ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ + + ------Boundary102 + Content-Type: message/rfc822 + Content-Disposition: attachment + Content-Transfer-Encoding: 7bit + + From: from@example.com + To: to@example.com + Subject: Test Message + Date: Wed, 28 Aug 2013 08:51:09 -0400 + MIME-Version: 1.0 + Content-Type: multipart/mixed; boundary="----Boundary101" + Content-Transfer-Encoding: 7bit + + ------Boundary101 + Content-Transfer-Encoding: quoted-printable + Content-Type: text/plain; + charset=utf-8 + + Testing=2E + This is a text body with some greek characters=2E + =CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8 + End of test=2E + + ------Boundary101 + Content-Type: application/octet-stream + Content-Transfer-Encoding: base64 + + ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ + + ------Boundary101-- + + ------Boundary102-- + + ------Boundary103-- + + """.trimIndent().crlf()) + } + + @Test + fun toBodyPart() { + mimeBoundary = 101 + val message = nestedMessage(nestedMessage(sampleMessage())) + val out = ByteArrayOutputStream() + val bodyPart = message.toBodyPart() + + bodyPart.writeTo(out) + + assertThat(out.toString()).isEqualTo(""" + Content-Type: multipart/mixed; boundary="----Boundary103" + Content-Transfer-Encoding: 7bit + + ------Boundary103 + Content-Transfer-Encoding: quoted-printable + Content-Type: text/plain; + charset=utf-8 + + Testing=2E + This is a text body with some greek characters=2E + =CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8 + End of test=2E + + ------Boundary103 + Content-Type: application/octet-stream + Content-Transfer-Encoding: base64 + + ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ + + ------Boundary103 + Content-Type: message/rfc822 + Content-Disposition: attachment + Content-Transfer-Encoding: 7bit + + From: from@example.com + To: to@example.com + Subject: Test Message + Date: Wed, 28 Aug 2013 08:51:09 -0400 + MIME-Version: 1.0 + Content-Type: multipart/mixed; boundary="----Boundary102" + Content-Transfer-Encoding: 7bit + + ------Boundary102 + Content-Transfer-Encoding: quoted-printable + Content-Type: text/plain; + charset=utf-8 + + Testing=2E + This is a text body with some greek characters=2E + =CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8 + End of test=2E + + ------Boundary102 + Content-Type: application/octet-stream + Content-Transfer-Encoding: base64 + + ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ + + ------Boundary102 + Content-Type: message/rfc822 + Content-Disposition: attachment + Content-Transfer-Encoding: 7bit + + From: from@example.com + To: to@example.com + Subject: Test Message + Date: Wed, 28 Aug 2013 08:51:09 -0400 + MIME-Version: 1.0 + Content-Type: multipart/mixed; boundary="----Boundary101" + Content-Transfer-Encoding: 7bit + + ------Boundary101 + Content-Transfer-Encoding: quoted-printable + Content-Type: text/plain; + charset=utf-8 + + Testing=2E + This is a text body with some greek characters=2E + =CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8 + End of test=2E + + ------Boundary101 + Content-Type: application/octet-stream + Content-Transfer-Encoding: base64 + + ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ + + ------Boundary101-- + + ------Boundary102-- + + ------Boundary103-- + + """.trimIndent().crlf()) + } + + + private fun sampleMessage(): MimeMessage { + val message = MimeMessage().apply { + setFrom(Address("from@example.com")) + setRecipient(RecipientType.TO, Address("to@example.com")) + subject = "Test Message" + setHeader("Date", "Wed, 28 Aug 2013 08:51:09 -0400") + setEncoding(MimeUtil.ENC_7BIT) + } + + val multipartBody = MimeMultipart("multipart/mixed", generateBoundary()).apply { + addBodyPart(textBodyPart()) + addBodyPart(binaryBodyPart()) + } + + MimeMessageHelper.setBody(message, multipartBody) + + return message + } + + private fun nestedMessage(subMessage: MimeMessage): MimeMessage { + val tempMessageBody = BinaryTempFileMessageBody(MimeUtil.ENC_8BIT).apply { + outputStream.use { subMessage.writeTo(it) } + } + + val bodyPart = MimeBodyPart(tempMessageBody, "message/rfc822").apply { + setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "attachment") + setEncoding(MimeUtil.ENC_7BIT) + } + + return sampleMessage().apply { + val multipart = body as Multipart + multipart.addBodyPart(bodyPart) + } + } + + private fun binaryBodyPart(): MimeBodyPart { + val buffer = Buffer().writeUtf8("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n") + val tempFileBody = BinaryTempFileBody(MimeUtil.ENC_BASE64).apply { + outputStream.use { buffer.writeTo(it) } + } + + return MimeBodyPart(tempFileBody, "application/octet-stream").apply { + setEncoding(MimeUtil.ENC_BASE64) + } + } + + private fun textBodyPart(): MimeBodyPart { + val textBody = TextBody(""" + Testing. + This is a text body with some greek characters. + αβγδεζηθ + End of test. + + """.trimIndent().crlf() + ).apply { + setCharset("utf-8") + } + + return MimeBodyPart().apply { + MimeMessageHelper.setBody(this, textBody) + CharsetSupport.setCharset("utf-8", this) + } + } + + private fun generateBoundary(): String { + return "----Boundary${mimeBoundary++}" + } +} + +private fun Message.getFirstHeader(header: String): String = getHeader(header)[0] + +private fun String.crlf() = replace("\n", "\r\n") diff --git a/k9mail/build.gradle b/k9mail/build.gradle index c4613c714..6427ccc14 100644 --- a/k9mail/build.gradle +++ b/k9mail/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' if (!rootProject.optimizeForDevelopment) { apply from: '../gradle/plugins/checkstyle-android.gradle' @@ -39,8 +40,10 @@ dependencies { androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' + testCompile "org.jetbrains.kotlin:kotlin-stdlib-jre7:${kotlinVersion}" testCompile "org.robolectric:robolectric:${robolectricVersion}" testCompile "junit:junit:${junitVersion}" + testCompile "com.google.truth:truth:${truthVersion}" testCompile "org.mockito:mockito-core:${mockitoVersion}" testCompile "org.jdom:jdom2:2.0.6" } diff --git a/k9mail/src/test/java/com/fsck/k9/view/MessageHeaderTest.java b/k9mail/src/test/java/com/fsck/k9/view/MessageHeaderTest.java deleted file mode 100644 index 3a561cdb7..000000000 --- a/k9mail/src/test/java/com/fsck/k9/view/MessageHeaderTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fsck.k9.view; - -import android.util.AttributeSet; - -import com.fsck.k9.K9RobolectricTestRunner; -import com.fsck.k9.mail.Address; -import com.fsck.k9.mail.Message; -import com.fsck.k9.mail.internet.MimeMessage; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; -import static org.mockito.Mockito.mock; - -@RunWith(K9RobolectricTestRunner.class) -public class MessageHeaderTest { - - private static final Address FROM_ADDRESS = Address.parse("from@example1.com")[0]; - private static final Address SENDER_ADDRESS = Address.parse("sender@example2.com")[0]; - - @Test - public void shouldShowSender_withSender_shouldReturnTrue() { - Message message = createMessage(FROM_ADDRESS, SENDER_ADDRESS); - - boolean showSender = MessageHeader.shouldShowSender(message); - - assertTrue(showSender); - } - - @Test - public void shouldShowSender_withoutSender_shouldReturnFalse() { - Message message = createMessage(FROM_ADDRESS, null); - - boolean showSender = MessageHeader.shouldShowSender(message); - - assertFalse(showSender); - } - - private Message createMessage(Address from, Address sender) { - Message message = new MimeMessage(); - message.setFrom(from); - message.setSender(sender); - return message; - } -} diff --git a/k9mail/src/test/java/com/fsck/k9/view/MessageHeaderTest.kt b/k9mail/src/test/java/com/fsck/k9/view/MessageHeaderTest.kt new file mode 100644 index 000000000..c4d22962f --- /dev/null +++ b/k9mail/src/test/java/com/fsck/k9/view/MessageHeaderTest.kt @@ -0,0 +1,37 @@ +package com.fsck.k9.view + +import com.fsck.k9.K9RobolectricTestRunner +import com.fsck.k9.mail.Address +import com.fsck.k9.mail.internet.MimeMessage +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(K9RobolectricTestRunner::class) +class MessageHeaderTest { + + @Test + fun shouldShowSender_withSender_shouldReturnTrue() { + val message = createMessage("from@example1.com", "sender@example2.com") + + val showSender = MessageHeader.shouldShowSender(message) + + assertThat(showSender).isTrue() + } + + @Test + fun shouldShowSender_withoutSender_shouldReturnFalse() { + val message = createMessage("from@example1.com") + + val showSender = MessageHeader.shouldShowSender(message) + + assertThat(showSender).isFalse() + } + + private fun createMessage(from: String, sender: String? = null) = MimeMessage().apply { + setFrom(from.toAddress()) + setSender(sender?.toAddress()) + } + + private fun String.toAddress() = Address.parse(this)[0] +}