Test sending of pending messages
This commit is contained in:
parent
8ee9b2c591
commit
2e01043a28
5 changed files with 224 additions and 52 deletions
|
@ -15,24 +15,12 @@ import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
public abstract class Transport {
|
public abstract class Transport {
|
||||||
|
|
||||||
protected static final int SOCKET_CONNECT_TIMEOUT = 10000;
|
protected static final int SOCKET_CONNECT_TIMEOUT = 10000;
|
||||||
|
|
||||||
// RFC 1047
|
// RFC 1047
|
||||||
protected static final int SOCKET_READ_TIMEOUT = 300000;
|
protected static final int SOCKET_READ_TIMEOUT = 300000;
|
||||||
|
|
||||||
public static synchronized Transport getInstance(Context context, StoreConfig storeConfig)
|
|
||||||
throws MessagingException {
|
|
||||||
String uri = storeConfig.getTransportUri();
|
|
||||||
if (uri.startsWith("smtp")) {
|
|
||||||
OAuth2TokenProvider oauth2TokenProvider = null;
|
|
||||||
return new SmtpTransport(storeConfig, new DefaultTrustedSocketFactory(context), oauth2TokenProvider);
|
|
||||||
} else if (uri.startsWith("webdav")) {
|
|
||||||
return new WebDavTransport(storeConfig);
|
|
||||||
} else {
|
|
||||||
throw new MessagingException("Unable to locate an applicable Transport for " + uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes the contents of transport-specific URIs and puts them into a {@link ServerSettings}
|
* Decodes the contents of transport-specific URIs and puts them into a {@link ServerSettings}
|
||||||
* object.
|
* object.
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.fsck.k9.mail;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.fsck.k9.mail.oauth.OAuth2TokenProvider;
|
||||||
|
import com.fsck.k9.mail.ssl.DefaultTrustedSocketFactory;
|
||||||
|
import com.fsck.k9.mail.store.StoreConfig;
|
||||||
|
import com.fsck.k9.mail.transport.SmtpTransport;
|
||||||
|
import com.fsck.k9.mail.transport.WebDavTransport;
|
||||||
|
|
||||||
|
public class TransportProvider {
|
||||||
|
private static TransportProvider transportProvider = new TransportProvider();
|
||||||
|
|
||||||
|
public static TransportProvider getInstance() {
|
||||||
|
return transportProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Transport getInstance(Context context, StoreConfig storeConfig)
|
||||||
|
throws MessagingException {
|
||||||
|
String uri = storeConfig.getTransportUri();
|
||||||
|
if (uri.startsWith("smtp")) {
|
||||||
|
OAuth2TokenProvider oauth2TokenProvider = null;
|
||||||
|
return new SmtpTransport(storeConfig, new DefaultTrustedSocketFactory(context),
|
||||||
|
oauth2TokenProvider);
|
||||||
|
} else if (uri.startsWith("webdav")) {
|
||||||
|
return new WebDavTransport(storeConfig);
|
||||||
|
} else {
|
||||||
|
throw new MessagingException("Unable to locate an applicable Transport for " + uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ import com.fsck.k9.mail.CertificateValidationException;
|
||||||
import com.fsck.k9.mail.MessagingException;
|
import com.fsck.k9.mail.MessagingException;
|
||||||
import com.fsck.k9.mail.Store;
|
import com.fsck.k9.mail.Store;
|
||||||
import com.fsck.k9.mail.Transport;
|
import com.fsck.k9.mail.Transport;
|
||||||
|
import com.fsck.k9.mail.TransportProvider;
|
||||||
import com.fsck.k9.mail.store.webdav.WebDavStore;
|
import com.fsck.k9.mail.store.webdav.WebDavStore;
|
||||||
import com.fsck.k9.mail.filter.Hex;
|
import com.fsck.k9.mail.filter.Hex;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
@ -475,7 +476,7 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
||||||
if (!(account.getRemoteStore() instanceof WebDavStore)) {
|
if (!(account.getRemoteStore() instanceof WebDavStore)) {
|
||||||
publishProgress(R.string.account_setup_check_settings_check_outgoing_msg);
|
publishProgress(R.string.account_setup_check_settings_check_outgoing_msg);
|
||||||
}
|
}
|
||||||
Transport transport = Transport.getInstance(K9.app, account);
|
Transport transport = TransportProvider.getInstance().getInstance(K9.app, account);
|
||||||
transport.close();
|
transport.close();
|
||||||
try {
|
try {
|
||||||
transport.open();
|
transport.open();
|
||||||
|
|
|
@ -82,6 +82,7 @@ import com.fsck.k9.mail.PushReceiver;
|
||||||
import com.fsck.k9.mail.Pusher;
|
import com.fsck.k9.mail.Pusher;
|
||||||
import com.fsck.k9.mail.Store;
|
import com.fsck.k9.mail.Store;
|
||||||
import com.fsck.k9.mail.Transport;
|
import com.fsck.k9.mail.Transport;
|
||||||
|
import com.fsck.k9.mail.TransportProvider;
|
||||||
import com.fsck.k9.mail.internet.MessageExtractor;
|
import com.fsck.k9.mail.internet.MessageExtractor;
|
||||||
import com.fsck.k9.mail.internet.MimeMessage;
|
import com.fsck.k9.mail.internet.MimeMessage;
|
||||||
import com.fsck.k9.mail.internet.MimeMessageHelper;
|
import com.fsck.k9.mail.internet.MimeMessageHelper;
|
||||||
|
@ -140,6 +141,7 @@ public class MessagingController {
|
||||||
private final ConcurrentHashMap<Account, Pusher> pushers = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<Account, Pusher> pushers = new ConcurrentHashMap<>();
|
||||||
private final ExecutorService threadPool = Executors.newCachedThreadPool();
|
private final ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||||
private final MemorizingMessagingListener memorizingMessagingListener = new MemorizingMessagingListener();
|
private final MemorizingMessagingListener memorizingMessagingListener = new MemorizingMessagingListener();
|
||||||
|
private final TransportProvider transportProvider;
|
||||||
|
|
||||||
|
|
||||||
private MessagingListener checkMailListener = null;
|
private MessagingListener checkMailListener = null;
|
||||||
|
@ -151,17 +153,20 @@ public class MessagingController {
|
||||||
Context appContext = context.getApplicationContext();
|
Context appContext = context.getApplicationContext();
|
||||||
NotificationController notificationController = NotificationController.newInstance(appContext);
|
NotificationController notificationController = NotificationController.newInstance(appContext);
|
||||||
Contacts contacts = Contacts.getInstance(context);
|
Contacts contacts = Contacts.getInstance(context);
|
||||||
inst = new MessagingController(appContext, notificationController, contacts);
|
TransportProvider transportProvider = TransportProvider.getInstance();
|
||||||
|
inst = new MessagingController(appContext, notificationController, contacts, transportProvider);
|
||||||
}
|
}
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
MessagingController(Context context, NotificationController notificationController, Contacts contacts) {
|
MessagingController(Context context, NotificationController notificationController,
|
||||||
|
Contacts contacts, TransportProvider transportProvider) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.notificationController = notificationController;
|
this.notificationController = notificationController;
|
||||||
this.contacts = contacts;
|
this.contacts = contacts;
|
||||||
|
this.transportProvider = transportProvider;
|
||||||
|
|
||||||
controllerThread = new Thread(new Runnable() {
|
controllerThread = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -2717,7 +2722,8 @@ public class MessagingController {
|
||||||
/**
|
/**
|
||||||
* Attempt to send any messages that are sitting in the Outbox.
|
* Attempt to send any messages that are sitting in the Outbox.
|
||||||
*/
|
*/
|
||||||
private void sendPendingMessagesSynchronous(final Account account) {
|
@VisibleForTesting
|
||||||
|
protected void sendPendingMessagesSynchronous(final Account account) {
|
||||||
LocalFolder localFolder = null;
|
LocalFolder localFolder = null;
|
||||||
Exception lastFailure = null;
|
Exception lastFailure = null;
|
||||||
boolean wasPermanentFailure = false;
|
boolean wasPermanentFailure = false;
|
||||||
|
@ -2726,6 +2732,9 @@ public class MessagingController {
|
||||||
localFolder = localStore.getFolder(
|
localFolder = localStore.getFolder(
|
||||||
account.getOutboxFolderName());
|
account.getOutboxFolderName());
|
||||||
if (!localFolder.exists()) {
|
if (!localFolder.exists()) {
|
||||||
|
if (K9.DEBUG) {
|
||||||
|
Log.v(K9.LOG_TAG, "Outbox does not exist");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (MessagingListener l : getListeners()) {
|
for (MessagingListener l : getListeners()) {
|
||||||
|
@ -2748,9 +2757,11 @@ public class MessagingController {
|
||||||
fp.add(FetchProfile.Item.BODY);
|
fp.add(FetchProfile.Item.BODY);
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.i(K9.LOG_TAG, "Scanning folder '" + account.getOutboxFolderName() + "' (" + localFolder.getId() + ") for messages to send");
|
Log.i(K9.LOG_TAG, "Scanning folder '" + account.getOutboxFolderName()
|
||||||
|
+ "' (" + localFolder.getId() + ") for messages to send");
|
||||||
|
|
||||||
|
Transport transport = transportProvider.getInstance(K9.app, account);
|
||||||
|
|
||||||
Transport transport = Transport.getInstance(K9.app, account);
|
|
||||||
for (LocalMessage message : localMessages) {
|
for (LocalMessage message : localMessages) {
|
||||||
if (message.isSet(Flag.DELETED)) {
|
if (message.isSet(Flag.DELETED)) {
|
||||||
message.destroy();
|
message.destroy();
|
||||||
|
@ -2762,31 +2773,25 @@ public class MessagingController {
|
||||||
if (oldCount != null) {
|
if (oldCount != null) {
|
||||||
count = oldCount;
|
count = oldCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.i(K9.LOG_TAG, "Send count for message " + message.getUid() + " is " + count.get());
|
Log.i(K9.LOG_TAG, "Send count for message " + message.getUid() + " is " + count.get());
|
||||||
|
|
||||||
if (count.incrementAndGet() > K9.MAX_SEND_ATTEMPTS) {
|
if (count.incrementAndGet() > K9.MAX_SEND_ATTEMPTS) {
|
||||||
Log.e(K9.LOG_TAG, "Send count for message " + message.getUid() + " can't be delivered after " + K9.MAX_SEND_ATTEMPTS + " attempts. Giving up until the user restarts the device");
|
Log.e(K9.LOG_TAG, "Send count for message " + message.getUid() + " can't be delivered after "
|
||||||
|
+ K9.MAX_SEND_ATTEMPTS + " attempts. Giving up until the user restarts the device");
|
||||||
notificationController.showSendFailedNotification(account,
|
notificationController.showSendFailedNotification(account,
|
||||||
new MessagingException(message.getSubject()));
|
new MessagingException(message.getSubject()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
localFolder.fetch(Collections.singletonList(message), fp, null);
|
localFolder.fetch(Collections.singletonList(message), fp, null);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
||||||
if (message.getHeader(K9.IDENTITY_HEADER).length > 0) {
|
if (message.getHeader(K9.IDENTITY_HEADER).length > 0) {
|
||||||
Log.v(K9.LOG_TAG, "The user has set the Outbox and Drafts folder to the same thing. " +
|
Log.v(K9.LOG_TAG, "The user has set the Outbox and Drafts folder to the same thing. " +
|
||||||
"This message appears to be a draft, so K-9 will not send it");
|
"This message appears to be a draft, so K-9 will not send it");
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
message.setFlag(Flag.X_SEND_IN_PROGRESS, true);
|
message.setFlag(Flag.X_SEND_IN_PROGRESS, true);
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.i(K9.LOG_TAG, "Sending message with UID " + message.getUid());
|
Log.i(K9.LOG_TAG, "Sending message with UID " + message.getUid());
|
||||||
|
@ -2797,24 +2802,7 @@ public class MessagingController {
|
||||||
for (MessagingListener l : getListeners()) {
|
for (MessagingListener l : getListeners()) {
|
||||||
l.synchronizeMailboxProgress(account, account.getSentFolderName(), progress, todo);
|
l.synchronizeMailboxProgress(account, account.getSentFolderName(), progress, todo);
|
||||||
}
|
}
|
||||||
if (!account.hasSentFolder()) {
|
moveOrDeleteSentMessage(account, localStore, localFolder, message);
|
||||||
if (K9.DEBUG)
|
|
||||||
Log.i(K9.LOG_TAG, "Account does not have a sent mail folder; deleting sent message");
|
|
||||||
message.setFlag(Flag.DELETED, true);
|
|
||||||
} else {
|
|
||||||
LocalFolder localSentFolder = localStore.getFolder(account.getSentFolderName());
|
|
||||||
if (K9.DEBUG)
|
|
||||||
Log.i(K9.LOG_TAG, "Moving sent message to folder '" + account.getSentFolderName() + "' (" + localSentFolder.getId() + ") ");
|
|
||||||
|
|
||||||
localFolder.moveMessages(Collections.singletonList(message), localSentFolder);
|
|
||||||
|
|
||||||
if (K9.DEBUG)
|
|
||||||
Log.i(K9.LOG_TAG, "Moved sent message to folder '" + account.getSentFolderName() + "' (" + localSentFolder.getId() + ") ");
|
|
||||||
|
|
||||||
PendingCommand command = PendingAppend.create(localSentFolder.getName(), message.getUid());
|
|
||||||
queuePendingCommand(account, command);
|
|
||||||
processPendingCommands(account);
|
|
||||||
}
|
|
||||||
} catch (AuthenticationFailedException e) {
|
} catch (AuthenticationFailedException e) {
|
||||||
lastFailure = e;
|
lastFailure = e;
|
||||||
wasPermanentFailure = false;
|
wasPermanentFailure = false;
|
||||||
|
@ -2841,9 +2829,7 @@ public class MessagingController {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
lastFailure = e;
|
lastFailure = e;
|
||||||
wasPermanentFailure = false;
|
wasPermanentFailure = false;
|
||||||
|
|
||||||
Log.e(K9.LOG_TAG, "Failed to fetch message for sending", e);
|
Log.e(K9.LOG_TAG, "Failed to fetch message for sending", e);
|
||||||
|
|
||||||
addErrorMessage(account, "Failed to fetch message for sending", e);
|
addErrorMessage(account, "Failed to fetch message for sending", e);
|
||||||
notifySynchronizeMailboxFailed(account, localFolder, e);
|
notifySynchronizeMailboxFailed(account, localFolder, e);
|
||||||
}
|
}
|
||||||
|
@ -2864,6 +2850,9 @@ public class MessagingController {
|
||||||
Log.i(K9.LOG_TAG, "Failed to send pending messages because storage is not available - trying again later.");
|
Log.i(K9.LOG_TAG, "Failed to send pending messages because storage is not available - trying again later.");
|
||||||
throw new UnavailableAccountException(e);
|
throw new UnavailableAccountException(e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
if (K9.DEBUG) {
|
||||||
|
Log.v(K9.LOG_TAG, "Failed to send pending messages", e);
|
||||||
|
}
|
||||||
for (MessagingListener l : getListeners()) {
|
for (MessagingListener l : getListeners()) {
|
||||||
l.sendPendingMessagesFailed(account);
|
l.sendPendingMessagesFailed(account);
|
||||||
}
|
}
|
||||||
|
@ -2877,6 +2866,28 @@ public class MessagingController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void moveOrDeleteSentMessage(Account account, LocalStore localStore,
|
||||||
|
LocalFolder localFolder, LocalMessage message) throws MessagingException {
|
||||||
|
if (!account.hasSentFolder()) {
|
||||||
|
if (K9.DEBUG)
|
||||||
|
Log.i(K9.LOG_TAG, "Account does not have a sent mail folder; deleting sent message");
|
||||||
|
message.setFlag(Flag.DELETED, true);
|
||||||
|
} else {
|
||||||
|
LocalFolder localSentFolder = localStore.getFolder(account.getSentFolderName());
|
||||||
|
if (K9.DEBUG)
|
||||||
|
Log.i(K9.LOG_TAG, "Moving sent message to folder '" + account.getSentFolderName() + "' (" + localSentFolder.getId() + ") ");
|
||||||
|
|
||||||
|
localFolder.moveMessages(Collections.singletonList(message), localSentFolder);
|
||||||
|
|
||||||
|
if (K9.DEBUG)
|
||||||
|
Log.i(K9.LOG_TAG, "Moved sent message to folder '" + account.getSentFolderName() + "' (" + localSentFolder.getId() + ") ");
|
||||||
|
|
||||||
|
PendingCommand command = PendingAppend.create(localSentFolder.getName(), message.getUid());
|
||||||
|
queuePendingCommand(account, command);
|
||||||
|
processPendingCommands(account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleSendFailure(Account account, Store localStore, Folder localFolder, Message message,
|
private void handleSendFailure(Account account, Store localStore, Folder localFolder, Message message,
|
||||||
Exception exception, boolean permanentFailure) throws MessagingException {
|
Exception exception, boolean permanentFailure) throws MessagingException {
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ import com.fsck.k9.K9;
|
||||||
import com.fsck.k9.K9RobolectricTestRunner;
|
import com.fsck.k9.K9RobolectricTestRunner;
|
||||||
import com.fsck.k9.Preferences;
|
import com.fsck.k9.Preferences;
|
||||||
import com.fsck.k9.helper.Contacts;
|
import com.fsck.k9.helper.Contacts;
|
||||||
|
import com.fsck.k9.mail.AuthenticationFailedException;
|
||||||
|
import com.fsck.k9.mail.CertificateValidationException;
|
||||||
import com.fsck.k9.mail.FetchProfile;
|
import com.fsck.k9.mail.FetchProfile;
|
||||||
import com.fsck.k9.mail.Flag;
|
import com.fsck.k9.mail.Flag;
|
||||||
import com.fsck.k9.mail.Folder;
|
import com.fsck.k9.mail.Folder;
|
||||||
|
@ -24,6 +26,8 @@ import com.fsck.k9.mail.Message;
|
||||||
import com.fsck.k9.mail.MessageRetrievalListener;
|
import com.fsck.k9.mail.MessageRetrievalListener;
|
||||||
import com.fsck.k9.mail.MessagingException;
|
import com.fsck.k9.mail.MessagingException;
|
||||||
import com.fsck.k9.mail.Store;
|
import com.fsck.k9.mail.Store;
|
||||||
|
import com.fsck.k9.mail.Transport;
|
||||||
|
import com.fsck.k9.mail.TransportProvider;
|
||||||
import com.fsck.k9.mailstore.LocalFolder;
|
import com.fsck.k9.mailstore.LocalFolder;
|
||||||
import com.fsck.k9.mailstore.LocalMessage;
|
import com.fsck.k9.mailstore.LocalMessage;
|
||||||
import com.fsck.k9.mailstore.LocalStore;
|
import com.fsck.k9.mailstore.LocalStore;
|
||||||
|
@ -36,12 +40,14 @@ import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Captor;
|
import org.mockito.Captor;
|
||||||
|
import org.mockito.InOrder;
|
||||||
import org.mockito.Matchers;
|
import org.mockito.Matchers;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
import org.robolectric.shadows.ShadowApplication;
|
import org.robolectric.shadows.ShadowApplication;
|
||||||
|
import org.robolectric.shadows.ShadowLog;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
@ -54,10 +60,12 @@ import static org.mockito.Mockito.atLeast;
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.doThrow;
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.inOrder;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,6 +73,7 @@ import static org.mockito.Mockito.when;
|
||||||
@RunWith(K9RobolectricTestRunner.class)
|
@RunWith(K9RobolectricTestRunner.class)
|
||||||
public class MessagingControllerTest {
|
public class MessagingControllerTest {
|
||||||
private static final String FOLDER_NAME = "Folder";
|
private static final String FOLDER_NAME = "Folder";
|
||||||
|
private static final String SENT_FOLDER_NAME = "Sent";
|
||||||
private static final int MAXIMUM_SMALL_MESSAGE_SIZE = 1000;
|
private static final int MAXIMUM_SMALL_MESSAGE_SIZE = 1000;
|
||||||
private static final String MESSAGE_UID1 = "message-uid1";
|
private static final String MESSAGE_UID1 = "message-uid1";
|
||||||
|
|
||||||
|
@ -85,6 +94,8 @@ public class MessagingControllerTest {
|
||||||
@Mock
|
@Mock
|
||||||
private LocalFolder errorFolder;
|
private LocalFolder errorFolder;
|
||||||
@Mock
|
@Mock
|
||||||
|
private LocalFolder sentFolder;
|
||||||
|
@Mock
|
||||||
private Folder remoteFolder;
|
private Folder remoteFolder;
|
||||||
@Mock
|
@Mock
|
||||||
private LocalStore localStore;
|
private LocalStore localStore;
|
||||||
|
@ -92,6 +103,10 @@ public class MessagingControllerTest {
|
||||||
private Store remoteStore;
|
private Store remoteStore;
|
||||||
@Mock
|
@Mock
|
||||||
private NotificationController notificationController;
|
private NotificationController notificationController;
|
||||||
|
@Mock
|
||||||
|
private TransportProvider transportProvider;
|
||||||
|
@Mock
|
||||||
|
private Transport transport;
|
||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<List<Message>> messageListCaptor;
|
private ArgumentCaptor<List<Message>> messageListCaptor;
|
||||||
@Captor
|
@Captor
|
||||||
|
@ -116,15 +131,18 @@ public class MessagingControllerTest {
|
||||||
private LocalMessage localNewMessage1;
|
private LocalMessage localNewMessage1;
|
||||||
@Mock
|
@Mock
|
||||||
private LocalMessage localNewMessage2;
|
private LocalMessage localNewMessage2;
|
||||||
|
@Mock
|
||||||
|
private LocalMessage localMessageToSend1;
|
||||||
private volatile boolean hasFetchedMessage = false;
|
private volatile boolean hasFetchedMessage = false;
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws MessagingException {
|
public void setUp() throws MessagingException {
|
||||||
|
ShadowLog.stream = System.out;
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
appContext = ShadowApplication.getInstance().getApplicationContext();
|
appContext = ShadowApplication.getInstance().getApplicationContext();
|
||||||
|
|
||||||
controller = new MessagingController(appContext, notificationController, contacts);
|
controller = new MessagingController(appContext, notificationController, contacts, transportProvider);
|
||||||
|
|
||||||
configureAccount();
|
configureAccount();
|
||||||
configureLocalStore();
|
configureLocalStore();
|
||||||
|
@ -164,12 +182,14 @@ public class MessagingControllerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test()
|
@Test()
|
||||||
public void clearFolderSynchronous_whenExceptionThrown_shouldAddErrorMessage() throws MessagingException {
|
public void clearFolderSynchronous_whenExceptionThrown_shouldAddErrorMessageInDebug() throws MessagingException {
|
||||||
doThrow(new RuntimeException("Test")).when(localFolder).open(Folder.OPEN_MODE_RW);
|
if (K9.DEBUG) {
|
||||||
|
doThrow(new RuntimeException("Test")).when(localFolder).open(Folder.OPEN_MODE_RW);
|
||||||
|
|
||||||
controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
|
controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
|
||||||
|
|
||||||
verify(errorFolder).appendMessages(any(List.class));
|
verify(errorFolder).appendMessages(any(List.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test()
|
@Test()
|
||||||
|
@ -532,6 +552,112 @@ public class MessagingControllerTest {
|
||||||
verify(listener).remoteSearchFinished(FOLDER_NAME, 0, 50, Collections.<Message>emptyList());
|
verify(listener).remoteSearchFinished(FOLDER_NAME, 0, 50, Collections.<Message>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_withNonExistentOutbox_shouldNotStartSync() throws MessagingException {
|
||||||
|
when(account.getOutboxFolderName()).thenReturn(FOLDER_NAME);
|
||||||
|
when(localFolder.exists()).thenReturn(false);
|
||||||
|
controller.addListener(listener);
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verifyZeroInteractions(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_shouldCallListenerOnStart() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verify(listener).sendPendingMessagesStarted(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_shouldSetProgress() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verify(listener).synchronizeMailboxProgress(account, "Sent", 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_shouldSendMessageUsingTransport() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verify(transport).sendMessage(localMessageToSend1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_shouldSetAndRemoveSendInProgressFlag() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
InOrder ordering = inOrder(localMessageToSend1, transport);
|
||||||
|
ordering.verify(localMessageToSend1).setFlag(Flag.X_SEND_IN_PROGRESS, true);
|
||||||
|
ordering.verify(transport).sendMessage(localMessageToSend1);
|
||||||
|
ordering.verify(localMessageToSend1).setFlag(Flag.X_SEND_IN_PROGRESS, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_shouldMarkSentMessageAsSeen() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verify(localMessageToSend1).setFlag(Flag.SEEN, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_whenMessageSentSuccesfully_shouldUpdateProgress() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verify(listener).synchronizeMailboxProgress(account, "Sent", 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_shouldUpdateProgress() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verify(listener).synchronizeMailboxProgress(account, "Sent", 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_withAuthenticationFailure_shouldNotify() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
doThrow(new AuthenticationFailedException("Test")).when(transport).sendMessage(localMessageToSend1);
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verify(notificationController).showAuthenticationErrorNotification(account, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_withCertificateFailure_shouldNotify() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
doThrow(new CertificateValidationException("Test")).when(transport).sendMessage(localMessageToSend1);
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verify(notificationController).showCertificateErrorNotification(account, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendPendingMessagesSynchronous_shouldCallListenerOnCompletion() throws MessagingException {
|
||||||
|
setupAccountWithMessageToSend();
|
||||||
|
|
||||||
|
controller.sendPendingMessagesSynchronous(account);
|
||||||
|
|
||||||
|
verify(listener).sendPendingMessagesCompleted(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void synchronizeMailboxSynchronous_withOneMessageInRemoteFolder_shouldFinishWithoutError()
|
public void synchronizeMailboxSynchronous_withOneMessageInRemoteFolder_shouldFinishWithoutError()
|
||||||
|
@ -758,6 +884,20 @@ public class MessagingControllerTest {
|
||||||
assertEquals(FetchProfile.Item.BODY_SANE, fetchProfileCaptor.getAllValues().get(3).get(0));
|
assertEquals(FetchProfile.Item.BODY_SANE, fetchProfileCaptor.getAllValues().get(3).get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupAccountWithMessageToSend() throws MessagingException {
|
||||||
|
when(account.getOutboxFolderName()).thenReturn(FOLDER_NAME);
|
||||||
|
when(account.hasSentFolder()).thenReturn(true);
|
||||||
|
when(account.getSentFolderName()).thenReturn(SENT_FOLDER_NAME);
|
||||||
|
when(localStore.getFolder(SENT_FOLDER_NAME)).thenReturn(sentFolder);
|
||||||
|
when(sentFolder.getId()).thenReturn(1L);
|
||||||
|
when(localFolder.exists()).thenReturn(true);
|
||||||
|
when(transportProvider.getInstance(appContext, account)).thenReturn(transport);
|
||||||
|
when(localFolder.getMessages(null)).thenReturn(Collections.singletonList(localMessageToSend1));
|
||||||
|
when(localMessageToSend1.getUid()).thenReturn("localMessageToSend1");
|
||||||
|
when(localMessageToSend1.getHeader(K9.IDENTITY_HEADER)).thenReturn(new String[]{});
|
||||||
|
controller.addListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
private void respondToFetchEnvelopesWithMessage(final Message message) throws MessagingException {
|
private void respondToFetchEnvelopesWithMessage(final Message message) throws MessagingException {
|
||||||
doAnswer(new Answer() {
|
doAnswer(new Answer() {
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue