Add tests for remote search
This commit is contained in:
parent
bb8042669b
commit
4bb116f2f4
2 changed files with 167 additions and 19 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";
|
||||
|
@ -459,6 +440,7 @@ public class MessagingController implements Runnable {
|
|||
for (Folder localFolder : localFolders) {
|
||||
localFolderNames.add(localFolder.getName());
|
||||
}
|
||||
|
||||
for (Folder remoteFolder : remoteFolders) {
|
||||
if (localFolderNames.contains(remoteFolder.getName()) == false) {
|
||||
LocalFolder localFolder = localStore.getFolder(remoteFolder.getName());
|
||||
|
|
|
@ -4,8 +4,10 @@ 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;
|
||||
|
||||
|
@ -13,6 +15,7 @@ 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;
|
||||
|
@ -30,6 +33,7 @@ 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;
|
||||
|
@ -42,12 +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;
|
||||
|
||||
|
@ -89,6 +97,21 @@ public class MessagingControllerTest {
|
|||
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
|
||||
|
@ -308,6 +331,147 @@ public class MessagingControllerTest {
|
|||
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 {
|
||||
|
@ -595,11 +759,13 @@ 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)
|
||||
|
|
Loading…
Reference in a new issue