Add unit tests for ImapStore
This commit is contained in:
parent
7f3fc84c11
commit
2d887b31ac
2 changed files with 340 additions and 8 deletions
|
@ -437,7 +437,7 @@ public class ImapStore extends RemoteStore {
|
|||
* @throws IOException uh oh!
|
||||
* @throws MessagingException uh oh!
|
||||
*/
|
||||
private void autoconfigureFolders(final ImapConnection connection) throws IOException, MessagingException {
|
||||
void autoconfigureFolders(final ImapConnection connection) throws IOException, MessagingException {
|
||||
String commandResponse;
|
||||
String commandOptions = "";
|
||||
|
||||
|
@ -513,10 +513,7 @@ public class ImapStore extends RemoteStore {
|
|||
@Override
|
||||
public void checkSettings() throws MessagingException {
|
||||
try {
|
||||
ImapConnection connection = new ImapConnection(
|
||||
new StoreImapSettings(),
|
||||
mTrustedSocketFactory,
|
||||
mConnectivityManager);
|
||||
ImapConnection connection = createImapConnection();
|
||||
|
||||
connection.open();
|
||||
autoconfigureFolders(connection);
|
||||
|
@ -538,9 +535,7 @@ public class ImapStore extends RemoteStore {
|
|||
}
|
||||
}
|
||||
if (connection == null) {
|
||||
connection = new ImapConnection(new StoreImapSettings(),
|
||||
mTrustedSocketFactory,
|
||||
mConnectivityManager);
|
||||
connection = createImapConnection();
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
@ -554,6 +549,10 @@ public class ImapStore extends RemoteStore {
|
|||
}
|
||||
}
|
||||
|
||||
ImapConnection createImapConnection() {
|
||||
return new ImapConnection(new StoreImapSettings(), mTrustedSocketFactory, mConnectivityManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a string to be able to use it in an IMAP command.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,333 @@
|
|||
package com.fsck.k9.mail.store.imap;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import android.net.ConnectivityManager;
|
||||
|
||||
import com.fsck.k9.mail.Folder;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.ssl.TrustedSocketFactory;
|
||||
import com.fsck.k9.mail.store.StoreConfig;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.util.collections.Sets;
|
||||
|
||||
import static com.fsck.k9.mail.store.imap.ImapResponseHelper.createImapResponse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
public class ImapStoreTest {
|
||||
private StoreConfig storeConfig;
|
||||
private TestImapStore imapStore;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
storeConfig = createStoreConfig();
|
||||
TrustedSocketFactory trustedSocketFactory = mock(TrustedSocketFactory.class);
|
||||
ConnectivityManager connectivityManager = mock(ConnectivityManager.class);
|
||||
|
||||
imapStore = new TestImapStore(storeConfig, trustedSocketFactory, connectivityManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolder_shouldReturnImapFolderInstance() throws Exception {
|
||||
Folder result = imapStore.getFolder("INBOX");
|
||||
|
||||
assertEquals(ImapFolder.class, result.getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolder_calledTwice_shouldReturnFirstInstance() throws Exception {
|
||||
String folderName = "Trash";
|
||||
Folder imapFolder = imapStore.getFolder(folderName);
|
||||
|
||||
Folder result = imapStore.getFolder(folderName);
|
||||
|
||||
assertEquals(imapFolder, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkSettings_shouldCreateImapConnectionAndCallOpen() throws Exception {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
|
||||
imapStore.checkSettings();
|
||||
|
||||
verify(imapConnection).open();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkSettings_withOpenThrowing_shouldThrowMessagingException() throws Exception {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
doThrow(IOException.class).when(imapConnection).open();
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
|
||||
try {
|
||||
imapStore.checkSettings();
|
||||
fail("Expected exception");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("Unable to connect", e.getMessage());
|
||||
assertNotNull(e.getCause());
|
||||
assertEquals(IOException.class, e.getCause().getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoconfigureFolders_withSpecialUseCapability_shouldSetSpecialFolders() throws Exception {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
when(imapConnection.hasCapability(Capabilities.SPECIAL_USE)).thenReturn(true);
|
||||
List<ImapResponse> imapResponses = Arrays.asList(
|
||||
createImapResponse("* LIST (\\HasNoChildren) \"/\" \"INBOX\""),
|
||||
createImapResponse("* LIST (\\Noselect \\HasChildren) \"/\" \"[Gmail]\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren \\All) \"/\" \"[Gmail]/All Mail\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren \\Drafts) \"/\" \"[Gmail]/Drafts\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren \\Important) \"/\" \"[Gmail]/Important\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren \\Sent) \"/\" \"[Gmail]/Sent Mail\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren \\Junk) \"/\" \"[Gmail]/Spam\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren \\Flagged) \"/\" \"[Gmail]/Starred\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren \\Trash) \"/\" \"[Gmail]/Trash\""),
|
||||
createImapResponse("5 OK Success")
|
||||
);
|
||||
when(imapConnection.executeSimpleCommand("LIST (SPECIAL-USE) \"\" \"*\"")).thenReturn(imapResponses);
|
||||
|
||||
imapStore.autoconfigureFolders(imapConnection);
|
||||
|
||||
verify(storeConfig).setDraftsFolderName("[Gmail]/Drafts");
|
||||
verify(storeConfig).setSentFolderName("[Gmail]/Sent Mail");
|
||||
verify(storeConfig).setSpamFolderName("[Gmail]/Spam");
|
||||
verify(storeConfig).setTrashFolderName("[Gmail]/Trash");
|
||||
//FIXME: currently fails
|
||||
verify(storeConfig).setArchiveFolderName("[Gmail]/All Mail");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoconfigureFolders_withoutSpecialUseCapability_shouldNotIssueImapCommand() throws Exception {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
when(imapConnection.hasCapability(Capabilities.SPECIAL_USE)).thenReturn(false);
|
||||
|
||||
imapStore.autoconfigureFolders(imapConnection);
|
||||
|
||||
verify(imapConnection, atLeastOnce()).hasCapability(anyString());
|
||||
verifyNoMoreInteractions(imapConnection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPersonalNamespaces_withForceListAll() throws Exception {
|
||||
when(storeConfig.subscribedFoldersOnly()).thenReturn(true);
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
List<ImapResponse> imapResponses = Arrays.asList(
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"INBOX\""),
|
||||
createImapResponse("* LIST (\\Noselect \\HasChildren) \".\" \"Folder\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"Folder.SubFolder\""),
|
||||
createImapResponse("6 OK Success")
|
||||
);
|
||||
when(imapConnection.executeSimpleCommand("LIST \"\" \"*\"")).thenReturn(imapResponses);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
|
||||
List<? extends Folder> result = imapStore.getPersonalNamespaces(true);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(Sets.newSet("INBOX", "Folder.SubFolder"), extractFolderNames(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPersonalNamespaces_withoutForceListAllAndWithoutSubscribedFoldersOnly() throws Exception {
|
||||
when(storeConfig.subscribedFoldersOnly()).thenReturn(false);
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
List<ImapResponse> imapResponses = Arrays.asList(
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"INBOX\""),
|
||||
createImapResponse("* LIST (\\Noselect \\HasChildren) \".\" \"Folder\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"Folder.SubFolder\""),
|
||||
createImapResponse("6 OK Success")
|
||||
);
|
||||
when(imapConnection.executeSimpleCommand("LIST \"\" \"*\"")).thenReturn(imapResponses);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
|
||||
List<? extends Folder> result = imapStore.getPersonalNamespaces(false);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(Sets.newSet("INBOX", "Folder.SubFolder"), extractFolderNames(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPersonalNamespaces_withSubscribedFoldersOnlyAndWithoutForceListAll_shouldOnlyReturnExistingSubscribedFolders()
|
||||
throws Exception {
|
||||
when(storeConfig.subscribedFoldersOnly()).thenReturn(true);
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
List<ImapResponse> lsubResponses = Arrays.asList(
|
||||
createImapResponse("* LSUB (\\HasNoChildren) \".\" \"INBOX\""),
|
||||
createImapResponse("* LSUB (\\Noselect \\HasChildren) \".\" \"Folder\""),
|
||||
createImapResponse("* LSUB (\\HasNoChildren) \".\" \"Folder.SubFolder\""),
|
||||
createImapResponse("* LSUB (\\HasNoChildren) \".\" \"SubscribedFolderThatHasBeenDeleted\""),
|
||||
createImapResponse("5 OK Success")
|
||||
);
|
||||
when(imapConnection.executeSimpleCommand("LSUB \"\" \"*\"")).thenReturn(lsubResponses);
|
||||
List<ImapResponse> imapResponses = Arrays.asList(
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"INBOX\""),
|
||||
createImapResponse("* LIST (\\Noselect \\HasChildren) \".\" \"Folder\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"Folder.SubFolder\""),
|
||||
createImapResponse("6 OK Success")
|
||||
);
|
||||
when(imapConnection.executeSimpleCommand("LIST \"\" \"*\"")).thenReturn(imapResponses);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
|
||||
List<? extends Folder> result = imapStore.getPersonalNamespaces(false);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(Sets.newSet("INBOX", "Folder.SubFolder"), extractFolderNames(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPersonalNamespaces_withoutException_shouldLeaveImapConnectionOpen() throws Exception {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
List<ImapResponse> imapResponses = Collections.singletonList(createImapResponse("5 OK Success"));
|
||||
when(imapConnection.executeSimpleCommand(anyString())).thenReturn(imapResponses);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
|
||||
imapStore.getPersonalNamespaces(true);
|
||||
|
||||
verify(imapConnection, never()).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPersonalNamespaces_withIoException_shouldCloseImapConnection() throws Exception {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
doThrow(IOException.class).when(imapConnection).executeSimpleCommand("LIST \"\" \"*\"");
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
|
||||
try {
|
||||
imapStore.getPersonalNamespaces(true);
|
||||
fail("Expected exception");
|
||||
} catch (MessagingException ignored) {
|
||||
}
|
||||
|
||||
verify(imapConnection).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_shouldCreateImapConnection() throws Exception {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
|
||||
assertSame(imapConnection, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_calledTwiceWithoutRelease_shouldCreateTwoImapConnection() throws Exception {
|
||||
ImapConnection imapConnectionOne = mock(ImapConnection.class);
|
||||
ImapConnection imapConnectionTwo = mock(ImapConnection.class);
|
||||
imapStore.enqueueImapConnection(imapConnectionOne);
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo);
|
||||
|
||||
ImapConnection resultOne = imapStore.getConnection();
|
||||
ImapConnection resultTwo = imapStore.getConnection();
|
||||
|
||||
assertSame(imapConnectionOne, resultOne);
|
||||
assertSame(imapConnectionTwo, resultTwo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_calledAfterRelease_shouldReturnCachedImapConnection() throws Exception {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
when(imapConnection.isOpen()).thenReturn(true);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
ImapConnection connection = imapStore.getConnection();
|
||||
imapStore.releaseConnection(connection);
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
|
||||
assertSame(imapConnection, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_calledAfterReleaseWithAClosedConnection_shouldReturnNewImapConnectionInstance()
|
||||
throws Exception {
|
||||
ImapConnection imapConnectionOne = mock(ImapConnection.class);
|
||||
ImapConnection imapConnectionTwo = mock(ImapConnection.class);
|
||||
imapStore.enqueueImapConnection(imapConnectionOne);
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo);
|
||||
imapStore.getConnection();
|
||||
when(imapConnectionOne.isOpen()).thenReturn(false);
|
||||
imapStore.releaseConnection(imapConnectionOne);
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
|
||||
assertSame(imapConnectionTwo, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_withDeadConnectionInPool_shouldReturnNewImapConnectionInstance() throws Exception {
|
||||
ImapConnection imapConnectionOne = mock(ImapConnection.class);
|
||||
ImapConnection imapConnectionTwo = mock(ImapConnection.class);
|
||||
imapStore.enqueueImapConnection(imapConnectionOne);
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo);
|
||||
imapStore.getConnection();
|
||||
when(imapConnectionOne.isOpen()).thenReturn(true);
|
||||
doThrow(IOException.class).when(imapConnectionOne).executeSimpleCommand(Commands.NOOP);
|
||||
imapStore.releaseConnection(imapConnectionOne);
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
|
||||
assertSame(imapConnectionTwo, result);
|
||||
}
|
||||
|
||||
private StoreConfig createStoreConfig() {
|
||||
StoreConfig storeConfig = mock(StoreConfig.class);
|
||||
when(storeConfig.getInboxFolderName()).thenReturn("INBOX");
|
||||
when(storeConfig.getStoreUri()).thenReturn("imap://user:password@imap.example.org");
|
||||
|
||||
return storeConfig;
|
||||
}
|
||||
|
||||
private Set<String> extractFolderNames(List<? extends Folder> folders) {
|
||||
Set<String> folderNames = new HashSet<>(folders.size());
|
||||
for (Folder folder : folders) {
|
||||
folderNames.add(folder.getName());
|
||||
}
|
||||
|
||||
return folderNames;
|
||||
}
|
||||
|
||||
|
||||
static class TestImapStore extends ImapStore {
|
||||
private Deque<ImapConnection> imapConnections = new ArrayDeque<>();
|
||||
|
||||
public TestImapStore(StoreConfig storeConfig, TrustedSocketFactory trustedSocketFactory,
|
||||
ConnectivityManager connectivityManager) throws MessagingException {
|
||||
super(storeConfig, trustedSocketFactory, connectivityManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
ImapConnection createImapConnection() {
|
||||
if (imapConnections.isEmpty()) {
|
||||
throw new AssertionError("Unexpectedly tried to create an ImapConnection instance");
|
||||
}
|
||||
return imapConnections.pop();
|
||||
}
|
||||
|
||||
public void enqueueImapConnection(ImapConnection imapConnection) {
|
||||
imapConnections.add(imapConnection);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue