diff --git a/k9mail/src/main/java/com/fsck/k9/mailstore/migrations/MigrationTo51.java b/k9mail/src/main/java/com/fsck/k9/mailstore/migrations/MigrationTo51.java
index 2233d3c36..3fe6d1fb2 100644
--- a/k9mail/src/main/java/com/fsck/k9/mailstore/migrations/MigrationTo51.java
+++ b/k9mail/src/main/java/com/fsck/k9/mailstore/migrations/MigrationTo51.java
@@ -66,7 +66,7 @@ class MigrationTo51 {
File attachmentDirNew, attachmentDirOld;
Account account = migrationsHelper.getAccount();
- attachmentDirNew = StorageManager.getInstance(K9.app).getAttachmentDirectory(
+ attachmentDirNew = StorageManager.getInstance(migrationsHelper.getContext()).getAttachmentDirectory(
account.getUuid(), account.getLocalStorageProviderId());
attachmentDirOld = renameOldAttachmentDirAndCreateNew(account, attachmentDirNew);
diff --git a/k9mail/src/test/java/com/fsck/k9/mailstore/migrations/MigrationTo51Test.java b/k9mail/src/test/java/com/fsck/k9/mailstore/migrations/MigrationTo51Test.java
new file mode 100644
index 000000000..fefca3335
--- /dev/null
+++ b/k9mail/src/test/java/com/fsck/k9/mailstore/migrations/MigrationTo51Test.java
@@ -0,0 +1,222 @@
+package com.fsck.k9.mailstore.migrations;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.fsck.k9.Account;
+import com.fsck.k9.mailstore.StorageManager;
+import org.apache.commons.io.IOUtils;
+import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class MigrationTo51Test {
+ private MigrationsHelper mockMigrationsHelper;
+ private Account account;
+ private StorageManager storageManager;
+ private SQLiteDatabase database;
+
+ @Before
+ public void before() {
+ mockMigrationsHelper = mock(MigrationsHelper.class);
+ account = mock(Account.class);
+ storageManager = StorageManager.getInstance(RuntimeEnvironment.application);
+ storageManager.getDefaultProviderId();
+ when(account.getUuid()).thenReturn("001");
+ when(account.getLocalStorageProviderId()).thenReturn(storageManager.getDefaultProviderId());
+ when(mockMigrationsHelper.getContext()).thenReturn(RuntimeEnvironment.application);
+ when(mockMigrationsHelper.getAccount()).thenReturn(account);
+
+ database = createWithV50Table();
+ }
+
+ private SQLiteDatabase createWithV50Table() {
+ SQLiteDatabase database = SQLiteDatabase.create(null);
+ database.execSQL("CREATE TABLE messages (" +
+ "id INTEGER PRIMARY KEY, " +
+ "deleted INTEGER default 0, " +
+ "folder_id INTEGER, " +
+ "uid TEXT, " +
+ "subject TEXT, " +
+ "date INTEGER, " +
+ "sender_list TEXT, " +
+ "to_list TEXT, " +
+ "cc_list TEXT, " +
+ "bcc_list TEXT, " +
+ "reply_to_list TEXT, " +
+ "attachment_count INTEGER, " +
+ "internal_date INTEGER, " +
+ "message_id TEXT, " +
+ "preview TEXT, " +
+ "mime_type TEXT, " +
+ "html_content TEXT, " +
+ "text_content TEXT, " +
+ "flags TEXT, " +
+ "normalized_subject_hash INTEGER, " +
+ "empty INTEGER default 0, " +
+ "read INTEGER default 0, " +
+ "flagged INTEGER default 0, " +
+ "answered INTEGER default 0 )");
+ database.execSQL("CREATE TABLE headers ("+
+ "id INTEGER PRIMARY KEY," +
+ "name TEXT," +
+ "value TEXT," +
+ "message_id INTEGER)");
+ database.execSQL("CREATE TABLE attachments ("+
+ "id INTEGER PRIMARY KEY," +
+ "size INTEGER, " +
+ "name TEXT, " +
+ "mime_type TEXT, " +
+ "store_data TEXT, " +
+ "content_uri TEXT, " +
+ "content_id TEXT, " +
+ "content_disposition TEXT," +
+ "message_id INTEGER)");
+ return database;
+ }
+
+ private void addTextPlainMessage() {
+ database.execSQL(
+ "INSERT INTO messages (flags, html_content, text_content, " +
+ "mime_type, attachment_count) " +
+ "VALUES(?,?,?,?,?)", new Object[]{"",null,"Text","text/plain",0});
+ }
+
+ private void addTextHtmlMessage() {
+ database.execSQL(
+ "INSERT INTO messages (flags, html_content, text_content, " +
+ "mime_type, attachment_count) " +
+ "VALUES(?,?,?,?,?)", new Object[]{"","","Text","text/html",0});
+ }
+
+ private void addMultipartAlternativeMessage() {
+ database.execSQL(
+ "INSERT INTO messages (flags, html_content, text_content, " +
+ "mime_type, attachment_count) " +
+ "VALUES(?,?,?,?,?)", new Object[]{"","",null,"multipart/alternative",0});
+ }
+
+ private void addMultipartMixedMessage() {
+ database.execSQL(
+ "INSERT INTO messages (flags, html_content, text_content, " +
+ "mime_type, attachment_count) " +
+ "VALUES(?,?,?,?,?)", new Object[]{"","","Text","multipart/mixed",0});
+ }
+
+ private void addMultipartMixedMessageWithAttachment() {
+ database.execSQL(
+ "INSERT INTO messages (flags, html_content, text_content, " +
+ "mime_type, attachment_count) " +
+ "VALUES(?,?,?,?,?)",
+ new Object[]{"","",null,"multipart/mixed",1});
+ database.execSQL(
+ "INSERT INTO attachments (size, name, mime_type, store_data, " +
+ "content_uri, content_id, content_disposition, message_id) VALUES(?,?,?,?, ?,?,?,?)",
+ new Object[]{1, "a.jpg", "image/jpg", "a", "testUri", "content*user@host", "disposition", 1}
+ );
+ }
+
+ private void addMultipartMixedMessageWithAttachmentWithUnusualContentId() {
+ database.execSQL(
+ "INSERT INTO messages (flags, html_content, text_content, " +
+ "mime_type, attachment_count) " +
+ "VALUES(?,?,?,?,?)",
+ new Object[]{"","",null,"multipart/mixed",1});
+ database.execSQL(
+ "INSERT INTO attachments (size, name, mime_type, store_data, " +
+ "content_uri, content_id, content_disposition, message_id) VALUES(?,?,?,?, ?,?,?,?)",
+ new Object[]{1, "a.jpg", "image/jpg", "a", "testUri", "a$b@host", "disposition", 1}
+ );
+ }
+
+ @Test
+ public void db51MigrateMessageFormat_canMigrateEmptyMessagesTable() {
+ MigrationTo51.db51MigrateMessageFormat(database, mockMigrationsHelper);
+ }
+
+ @Test
+ public void db51MigrateMessageFormat_canMigrateTextPlainMessage() {
+ addTextPlainMessage();
+ MigrationTo51.db51MigrateMessageFormat(database, mockMigrationsHelper);
+ }
+
+ @Test
+ public void db51MigrateMessageFormat_canMigrateTextHtmlMessage() {
+ addTextHtmlMessage();
+ MigrationTo51.db51MigrateMessageFormat(database, mockMigrationsHelper);
+ }
+
+ @Test
+ public void db51MigrateMessageFormat_canMigrateMultipartAlternativeMessage() {
+ addMultipartAlternativeMessage();
+ MigrationTo51.db51MigrateMessageFormat(database, mockMigrationsHelper);
+ }
+
+ @Test
+ public void db51MigrateMessageFormat_canMigrateMultipartMixedMessage() {
+ addMultipartMixedMessage();
+ MigrationTo51.db51MigrateMessageFormat(database, mockMigrationsHelper);
+ }
+
+ @Test
+ public void db51MigrateMessageFormat_canMigrateMultipartMixedMessageWithAttachment() {
+ addMultipartMixedMessageWithAttachment();
+ MigrationTo51.db51MigrateMessageFormat(database, mockMigrationsHelper);
+ }
+
+ @Test
+ public void db51MigrateMessageFormat_withMultipartMixedMessageWithAttachment_stores_messagePart() {
+ addMultipartMixedMessageWithAttachment();
+ MigrationTo51.db51MigrateMessageFormat(database, mockMigrationsHelper);
+
+ Cursor cursor = database.query("message_parts", new String[]{"data"}, "mime_type = 'text/html'", null, null, null, null);
+ boolean isNotEmpty = cursor.moveToNext();
+
+ assertTrue(isNotEmpty);
+ }
+
+ @Test
+ public void db51MigrateMessageFormat_withMultipartMixedMessageWithAttachment_updatesContentReference()
+ throws IOException {
+ addMultipartMixedMessageWithAttachment();
+ MigrationTo51.db51MigrateMessageFormat(database, mockMigrationsHelper);
+ Cursor cursor = database.query("message_parts", new String[]{"data"}, "mime_type = 'text/html'", null, null, null, null);
+ boolean isNotEmpty = cursor.moveToNext();
+ assertTrue(isNotEmpty);
+ String partDataAsString = IOUtils.toString(
+ new QuotedPrintableInputStream(new ByteArrayInputStream(cursor.getBlob(0))));
+
+ assertEquals("", partDataAsString);
+ }
+
+ @Test
+ public void db51MigrateMessageFormat_withMultipartMixedMessageWithAttachmentWithUnusualContentID_updatesContentReference()
+ throws IOException {
+ addMultipartMixedMessageWithAttachmentWithUnusualContentId();
+ MigrationTo51.db51MigrateMessageFormat(database, mockMigrationsHelper);
+ Cursor cursor = database.query("message_parts", new String[]{"data"}, "mime_type = 'text/html'", null, null, null, null);
+ boolean isNotEmpty = cursor.moveToNext();
+ assertTrue(isNotEmpty);
+ String partDataAsString = IOUtils.toString(
+ new QuotedPrintableInputStream(new ByteArrayInputStream(cursor.getBlob(0))));
+
+ assertEquals("", partDataAsString);
+ }
+}