blob: 853c354b13034a6eaa859c4b1acea3a1a7d73012 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.email;
import com.android.email.provider.ProviderTestUtils;
import com.android.emailcommon.Logging;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.provider.Account;
import android.content.Context;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import junit.framework.Assert;
@LargeTest
public class RefreshManagerTest extends InstrumentationTestCase {
private static final int WAIT_UNTIL_TIMEOUT_SECONDS = 15;
private MockClock mClock;
private MockController mController;
private RefreshManager mTarget;
private RefreshListener mListener;
private Context mContext;
// Isolated Context for providers.
private Context mProviderContext;
private static final MessagingException EXCEPTION = new MessagingException("test");
// Looks silly, but it'll make it more readable.
private static final long ACCOUNT_1 = 1;
private static final long ACCOUNT_2 = 2;
private static final long MAILBOX_1 = 3;
private static final long MAILBOX_2 = 4;
@Override
protected void setUp() throws Exception {
super.setUp();
mClock = new MockClock();
mContext = getInstrumentation().getTargetContext();
mController = new MockController(mContext);
mListener = new RefreshListener();
mProviderContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext(mContext);
mTarget = new RefreshManager(mProviderContext, mController, mClock, null);
mTarget.registerListener(mListener);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
mController.cleanupForTest();
}
public void testRegisterUnregisterListener() {
// mListener is already registered
assertEquals(1, mTarget.getListenersForTest().size());
mTarget.unregisterListener(mListener);
assertEquals(0, mTarget.getListenersForTest().size());
}
public void testRefreshStatus() {
RefreshManager.Status s = new RefreshManager.Status();
assertFalse(s.isRefreshing());
assertTrue(s.canRefresh());
assertEquals(0, s.getLastRefreshTime());
// Request refresh
s.onRefreshRequested();
assertTrue(s.isRefreshing());
assertFalse(s.canRefresh());
assertEquals(0, s.getLastRefreshTime());
// Refresh start
s.onCallback(null, 0, mClock);
assertTrue(s.isRefreshing());
assertFalse(s.canRefresh());
assertEquals(0, s.getLastRefreshTime());
// Refresh 50% done -- nothing changes
s.onCallback(null, 50, mClock);
assertTrue(s.isRefreshing());
assertFalse(s.canRefresh());
assertEquals(0, s.getLastRefreshTime());
// Refresh finish
s.onCallback(null, 100, mClock);
assertFalse(s.isRefreshing());
assertTrue(s.canRefresh());
assertEquals(mClock.mTime, s.getLastRefreshTime());
// Refresh start without request
s.onCallback(null, 0, mClock);
assertTrue(s.isRefreshing());
assertFalse(s.canRefresh());
assertEquals(mClock.mTime, s.getLastRefreshTime());
mClock.advance();
// Refresh finish with error.
s.onCallback(EXCEPTION, 0, mClock);
assertFalse(s.isRefreshing());
assertTrue(s.canRefresh());
assertEquals(mClock.mTime, s.getLastRefreshTime());
}
public void testRefreshMailboxList() {
// request refresh for account 1
assertTrue(mTarget.refreshMailboxList(ACCOUNT_1));
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_1, mListener.mAccountId);
assertEquals(-1, mListener.mMailboxId);
mListener.reset();
assertTrue(mController.mCalledUpdateMailboxList);
assertEquals(ACCOUNT_1, mController.mAccountId);
assertEquals(-1, mController.mMailboxId);
mController.reset();
assertTrue(mTarget.isMailboxListRefreshing(ACCOUNT_1));
assertTrue(mTarget.isRefreshingAnyMailboxListForTest());
// Request again -- shouldn't be accepted.
assertFalse(mTarget.refreshMailboxList(ACCOUNT_1));
assertFalse(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
mListener.reset();
assertFalse(mController.mCalledUpdateMailboxList);
mController.reset();
// request refresh for account 2
assertTrue(mTarget.refreshMailboxList(ACCOUNT_2));
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_2, mListener.mAccountId);
assertEquals(-1, mListener.mMailboxId);
mListener.reset();
assertTrue(mController.mCalledUpdateMailboxList);
assertEquals(ACCOUNT_2, mController.mAccountId);
assertEquals(-1, mController.mMailboxId);
mController.reset();
assertTrue(mTarget.isMailboxListRefreshing(ACCOUNT_2));
assertTrue(mTarget.isRefreshingAnyMailboxListForTest());
// Refreshing for account 1...
mController.mListener.updateMailboxListCallback(null, ACCOUNT_1, 0);
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_1, mListener.mAccountId);
assertEquals(-1, mListener.mMailboxId);
mListener.reset();
assertTrue(mTarget.isMailboxListRefreshing(ACCOUNT_1));
assertEquals(0, mTarget.getMailboxListStatusForTest(ACCOUNT_1).getLastRefreshTime());
// Done.
Log.w(Logging.LOG_TAG, "" + mController.mListener.getClass());
mController.mListener.updateMailboxListCallback(null, ACCOUNT_1, 100);
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_1, mListener.mAccountId);
assertEquals(-1, mListener.mMailboxId);
mListener.reset();
assertFalse(mTarget.isMailboxListRefreshing(ACCOUNT_1));
assertEquals(mClock.mTime, mTarget.getMailboxListStatusForTest(ACCOUNT_1)
.getLastRefreshTime());
// Check "any" method.
assertTrue(mTarget.isRefreshingAnyMailboxListForTest()); // still refreshing account 2
// Refreshing for account 2...
mClock.advance();
mController.mListener.updateMailboxListCallback(null, ACCOUNT_2, 0);
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_2, mListener.mAccountId);
assertEquals(-1, mListener.mMailboxId);
mListener.reset();
assertTrue(mTarget.isMailboxListRefreshing(ACCOUNT_2));
assertEquals(0, mTarget.getMailboxListStatusForTest(ACCOUNT_2).getLastRefreshTime());
// Done with exception.
mController.mListener.updateMailboxListCallback(EXCEPTION, ACCOUNT_2, 0);
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertTrue(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_2, mListener.mAccountId);
assertEquals(-1, mListener.mMailboxId);
assertEquals(MessagingExceptionStrings.getErrorString(mContext, EXCEPTION),
mListener.mMessage);
mListener.reset();
assertFalse(mTarget.isMailboxListRefreshing(ACCOUNT_2));
assertEquals(mClock.mTime, mTarget.getMailboxListStatusForTest(ACCOUNT_2)
.getLastRefreshTime());
// Check "any" method.
assertFalse(mTarget.isRefreshingAnyMailboxListForTest());
}
public void testRefreshMessageList() {
// request refresh mailbox 1
assertTrue(mTarget.refreshMessageList(ACCOUNT_1, MAILBOX_1, false));
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_1, mListener.mAccountId);
assertEquals(MAILBOX_1, mListener.mMailboxId);
mListener.reset();
assertTrue(mController.mCalledUpdateMailbox);
assertEquals(ACCOUNT_1, mController.mAccountId);
assertEquals(MAILBOX_1, mController.mMailboxId);
mController.reset();
assertTrue(mTarget.isMessageListRefreshing(MAILBOX_1));
assertTrue(mTarget.isRefreshingAnyMessageListForTest());
// Request again -- shouldn't be accepted.
assertFalse(mTarget.refreshMessageList(ACCOUNT_1, MAILBOX_1, false));
assertFalse(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
mListener.reset();
assertFalse(mController.mCalledUpdateMailbox);
mController.reset();
// request refresh mailbox 2
assertTrue(mTarget.refreshMessageList(ACCOUNT_2, MAILBOX_2, false));
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_2, mListener.mAccountId);
assertEquals(MAILBOX_2, mListener.mMailboxId);
mListener.reset();
assertTrue(mController.mCalledUpdateMailbox);
assertEquals(ACCOUNT_2, mController.mAccountId);
assertEquals(MAILBOX_2, mController.mMailboxId);
mController.reset();
assertTrue(mTarget.isMessageListRefreshing(MAILBOX_2));
assertTrue(mTarget.isRefreshingAnyMessageListForTest());
// Refreshing mailbox 1...
mController.mListener.updateMailboxCallback(null, ACCOUNT_1, MAILBOX_1, 0, 0, null);
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_1, mListener.mAccountId);
assertEquals(MAILBOX_1, mListener.mMailboxId);
mListener.reset();
assertTrue(mTarget.isMessageListRefreshing(MAILBOX_1));
assertEquals(0, mTarget.getMessageListStatusForTest(MAILBOX_1).getLastRefreshTime());
// Done.
Log.w(Logging.LOG_TAG, "" + mController.mListener.getClass());
mController.mListener.updateMailboxCallback(null, ACCOUNT_1, MAILBOX_1, 100, 0, null);
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_1, mListener.mAccountId);
assertEquals(MAILBOX_1, mListener.mMailboxId);
mListener.reset();
assertFalse(mTarget.isMessageListRefreshing(MAILBOX_1));
assertEquals(mClock.mTime, mTarget.getMessageListStatusForTest(MAILBOX_1)
.getLastRefreshTime());
// Check "any" method.
assertTrue(mTarget.isRefreshingAnyMessageListForTest()); // still refreshing mailbox 2
// Refreshing mailbox 2...
mClock.advance();
mController.mListener.updateMailboxCallback(null, ACCOUNT_2, MAILBOX_2, 0, 0, null);
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_2, mListener.mAccountId);
assertEquals(MAILBOX_2, mListener.mMailboxId);
mListener.reset();
assertTrue(mTarget.isMessageListRefreshing(MAILBOX_2));
assertEquals(0, mTarget.getMessageListStatusForTest(MAILBOX_2).getLastRefreshTime());
// Done with exception.
mController.mListener.updateMailboxCallback(EXCEPTION, ACCOUNT_2, MAILBOX_2, 0, 0, null);
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertTrue(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_2, mListener.mAccountId);
assertEquals(MAILBOX_2, mListener.mMailboxId);
assertEquals(MessagingExceptionStrings.getErrorString(mContext, EXCEPTION),
mListener.mMessage);
mListener.reset();
assertFalse(mTarget.isMessageListRefreshing(MAILBOX_2));
assertEquals(mClock.mTime, mTarget.getMessageListStatusForTest(MAILBOX_2)
.getLastRefreshTime());
// Check "any" method.
assertFalse(mTarget.isRefreshingAnyMessageListForTest());
}
public void testSendPendingMessages() {
// request sending for account 1
assertTrue(mTarget.sendPendingMessages(ACCOUNT_1));
assertTrue(mListener.mCalledOnRefreshStatusChanged);
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_1, mListener.mAccountId);
assertEquals(-1, mListener.mMailboxId);
mListener.reset();
assertTrue(mController.mCalledSendPendingMessages);
assertEquals(ACCOUNT_1, mController.mAccountId);
assertEquals(-1, mController.mMailboxId);
mController.reset();
// request sending for account 2
assertTrue(mTarget.sendPendingMessages(ACCOUNT_2));
assertFalse(mListener.mCalledOnConnectionError);
assertEquals(ACCOUNT_2, mListener.mAccountId);
assertEquals(-1, mListener.mMailboxId);
mListener.reset();
assertTrue(mController.mCalledSendPendingMessages);
assertEquals(ACCOUNT_2, mController.mAccountId);
assertEquals(-1, mController.mMailboxId);
mController.reset();
// Sending start for account 1...
// batch send start. (message id == -1, progress == 0)
mController.mListener.sendMailCallback(null, ACCOUNT_1, -1, 0);
assertFalse(mListener.mCalledOnConnectionError);
mListener.reset();
// Per message callback
mController.mListener.sendMailCallback(null, ACCOUNT_1, 100, 0);
mController.mListener.sendMailCallback(null, ACCOUNT_1, 101, 0);
assertFalse(mListener.mCalledOnConnectionError);
mListener.reset();
// Exception -- first error will be reported.
mController.mListener.sendMailCallback(EXCEPTION, ACCOUNT_1, 102, 0);
assertTrue(mListener.mCalledOnConnectionError);
assertEquals(MessagingExceptionStrings.getErrorString(mContext, EXCEPTION),
mListener.mMessage);
mListener.reset();
// Exception again -- no more error callbacks
mController.mListener.sendMailCallback(null, ACCOUNT_1, 103, 0);
mController.mListener.sendMailCallback(EXCEPTION, ACCOUNT_1, 104, 0);
assertFalse(mListener.mCalledOnConnectionError);
mListener.reset();
// Done.
Log.w(Logging.LOG_TAG, "" + mController.mListener.getClass());
mController.mListener.sendMailCallback(null, ACCOUNT_1, -1, 100);
assertFalse(mListener.mCalledOnConnectionError);
mListener.reset();
}
public void testSendPendingMessagesForAllAccounts() throws Throwable {
Account acct1 = ProviderTestUtils.setupAccount("acct1", true, mProviderContext);
Account acct2 = ProviderTestUtils.setupAccount("acct2", true, mProviderContext);
// AsyncTask needs to be created on the UI thread.
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mTarget.sendPendingMessagesForAllAccounts();
}
});
// sendPendingMessagesForAllAccounts uses Utility.ForEachAccount, which has it's own test,
// so we don't really have to check everything.
// Here, we just check if sendPendingMessages() has been called at least for once,
// which is a enough check.
TestUtils.waitUntil(new TestUtils.Condition() {
@Override
public boolean isMet() {
// The write to this is done on the UI thread, but we're checking it here
// on the test thread, so mCalledSendPendingMessages needs to be volatile.
return mController.mCalledSendPendingMessages;
}
}, WAIT_UNTIL_TIMEOUT_SECONDS);
}
public void testLoadMoreMessages() {
final long ACCOUNT_ID = 123;
final long MAILBOX_ID = 456;
mTarget.loadMoreMessages(ACCOUNT_ID, MAILBOX_ID);
assertTrue(mController.mCalledLoadMoreMessages);
assertEquals(mController.mMailboxId, MAILBOX_ID);
assertFalse(mController.mCalledUpdateMailbox);
}
// volatile is necessary for testSendPendingMessagesForAllAccounts().
// (Not all of them are actually necessary, but added for consistency.)
private static class MockController extends Controller {
public volatile long mAccountId = -1;
public volatile long mMailboxId = -1;
public volatile boolean mCalledSendPendingMessages;
public volatile boolean mCalledUpdateMailbox;
public volatile boolean mCalledUpdateMailboxList;
public volatile boolean mCalledLoadMoreMessages;
public volatile Result mListener;
protected MockController(Context context) {
super(context);
}
public void reset() {
mAccountId = -1;
mMailboxId = -1;
mCalledSendPendingMessages = false;
mCalledUpdateMailbox = false;
mCalledUpdateMailboxList = false;
}
@Override
public void sendPendingMessages(long accountId) {
mCalledSendPendingMessages = true;
mAccountId = accountId;
}
@Override
public void updateMailbox(long accountId, long mailboxId, boolean userRequest) {
mCalledUpdateMailbox = true;
mAccountId = accountId;
mMailboxId = mailboxId;
}
@Override
public void updateMailboxList(long accountId) {
mCalledUpdateMailboxList = true;
mAccountId = accountId;
}
@Override
public void loadMoreMessages(long mailboxId) {
mCalledLoadMoreMessages = true;
mAccountId = -1;
mMailboxId = mailboxId;
}
@Override
public void addResultCallback(Result listener) {
Assert.assertTrue(mListener == null);
mListener = listener;
// Let it call listener.setRegistered(). Otherwise callbacks won't fire.
super.addResultCallback(listener);
}
}
private static class RefreshListener implements RefreshManager.Listener {
public long mAccountId = -1;
public long mMailboxId = -1;
public String mMessage;
public boolean mCalledOnConnectionError;
public boolean mCalledOnRefreshStatusChanged;
public void reset() {
mAccountId = -1;
mMailboxId = -1;
mMessage = null;
mCalledOnConnectionError = false;
mCalledOnRefreshStatusChanged = false;
}
@Override
public void onRefreshStatusChanged(long accountId, long mailboxId) {
mAccountId = accountId;
mMailboxId = mailboxId;
mCalledOnRefreshStatusChanged = true;
}
@Override
public void onMessagingError(long accountId, long mailboxId, String message) {
mAccountId = accountId;
mMailboxId = mailboxId;
mMessage = message;
mCalledOnConnectionError = true;
}
}
}