Merge pull request #2203 from philipwhiuk/clearFolderNotOnUiThread

Clear folder using the MessagingController instead of on the UI thread
This commit is contained in:
cketti 2017-02-13 03:50:10 +01:00 committed by GitHub
commit 8ee9b2c591
3 changed files with 98 additions and 24 deletions

View file

@ -476,31 +476,9 @@ public class FolderList extends K9ListActivity {
} }
private void onClearFolder(Account account, String folderName) { private void onClearFolder(Account account, String folderName) {
// There has to be a cheaper way to get at the localFolder object than this MessagingController.getInstance(getApplication()).clearFolder(account, folderName, mAdapter.mListener);
LocalFolder localFolder = null;
try {
if (account == null || folderName == null || !account.isAvailable(FolderList.this)) {
Log.i(K9.LOG_TAG, "not clear folder of unavailable account");
return;
}
localFolder = account.getLocalStore().getFolder(folderName);
localFolder.open(Folder.OPEN_MODE_RW);
localFolder.clearAllMessages();
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Exception while clearing folder", e);
} finally {
if (localFolder != null) {
localFolder.close();
}
}
onRefresh(!REFRESH_REMOTE);
} }
private void sendMail(Account account) { private void sendMail(Account account) {
MessagingController.getInstance(getApplication()).sendPendingMessages(account, mAdapter.mListener); MessagingController.getInstance(getApplication()).sendPendingMessages(account, mAdapter.mListener);
} }

View file

