package com.zegoggles.smssync.mail; import android.content.ContentValues; import android.database.MatrixCursor; import android.provider.CallLog; import android.provider.Telephony; import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.internet.BinaryTempFileBody; import com.fsck.k9.mail.internet.MimeMessage; import com.zegoggles.smssync.contacts.ContactAccessor; import com.zegoggles.smssync.preferences.AddressStyle; import com.zegoggles.smssync.preferences.MarkAsReadTypes; import com.zegoggles.smssync.preferences.Preferences; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import java.io.ByteArrayInputStream; import java.io.IOException; import static org.fest.assertions.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; @RunWith(RobolectricTestRunner.class) public class MessageConverterTest { private MessageConverter messageConverter; @Mock private Preferences preferences; @Mock private PersonLookup personLookup; @Mock private ContactAccessor contactAccessor; @Before public void setUp() throws Exception { initMocks(this); BinaryTempFileBody.setTempDirectory(Robolectric.application.getCacheDir()); messageConverter = new MessageConverter(Robolectric.application, preferences, "foo@example.com", personLookup, contactAccessor); } @Test(expected = MessagingException.class) public void testMessageToContentValuesWithNullMessageThrowsMessagingException() throws Exception { messageConverter.messageToContentValues(null); } @Test public void testMessageToContentValuesWithUnknownMessageTypeGetParsedAsSMS() throws Exception { final String message = "Subject: Call with +12121\n" + "From: +12121 <+12121@unknown.email>\n" + "To: test@example.com\n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain;\n" + " charset=utf-8\n" + "References: <3j20u1wmbcyik9lw0yaf8bfc.+12121@sms-backup-plus.local>\n" + "Message-ID: <5c0e190205376da44656936fd7d9900c@sms-backup-plus.local>\n" + "X-smssync-datatype: INVALID\n" + "Content-Transfer-Encoding: quoted-printable\n" + "\n" + "Some Text"; final MimeMessage mimeMessage = MimeMessage.parseMimeMessage(new ByteArrayInputStream(message.getBytes()), true); final ContentValues values = messageConverter.messageToContentValues(mimeMessage); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.ADDRESS)).isNull(); } @Test public void testMessageToContentValuesWithSMS() throws Exception { final ContentValues values = messageConverter.messageToContentValues(createSMSMessage()); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.ADDRESS)).isEqualTo("+121332"); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.TYPE)).isEqualTo("2"); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.PROTOCOL)).isNull(); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.SERVICE_CENTER)).isNull(); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.DATE)).isEqualTo("1420759456762"); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.STATUS)).isEqualTo("-1"); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.THREAD_ID)).isNull(); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.READ)).isEqualTo("1"); assertThat(values.getAsString(Telephony.TextBasedSmsColumns.BODY)).isEqualTo("DasßAsß"); } @Test public void testMessageToContentValuesWithCalllog() throws Exception { PersonRecord record = new PersonRecord(1, "The name", "email@foo.com", "+1234"); when(personLookup.lookupPerson("+12121")).thenReturn(record); final ContentValues values = messageConverter.messageToContentValues(createCallLogMessage()); assertThat(values.getAsString(CallLog.Calls.NUMBER)).isEqualTo("+12121"); assertThat(values.getAsString(CallLog.Calls.TYPE)).isEqualTo("3"); assertThat(values.getAsString(CallLog.Calls.DATE)).isEqualTo("1419163218194"); assertThat(values.getAsLong(CallLog.Calls.DURATION)).isEqualTo(44L); assertThat(values.getAsInteger(CallLog.Calls.NEW)).isEqualTo(0); assertThat(values.getAsString(CallLog.Calls.CACHED_NAME)).isEqualTo("The name"); assertThat(values.getAsInteger(CallLog.Calls.CACHED_NUMBER_TYPE)).isEqualTo(-2); } @Test public void testMessageToContentValuesWithCalllogFromUnknownPerson() throws Exception { PersonRecord record = new PersonRecord(-1, null, null, null); when(personLookup.lookupPerson("+12121")).thenReturn(record); final ContentValues values = messageConverter.messageToContentValues(createCallLogMessage()); assertThat(values.containsKey(CallLog.Calls.CACHED_NAME)).isFalse(); assertThat(values.containsKey(CallLog.Calls.CACHED_NUMBER_TYPE)).isFalse(); } @Test public void testConvertMessagesSeenFlagFromMessageStatusWithSMS() throws Exception { MatrixCursor cursor = new MatrixCursor(new String[] {Telephony.TextBasedSmsColumns.ADDRESS, Telephony.TextBasedSmsColumns.READ} ); cursor.addRow(new Object[]{ "foo", "0" }); cursor.addRow(new Object[]{ "foo", "1" }); cursor.moveToFirst(); PersonRecord record = mock(PersonRecord.class); when(personLookup.lookupPerson(any(String.class))).thenReturn(record); when(record.getAddress(any(AddressStyle.class))).thenReturn(new Address("foo")); when(preferences.getMarkAsReadType()).thenReturn(MarkAsReadTypes.MESSAGE_STATUS); messageConverter = new MessageConverter(Robolectric.application, preferences, "foo@example.com", personLookup, contactAccessor); ConversionResult res = messageConverter.convertMessages(cursor, DataType.SMS); assertThat(res.getMessages().get(0).isSet(Flag.SEEN)).isFalse(); cursor.moveToNext(); res = messageConverter.convertMessages(cursor, DataType.SMS); assertThat(res.getMessages().get(0).isSet(Flag.SEEN)).isTrue(); } @Test public void testConvertMessagesSeenFlagUnreadWithSMS() throws Exception { MatrixCursor cursor = new MatrixCursor(new String[] {Telephony.TextBasedSmsColumns.ADDRESS, Telephony.TextBasedSmsColumns.READ} ); cursor.addRow(new Object[]{ "foo", "0" }); cursor.addRow(new Object[]{ "foo", "1" }); cursor.moveToFirst(); PersonRecord record = mock(PersonRecord.class); when(personLookup.lookupPerson(any(String.class))).thenReturn(record); when(record.getAddress(any(AddressStyle.class))).thenReturn(new Address("foo")); when(preferences.getMarkAsReadType()).thenReturn(MarkAsReadTypes.UNREAD); messageConverter = new MessageConverter(Robolectric.application, preferences, "foo@example.com", personLookup, contactAccessor); ConversionResult res = messageConverter.convertMessages(cursor, DataType.SMS); assertThat(res.getMessages().get(0).isSet(Flag.SEEN)).isFalse(); cursor.moveToNext(); res = messageConverter.convertMessages(cursor, DataType.SMS); assertThat(res.getMessages().get(0).isSet(Flag.SEEN)).isFalse(); } @Test public void testConvertMessagesSeenFlagReadWithSMS() throws Exception { MatrixCursor cursor = new MatrixCursor(new String[] {Telephony.TextBasedSmsColumns.ADDRESS, Telephony.TextBasedSmsColumns.READ} ); cursor.addRow(new Object[]{ "foo", "0" }); cursor.addRow(new Object[]{ "foo", "1" }); cursor.moveToFirst(); PersonRecord record = mock(PersonRecord.class); when(personLookup.lookupPerson(any(String.class))).thenReturn(record); when(record.getAddress(any(AddressStyle.class))).thenReturn(new Address("foo")); when(preferences.getMarkAsReadType()).thenReturn(MarkAsReadTypes.READ); messageConverter = new MessageConverter(Robolectric.application, preferences, "foo@example.com", personLookup, contactAccessor); ConversionResult res = messageConverter.convertMessages(cursor, DataType.SMS); assertThat(res.getMessages().get(0).isSet(Flag.SEEN)).isTrue(); cursor.moveToNext(); res = messageConverter.convertMessages(cursor, DataType.SMS); assertThat(res.getMessages().get(0).isSet(Flag.SEEN)).isTrue(); } private MimeMessage createSMSMessage() throws IOException, MessagingException { final String message = "Subject: SMS with +121332\n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain;\n" + " charset=utf-8\n" + "To: +121332 <+121332@unknown.email>\n" + "From: foo@test.com\n" + "References: <3j20u1wmbcyik9lw0yaf8bfc.+121332@sms-backup-plus.local>\n" + "Message-ID: <215765a03863b133d3b64d114a501251@sms-backup-plus.local>\n" + "X-smssync-address: +121332\n" + "X-smssync-datatype: SMS\n" + "X-smssync-backup-time: 8 Jan 2015 23:26:20 GMT\n" + "X-smssync-version: 1549\n" + "Date: Thu, 08 Jan 2015 18:24:16 -0500\n" + "X-smssync-id: 12\n" + "X-smssync-type: 2\n" + "X-smssync-date: 1420759456762\n" + "X-smssync-thread: 23\n" + "X-smssync-read: 1\n" + "X-smssync-status: -1\n" + "Content-Transfer-Encoding: quoted-printable\n" + "\n" + "Das=C3=9FAs=C3=9F"; return MimeMessage.parseMimeMessage(new ByteArrayInputStream(message.getBytes()), true); } private MimeMessage createCallLogMessage() throws IOException, MessagingException { final String message = "Subject: Call with +12121\n" + "From: +12121 <+12121@unknown.email>\n" + "To: test@example.com\n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain;\n" + " charset=utf-8\n" + "References: <3j20u1wmbcyik9lw0yaf8bfc.+12121@sms-backup-plus.local>\n" + "Message-ID: <5c0e190205376da44656936fd7d9900c@sms-backup-plus.local>\n" + "X-smssync-address: +12121\n" + "X-smssync-datatype: CALLLOG\n" + "X-smssync-backup-time: 7 Jan 2015 01:12:04 GMT\n" + "X-smssync-version: 1548\n" + "Date: Sun, 21 Dec 2014 07:00:18 -0500\n" + "X-smssync-id: 1\n" + "X-smssync-type: 3\n" + "X-smssync-date: 1419163218194\n" + "X-smssync-duration: 44\n" + "Content-Transfer-Encoding: quoted-printable\n" + "\n" + "+12121 (missed call)"; return MimeMessage.parseMimeMessage(new ByteArrayInputStream(message.getBytes()), true); } }