Merge pull request #1317 from philipwhiuk/messagingControllerImprovement

Tests for MessagingController
This commit is contained in:
cketti 2016-04-29 03:25:00 +02:00
commit e6d84afacc
2 changed files with 467 additions and 86 deletions

View file

@ -107,25 +107,6 @@ public class MessagingController implements Runnable {
*/
private static final String[] EMPTY_STRING_ARRAY = new String[0];
/**
* The maximum message size that we'll consider to be "small". A small message is downloaded
* in full immediately instead of in pieces. Anything over this size will be downloaded in
* pieces with attachments being left off completely and downloaded on demand.
*
*
* 25k for a "small" message was picked by educated trial and error.
* http://answers.google.com/answers/threadview?id=312463 claims that the
* average size of an email is 59k, which I feel is too large for our
* blind download. The following tests were performed on a download of
* 25 random messages.
* <pre>
* 5k - 61 seconds,
* 25k - 51 seconds,
* 55k - 53 seconds,
* </pre>
* So 25k gives good performance and a reasonable data footprint. Sounds good to me.
*/
private static final String PENDING_COMMAND_MOVE_OR_COPY = "com.fsck.k9.MessagingController.moveOrCopy";
private static final String PENDING_COMMAND_MOVE_OR_COPY_BULK = "com.fsck.k9.MessagingController.moveOrCopyBulk";
private static final String PENDING_COMMAND_MOVE_OR_COPY_BULK_NEW = "com.fsck.k9.MessagingController.moveOrCopyBulkNew";
@ -327,7 +308,6 @@ public class MessagingController implements Runnable {
throw new Error(e);
}
public void addListener(MessagingListener listener) {
mListeners.add(listener);
refreshListener(listener);
@ -438,74 +418,80 @@ public class MessagingController implements Runnable {
put("doRefreshRemote", listener, new Runnable() {
@Override
public void run() {
List<LocalFolder> localFolders = null;
try {
Store store = account.getRemoteStore();
List <? extends Folder > remoteFolders = store.getPersonalNamespaces(false);
LocalStore localStore = account.getLocalStore();
Set<String> remoteFolderNames = new HashSet<String>();
List<LocalFolder> foldersToCreate = new LinkedList<LocalFolder>();
localFolders = localStore.getPersonalNamespaces(false);
Set<String> localFolderNames = new HashSet<String>();
for (Folder localFolder : localFolders) {
localFolderNames.add(localFolder.getName());
}
for (Folder remoteFolder : remoteFolders) {
if (localFolderNames.contains(remoteFolder.getName()) == false) {
LocalFolder localFolder = localStore.getFolder(remoteFolder.getName());
foldersToCreate.add(localFolder);
}
remoteFolderNames.add(remoteFolder.getName());
}
localStore.createFolders(foldersToCreate, account.getDisplayCount());
localFolders = localStore.getPersonalNamespaces(false);
/*
* Clear out any folders that are no longer on the remote store.
*/
for (Folder localFolder : localFolders) {
String localFolderName = localFolder.getName();
// FIXME: This is a hack used to clean up when we accidentally created the
// special placeholder folder "-NONE-".
if (K9.FOLDER_NONE.equals(localFolderName)) {
localFolder.delete(false);
}
if (!account.isSpecialFolder(localFolderName) &&
!remoteFolderNames.contains(localFolderName)) {
localFolder.delete(false);
}
}
localFolders = localStore.getPersonalNamespaces(false);
for (MessagingListener l : getListeners(listener)) {
l.listFolders(account, localFolders);
}
for (MessagingListener l : getListeners(listener)) {
l.listFoldersFinished(account);
}
} catch (Exception e) {
for (MessagingListener l : getListeners(listener)) {
l.listFoldersFailed(account, "");
}
addErrorMessage(account, null, e);
} finally {
if (localFolders != null) {
for (Folder localFolder : localFolders) {
closeFolder(localFolder);
}
}
}
refreshRemoteSynchronous(account, listener);
}
});
}
@VisibleForTesting
void refreshRemoteSynchronous(final Account account, final MessagingListener listener) {
List<LocalFolder> localFolders = null;
try {
Store store = account.getRemoteStore();
List <? extends Folder > remoteFolders = store.getPersonalNamespaces(false);
LocalStore localStore = account.getLocalStore();
Set<String> remoteFolderNames = new HashSet<String>();
List<LocalFolder> foldersToCreate = new LinkedList<LocalFolder>();
localFolders = localStore.getPersonalNamespaces(false);
Set<String> localFolderNames = new HashSet<String>();
for (Folder localFolder : localFolders) {
localFolderNames.add(localFolder.getName());
}
for (Folder remoteFolder : remoteFolders) {
if (localFolderNames.contains(remoteFolder.getName()) == false) {
LocalFolder localFolder = localStore.getFolder(remoteFolder.getName());
foldersToCreate.add(localFolder);
}
remoteFolderNames.add(remoteFolder.getName());
}
localStore.createFolders(foldersToCreate, account.getDisplayCount());
localFolders = localStore.getPersonalNamespaces(false);
/*
* Clear out any folders that are no longer on the remote store.
*/
for (Folder localFolder : localFolders) {
String localFolderName = localFolder.getName();
// FIXME: This is a hack used to clean up when we accidentally created the
// special placeholder folder "-NONE-".
if (K9.FOLDER_NONE.equals(localFolderName)) {
localFolder.delete(false);
}
if (!account.isSpecialFolder(localFolderName) &&
!remoteFolderNames.contains(localFolderName)) {
localFolder.delete(false);
}
}
localFolders = localStore.getPersonalNamespaces(false);
for (MessagingListener l : getListeners(listener)) {
l.listFolders(account, localFolders);
}
for (MessagingListener l : getListeners(listener)) {
l.listFoldersFinished(account);
}
} catch (Exception e) {
for (MessagingListener l : getListeners(listener)) {
l.listFoldersFailed(account, "");
}
addErrorMessage(account, null, e);
} finally {
if (localFolders != null) {
for (Folder localFolder : localFolders) {
closeFolder(localFolder);
}
}
}
}
/**
* Find all messages in any local account which match the query 'query'
* @throws MessagingException

View file

@ -1,15 +1,21 @@
package com.fsck.k9.controller;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import android.content.Context;
import com.fsck.k9.Account;
import com.fsck.k9.AccountStats;
import com.fsck.k9.Preferences;
import com.fsck.k9.mail.FetchProfile;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Folder;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessageRetrievalListener;
@ -19,12 +25,15 @@ import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.LocalMessage;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.notification.NotificationController;
import com.fsck.k9.search.LocalSearch;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
@ -37,11 +46,16 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anySet;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -62,6 +76,8 @@ public class MessagingControllerTest {
@Mock
private MessagingListener listener;
@Mock
private LocalSearch search;
@Mock
private LocalFolder localFolder;
@Mock
private Folder remoteFolder;
@ -74,13 +90,34 @@ public class MessagingControllerTest {
@Captor
private ArgumentCaptor<List<Message>> messageListCaptor;
@Captor
private ArgumentCaptor<List<LocalFolder>> localFolderListCaptor;
@Captor
private ArgumentCaptor<FetchProfile> fetchProfileCaptor;
@Captor
private ArgumentCaptor<MessageRetrievalListener<LocalMessage>> messageRetrievalListenerCaptor;
private Context appContext;
private Set<Flag> reqFlags;
private Set<Flag> forbiddenFlags;
private List<Message> remoteMessages;
@Mock
private Message remoteOldMessage;
@Mock
private Message remoteNewMessage1;
@Mock
private Message remoteNewMessage2;
@Mock
private LocalMessage localNewMessage1;
@Mock
private LocalMessage localNewMessage2;
private volatile boolean hasFetchedMessage = false;
@Before
public void setUp() throws MessagingException {
MockitoAnnotations.initMocks(this);
Context appContext = ShadowApplication.getInstance().getApplicationContext();
appContext = ShadowApplication.getInstance().getApplicationContext();
controller = new MessagingController(appContext, notificationController);
@ -93,6 +130,348 @@ public class MessagingControllerTest {
controller.stop();
}
@Test
public void listFoldersSynchronous_shouldNotifyTheListenerListingStarted() throws MessagingException {
List<LocalFolder> folders = Collections.singletonList(localFolder);
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
controller.listFoldersSynchronous(account, false, listener);
verify(listener).listFoldersStarted(account);
}
@Test
public void listFoldersSynchronous_shouldNotifyTheListenerOfTheListOfFolders() throws MessagingException {
List<LocalFolder> folders = Collections.singletonList(localFolder);
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
controller.listFoldersSynchronous(account, false, listener);
verify(listener).listFolders(eq(account), localFolderListCaptor.capture());
assertEquals(folders, localFolderListCaptor.getValue());
}
@Test
public void listFoldersSynchronous_shouldNotifyFailureOnException() throws MessagingException {
when(localStore.getPersonalNamespaces(false)).thenThrow(new MessagingException("Test"));
controller.listFoldersSynchronous(account, true, listener);
verify(listener).listFoldersFailed(account, "Test");
}
@Test
public void listFoldersSynchronous_shouldNotNotifyFinishedAfterFailure() throws MessagingException {
when(localStore.getPersonalNamespaces(false)).thenThrow(new MessagingException("Test"));
controller.listFoldersSynchronous(account, true, listener);
verify(listener, never()).listFoldersFinished(account);
}
@Test
public void listFoldersSynchronous_shouldNotifyFinishedAfterSuccess() throws MessagingException {
List<LocalFolder> folders = Collections.singletonList(localFolder);
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
controller.listFoldersSynchronous(account, false, listener);
verify(listener).listFoldersFinished(account);
}
@Test
public void refreshRemoteSynchronous_shouldCreateFoldersFromRemote() throws MessagingException {
configureRemoteStoreWithFolder();
LocalFolder newLocalFolder = mock(LocalFolder.class);
List<Folder> folders = Collections.singletonList(remoteFolder);
when(remoteStore.getPersonalNamespaces(false)).thenAnswer(createAnswer(folders));
when(remoteFolder.getName()).thenReturn("NewFolder");
when(localStore.getFolder("NewFolder")).thenReturn(newLocalFolder);
controller.refreshRemoteSynchronous(account, listener);
verify(localStore).createFolders(eq(Collections.singletonList(newLocalFolder)), anyInt());
}
@Test
public void refreshRemoteSynchronous_shouldDeleteFoldersNotOnRemote() throws MessagingException {
configureRemoteStoreWithFolder();
LocalFolder oldLocalFolder = mock(LocalFolder.class);
when(oldLocalFolder.getName()).thenReturn("OldLocalFolder");
when(localStore.getPersonalNamespaces(false))
.thenReturn(Collections.singletonList(oldLocalFolder));
List<Folder> folders = Collections.emptyList();
when(remoteStore.getPersonalNamespaces(false)).thenAnswer(createAnswer(folders));
controller.refreshRemoteSynchronous(account, listener);
verify(oldLocalFolder).delete(false);
}
@Test
public void refreshRemoteSynchronous_shouldNotDeleteFoldersOnRemote() throws MessagingException {
configureRemoteStoreWithFolder();
when(localStore.getPersonalNamespaces(false))
.thenReturn(Collections.singletonList(localFolder));
List<Folder> folders = Collections.singletonList(remoteFolder);
when(remoteStore.getPersonalNamespaces(false)).thenAnswer(createAnswer(folders));
controller.refreshRemoteSynchronous(account, listener);
verify(localFolder, never()).delete(false);
}
@Test
public void refreshRemoteSynchronous_shouldNotDeleteSpecialFoldersNotOnRemote() throws MessagingException {
configureRemoteStoreWithFolder();
LocalFolder missingSpecialFolder = mock(LocalFolder.class);
when(account.isSpecialFolder("Outbox")).thenReturn(true);
when(missingSpecialFolder.getName()).thenReturn("Outbox");
when(localStore.getPersonalNamespaces(false))
.thenReturn(Collections.singletonList(missingSpecialFolder));
List<Folder> folders = Collections.emptyList();
when(remoteStore.getPersonalNamespaces(false)).thenAnswer(createAnswer(folders));
controller.refreshRemoteSynchronous(account, listener);
verify(missingSpecialFolder, never()).delete(false);
}
public static <T> Answer<T> createAnswer(final T value) {
return new Answer<T>() {
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
return value;
}
};
}
@Test
public void refreshRemoteSynchronous_shouldProvideFolderList() throws MessagingException {
configureRemoteStoreWithFolder();
List<LocalFolder> folders = Collections.singletonList(localFolder);
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
controller.refreshRemoteSynchronous(account, listener);
verify(listener).listFolders(account, folders);
}
@Test
public void refreshRemoteSynchronous_shouldNotifyFinishedAfterSuccess() throws MessagingException {
configureRemoteStoreWithFolder();
List<LocalFolder> folders = Collections.singletonList(localFolder);
when(localStore.getPersonalNamespaces(false)).thenReturn(folders);
controller.refreshRemoteSynchronous(account, listener);
verify(listener).listFoldersFinished(account);
}
@Test
public void refreshRemoteSynchronous_shouldNotNotifyFinishedAfterFailure() throws MessagingException {
configureRemoteStoreWithFolder();
when(localStore.getPersonalNamespaces(false)).thenThrow(new MessagingException("Test"));
controller.refreshRemoteSynchronous(account, listener);
verify(listener, never()).listFoldersFinished(account);
}
@Test
public void searchLocalMessagesSynchronous_shouldNotifyStartedListingLocalMessages()
throws Exception {
setAccountsInPreferences(Collections.singletonMap("1", account));
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
controller.searchLocalMessagesSynchronous(search, listener);
verify(listener).listLocalMessagesStarted(account, null);
}
@Test
public void searchLocalMessagesSynchronous_shouldCallSearchForMessagesOnLocalStore()
throws Exception {
setAccountsInPreferences(Collections.singletonMap("1", account));
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
controller.searchLocalMessagesSynchronous(search, listener);
verify(localStore).searchForMessages(any(MessageRetrievalListener.class), eq(search));
}
@Test
public void searchLocalMessagesSynchronous_shouldNotifyFailureIfStoreThrowsException() throws Exception {
setAccountsInPreferences(Collections.singletonMap("1", account));
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
when(localStore.searchForMessages(any(MessageRetrievalListener.class), eq(search)))
.thenThrow(new MessagingException("Test"));
controller.searchLocalMessagesSynchronous(search, listener);
verify(listener).listLocalMessagesFailed(account, null, "Test");
}
@Test
public void searchLocalMessagesSynchronous_shouldNotifyWhenStoreFinishesRetrievingAMessage()
throws Exception {
setAccountsInPreferences(Collections.singletonMap("1", account));
LocalMessage localMessage = mock(LocalMessage.class);
when(localMessage.getFolder()).thenReturn(localFolder);
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
when(localStore.searchForMessages(any(MessageRetrievalListener.class), eq(search)))
.thenThrow(new MessagingException("Test"));
controller.searchLocalMessagesSynchronous(search, listener);
verify(localStore).searchForMessages(messageRetrievalListenerCaptor.capture(), eq(search));
messageRetrievalListenerCaptor.getValue().messageFinished(localMessage, 1, 1);
verify(listener).listLocalMessagesAddMessages(eq(account),
eq((String) null), eq(Collections.singletonList(localMessage)));
}
private void setupRemoteSearch() throws Exception {
setAccountsInPreferences(Collections.singletonMap("1", account));
configureRemoteStoreWithFolder();
remoteMessages = new ArrayList<>();
Collections.addAll(remoteMessages, remoteOldMessage, remoteNewMessage1, remoteNewMessage2);
List<Message> newRemoteMessages = new ArrayList<>();
Collections.addAll(newRemoteMessages, remoteNewMessage1, remoteNewMessage2);
when(remoteOldMessage.getUid()).thenReturn("oldMessageUid");
when(remoteNewMessage1.getUid()).thenReturn("newMessageUid1");
when(localNewMessage1.getUid()).thenReturn("newMessageUid1");
when(remoteNewMessage2.getUid()).thenReturn("newMessageUid2");
when(localNewMessage2.getUid()).thenReturn("newMessageUid2");
when(remoteFolder.search(anyString(), anySet(), anySet())).thenReturn(remoteMessages);
when(localFolder.extractNewMessages(Matchers.<List<Message>>any())).thenReturn(newRemoteMessages);
when(localFolder.getMessage("newMessageUid1")).thenReturn(localNewMessage1);
when(localFolder.getMessage("newMessageUid2")).thenAnswer(
new Answer<LocalMessage>() {
@Override
public LocalMessage answer(InvocationOnMock invocation) throws Throwable {
if(hasFetchedMessage) {
return localNewMessage2;
}
else
return null;
}
}
);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
hasFetchedMessage = true;
return null;
}
}).when(remoteFolder).fetch(
Matchers.<List<Message>>eq(Collections.singletonList(remoteNewMessage2)),
any(FetchProfile.class),
Matchers.<MessageRetrievalListener>eq(null));
reqFlags = Collections.singleton(Flag.ANSWERED);
forbiddenFlags = Collections.singleton(Flag.DELETED);
when(account.getRemoteSearchNumResults()).thenReturn(50);
}
@Test
public void searchRemoteMessagesSynchronous_shouldNotifyStartedListingRemoteMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(listener).remoteSearchStarted(FOLDER_NAME);
}
@Test
public void searchRemoteMessagesSynchronous_shouldQueryRemoteFolder() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(remoteFolder).search("query", reqFlags, forbiddenFlags);
}
@Test
public void searchRemoteMessagesSynchronous_shouldAskLocalFolderToDetermineNewMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(localFolder).extractNewMessages(remoteMessages);
}
@Test
public void searchRemoteMessagesSynchronous_shouldTryAndGetNewMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(localFolder).getMessage("newMessageUid1");
}
@Test
public void searchRemoteMessagesSynchronous_shouldNotTryAndGetOldMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(localFolder, never()).getMessage("oldMessageUid");
}
@Test
public void searchRemoteMessagesSynchronous_shouldFetchNewMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(remoteFolder, times(2)).fetch(eq(Collections.singletonList(remoteNewMessage2)),
fetchProfileCaptor.capture(), Matchers.<MessageRetrievalListener>eq(null));
}
@Test
public void searchRemoteMessagesSynchronous_shouldNotFetchExistingMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(remoteFolder, never()).fetch(eq(Collections.singletonList(remoteNewMessage1)),
fetchProfileCaptor.capture(), Matchers.<MessageRetrievalListener>eq(null));
}
@Test
public void searchRemoteMessagesSynchronous_shouldNotifyListenerOfNewMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(listener).remoteSearchAddMessage(FOLDER_NAME, localNewMessage1, 1, 2);
verify(listener).remoteSearchAddMessage(FOLDER_NAME, localNewMessage2, 2, 2);
}
@Test
public void searchRemoteMessagesSynchronous_shouldNotifyOnFailure() throws Exception {
setupRemoteSearch();
when(account.getRemoteStore()).thenThrow(new MessagingException("Test"));
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(listener).remoteSearchFailed(null, "Test");
}
@Test
public void searchRemoteMessagesSynchronous_shouldNotifyOnFinish() throws Exception {
setupRemoteSearch();
when(account.getRemoteStore()).thenThrow(new MessagingException("Test"));
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(listener).remoteSearchFinished(FOLDER_NAME, 0, 50, Collections.<Message>emptyList());
}
@Test
public void synchronizeMailboxSynchronous_withOneMessageInRemoteFolder_shouldFinishWithoutError()
throws Exception {
@ -372,6 +751,7 @@ public class MessagingControllerTest {
}
private void configureAccount() throws MessagingException {
when(account.isAvailable(appContext)).thenReturn(true);
when(account.getLocalStore()).thenReturn(localStore);
when(account.getStats(any(Context.class))).thenReturn(accountStats);
when(account.getMaximumAutoDownloadMessageSize()).thenReturn(MAXIMUM_SMALL_MESSAGE_SIZE);
@ -379,10 +759,25 @@ public class MessagingControllerTest {
private void configureLocalStore() {
when(localStore.getFolder(FOLDER_NAME)).thenReturn(localFolder);
when(localFolder.getName()).thenReturn(FOLDER_NAME);
}
private void configureRemoteStoreWithFolder() throws MessagingException {
when(account.getRemoteStore()).thenReturn(remoteStore);
when(remoteStore.getFolder(FOLDER_NAME)).thenReturn(remoteFolder);
when(remoteFolder.getName()).thenReturn(FOLDER_NAME);
}
private void setAccountsInPreferences(Map<String, Account> newAccounts)
throws Exception {
Field accounts = Preferences.class.getDeclaredField("accounts");
accounts.setAccessible(true);
accounts.set(Preferences.getPreferences(appContext), newAccounts);
Field accountsInOrder = Preferences.class.getDeclaredField("accountsInOrder");
accountsInOrder.setAccessible(true);
ArrayList<Account> newAccountsInOrder = new ArrayList<>();
newAccountsInOrder.addAll(newAccounts.values());
accountsInOrder.set(Preferences.getPreferences(appContext), newAccountsInOrder);
}
}