Merge pull request #1317 from philipwhiuk/messagingControllerImprovement
Tests for MessagingController
This commit is contained in:
commit
e6d84afacc
2 changed files with 467 additions and 86 deletions
|
@ -107,25 +107,6 @@ public class MessagingController implements Runnable {
|
|||
*/
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
/**
|
||||
* The maximum message size that we'll consider to be "small". A small message is downloaded
|
||||
* in full immediately instead of in pieces. Anything over this size will be downloaded in
|
||||
* pieces with attachments being left off completely and downloaded on demand.
|
||||
*
|
||||
*
|
||||
* 25k for a "small" message was picked by educated trial and error.
|
||||
* http://answers.google.com/answers/threadview?id=312463 claims that the
|
||||
* average size of an email is 59k, which I feel is too large for our
|
||||
* blind download. The following tests were performed on a download of
|
||||
* 25 random messages.
|
||||
* <pre>
|
||||
* 5k - 61 seconds,
|
||||
* 25k - 51 seconds,
|
||||
* 55k - 53 seconds,
|
||||
* </pre>
|
||||
* So 25k gives good performance and a reasonable data footprint. Sounds good to me.
|
||||
*/
|
||||
|
||||
private static final String PENDING_COMMAND_MOVE_OR_COPY = "com.fsck.k9.MessagingController.moveOrCopy";
|
||||
private static final String PENDING_COMMAND_MOVE_OR_COPY_BULK = "com.fsck.k9.MessagingController.moveOrCopyBulk";
|
||||
private static final String PENDING_COMMAND_MOVE_OR_COPY_BULK_NEW = "com.fsck.k9.MessagingController.moveOrCopyBulkNew";
|
||||
|
@ -327,7 +308,6 @@ public class MessagingController implements Runnable {
|
|||
throw new Error(e);
|
||||
}
|
||||
|
||||
|
||||
public void addListener(MessagingListener listener) {
|
||||
mListeners.add(listener);
|
||||
refreshListener(listener);
|
||||
|
@ -438,74 +418,80 @@ public class MessagingController implements Runnable {
|
|||
put("doRefreshRemote", listener, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<LocalFolder> localFolders = null;
|
||||
try {
|
||||
Store store = account.getRemoteStore();
|
||||
|
||||
List <? extends Folder > remoteFolders = store.getPersonalNamespaces(false);
|
||||
|
||||
LocalStore localStore = account.getLocalStore();
|
||||
Set<String> remoteFolderNames = new HashSet<String>();
|
||||
List<LocalFolder> foldersToCreate = new LinkedList<LocalFolder>();
|
||||
|
||||
localFolders = localStore.getPersonalNamespaces(false);
|
||||
Set<String> localFolderNames = new HashSet<String>();
|
||||
for (Folder localFolder : localFolders) {
|
||||
localFolderNames.add(localFolder.getName());
|
||||
}
|
||||
for (Folder remoteFolder : remoteFolders) {
|
||||
if (localFolderNames.contains(remoteFolder.getName()) == false) {
|
||||
LocalFolder localFolder = localStore.getFolder(remoteFolder.getName());
|
||||
foldersToCreate.add(localFolder);
|
||||
}
|
||||
remoteFolderNames.add(remoteFolder.getName());
|
||||
}
|
||||
localStore.createFolders(foldersToCreate, account.getDisplayCount());
|
||||
|
||||
localFolders = localStore.getPersonalNamespaces(false);
|
||||
|
||||
/*
|
||||
* Clear out any folders that are no longer on the remote store.
|
||||
*/
|
||||
for (Folder localFolder : localFolders) {
|
||||
String localFolderName = localFolder.getName();
|
||||
|
||||
// FIXME: This is a hack used to clean up when we accidentally created the
|
||||
// special placeholder folder "-NONE-".
|
||||
if (K9.FOLDER_NONE.equals(localFolderName)) {
|
||||
localFolder.delete(false);
|
||||
}
|
||||
|
||||
if (!account.isSpecialFolder(localFolderName) &&
|
||||
!remoteFolderNames.contains(localFolderName)) {
|
||||
localFolder.delete(false);
|
||||
}
|
||||
}
|
||||
|
||||
localFolders = localStore.getPersonalNamespaces(false);
|
||||
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.listFolders(account, localFolders);
|
||||
}
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.listFoldersFinished(account);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.listFoldersFailed(account, "");
|
||||
}
|
||||
addErrorMessage(account, null, e);
|
||||
} finally {
|
||||
if (localFolders != null) {
|
||||
for (Folder localFolder : localFolders) {
|
||||
closeFolder(localFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
refreshRemoteSynchronous(account, listener);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void refreshRemoteSynchronous(final Account account, final MessagingListener listener) {
|
||||
List<LocalFolder> localFolders = null;
|
||||
try {
|
||||
Store store = account.getRemoteStore();
|
||||
|
||||
List <? extends Folder > remoteFolders = store.getPersonalNamespaces(false);
|
||||
|
||||
LocalStore localStore = account.getLocalStore();
|
||||
Set<String> remoteFolderNames = new HashSet<String>();
|
||||
List<LocalFolder> foldersToCreate = new LinkedList<LocalFolder>();
|
||||
|
||||
localFolders = localStore.getPersonalNamespaces(false);
|
||||
Set<String> localFolderNames = new HashSet<String>();
|
||||
for (Folder localFolder : localFolders) {
|
||||
localFolderNames.add(localFolder.getName());
|
||||
}
|
||||
|
||||
for (Folder remoteFolder : remoteFolders) {
|
||||
if (localFolderNames.contains(remoteFolder.getName()) == false) {
|
||||
LocalFolder localFolder = localStore.getFolder(remoteFolder.getName());
|
||||
foldersToCreate.add(localFolder);
|
||||
}
|
||||
remoteFolderNames.add(remoteFolder.getName());
|
||||
}
|
||||
localStore.createFolders(foldersToCreate, account.getDisplayCount());
|
||||
|
||||
localFolders = localStore.getPersonalNamespaces(false);
|
||||
|
||||
/*
|
||||
* Clear out any folders that are no longer on the remote store.
|
||||
*/
|
||||
for (Folder localFolder : localFolders) {
|
||||
String localFolderName = localFolder.getName();
|
||||
|
||||
// FIXME: This is a hack used to clean up when we accidentally created the
|
||||
// special placeholder folder "-NONE-".
|
||||
if (K9.FOLDER_NONE.equals(localFolderName)) {
|
||||
localFolder.delete(false);
|
||||
}
|
||||
|
||||
if (!account.isSpecialFolder(localFolderName) &&
|
||||
!remoteFolderNames.contains(localFolderName)) {
|
||||
localFolder.delete(false);
|
||||
}
|
||||
}
|
||||
|
||||
localFolders = localStore.getPersonalNamespaces(false);
|
||||
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.listFolders(account, localFolders);
|
||||
}
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.listFoldersFinished(account);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.listFoldersFailed(account, "");
|
||||
}
|
||||
addErrorMessage(account, null, e);
|
||||
} finally {
|
||||
if (localFolders != null) {
|
||||
for (Folder localFolder : localFolders) {
|
||||
closeFolder(localFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all messages in any local account which match the query 'query'
|
||||
* @throws MessagingException
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
package com.fsck.k9.controller;
|
||||
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.AccountStats;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.mail.FetchProfile;
|
||||
import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Folder;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessageRetrievalListener;
|
||||
|
@ -19,12 +25,15 @@ import com.fsck.k9.mailstore.LocalFolder;
|
|||
import com.fsck.k9.mailstore.LocalMessage;
|
||||
import com.fsck.k9.mailstore.LocalStore;
|
||||
import com.fsck.k9.notification.NotificationController;
|
||||
import com.fsck.k9.search.LocalSearch;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
|
@ -37,11 +46,16 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anySet;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.isNull;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -62,6 +76,8 @@ public class MessagingControllerTest {
|
|||
@Mock
|
||||
private MessagingListener listener;
|
||||
@Mock
|
||||
private LocalSearch search;
|
||||
@Mock
|
||||
private LocalFolder localFolder;
|
||||
@Mock
|
||||
private Folder remoteFolder;
|
||||
|
@ -74,13 +90,34 @@ public class MessagingControllerTest {
|
|||
@Captor
|
||||
private ArgumentCaptor<List<Message>> messageListCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<List<LocalFolder>> localFolderListCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<FetchProfile> fetchProfileCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<MessageRetrievalListener<LocalMessage>> messageRetrievalListenerCaptor;
|
||||
|
||||
private Context appContext;
|
||||
private Set<Flag> reqFlags;
|
||||
private Set<Flag> forbiddenFlags;
|
||||
|
||||
private List<Message> remoteMessages;
|
||||
@Mock
|
||||
private Message remoteOldMessage;
|
||||
@Mock
|
||||
private Message remoteNewMessage1;
|
||||
@Mock
|
||||
private Message remoteNewMessage2;
|
||||
@Mock
|
||||
private LocalMessage localNewMessage1;
|
||||
@Mock
|
||||
private LocalMessage localNewMessage2;
|
||||
private volatile boolean hasFetchedMessage = false;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws MessagingException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
Context appContext = ShadowApplication.getInstance().getApplicationContext();
|
||||
appContext = ShadowApplication.getInstance().getApplicationContext();
|
||||
|
||||
controller = new MessagingController(appContext, notificationController);
|
||||
|
||||
|
@ -93,6 +130,348 @@ public class MessagingControllerTest {
|
|||
controller.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listFoldersSynchronous_shouldNotifyTheListenerListingStarted() throws MessagingException {
|
||||
List<LocalFolder> folders = Collections.singletonList(localFolder);
|
||||
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
|
||||
|
||||
controller.listFoldersSynchronous(account, false, listener);
|
||||
|
||||
verify(listener).listFoldersStarted(account);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listFoldersSynchronous_shouldNotifyTheListenerOfTheListOfFolders() throws MessagingException {
|
||||
List<LocalFolder> folders = Collections.singletonList(localFolder);
|
||||
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
|
||||
|
||||
controller.listFoldersSynchronous(account, false, listener);
|
||||
|
||||
verify(listener).listFolders(eq(account), localFolderListCaptor.capture());
|
||||
assertEquals(folders, localFolderListCaptor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listFoldersSynchronous_shouldNotifyFailureOnException() throws MessagingException {
|
||||
when(localStore.getPersonalNamespaces(false)).thenThrow(new MessagingException("Test"));
|
||||
|
||||
controller.listFoldersSynchronous(account, true, listener);
|
||||
|
||||
verify(listener).listFoldersFailed(account, "Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listFoldersSynchronous_shouldNotNotifyFinishedAfterFailure() throws MessagingException {
|
||||
when(localStore.getPersonalNamespaces(false)).thenThrow(new MessagingException("Test"));
|
||||
|
||||
controller.listFoldersSynchronous(account, true, listener);
|
||||
|
||||
verify(listener, never()).listFoldersFinished(account);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listFoldersSynchronous_shouldNotifyFinishedAfterSuccess() throws MessagingException {
|
||||
List<LocalFolder> folders = Collections.singletonList(localFolder);
|
||||
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
|
||||
|
||||
controller.listFoldersSynchronous(account, false, listener);
|
||||
|
||||
verify(listener).listFoldersFinished(account);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshRemoteSynchronous_shouldCreateFoldersFromRemote() throws MessagingException {
|
||||
configureRemoteStoreWithFolder();
|
||||
LocalFolder newLocalFolder = mock(LocalFolder.class);
|
||||
|
||||
List<Folder> folders = Collections.singletonList(remoteFolder);
|
||||
when(remoteStore.getPersonalNamespaces(false)).thenAnswer(createAnswer(folders));
|
||||
when(remoteFolder.getName()).thenReturn("NewFolder");
|
||||
when(localStore.getFolder("NewFolder")).thenReturn(newLocalFolder);
|
||||
|
||||
controller.refreshRemoteSynchronous(account, listener);
|
||||
|
||||
verify(localStore).createFolders(eq(Collections.singletonList(newLocalFolder)), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshRemoteSynchronous_shouldDeleteFoldersNotOnRemote() throws MessagingException {
|
||||
configureRemoteStoreWithFolder();
|
||||
LocalFolder oldLocalFolder = mock(LocalFolder.class);
|
||||
when(oldLocalFolder.getName()).thenReturn("OldLocalFolder");
|
||||
when(localStore.getPersonalNamespaces(false))
|
||||
.thenReturn(Collections.singletonList(oldLocalFolder));
|
||||
List<Folder> folders = Collections.emptyList();
|
||||
when(remoteStore.getPersonalNamespaces(false)).thenAnswer(createAnswer(folders));
|
||||
|
||||
controller.refreshRemoteSynchronous(account, listener);
|
||||
|
||||
verify(oldLocalFolder).delete(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshRemoteSynchronous_shouldNotDeleteFoldersOnRemote() throws MessagingException {
|
||||
configureRemoteStoreWithFolder();
|
||||
when(localStore.getPersonalNamespaces(false))
|
||||
.thenReturn(Collections.singletonList(localFolder));
|
||||
List<Folder> folders = Collections.singletonList(remoteFolder);
|
||||
when(remoteStore.getPersonalNamespaces(false)).thenAnswer(createAnswer(folders));
|
||||
|
||||
controller.refreshRemoteSynchronous(account, listener);
|
||||
|
||||
verify(localFolder, never()).delete(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshRemoteSynchronous_shouldNotDeleteSpecialFoldersNotOnRemote() throws MessagingException {
|
||||
configureRemoteStoreWithFolder();
|
||||
LocalFolder missingSpecialFolder = mock(LocalFolder.class);
|
||||
when(account.isSpecialFolder("Outbox")).thenReturn(true);
|
||||
when(missingSpecialFolder.getName()).thenReturn("Outbox");
|
||||
when(localStore.getPersonalNamespaces(false))
|
||||
.thenReturn(Collections.singletonList(missingSpecialFolder));
|
||||
List<Folder> folders = Collections.emptyList();
|
||||
when(remoteStore.getPersonalNamespaces(false)).thenAnswer(createAnswer(folders));
|
||||
|
||||
controller.refreshRemoteSynchronous(account, listener);
|
||||
|
||||
verify(missingSpecialFolder, never()).delete(false);
|
||||
}
|
||||
|
||||
public static <T> Answer<T> createAnswer(final T value) {
|
||||
return new Answer<T>() {
|
||||
@Override
|
||||
public T answer(InvocationOnMock invocation) throws Throwable {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshRemoteSynchronous_shouldProvideFolderList() throws MessagingException {
|
||||
configureRemoteStoreWithFolder();
|
||||
List<LocalFolder> folders = Collections.singletonList(localFolder);
|
||||
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
|
||||
|
||||
controller.refreshRemoteSynchronous(account, listener);
|
||||
|
||||
verify(listener).listFolders(account, folders);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshRemoteSynchronous_shouldNotifyFinishedAfterSuccess() throws MessagingException {
|
||||
configureRemoteStoreWithFolder();
|
||||
List<LocalFolder> folders = Collections.singletonList(localFolder);
|
||||
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
|
||||
|
||||
controller.refreshRemoteSynchronous(account, listener);
|
||||
|
||||
verify(listener).listFoldersFinished(account);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshRemoteSynchronous_shouldNotNotifyFinishedAfterFailure() throws MessagingException {
|
||||
configureRemoteStoreWithFolder();
|
||||
when(localStore.getPersonalNamespaces(false)).thenThrow(new MessagingException("Test"));
|
||||
|
||||
controller.refreshRemoteSynchronous(account, listener);
|
||||
|
||||
verify(listener, never()).listFoldersFinished(account);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchLocalMessagesSynchronous_shouldNotifyStartedListingLocalMessages()
|
||||
throws Exception {
|
||||
setAccountsInPreferences(Collections.singletonMap("1", account));
|
||||
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
|
||||
|
||||
controller.searchLocalMessagesSynchronous(search, listener);
|
||||
|
||||
verify(listener).listLocalMessagesStarted(account, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchLocalMessagesSynchronous_shouldCallSearchForMessagesOnLocalStore()
|
||||
throws Exception {
|
||||
setAccountsInPreferences(Collections.singletonMap("1", account));
|
||||
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
|
||||
|
||||
controller.searchLocalMessagesSynchronous(search, listener);
|
||||
|
||||
verify(localStore).searchForMessages(any(MessageRetrievalListener.class), eq(search));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchLocalMessagesSynchronous_shouldNotifyFailureIfStoreThrowsException() throws Exception {
|
||||
setAccountsInPreferences(Collections.singletonMap("1", account));
|
||||
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
|
||||
when(localStore.searchForMessages(any(MessageRetrievalListener.class), eq(search)))
|
||||
.thenThrow(new MessagingException("Test"));
|
||||
|
||||
controller.searchLocalMessagesSynchronous(search, listener);
|
||||
|
||||
verify(listener).listLocalMessagesFailed(account, null, "Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchLocalMessagesSynchronous_shouldNotifyWhenStoreFinishesRetrievingAMessage()
|
||||
throws Exception {
|
||||
setAccountsInPreferences(Collections.singletonMap("1", account));
|
||||
LocalMessage localMessage = mock(LocalMessage.class);
|
||||
when(localMessage.getFolder()).thenReturn(localFolder);
|
||||
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
|
||||
when(localStore.searchForMessages(any(MessageRetrievalListener.class), eq(search)))
|
||||
.thenThrow(new MessagingException("Test"));
|
||||
|
||||
controller.searchLocalMessagesSynchronous(search, listener);
|
||||
|
||||
verify(localStore).searchForMessages(messageRetrievalListenerCaptor.capture(), eq(search));
|
||||
messageRetrievalListenerCaptor.getValue().messageFinished(localMessage, 1, 1);
|
||||
verify(listener).listLocalMessagesAddMessages(eq(account),
|
||||
eq((String) null), eq(Collections.singletonList(localMessage)));
|
||||
}
|
||||
|
||||
private void setupRemoteSearch() throws Exception {
|
||||
setAccountsInPreferences(Collections.singletonMap("1", account));
|
||||
configureRemoteStoreWithFolder();
|
||||
|
||||
remoteMessages = new ArrayList<>();
|
||||
Collections.addAll(remoteMessages, remoteOldMessage, remoteNewMessage1, remoteNewMessage2);
|
||||
List<Message> newRemoteMessages = new ArrayList<>();
|
||||
Collections.addAll(newRemoteMessages, remoteNewMessage1, remoteNewMessage2);
|
||||
|
||||
when(remoteOldMessage.getUid()).thenReturn("oldMessageUid");
|
||||
when(remoteNewMessage1.getUid()).thenReturn("newMessageUid1");
|
||||
when(localNewMessage1.getUid()).thenReturn("newMessageUid1");
|
||||
when(remoteNewMessage2.getUid()).thenReturn("newMessageUid2");
|
||||
when(localNewMessage2.getUid()).thenReturn("newMessageUid2");
|
||||
when(remoteFolder.search(anyString(), anySet(), anySet())).thenReturn(remoteMessages);
|
||||
when(localFolder.extractNewMessages(Matchers.<List<Message>>any())).thenReturn(newRemoteMessages);
|
||||
when(localFolder.getMessage("newMessageUid1")).thenReturn(localNewMessage1);
|
||||
when(localFolder.getMessage("newMessageUid2")).thenAnswer(
|
||||
new Answer<LocalMessage>() {
|
||||
@Override
|
||||
public LocalMessage answer(InvocationOnMock invocation) throws Throwable {
|
||||
if(hasFetchedMessage) {
|
||||
return localNewMessage2;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
hasFetchedMessage = true;
|
||||
return null;
|
||||
}
|
||||
}).when(remoteFolder).fetch(
|
||||
Matchers.<List<Message>>eq(Collections.singletonList(remoteNewMessage2)),
|
||||
any(FetchProfile.class),
|
||||
Matchers.<MessageRetrievalListener>eq(null));
|
||||
reqFlags = Collections.singleton(Flag.ANSWERED);
|
||||
forbiddenFlags = Collections.singleton(Flag.DELETED);
|
||||
|
||||
when(account.getRemoteSearchNumResults()).thenReturn(50);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldNotifyStartedListingRemoteMessages() throws Exception {
|
||||
setupRemoteSearch();
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(listener).remoteSearchStarted(FOLDER_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldQueryRemoteFolder() throws Exception {
|
||||
setupRemoteSearch();
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(remoteFolder).search("query", reqFlags, forbiddenFlags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldAskLocalFolderToDetermineNewMessages() throws Exception {
|
||||
setupRemoteSearch();
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(localFolder).extractNewMessages(remoteMessages);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldTryAndGetNewMessages() throws Exception {
|
||||
setupRemoteSearch();
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(localFolder).getMessage("newMessageUid1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldNotTryAndGetOldMessages() throws Exception {
|
||||
setupRemoteSearch();
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(localFolder, never()).getMessage("oldMessageUid");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldFetchNewMessages() throws Exception {
|
||||
setupRemoteSearch();
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(remoteFolder, times(2)).fetch(eq(Collections.singletonList(remoteNewMessage2)),
|
||||
fetchProfileCaptor.capture(), Matchers.<MessageRetrievalListener>eq(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldNotFetchExistingMessages() throws Exception {
|
||||
setupRemoteSearch();
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(remoteFolder, never()).fetch(eq(Collections.singletonList(remoteNewMessage1)),
|
||||
fetchProfileCaptor.capture(), Matchers.<MessageRetrievalListener>eq(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldNotifyListenerOfNewMessages() throws Exception {
|
||||
setupRemoteSearch();
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(listener).remoteSearchAddMessage(FOLDER_NAME, localNewMessage1, 1, 2);
|
||||
verify(listener).remoteSearchAddMessage(FOLDER_NAME, localNewMessage2, 2, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldNotifyOnFailure() throws Exception {
|
||||
setupRemoteSearch();
|
||||
when(account.getRemoteStore()).thenThrow(new MessagingException("Test"));
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(listener).remoteSearchFailed(null, "Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchRemoteMessagesSynchronous_shouldNotifyOnFinish() throws Exception {
|
||||
setupRemoteSearch();
|
||||
when(account.getRemoteStore()).thenThrow(new MessagingException("Test"));
|
||||
|
||||
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
|
||||
|
||||
verify(listener).remoteSearchFinished(FOLDER_NAME, 0, 50, Collections.<Message>emptyList());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void synchronizeMailboxSynchronous_withOneMessageInRemoteFolder_shouldFinishWithoutError()
|
||||
throws Exception {
|
||||
|
@ -372,6 +751,7 @@ public class MessagingControllerTest {
|
|||
}
|
||||
|
||||
private void configureAccount() throws MessagingException {
|
||||
when(account.isAvailable(appContext)).thenReturn(true);
|
||||
when(account.getLocalStore()).thenReturn(localStore);
|
||||
when(account.getStats(any(Context.class))).thenReturn(accountStats);
|
||||
when(account.getMaximumAutoDownloadMessageSize()).thenReturn(MAXIMUM_SMALL_MESSAGE_SIZE);
|
||||
|
@ -379,10 +759,25 @@ public class MessagingControllerTest {
|
|||
|
||||
private void configureLocalStore() {
|
||||
when(localStore.getFolder(FOLDER_NAME)).thenReturn(localFolder);
|
||||
when(localFolder.getName()).thenReturn(FOLDER_NAME);
|
||||
}
|
||||
|
||||
private void configureRemoteStoreWithFolder() throws MessagingException {
|
||||
when(account.getRemoteStore()).thenReturn(remoteStore);
|
||||
when(remoteStore.getFolder(FOLDER_NAME)).thenReturn(remoteFolder);
|
||||
when(remoteFolder.getName()).thenReturn(FOLDER_NAME);
|
||||
}
|
||||
|
||||
private void setAccountsInPreferences(Map<String, Account> newAccounts)
|
||||
throws Exception {
|
||||
Field accounts = Preferences.class.getDeclaredField("accounts");
|
||||
accounts.setAccessible(true);
|
||||
accounts.set(Preferences.getPreferences(appContext), newAccounts);
|
||||
|
||||
Field accountsInOrder = Preferences.class.getDeclaredField("accountsInOrder");
|
||||
accountsInOrder.setAccessible(true);
|
||||
ArrayList<Account> newAccountsInOrder = new ArrayList<>();
|
||||
newAccountsInOrder.addAll(newAccounts.values());
|
||||
accountsInOrder.set(Preferences.getPreferences(appContext), newAccountsInOrder);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue