Convert RealImapStoreTest
to Kotlin
This commit is contained in:
parent
48f13ca3dc
commit
002b70fcf9
1 changed files with 311 additions and 359 deletions
|
@ -1,489 +1,441 @@
|
|||
package com.fsck.k9.mail.store.imap;
|
||||
package com.fsck.k9.mail.store.imap
|
||||
|
||||
import com.fsck.k9.mail.AuthType
|
||||
import com.fsck.k9.mail.ConnectionSecurity
|
||||
import com.fsck.k9.mail.FolderType
|
||||
import com.fsck.k9.mail.MessagingException
|
||||
import com.fsck.k9.mail.ServerSettings
|
||||
import com.fsck.k9.mail.oauth.OAuth2TokenProvider
|
||||
import com.fsck.k9.mail.ssl.TrustedSocketFactory
|
||||
import com.fsck.k9.mail.store.imap.ImapResponseHelper.createImapResponse
|
||||
import com.fsck.k9.mail.store.imap.ImapStoreSettings.createExtra
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import java.io.IOException
|
||||
import java.util.ArrayDeque
|
||||
import java.util.Deque
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentMatchers.anyString
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.doThrow
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.never
|
||||
import org.mockito.kotlin.stub
|
||||
import org.mockito.kotlin.verify
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
class RealImapStoreTest {
|
||||
private val imapStore = createTestImapStore()
|
||||
|
||||
import com.fsck.k9.mail.AuthType;
|
||||
import com.fsck.k9.mail.ConnectionSecurity;
|
||||
import com.fsck.k9.mail.FolderType;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.oauth.OAuth2TokenProvider;
|
||||
import com.fsck.k9.mail.ssl.TrustedSocketFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.util.collections.Sets;
|
||||
@Test
|
||||
fun `checkSettings() should create ImapConnection and call open()`() {
|
||||
val imapConnection = createMockConnection()
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
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.ArgumentMatchers.anyString;
|
||||
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.when;
|
||||
imapStore.checkSettings()
|
||||
|
||||
|
||||
public class RealImapStoreTest {
|
||||
private ImapStoreConfig config = mock(ImapStoreConfig.class);
|
||||
private TestImapStore imapStore;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
ServerSettings serverSettings = createServerSettings();
|
||||
TrustedSocketFactory trustedSocketFactory = mock(TrustedSocketFactory.class);
|
||||
OAuth2TokenProvider oauth2TokenProvider = mock(OAuth2TokenProvider.class);
|
||||
|
||||
imapStore = new TestImapStore(serverSettings, config, trustedSocketFactory,
|
||||
oauth2TokenProvider);
|
||||
verify(imapConnection).open()
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkSettings_shouldCreateImapConnectionAndCallOpen() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
|
||||
imapStore.checkSettings();
|
||||
|
||||
verify(imapConnection).open();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkSettings_withOpenThrowing_shouldThrowMessagingException() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
doThrow(IOException.class).when(imapConnection).open();
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
fun `checkSettings() with open throwing should throw MessagingException`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { open() } doThrow IOException::class
|
||||
}
|
||||
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());
|
||||
imapStore.checkSettings()
|
||||
fail("Expected exception")
|
||||
} catch (e: MessagingException) {
|
||||
assertThat(e).hasMessageThat().isEqualTo("Unable to connect")
|
||||
assertThat(e).hasCauseThat().isInstanceOf(IOException::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withSpecialUseCapability_shouldReturnSpecialFolderInfo() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
when(imapConnection.hasCapability(Capabilities.LIST_EXTENDED)).thenReturn(true);
|
||||
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\""),
|
||||
fun `getFolders() with SPECIAL-USE capability should return special FolderInfo`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { hasCapability(Capabilities.LIST_EXTENDED) } doReturn true
|
||||
on { hasCapability(Capabilities.SPECIAL_USE) } doReturn true
|
||||
on { executeSimpleCommand("""LIST "" "*" RETURN (SPECIAL-USE)""") } doReturn listOf(
|
||||
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 \"\" \"*\" RETURN (SPECIAL-USE)")).thenReturn(imapResponses);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
)
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
List<FolderListItem> folders = imapStore.getFolders();
|
||||
val folders = imapStore.getFolders()
|
||||
|
||||
Map<String, FolderListItem> folderMap = toFolderMap(folders);
|
||||
assertEquals(FolderType.INBOX, folderMap.get("INBOX").getType());
|
||||
assertEquals(FolderType.DRAFTS, folderMap.get("[Gmail]/Drafts").getType());
|
||||
assertEquals(FolderType.SENT, folderMap.get("[Gmail]/Sent Mail").getType());
|
||||
assertEquals(FolderType.SPAM, folderMap.get("[Gmail]/Spam").getType());
|
||||
assertEquals(FolderType.TRASH, folderMap.get("[Gmail]/Trash").getType());
|
||||
assertEquals(FolderType.ARCHIVE, folderMap.get("[Gmail]/All Mail").getType());
|
||||
val foldersMap = folders.map { it.serverId to it.type }
|
||||
assertThat(foldersMap).containsExactly(
|
||||
"INBOX" to FolderType.INBOX,
|
||||
"[Gmail]/All Mail" to FolderType.ARCHIVE,
|
||||
"[Gmail]/Drafts" to FolderType.DRAFTS,
|
||||
"[Gmail]/Important" to FolderType.REGULAR,
|
||||
"[Gmail]/Sent Mail" to FolderType.SENT,
|
||||
"[Gmail]/Spam" to FolderType.SPAM,
|
||||
"[Gmail]/Starred" to FolderType.REGULAR,
|
||||
"[Gmail]/Trash" to FolderType.TRASH
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withoutSpecialUseCapability_shouldUseSimpleListCommand() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
when(imapConnection.hasCapability(Capabilities.LIST_EXTENDED)).thenReturn(true);
|
||||
when(imapConnection.hasCapability(Capabilities.SPECIAL_USE)).thenReturn(false);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
fun `getFolders() without SPECIAL-USE capability should use simple LIST command`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { hasCapability(Capabilities.LIST_EXTENDED) } doReturn true
|
||||
on { hasCapability(Capabilities.SPECIAL_USE) } doReturn false
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
imapStore.getFolders();
|
||||
imapStore.getFolders()
|
||||
|
||||
verify(imapConnection, never()).executeSimpleCommand("LIST \"\" \"*\" RETURN (SPECIAL-USE)");
|
||||
verify(imapConnection).executeSimpleCommand("LIST \"\" \"*\"");
|
||||
verify(imapConnection, never()).executeSimpleCommand("""LIST "" "*" RETURN (SPECIAL-USE)""")
|
||||
verify(imapConnection).executeSimpleCommand("""LIST "" "*"""")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withoutListExtendedCapability_shouldUseSimpleListCommand() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
when(imapConnection.hasCapability(Capabilities.LIST_EXTENDED)).thenReturn(false);
|
||||
when(imapConnection.hasCapability(Capabilities.SPECIAL_USE)).thenReturn(true);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
fun `getFolders() without LIST-EXTENDED capability should use simple LIST command`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { hasCapability(Capabilities.LIST_EXTENDED) } doReturn false
|
||||
on { hasCapability(Capabilities.SPECIAL_USE) } doReturn true
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
imapStore.getFolders();
|
||||
imapStore.getFolders()
|
||||
|
||||
verify(imapConnection, never()).executeSimpleCommand("LIST \"\" \"*\" RETURN (SPECIAL-USE)");
|
||||
verify(imapConnection).executeSimpleCommand("LIST \"\" \"*\"");
|
||||
verify(imapConnection, never()).executeSimpleCommand("""LIST "" "*" RETURN (SPECIAL-USE)""")
|
||||
verify(imapConnection).executeSimpleCommand("""LIST "" "*"""")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withoutSubscribedFoldersOnly() throws Exception {
|
||||
when(config.isSubscribedFoldersOnly()).thenReturn(false);
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
List<ImapResponse> imapResponses = Arrays.asList(
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"INBOX\""),
|
||||
createImapResponse("* LIST (\\Noselect \\HasChildren) \".\" \"Folder\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"Folder.SubFolder\""),
|
||||
fun `getFolders() with subscribedFoldersOnly = false`() {
|
||||
val imapStore = createTestImapStore(isSubscribedFoldersOnly = false)
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { executeSimpleCommand("""LIST "" "*"""") } doReturn listOf(
|
||||
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);
|
||||
)
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
List<FolderListItem> result = imapStore.getFolders();
|
||||
val folders = imapStore.getFolders()
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(Sets.newSet("INBOX", "Folder.SubFolder"), extractFolderServerIds(result));
|
||||
assertThat(folders).isNotNull()
|
||||
assertThat(folders.map { it.serverId }).containsExactly("INBOX", "Folder.SubFolder")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withSubscribedFoldersOnly_shouldOnlyReturnExistingSubscribedFolders()
|
||||
throws Exception {
|
||||
when(config.isSubscribedFoldersOnly()).thenReturn(true);
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
List<ImapResponse> lsubResponses = Arrays.asList(
|
||||
createImapResponse("* LSUB (\\HasNoChildren) \".\" \"INBOX\""),
|
||||
createImapResponse("* LSUB (\\Noselect \\HasChildren) \".\" \"Folder\""),
|
||||
createImapResponse("* LSUB (\\HasNoChildren) \".\" \"Folder.SubFolder\""),
|
||||
createImapResponse("* LSUB (\\HasNoChildren) \".\" \"SubscribedFolderThatHasBeenDeleted\""),
|
||||
fun `getFolders() with subscribedFoldersOnly = true should only return existing subscribed folders`() {
|
||||
val imapStore = createTestImapStore(isSubscribedFoldersOnly = true)
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { executeSimpleCommand("""LSUB "" "*"""") } doReturn listOf(
|
||||
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\""),
|
||||
)
|
||||
on { executeSimpleCommand("""LIST "" "*"""") } doReturn listOf(
|
||||
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);
|
||||
)
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
List<FolderListItem> result = imapStore.getFolders();
|
||||
val folders = imapStore.getFolders()
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(Sets.newSet("INBOX", "Folder.SubFolder"), extractFolderServerIds(result));
|
||||
assertThat(folders).isNotNull()
|
||||
assertThat(folders.map { it.serverId }).containsExactly("INBOX", "Folder.SubFolder")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withNamespacePrefix() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
List<ImapResponse> imapResponses = Arrays.asList(
|
||||
createImapResponse("* LIST () \".\" \"INBOX\""),
|
||||
createImapResponse("* LIST () \".\" \"INBOX.FolderOne\""),
|
||||
createImapResponse("* LIST () \".\" \"INBOX.FolderTwo\""),
|
||||
fun `getFolders() with namespace prefix`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { executeSimpleCommand("""LIST "" "INBOX.*"""") } doReturn listOf(
|
||||
createImapResponse("""* LIST () "." "INBOX""""),
|
||||
createImapResponse("""* LIST () "." "INBOX.FolderOne""""),
|
||||
createImapResponse("""* LIST () "." "INBOX.FolderTwo""""),
|
||||
createImapResponse("5 OK Success")
|
||||
);
|
||||
when(imapConnection.executeSimpleCommand("LIST \"\" \"INBOX.*\"")).thenReturn(imapResponses);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
imapStore.setTestCombinedPrefix("INBOX.");
|
||||
)
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
imapStore.setTestCombinedPrefix("INBOX.")
|
||||
|
||||
List<FolderListItem> result = imapStore.getFolders();
|
||||
val folders = imapStore.getFolders()
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(Sets.newSet("INBOX", "INBOX.FolderOne", "INBOX.FolderTwo"), extractFolderServerIds(result));
|
||||
assertEquals(Sets.newSet("INBOX", "FolderOne", "FolderTwo"), extractFolderNames(result));
|
||||
assertEquals(Sets.newSet("INBOX", "FolderOne", "FolderTwo"), extractOldFolderServerIds(result));
|
||||
assertThat(folders).isNotNull()
|
||||
assertThat(folders.map { it.serverId }).containsExactly("INBOX", "INBOX.FolderOne", "INBOX.FolderTwo")
|
||||
assertThat(folders.map { it.name }).containsExactly("INBOX", "FolderOne", "FolderTwo")
|
||||
assertThat(folders.map { it.oldServerId }).containsExactly("INBOX", "FolderOne", "FolderTwo")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withFolderNotMatchingNamespacePrefix() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
List<ImapResponse> imapResponses = Arrays.asList(
|
||||
createImapResponse("* LIST () \".\" \"INBOX\""),
|
||||
createImapResponse("* LIST () \".\" \"INBOX.FolderOne\""),
|
||||
createImapResponse("* LIST () \".\" \"FolderTwo\""),
|
||||
fun `getFolders() with folder not matching namespace prefix`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { executeSimpleCommand("""LIST "" "INBOX.*"""") } doReturn listOf(
|
||||
createImapResponse("""* LIST () "." "INBOX""""),
|
||||
createImapResponse("""* LIST () "." "INBOX.FolderOne""""),
|
||||
createImapResponse("""* LIST () "." "FolderTwo""""),
|
||||
createImapResponse("5 OK Success")
|
||||
);
|
||||
when(imapConnection.executeSimpleCommand("LIST \"\" \"INBOX.*\"")).thenReturn(imapResponses);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
imapStore.setTestCombinedPrefix("INBOX.");
|
||||
)
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
imapStore.setTestCombinedPrefix("INBOX.")
|
||||
|
||||
List<FolderListItem> result = imapStore.getFolders();
|
||||
val folders = imapStore.getFolders()
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(Sets.newSet("INBOX", "INBOX.FolderOne", "FolderTwo"), extractFolderServerIds(result));
|
||||
assertEquals(Sets.newSet("INBOX", "FolderOne", "FolderTwo"), extractFolderNames(result));
|
||||
assertEquals(Sets.newSet("INBOX", "FolderOne"), extractOldFolderServerIds(result));
|
||||
assertThat(folders).isNotNull()
|
||||
assertThat(folders.map { it.serverId }).containsExactly("INBOX", "INBOX.FolderOne", "FolderTwo")
|
||||
assertThat(folders.map { it.name }).containsExactly("INBOX", "FolderOne", "FolderTwo")
|
||||
assertThat(folders.mapNotNull { it.oldServerId }).containsExactly("INBOX", "FolderOne")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withDuplicateFolderNames_shouldRemoveDuplicatesAndKeepFolderType()
|
||||
throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
when(imapConnection.hasCapability(Capabilities.LIST_EXTENDED)).thenReturn(true);
|
||||
when(imapConnection.hasCapability(Capabilities.SPECIAL_USE)).thenReturn(true);
|
||||
List<ImapResponse> imapResponses = Arrays.asList(
|
||||
createImapResponse("* LIST () \".\" \"INBOX\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"Junk\""),
|
||||
createImapResponse("* LIST (\\Junk) \".\" \"Junk\""),
|
||||
createImapResponse("* LIST (\\HasNoChildren) \".\" \"Junk\""),
|
||||
fun `getFolders() with duplicate folder names should remove duplicates and keep FolderType`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { hasCapability(Capabilities.LIST_EXTENDED) } doReturn true
|
||||
on { hasCapability(Capabilities.SPECIAL_USE) } doReturn true
|
||||
on { executeSimpleCommand("""LIST "" "*" RETURN (SPECIAL-USE)""") } doReturn listOf(
|
||||
createImapResponse("""* LIST () "." "INBOX""""),
|
||||
createImapResponse("""* LIST (\HasNoChildren) "." "Junk""""),
|
||||
createImapResponse("""* LIST (\Junk) "." "Junk""""),
|
||||
createImapResponse("""* LIST (\HasNoChildren) "." "Junk""""),
|
||||
createImapResponse("5 OK Success")
|
||||
);
|
||||
when(imapConnection.executeSimpleCommand("LIST \"\" \"*\" RETURN (SPECIAL-USE)")).thenReturn(imapResponses);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
)
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
List<FolderListItem> result = imapStore.getFolders();
|
||||
val folders = imapStore.getFolders()
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.size());
|
||||
FolderListItem junkFolder = getFolderByServerId(result, "Junk");
|
||||
assertNotNull(junkFolder);
|
||||
assertEquals(FolderType.SPAM, junkFolder.getType());
|
||||
assertThat(folders.map { it.serverId to it.type }).containsExactly(
|
||||
"INBOX" to FolderType.INBOX,
|
||||
"Junk" to FolderType.SPAM
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withoutException_shouldLeaveImapConnectionOpen() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
List<ImapResponse> imapResponses = Collections.singletonList(createImapResponse("5 OK Success"));
|
||||
when(imapConnection.executeSimpleCommand(anyString())).thenReturn(imapResponses);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
fun `getFolders() without exception should leave ImapConnection open`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { executeSimpleCommand(anyString()) } doReturn listOf(createImapResponse("5 OK Success"))
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
imapStore.getFolders();
|
||||
imapStore.getFolders()
|
||||
|
||||
verify(imapConnection, never()).close();
|
||||
verify(imapConnection, never()).close()
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFolders_withIoException_shouldCloseImapConnection() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
doThrow(IOException.class).when(imapConnection).executeSimpleCommand("LIST \"\" \"*\"");
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
fun `getFolders() with IOException should close ImapConnection`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { executeSimpleCommand("""LIST "" "*"""") } doThrow IOException::class
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
try {
|
||||
imapStore.getFolders();
|
||||
fail("Expected exception");
|
||||
} catch (MessagingException ignored) {
|
||||
imapStore.getFolders()
|
||||
fail("Expected exception")
|
||||
} catch (ignored: MessagingException) {
|
||||
}
|
||||
|
||||
verify(imapConnection).close();
|
||||
verify(imapConnection).close()
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_shouldCreateImapConnection() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
fun `getConnection() should create ImapConnection`() {
|
||||
val imapConnection = createMockConnection()
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
val result = imapStore.getConnection()
|
||||
|
||||
assertSame(imapConnection, result);
|
||||
assertThat(result).isSameInstanceAs(imapConnection)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_calledTwiceWithoutRelease_shouldCreateTwoImapConnection() throws Exception {
|
||||
ImapConnection imapConnectionOne = createMockConnection();
|
||||
ImapConnection imapConnectionTwo = createMockConnection();
|
||||
imapStore.enqueueImapConnection(imapConnectionOne);
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo);
|
||||
fun `getConnection() called twice without release should create two ImapConnection instances`() {
|
||||
val imapConnectionOne = createMockConnection()
|
||||
val imapConnectionTwo = createMockConnection()
|
||||
imapStore.enqueueImapConnection(imapConnectionOne)
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo)
|
||||
|
||||
ImapConnection resultOne = imapStore.getConnection();
|
||||
ImapConnection resultTwo = imapStore.getConnection();
|
||||
val resultOne = imapStore.getConnection()
|
||||
val resultTwo = imapStore.getConnection()
|
||||
|
||||
assertSame(imapConnectionOne, resultOne);
|
||||
assertSame(imapConnectionTwo, resultTwo);
|
||||
assertThat(resultOne).isSameInstanceAs(imapConnectionOne)
|
||||
assertThat(resultTwo).isSameInstanceAs(imapConnectionTwo)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_calledAfterRelease_shouldReturnCachedImapConnection() throws Exception {
|
||||
ImapConnection imapConnection = createMockConnection();
|
||||
when(imapConnection.isConnected()).thenReturn(true);
|
||||
imapStore.enqueueImapConnection(imapConnection);
|
||||
ImapConnection connection = imapStore.getConnection();
|
||||
imapStore.releaseConnection(connection);
|
||||
fun `getConnection() called after release should return cached ImapConnection`() {
|
||||
val imapConnection = createMockConnection().stub {
|
||||
on { isConnected } doReturn true
|
||||
}
|
||||
imapStore.enqueueImapConnection(imapConnection)
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
val connection = imapStore.getConnection()
|
||||
imapStore.releaseConnection(connection)
|
||||
|
||||
assertSame(imapConnection, result);
|
||||
val result = imapStore.getConnection()
|
||||
|
||||
assertThat(result).isSameInstanceAs(imapConnection)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_calledAfterReleaseWithAClosedConnection_shouldReturnNewImapConnectionInstance()
|
||||
throws Exception {
|
||||
ImapConnection imapConnectionOne = createMockConnection();
|
||||
ImapConnection imapConnectionTwo = createMockConnection();
|
||||
imapStore.enqueueImapConnection(imapConnectionOne);
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo);
|
||||
imapStore.getConnection();
|
||||
when(imapConnectionOne.isConnected()).thenReturn(false);
|
||||
imapStore.releaseConnection(imapConnectionOne);
|
||||
fun `getConnection() called after release with closed connection should return new ImapConnection instance`() {
|
||||
val imapConnectionOne = createMockConnection()
|
||||
val imapConnectionTwo = createMockConnection()
|
||||
imapStore.enqueueImapConnection(imapConnectionOne)
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo)
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
imapStore.getConnection()
|
||||
imapConnectionOne.stub {
|
||||
on { isConnected } doReturn false
|
||||
}
|
||||
imapStore.releaseConnection(imapConnectionOne)
|
||||
|
||||
assertSame(imapConnectionTwo, result);
|
||||
val result = imapStore.getConnection()
|
||||
|
||||
assertThat(result).isSameInstanceAs(imapConnectionTwo)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_withDeadConnectionInPool_shouldReturnNewImapConnectionInstance() throws Exception {
|
||||
ImapConnection imapConnectionOne = createMockConnection();
|
||||
ImapConnection imapConnectionTwo = createMockConnection();
|
||||
imapStore.enqueueImapConnection(imapConnectionOne);
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo);
|
||||
imapStore.getConnection();
|
||||
when(imapConnectionOne.isConnected()).thenReturn(true);
|
||||
doThrow(IOException.class).when(imapConnectionOne).executeSimpleCommand(Commands.NOOP);
|
||||
imapStore.releaseConnection(imapConnectionOne);
|
||||
fun `getConnection() with dead connection in pool should return new ImapConnection instance`() {
|
||||
val imapConnectionOne = createMockConnection()
|
||||
val imapConnectionTwo = createMockConnection()
|
||||
imapStore.enqueueImapConnection(imapConnectionOne)
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo)
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
imapStore.getConnection()
|
||||
imapConnectionOne.stub {
|
||||
on { isConnected } doReturn true
|
||||
on { executeSimpleCommand(Commands.NOOP) } doThrow IOException::class
|
||||
}
|
||||
imapStore.releaseConnection(imapConnectionOne)
|
||||
|
||||
assertSame(imapConnectionTwo, result);
|
||||
val result = imapStore.getConnection()
|
||||
|
||||
assertThat(result).isSameInstanceAs(imapConnectionTwo)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_withConnectionInPoolAndCloseAllConnections_shouldReturnNewImapConnectionInstance()
|
||||
throws Exception {
|
||||
ImapConnection imapConnectionOne = createMockConnection(1);
|
||||
ImapConnection imapConnectionTwo = createMockConnection(2);
|
||||
imapStore.enqueueImapConnection(imapConnectionOne);
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo);
|
||||
imapStore.getConnection();
|
||||
when(imapConnectionOne.isConnected()).thenReturn(true);
|
||||
imapStore.releaseConnection(imapConnectionOne);
|
||||
imapStore.closeAllConnections();
|
||||
fun `getConnection() with connection in pool and closeAllConnections() should return new ImapConnection instance`() {
|
||||
val imapConnectionOne = createMockConnection(1)
|
||||
val imapConnectionTwo = createMockConnection(2)
|
||||
imapStore.enqueueImapConnection(imapConnectionOne)
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo)
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
imapStore.getConnection()
|
||||
imapConnectionOne.stub {
|
||||
on { isConnected } doReturn true
|
||||
}
|
||||
imapStore.releaseConnection(imapConnectionOne)
|
||||
imapStore.closeAllConnections()
|
||||
|
||||
assertSame(imapConnectionTwo, result);
|
||||
val result = imapStore.getConnection()
|
||||
|
||||
assertThat(result).isSameInstanceAs(imapConnectionTwo)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConnection_withConnectionOutsideOfPoolAndCloseAllConnections_shouldReturnNewImapConnectionInstance()
|
||||
throws Exception {
|
||||
ImapConnection imapConnectionOne = createMockConnection(1);
|
||||
ImapConnection imapConnectionTwo = createMockConnection(2);
|
||||
imapStore.enqueueImapConnection(imapConnectionOne);
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo);
|
||||
imapStore.getConnection();
|
||||
when(imapConnectionOne.isConnected()).thenReturn(true);
|
||||
imapStore.closeAllConnections();
|
||||
imapStore.releaseConnection(imapConnectionOne);
|
||||
fun `getConnection() with connection outside of pool and closeAllConnections() should return new ImapConnection instance`() {
|
||||
val imapConnectionOne = createMockConnection(1)
|
||||
val imapConnectionTwo = createMockConnection(2)
|
||||
imapStore.enqueueImapConnection(imapConnectionOne)
|
||||
imapStore.enqueueImapConnection(imapConnectionTwo)
|
||||
|
||||
ImapConnection result = imapStore.getConnection();
|
||||
|
||||
assertSame(imapConnectionTwo, result);
|
||||
}
|
||||
|
||||
|
||||
private ImapConnection createMockConnection() {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
when(imapConnection.getConnectionGeneration()).thenReturn(1);
|
||||
return imapConnection;
|
||||
}
|
||||
|
||||
private ImapConnection createMockConnection(int connectionGeneration) {
|
||||
ImapConnection imapConnection = mock(ImapConnection.class);
|
||||
when(imapConnection.getConnectionGeneration()).thenReturn(connectionGeneration);
|
||||
return imapConnection;
|
||||
}
|
||||
|
||||
|
||||
private ServerSettings createServerSettings() {
|
||||
Map<String, String> extra = ImapStoreSettings.createExtra(true, null);
|
||||
return new ServerSettings(
|
||||
"imap",
|
||||
"imap.example.org",
|
||||
143,
|
||||
ConnectionSecurity.NONE,
|
||||
AuthType.PLAIN,
|
||||
"user",
|
||||
"password",
|
||||
null,
|
||||
extra);
|
||||
}
|
||||
|
||||
private Set<String> extractFolderServerIds(List<FolderListItem> folders) {
|
||||
Set<String> folderServerIds = new HashSet<>(folders.size());
|
||||
for (FolderListItem folder : folders) {
|
||||
folderServerIds.add(folder.getServerId());
|
||||
imapStore.getConnection()
|
||||
imapConnectionOne.stub {
|
||||
on { isConnected } doReturn true
|
||||
}
|
||||
imapStore.closeAllConnections()
|
||||
imapStore.releaseConnection(imapConnectionOne)
|
||||
|
||||
return folderServerIds;
|
||||
val result = imapStore.getConnection()
|
||||
|
||||
assertThat(result).isSameInstanceAs(imapConnectionTwo)
|
||||
}
|
||||
|
||||
private Set<String> extractFolderNames(List<FolderListItem> folders) {
|
||||
Set<String> folderNames = new HashSet<>(folders.size());
|
||||
for (FolderListItem folder : folders) {
|
||||
folderNames.add(folder.getName());
|
||||
private fun createMockConnection(connectionGeneration: Int = 1): ImapConnection {
|
||||
return mock {
|
||||
on { this.connectionGeneration } doReturn connectionGeneration
|
||||
}
|
||||
|
||||
return folderNames;
|
||||
}
|
||||
|
||||
private Set<String> extractOldFolderServerIds(List<FolderListItem> folders) {
|
||||
Set<String> folderNames = new HashSet<>(folders.size());
|
||||
for (FolderListItem folder : folders) {
|
||||
String oldServerId = folder.getOldServerId();
|
||||
if (oldServerId != null) {
|
||||
folderNames.add(oldServerId);
|
||||
}
|
||||
}
|
||||
|
||||
return folderNames;
|
||||
private fun createServerSettings(): ServerSettings {
|
||||
return ServerSettings(
|
||||
type = "imap",
|
||||
host = "imap.example.org",
|
||||
port = 143,
|
||||
connectionSecurity = ConnectionSecurity.NONE,
|
||||
authenticationType = AuthType.PLAIN,
|
||||
username = "user",
|
||||
password = "password",
|
||||
clientCertificateAlias = null,
|
||||
extra = createExtra(autoDetectNamespace = true, pathPrefix = null)
|
||||
)
|
||||
}
|
||||
|
||||
private FolderListItem getFolderByServerId(List<FolderListItem> result, String serverId) {
|
||||
for (FolderListItem imapFolder : result) {
|
||||
if (imapFolder.getServerId().equals(serverId)) {
|
||||
return imapFolder;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
private fun createTestImapStore(
|
||||
isSubscribedFoldersOnly: Boolean = false,
|
||||
useCompression: Boolean = false
|
||||
): TestImapStore {
|
||||
return TestImapStore(
|
||||
serverSettings = createServerSettings(),
|
||||
config = createImapStoreConfig(isSubscribedFoldersOnly, useCompression),
|
||||
trustedSocketFactory = mock(),
|
||||
oauth2TokenProvider = null
|
||||
)
|
||||
}
|
||||
|
||||
private Map<String, FolderListItem> toFolderMap(List<FolderListItem> folders) {
|
||||
Map<String, FolderListItem> folderMap = new HashMap<>();
|
||||
for (FolderListItem folder : folders) {
|
||||
folderMap.put(folder.getServerId(), folder);
|
||||
private fun createImapStoreConfig(isSubscribedFoldersOnly: Boolean, useCompression: Boolean): ImapStoreConfig {
|
||||
return object : ImapStoreConfig {
|
||||
override val logLabel: String = "irrelevant"
|
||||
override fun isSubscribedFoldersOnly(): Boolean = isSubscribedFoldersOnly
|
||||
override fun useCompression(): Boolean = useCompression
|
||||
}
|
||||
|
||||
return folderMap;
|
||||
}
|
||||
|
||||
private class TestImapStore(
|
||||
serverSettings: ServerSettings,
|
||||
config: ImapStoreConfig,
|
||||
trustedSocketFactory: TrustedSocketFactory,
|
||||
oauth2TokenProvider: OAuth2TokenProvider?
|
||||
) : RealImapStore(
|
||||
serverSettings, config, trustedSocketFactory, oauth2TokenProvider
|
||||
) {
|
||||
private val imapConnections: Deque<ImapConnection> = ArrayDeque()
|
||||
private var testCombinedPrefix: String? = null
|
||||
|
||||
static class TestImapStore extends RealImapStore {
|
||||
private Deque<ImapConnection> imapConnections = new ArrayDeque<>();
|
||||
private String testCombinedPrefix;
|
||||
|
||||
public TestImapStore(ServerSettings serverSettings, ImapStoreConfig config,
|
||||
TrustedSocketFactory trustedSocketFactory, OAuth2TokenProvider oauth2TokenProvider) {
|
||||
super(serverSettings, config, trustedSocketFactory, oauth2TokenProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImapConnection createImapConnection() {
|
||||
override fun createImapConnection(): ImapConnection {
|
||||
if (imapConnections.isEmpty()) {
|
||||
throw new AssertionError("Unexpectedly tried to create an ImapConnection instance");
|
||||
throw AssertionError("Unexpectedly tried to create an ImapConnection instance")
|
||||
}
|
||||
return imapConnections.pop();
|
||||
|
||||
return imapConnections.pop()
|
||||
}
|
||||
|
||||
public void enqueueImapConnection(ImapConnection imapConnection) {
|
||||
imapConnections.add(imapConnection);
|
||||
fun enqueueImapConnection(imapConnection: ImapConnection) {
|
||||
imapConnections.add(imapConnection)
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getCombinedPrefix() {
|
||||
return testCombinedPrefix != null ? testCombinedPrefix : super.getCombinedPrefix();
|
||||
override fun getCombinedPrefix(): String {
|
||||
return testCombinedPrefix ?: super.getCombinedPrefix()
|
||||
}
|
||||
|
||||
void setTestCombinedPrefix(String prefix) {
|
||||
testCombinedPrefix = prefix;
|
||||
fun setTestCombinedPrefix(prefix: String?) {
|
||||
testCombinedPrefix = prefix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue