Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ee9b2c5 authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #2203 from philipwhiuk/clearFolderNotOnUiThread

Clear folder using the MessagingController instead of on the UI thread
parents c150bafa 4161b914
Loading
Loading
Loading
Loading
+1 −23
Original line number Diff line number Diff line
@@ -476,31 +476,9 @@ public class FolderList extends K9ListActivity {
    }

    private void onClearFolder(Account account, String folderName) {
        // There has to be a cheaper way to get at the localFolder object than this
        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);
        MessagingController.getInstance(getApplication()).clearFolder(account, folderName, mAdapter.mListener);
    }





    private void sendMail(Account account) {
        MessagingController.getInstance(getApplication()).sendPendingMessages(account, mAdapter.mListener);
    }
+31 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import com.fsck.k9.K9;
import com.fsck.k9.K9.Intents;
import com.fsck.k9.Preferences;
import com.fsck.k9.R;
import com.fsck.k9.activity.ActivityListener;
import com.fsck.k9.activity.MessageReference;
import com.fsck.k9.activity.setup.AccountSetupCheckSettings.CheckDirection;
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.
     *
+66 −1
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ import android.content.Context;

import com.fsck.k9.Account;
import com.fsck.k9.AccountStats;
import com.fsck.k9.K9;
import com.fsck.k9.K9RobolectricTestRunner;
import com.fsck.k9.Preferences;
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.LocalMessage;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.UnavailableStorageException;
import com.fsck.k9.notification.NotificationController;
import com.fsck.k9.search.LocalSearch;
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.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -80,6 +83,8 @@ public class MessagingControllerTest {
    @Mock
    private LocalFolder localFolder;
    @Mock
    private LocalFolder errorFolder;
    @Mock
    private Folder remoteFolder;
    @Mock
    private LocalStore localStore;
@@ -130,6 +135,62 @@ public class MessagingControllerTest {
        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
    public void listFoldersSynchronous_shouldNotifyTheListenerListingStarted() throws MessagingException {
        List<LocalFolder> folders = Collections.singletonList(localFolder);
@@ -758,11 +819,15 @@ public class MessagingControllerTest {
        when(account.getLocalStore()).thenReturn(localStore);
        when(account.getStats(any(Context.class))).thenReturn(accountStats);
        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(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 {