@ -53,6 +53,7 @@ import com.fsck.k9.K9;
import com.fsck.k9.K9.Intents; import com.fsck.k9.K9.Intents;
import com.fsck.k9.Preferences; import com.fsck.k9.Preferences;
import com.fsck.k9.R; import com.fsck.k9.R;
import com.fsck.k9.activity.ActivityListener;
import com.fsck.k9.activity.MessageReference; import com.fsck.k9.activity.MessageReference;
import com.fsck.k9.activity.setup.AccountSetupCheckSettings.CheckDirection; import com.fsck.k9.activity.setup.AccountSetupCheckSettings.CheckDirection;
import com.fsck.k9.cache.EmailProviderCache; import com.fsck.k9.cache.EmailProviderCache;
@ -3513,6 +3514,36 @@ public class MessagingController {
}); });
} }
public void clearFolder(final Account account, final String folderName, final ActivityListener listener) {
putBackground("clearFolder", listener, new Runnable() {
@Override
public void run() {
clearFolderSynchronous(account, folderName, listener);
}
});
}
@VisibleForTesting
protected void clearFolderSynchronous(Account account, String folderName, MessagingListener listener) {
LocalFolder localFolder = null;
try {
localFolder = account.getLocalStore().getFolder(folderName);
localFolder.open(Folder.OPEN_MODE_RW);
localFolder.clearAllMessages();
} catch (UnavailableStorageException e) {
Log.i(K9.LOG_TAG, "Failed to clear folder because storage is not available - trying again later.");
throw new UnavailableAccountException(e);
} catch (Exception e) {
Log.e(K9.LOG_TAG, "clearFolder failed", e);
addErrorMessage(account, null, e);
} finally {
closeFolder(localFolder);
}
listFoldersSynchronous(account, false, listener);
}
/** /**
* Find out whether the account type only supports a local Trash folder. * Find out whether the account type only supports a local Trash folder.
* *

View file

@ -13,6 +13,7 @@ import android.content.Context;
import com.fsck.k9.Account; import com.fsck.k9.Account;
import com.fsck.k9.AccountStats; import com.fsck.k9.AccountStats;
import com.fsck.k9.K9;
import com.fsck.k9.K9RobolectricTestRunner; import com.fsck.k9.K9RobolectricTestRunner;
import com.fsck.k9.Preferences; import com.fsck.k9.Preferences;
import com.fsck.k9.helper.Contacts; import com.fsck.k9.helper.Contacts;
@ -26,6 +27,7 @@ import com.fsck.k9.mail.Store;
import com.fsck.k9.mailstore.LocalFolder; import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.LocalMessage; import com.fsck.k9.mailstore.LocalMessage;
import com.fsck.k9.mailstore.LocalStore; import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.UnavailableStorageException;
import com.fsck.k9.notification.NotificationController; import com.fsck.k9.notification.NotificationController;
import com.fsck.k9.search.LocalSearch; import com.fsck.k9.search.LocalSearch;
import org.junit.After; import org.junit.After;
@ -51,6 +53,7 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
@ -80,6 +83,8 @@ public class MessagingControllerTest {
@Mock @Mock
private LocalFolder localFolder; private LocalFolder localFolder;
@Mock @Mock
private LocalFolder errorFolder;
@Mock
private Folder remoteFolder; private Folder remoteFolder;
@Mock @Mock
private LocalStore localStore; private LocalStore localStore;
@ -130,6 +135,62 @@ public class MessagingControllerTest {
controller.stop(); controller.stop();
} }
@Test
public void clearFolderSynchronous_shouldOpenFolderForWriting() throws MessagingException {
controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
verify(localFolder).open(Folder.OPEN_MODE_RW);
}
@Test
public void clearFolderSynchronous_shouldClearAllMessagesInTheFolder() throws MessagingException {
controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
verify(localFolder).clearAllMessages();
}
@Test
public void clearFolderSynchronous_shouldCloseTheFolder() throws MessagingException {
controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
verify(localFolder, atLeastOnce()).close();
}
@Test(expected = UnavailableAccountException.class)
public void clearFolderSynchronous_whenStorageUnavailable_shouldThrowUnavailableAccountException() throws MessagingException {
doThrow(new UnavailableStorageException("Test")).when(localFolder).open(Folder.OPEN_MODE_RW);
controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
}
@Test()
public void clearFolderSynchronous_whenExceptionThrown_shouldAddErrorMessage() throws MessagingException {
doThrow(new RuntimeException("Test")).when(localFolder).open(Folder.OPEN_MODE_RW);
controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
verify(errorFolder).appendMessages(any(List.class));
}
@Test()
public void clearFolderSynchronous_whenExceptionThrown_shouldStillCloseFolder() throws MessagingException {
doThrow(new RuntimeException("Test")).when(localFolder).open(Folder.OPEN_MODE_RW);
try {
controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
} catch (Exception ignored){
}
verify(localFolder, atLeastOnce()).close();
}
@Test()
public void clearFolderSynchronous_shouldListFolders() throws MessagingException {
controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
verify(listener, atLeastOnce()).listFoldersStarted(account);
}
@Test @Test
public void listFoldersSynchronous_shouldNotifyTheListenerListingStarted() throws MessagingException { public void listFoldersSynchronous_shouldNotifyTheListenerListingStarted() throws MessagingException {
List<LocalFolder> folders = Collections.singletonList(localFolder); List<LocalFolder> folders = Collections.singletonList(localFolder);
@ -758,11 +819,15 @@ public class MessagingControllerTest {
when(account.getLocalStore()).thenReturn(localStore); when(account.getLocalStore()).thenReturn(localStore);
when(account.getStats(any(Context.class))).thenReturn(accountStats); when(account.getStats(any(Context.class))).thenReturn(accountStats);
when(account.getMaximumAutoDownloadMessageSize()).thenReturn(MAXIMUM_SMALL_MESSAGE_SIZE); when(account.getMaximumAutoDownloadMessageSize()).thenReturn(MAXIMUM_SMALL_MESSAGE_SIZE);
when(account.getErrorFolderName()).thenReturn(K9.ERROR_FOLDER_NAME);
when(account.getEmail()).thenReturn("user@host.com");
} }
private void configureLocalStore() { private void configureLocalStore() throws MessagingException {
when(localStore.getFolder(FOLDER_NAME)).thenReturn(localFolder); when(localStore.getFolder(FOLDER_NAME)).thenReturn(localFolder);
when(localFolder.getName()).thenReturn(FOLDER_NAME); when(localFolder.getName()).thenReturn(FOLDER_NAME);
when(localStore.getFolder(K9.ERROR_FOLDER_NAME)).thenReturn(errorFolder);
when(localStore.getPersonalNamespaces(false)).thenReturn(Collections.singletonList(localFolder));
} }
private void configureRemoteStoreWithFolder() throws MessagingException { private void configureRemoteStoreWithFolder() throws MessagingException {