Add hierarchical folders to IMAP

We now create folder hierarcies for IMAP. This also includes a nifty SQL
statement that will get your existing database into shape.

Change-Id: If07a0632e9b250cf0c33c3e16bfba5816beab94c
This commit is contained in:
Todd Kennedy 2011-04-22 15:45:11 -07:00
parent 1611d0baed
commit 22208771b7
14 changed files with 1163 additions and 524 deletions

View File

@ -2256,6 +2256,10 @@ public abstract class EmailContent {
public static final int CONTENT_VISIBLE_LIMIT_COLUMN = 13;
public static final int CONTENT_SYNC_STATUS_COLUMN = 14;
public static final int CONTENT_PARENT_KEY_COLUMN = 15;
/**
* <em>NOTE</em>: If fields are added or removed, the method {@link #getHashes()}
* MUST be updated.
*/
public static final String[] CONTENT_PROJECTION = new String[] {
RECORD_ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.SERVER_ID,
MailboxColumns.PARENT_SERVER_ID, MailboxColumns.ACCOUNT_KEY, MailboxColumns.TYPE,
@ -2270,9 +2274,9 @@ public abstract class EmailContent {
MailboxColumns.TYPE + " =?";
private static final String MAILBOX_TYPE_SELECTION =
MailboxColumns.TYPE + " =?";
/** Selection by display name for a given account */
private static final String NAME_AND_ACCOUNT_SELECTION =
MailboxColumns.DISPLAY_NAME + "=? and " + MailboxColumns.ACCOUNT_KEY + "=?";
/** Selection by server pathname for a given account */
private static final String PATH_AND_ACCOUNT_SELECTION =
MailboxColumns.SERVER_ID + "=? and " + MailboxColumns.ACCOUNT_KEY + "=?";
private static final String[] MAILBOX_SUM_OF_UNREAD_COUNT_PROJECTION = new String [] {
"sum(" + MailboxColumns.UNREAD_COUNT + ")"
@ -2413,7 +2417,8 @@ public abstract class EmailContent {
/**
* Returns a Mailbox from the database, given its pathname and account id. All mailbox
* paths for a particular account must be unique.
* paths for a particular account must be unique. Paths are stored in the column
* {@link MailboxColumns#SERVER_ID} for want of yet another column in the table.
* @param context
* @param accountId the ID of the account
* @param path the fully qualified, remote pathname
@ -2422,7 +2427,7 @@ public abstract class EmailContent {
Cursor c = context.getContentResolver().query(
Mailbox.CONTENT_URI,
Mailbox.CONTENT_PROJECTION,
Mailbox.NAME_AND_ACCOUNT_SELECTION,
Mailbox.PATH_AND_ACCOUNT_SELECTION,
new String[] { path, Long.toString(accountId) },
null);
// TODO for mblank; uncomment when you submit CL Iab059f9a68eecd797914a6229f1ff9c03d0f0800
@ -2616,6 +2621,48 @@ public abstract class EmailContent {
public static boolean isMailboxTypeReplyAndForwardable(int type) {
return (type != TYPE_TRASH) && (type != TYPE_DRAFTS);
}
/**
* Returns a set of hashes that can identify this mailbox. These can be used to
* determine if any of the fields have been modified.
*/
public Object[] getHashes() {
Object[] hash = new Object[CONTENT_PROJECTION.length];
hash[CONTENT_ID_COLUMN]
= mId;
hash[CONTENT_DISPLAY_NAME_COLUMN]
= mDisplayName;
hash[CONTENT_SERVER_ID_COLUMN]
= mServerId;
hash[CONTENT_PARENT_SERVER_ID_COLUMN]
= mParentServerId;
hash[CONTENT_ACCOUNT_KEY_COLUMN]
= mAccountKey;
hash[CONTENT_TYPE_COLUMN]
= mType;
hash[CONTENT_DELIMITER_COLUMN]
= mDelimiter;
hash[CONTENT_SYNC_KEY_COLUMN]
= mSyncKey;
hash[CONTENT_SYNC_LOOKBACK_COLUMN]
= mSyncLookback;
hash[CONTENT_SYNC_INTERVAL_COLUMN]
= mSyncInterval;
hash[CONTENT_SYNC_TIME_COLUMN]
= mSyncTime;
hash[CONTENT_FLAG_VISIBLE_COLUMN]
= mFlagVisible;
hash[CONTENT_FLAGS_COLUMN]
= mFlags;
hash[CONTENT_VISIBLE_LIMIT_COLUMN]
= mVisibleLimit;
hash[CONTENT_SYNC_STATUS_COLUMN]
= mSyncStatus;
hash[CONTENT_PARENT_KEY_COLUMN]
= mParentKey;
return hash;
}
}
public interface HostAuthColumns {

View File

@ -532,7 +532,7 @@ public class Controller {
box.mType = mailboxType;
box.mSyncInterval = EmailContent.Account.CHECK_INTERVAL_NEVER;
box.mFlagVisible = true;
box.mDisplayName = getMailboxServerName(mailboxType);
box.mServerId = box.mDisplayName = getMailboxServerName(mailboxType);
box.save(mProviderContext);
return box.mId;
}

View File

@ -199,13 +199,13 @@ public class MessagingController implements Runnable {
}
private static final int MAILBOX_COLUMN_ID = 0;
private static final int MAILBOX_COLUMN_DISPLAY_NAME = 1;
private static final int MAILBOX_COLUMN_SERVER_ID = 1;
private static final int MAILBOX_COLUMN_TYPE = 2;
/** Small projection for just the columns required for a sync. */
private static final String[] MAILBOX_PROJECTION = new String[] {
MailboxColumns.ID,
MailboxColumns.DISPLAY_NAME,
MailboxColumns.SERVER_ID,
MailboxColumns.TYPE,
};
@ -256,8 +256,7 @@ public class MessagingController implements Runnable {
// Step 3: Remove any local mailbox not on the remote list
while (localFolderCursor.moveToNext()) {
String mailboxPath
= localFolderCursor.getString(MAILBOX_COLUMN_DISPLAY_NAME);
String mailboxPath = localFolderCursor.getString(MAILBOX_COLUMN_SERVER_ID);
// Short circuit if we have a remote mailbox with the same name
if (remoteFolderNames.contains(mailboxPath)) {
continue;
@ -466,7 +465,7 @@ public class MessagingController implements Runnable {
// 2. Open the remote folder and create the remote folder if necessary
Store remoteStore = Store.getInstance(account, mContext, null);
Folder remoteFolder = remoteStore.getFolder(folder.mDisplayName);
Folder remoteFolder = remoteStore.getFolder(folder.mServerId);
/*
* If the folder is a "special" folder we need to see if it exists
@ -1394,7 +1393,7 @@ public class MessagingController implements Runnable {
}
// 2. Open the remote store & folder
Folder remoteFolder = remoteStore.getFolder(mailbox.mDisplayName);
Folder remoteFolder = remoteStore.getFolder(mailbox.mServerId);
if (!remoteFolder.exists()) {
return;
}
@ -1423,7 +1422,7 @@ public class MessagingController implements Runnable {
remoteFolder.setFlags(messages, FLAG_LIST_FLAGGED, newMessage.mFlagFavorite);
}
if (changeMailbox) {
Folder toFolder = remoteStore.getFolder(newMailbox.mDisplayName);
Folder toFolder = remoteStore.getFolder(newMailbox.mServerId);
if (!remoteFolder.exists()) {
return;
}
@ -1503,7 +1502,7 @@ public class MessagingController implements Runnable {
// The rest of this method handles server-side deletion
// 4. Find the remote mailbox (that we deleted from), and open it
Folder remoteFolder = remoteStore.getFolder(oldMailbox.mDisplayName);
Folder remoteFolder = remoteStore.getFolder(oldMailbox.mServerId);
if (!remoteFolder.exists()) {
return;
}
@ -1522,7 +1521,7 @@ public class MessagingController implements Runnable {
}
// 6. Find the remote trash folder, and create it if not found
Folder remoteTrashFolder = remoteStore.getFolder(newMailbox.mDisplayName);
Folder remoteTrashFolder = remoteStore.getFolder(newMailbox.mServerId);
if (!remoteTrashFolder.exists()) {
/*
* If the remote trash folder doesn't exist we try to create it.
@ -1589,7 +1588,7 @@ public class MessagingController implements Runnable {
}
// 2. Find the remote trash folder (that we are deleting from), and open it
Folder remoteTrashFolder = remoteStore.getFolder(oldMailbox.mDisplayName);
Folder remoteTrashFolder = remoteStore.getFolder(oldMailbox.mServerId);
if (!remoteTrashFolder.exists()) {
return;
}
@ -1633,7 +1632,7 @@ public class MessagingController implements Runnable {
boolean deleteMessage = false;
// 1. Find the remote folder that we're appending to and create and/or open it
Folder remoteFolder = remoteStore.getFolder(newMailbox.mDisplayName);
Folder remoteFolder = remoteStore.getFolder(newMailbox.mServerId);
if (!remoteFolder.exists()) {
if (!remoteFolder.canCreate(FolderType.HOLDS_MESSAGES)) {
// This is POP3, we cannot actually upload. Instead, we'll update the message
@ -1783,7 +1782,7 @@ public class MessagingController implements Runnable {
Store remoteStore =
Store.getInstance(account, mContext, null);
Folder remoteFolder = remoteStore.getFolder(mailbox.mDisplayName);
Folder remoteFolder = remoteStore.getFolder(mailbox.mServerId);
remoteFolder.open(OpenMode.READ_WRITE, null);
// 3. Not supported, because IMAP & POP don't use it: structure prefetch
@ -1872,7 +1871,7 @@ public class MessagingController implements Runnable {
Store remoteStore =
Store.getInstance(account, mContext, null);
Folder remoteFolder = remoteStore.getFolder(mailbox.mDisplayName);
Folder remoteFolder = remoteStore.getFolder(mailbox.mServerId);
remoteFolder.open(OpenMode.READ_WRITE, null);
// 3. Generate a shell message in which to retrieve the attachment,

View File

@ -342,7 +342,7 @@ public abstract class Store {
* Returns a {@link Mailbox} for the given path. If the path is not in the database, a new
* mailbox will be created.
*/
private static Mailbox getMailboxForPath(Context context, long accountId, String path) {
protected static Mailbox getMailboxForPath(Context context, long accountId, String path) {
Mailbox mailbox = Mailbox.restoreMailboxForPath(context, accountId, path);
if (mailbox == null) {
mailbox = new Mailbox();
@ -351,24 +351,19 @@ public abstract class Store {
}
/**
* Adds the mailbox with the given path to the folder list and to the database. If the folder
* already exists on the server (e.g. the path is identical), the database row will be updated.
* Otherwise, a new database row will be inserted.
* @param folders the list of folders
* @param mailboxPath The path of the mailbox to add
* @param delimiter A path delimiter. May be {@code null} if there is no delimiter.
* Updates the fields within the given mailbox. Only the fields that are important to
* non-EAS accounts are modified.
*/
protected void addMailbox(Context context, long accountId, String mailboxPath, String delimiter,
ArrayList<Folder> folders) throws MessagingException {
char delimiterChar = 0;
if (!TextUtils.isEmpty(delimiter)) {
delimiterChar = delimiter.charAt(0);
}
folders.add(getFolder(mailboxPath));
Mailbox mailbox = getMailboxForPath(context, accountId, mailboxPath);
protected static void updateMailbox(Mailbox mailbox, long accountId, String mailboxPath,
char delimiter, int type) {
mailbox.mAccountKey = accountId;
mailbox.mDelimiter = delimiterChar;
mailbox.mDisplayName = mailboxPath;
mailbox.mDelimiter = delimiter;
String displayPath = mailboxPath;
int pathIndex = mailboxPath.lastIndexOf(delimiter);
if (pathIndex > 0) {
displayPath = mailboxPath.substring(pathIndex + 1);
}
mailbox.mDisplayName = displayPath;
//mailbox.mFlags;
mailbox.mFlagVisible = true;
//mailbox.mParentKey;
@ -379,17 +374,8 @@ public abstract class Store {
//mailbox.mSyncKey;
//mailbox.mSyncLookback;
//mailbox.mSyncTime;
mailbox.mType = LegacyConversions.inferMailboxTypeFromName(context, mailboxPath);
mailbox.mType = type;
//box.mUnreadCount;
mailbox.mVisibleLimit = Email.VISIBLE_LIMIT_DEFAULT;
// TODO This is horribly inefficient. Only update db if the mailbox has really changed
if (mailbox.isSaved()) {
mailbox.update(context, mailbox.toContentValues());
} else {
mailbox.save(context);
}
// TODO ?? Add mailbox to Folder object ??
}
}

View File

@ -16,6 +16,7 @@
package com.android.email.mail.store;
import android.content.Context;
import android.text.TextUtils;
import android.util.Base64DataException;
import android.util.Log;
@ -53,6 +54,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
@ -65,6 +67,10 @@ class ImapFolder extends Folder {
private ImapConnection mConnection;
private OpenMode mMode;
private boolean mExists;
/** The local mailbox associated with this remote folder */
Mailbox mMailbox;
/** A set of hashes that can be used to track dirtiness */
Object mHash[];
/*package*/ ImapFolder(ImapStore store, String name) {
mStore = store;
@ -971,6 +977,25 @@ class ImapFolder extends Folder {
}
}
/**
* Persists this folder. We will always perform the proper database operation (e.g.
* 'save' or 'update'). As an optimization, if a folder has not been modified, no
* database operations are performed.
*/
void save(Context context) {
final Mailbox mailbox = mMailbox;
if (!mailbox.isSaved()) {
mailbox.save(context);
mHash = mailbox.getHashes();
} else {
Object[] hash = mailbox.getHashes();
if (!Arrays.equals(mHash, hash)) {
mailbox.update(context, mailbox.toContentValues());
mHash = hash; // Save updated hash
}
}
}
/**
* Selects the folder for use. Before performing any operations on this folder, it
* must be selected.
@ -1036,4 +1061,4 @@ class ImapFolder extends Folder {
public Message createMessage(String uid) {
return new ImapMessage(uid, this);
}
}
}

View File

@ -17,6 +17,7 @@
package com.android.email.mail.store;
import com.android.email.Email;
import com.android.email.LegacyConversions;
import com.android.email.Preferences;
import com.android.email.VendorPolicyLoader;
import com.android.email.mail.Store;
@ -39,6 +40,7 @@ import com.android.emailcommon.mail.Message;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.HostAuth;
import com.android.emailcommon.provider.EmailContent.Mailbox;
import com.android.emailcommon.service.EmailServiceProxy;
import com.android.emailcommon.utility.Utility;
import com.beetstra.jutf7.CharsetProvider;
@ -63,6 +65,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
@ -361,11 +364,77 @@ public class ImapStore extends Store {
return folder;
}
/**
* Creates a mailbox hierarchy out of the flat data provided by the server.
*/
@VisibleForTesting
static void createHierarchy(HashMap<String, ImapFolder> mailboxes) {
Set<String> pathnames = mailboxes.keySet();
for (String path : pathnames) {
final ImapFolder folder = mailboxes.get(path);
final Mailbox mailbox = folder.mMailbox;
int delimiterIdx = mailbox.mServerId.lastIndexOf(mailbox.mDelimiter);
long parentKey = -1L;
if (delimiterIdx != -1) {
String parentPath = path.substring(0, delimiterIdx);
final ImapFolder parentFolder = mailboxes.get(parentPath);
final Mailbox parentMailbox = (parentFolder == null) ? null : parentFolder.mMailbox;
if (parentMailbox != null) {
parentKey = parentMailbox.mId;
parentMailbox.mFlags
|= (Mailbox.FLAG_HAS_CHILDREN | Mailbox.FLAG_CHILDREN_VISIBLE);
}
}
mailbox.mParentKey = parentKey;
}
}
/**
* Creates a {@link Folder} and associated {@link Mailbox}. If the folder does not already
* exist in the local database, a new row will immediately be created in the mailbox table.
* Otherwise, the existing row will be used. Any changes to existing rows, will not be stored
* to the database immediately.
* @param accountId The ID of the account the mailbox is to be associated with
* @param mailboxPath The path of the mailbox to add
* @param delimiter A path delimiter. May be {@code null} if there is no delimiter.
*/
private ImapFolder addMailbox(Context context, long accountId, String mailboxPath,
char delimiter) {
ImapFolder folder = (ImapFolder) getFolder(mailboxPath);
Mailbox mailbox = getMailboxForPath(context, accountId, mailboxPath);
if (mailbox.isSaved()) {
// existing mailbox
// mailbox retrieved from database; save hash _before_ updating fields
folder.mHash = mailbox.getHashes();
}
updateMailbox(mailbox, accountId, mailboxPath, delimiter,
LegacyConversions.inferMailboxTypeFromName(context, mailboxPath));
if (folder.mHash == null) {
// new mailbox
// save hash after updating. allows tracking changes if the mailbox is saved
// outside of #saveMailboxList()
folder.mHash = mailbox.getHashes();
// We must save this here to make sure we have a valid ID for later
mailbox.save(mContext);
}
folder.mMailbox = mailbox;
return folder;
}
/**
* Persists the folders in the given list.
*/
private static void saveMailboxList(Context context, HashMap<String, ImapFolder> folderMap) {
for (ImapFolder imapFolder : folderMap.values()) {
imapFolder.save(context);
}
}
@Override
public Folder[] updateFolders() throws MessagingException {
ImapConnection connection = getConnection();
try {
ArrayList<Folder> folders = new ArrayList<Folder>();
HashMap<String, ImapFolder> mailboxes = new HashMap<String, ImapFolder>();
// Establish a connection to the IMAP server; if necessary
// This ensures a valid prefix if the prefix is automatically set by the server
connection.executeSimpleCommand(ImapConstants.NOOP);
@ -392,13 +461,22 @@ public class ImapStore extends Store {
includeFolder = false;
}
if (includeFolder) {
String delimiter = response.getStringOrEmpty(2).toString();
addMailbox(mContext, mAccount.mId, folderName, delimiter, folders);
String delimiter = response.getStringOrEmpty(2).getString();
char delimiterChar = '\0';
if (!TextUtils.isEmpty(delimiter)) {
delimiterChar = delimiter.charAt(0);
}
ImapFolder folder =
addMailbox(mContext, mAccount.mId, folderName, delimiterChar);
mailboxes.put(folderName, folder);
}
}
}
addMailbox(mContext, mAccount.mId, ImapConstants.INBOX, null, folders);
return folders.toArray(new Folder[] {});
Folder newFolder = addMailbox(mContext, mAccount.mId, ImapConstants.INBOX, '\0');
mailboxes.put(ImapConstants.INBOX, (ImapFolder)newFolder);
createHierarchy(mailboxes);
saveMailboxList(mContext, mailboxes);
return mailboxes.values().toArray(new Folder[] {});
} catch (IOException ioe) {
connection.close();
throw new MessagingException("Unable to get folder list.", ioe);

View File

@ -32,6 +32,7 @@ import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.mail.Folder.OpenMode;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.HostAuth;
import com.android.emailcommon.provider.EmailContent.Mailbox;
import com.android.emailcommon.service.EmailServiceProxy;
import com.android.emailcommon.utility.LoggingInputStream;
import com.android.emailcommon.utility.Utility;
@ -53,7 +54,8 @@ public class Pop3Store extends Store {
private static boolean DEBUG_LOG_RAW_STREAM = false;
private static final Flag[] PERMANENT_FLAGS = { Flag.DELETED };
/** The name of the only mailbox available to POP3 accounts */
private static final String POP3_MAILBOX_NAME = "INBOX";
private final Context mContext;
private final Account mAccount;
private Transport mTransport;
@ -154,10 +156,15 @@ public class Pop3Store extends Store {
}
@Override
public Folder[] updateFolders() throws MessagingException {
ArrayList<Folder> folders = new ArrayList<Folder>();
addMailbox(mContext, mAccount.mId, "INBOX", null, folders);
return folders.toArray(new Folder[] {});
public Folder[] updateFolders() {
Mailbox mailbox = getMailboxForPath(mContext, mAccount.mId, POP3_MAILBOX_NAME);
updateMailbox(mailbox, mAccount.mId, POP3_MAILBOX_NAME, '\0', Mailbox.TYPE_INBOX);
if (mailbox.isSaved()) {
mailbox.update(mContext, mailbox.toContentValues());
} else {
mailbox.save(mContext);
}
return new Folder[] { getFolder(POP3_MAILBOX_NAME) };
}
/**
@ -169,7 +176,7 @@ public class Pop3Store extends Store {
*/
@Override
public Bundle checkSettings() throws MessagingException {
Pop3Folder folder = new Pop3Folder("INBOX");
Pop3Folder folder = new Pop3Folder(POP3_MAILBOX_NAME);
Bundle bundle = null;
// Close any open or half-open connections - checkSettings should always be "fresh"
if (mTransport.isOpen()) {
@ -195,8 +202,8 @@ public class Pop3Store extends Store {
private Pop3Capabilities mCapabilities;
public Pop3Folder(String name) {
if (name.equalsIgnoreCase("INBOX")) {
mName = "INBOX";
if (name.equalsIgnoreCase(POP3_MAILBOX_NAME)) {
mName = POP3_MAILBOX_NAME;
} else {
mName = name;
}
@ -243,7 +250,7 @@ public class Pop3Store extends Store {
return;
}
if (!mName.equalsIgnoreCase("INBOX")) {
if (!mName.equalsIgnoreCase(POP3_MAILBOX_NAME)) {
throw new MessagingException("Folder does not exist");
}
@ -351,7 +358,7 @@ public class Pop3Store extends Store {
@Override
public boolean exists() {
return mName.equalsIgnoreCase("INBOX");
return mName.equalsIgnoreCase(POP3_MAILBOX_NAME);
}
@Override

View File

@ -34,6 +34,7 @@ import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.EmailContent.MessageColumns;
import com.android.emailcommon.provider.EmailContent.SyncColumns;
import com.google.common.annotations.VisibleForTesting;
import android.accounts.AccountManager;
import android.content.ContentProvider;
@ -111,7 +112,9 @@ public class EmailProvider extends ContentProvider {
// Version 15: Fix upgrade problem in version 14.
// Version 16: Add accountKey to Attachment table
// Version 17: Add parentKey to Mailbox table
public static final int DATABASE_VERSION = 17;
// Version 18: Copy Mailbox.displayName to Mailbox.serverId for all IMAP & POP3 mailboxes.
// Column Mailbox.serverId is used for the server-side pathname of a mailbox.
public static final int DATABASE_VERSION = 18;
// Any changes to the database format *must* include update-in-place code.
// Original version: 2
@ -944,6 +947,10 @@ public class EmailProvider extends ContentProvider {
}
oldVersion = 17;
}
if (oldVersion == 17) {
upgradeFromVersion17ToVersion18(db);
oldVersion = 18;
}
}
@Override
@ -1601,13 +1608,47 @@ public class EmailProvider extends ContentProvider {
}
}
/**
* Count the number of messages in each mailbox, and update the message count column.
*/
/* package */ static void recalculateMessageCount(SQLiteDatabase db) {
/** Counts the number of messages in each mailbox, and updates the message count column. */
@VisibleForTesting
static void recalculateMessageCount(SQLiteDatabase db) {
db.execSQL("update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.MESSAGE_COUNT +
"= (select count(*) from " + Message.TABLE_NAME +
" where " + Message.MAILBOX_KEY + " = " +
Mailbox.TABLE_NAME + "." + EmailContent.RECORD_ID + ")");
}
/** Upgrades the database from v17 to v18 */
@VisibleForTesting
static void upgradeFromVersion17ToVersion18(SQLiteDatabase db) {
// Copy the displayName column to the serverId column. In v18 of the database,
// we use the serverId for IMAP/POP3 mailboxes instead of overloading the
// display name.
//
// For posterity; this is the command we're executing:
//sqlite> UPDATE mailbox SET serverid=displayname WHERE mailbox._id in (
// ...> SELECT mailbox._id FROM mailbox,account,hostauth WHERE
// ...> mailbox.parentkey=0 AND mailbox.accountkey=account._id AND
// ...> account.hostauthkeyrecv=hostauth._id AND
// ...> (hostauth.protocol='imap' OR hostauth.protocol='pop3'));
try {
db.execSQL(
"UPDATE " + Mailbox.TABLE_NAME + " SET "
+ MailboxColumns.SERVER_ID + "=" + MailboxColumns.DISPLAY_NAME
+ " WHERE "
+ Mailbox.TABLE_NAME + "." + MailboxColumns.ID + " IN ( SELECT "
+ Mailbox.TABLE_NAME + "." + MailboxColumns.ID + " FROM "
+ Mailbox.TABLE_NAME + "," + Account.TABLE_NAME + ","
+ HostAuth.TABLE_NAME + " WHERE "
+ Mailbox.TABLE_NAME + "." + MailboxColumns.PARENT_KEY + "=0 AND "
+ Mailbox.TABLE_NAME + "." + MailboxColumns.ACCOUNT_KEY + "="
+ Account.TABLE_NAME + "." + AccountColumns.ID + " AND "
+ Account.TABLE_NAME + "." + AccountColumns.HOST_AUTH_KEY_RECV + "="
+ HostAuth.TABLE_NAME + "." + HostAuthColumns.ID + " AND ( "
+ HostAuth.TABLE_NAME + "." + HostAuthColumns.PROTOCOL + "='imap' OR "
+ HostAuth.TABLE_NAME + "." + HostAuthColumns.PROTOCOL + "='pop3' ) )");
} catch (SQLException e) {
// Shouldn't be needed unless we're debugging and interrupt the process
Log.w(TAG, "Exception upgrading EmailProvider.db from 17 to 18 " + e);
}
}
}

View File

@ -108,7 +108,7 @@ public class MailboxFinderTest extends InstrumentationTestCase {
*/
private long createMailbox(long accountId, int mailboxType) {
EmailContent.Mailbox box = new EmailContent.Mailbox();
box.mDisplayName = "mailbox";
box.mServerId = box.mDisplayName = "mailbox";
box.mAccountKey = accountId;
box.mType = mailboxType;
box.mFlagVisible = true;

View File

@ -21,6 +21,7 @@ import com.android.email.mail.Store.StoreInfo;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.HostAuth;
import com.android.emailcommon.provider.EmailContent.Mailbox;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
@ -132,4 +133,31 @@ public class StoreTests extends AndroidTestCase {
assertEquals(0, Store.sStores.size());
}
public void testUpdateMailbox() {
Mailbox testMailbox = new Mailbox();
Store.updateMailbox(testMailbox, 1L, "inbox", '/', Mailbox.TYPE_MAIL);
assertEquals(1L, testMailbox.mAccountKey);
assertEquals("inbox", testMailbox.mDisplayName);
assertEquals("inbox", testMailbox.mServerId);
assertEquals('/', testMailbox.mDelimiter);
Store.updateMailbox(testMailbox, 2L, "inbox/a", '/', Mailbox.TYPE_MAIL);
assertEquals(2L, testMailbox.mAccountKey);
assertEquals("a", testMailbox.mDisplayName);
assertEquals("inbox/a", testMailbox.mServerId);
assertEquals('/', testMailbox.mDelimiter);
Store.updateMailbox(testMailbox, 3L, "inbox/a/b/c/d", '/', Mailbox.TYPE_MAIL);
assertEquals(3L, testMailbox.mAccountKey);
assertEquals("d", testMailbox.mDisplayName);
assertEquals("inbox/a/b/c/d", testMailbox.mServerId);
assertEquals('/', testMailbox.mDelimiter);
Store.updateMailbox(testMailbox, 4L, "inbox/a/b/c", '\0', Mailbox.TYPE_MAIL);
assertEquals(4L, testMailbox.mAccountKey);
assertEquals("inbox/a/b/c", testMailbox.mDisplayName);
assertEquals("inbox/a/b/c", testMailbox.mServerId);
assertEquals('\0', testMailbox.mDelimiter);
}
}

View File

@ -45,6 +45,7 @@ import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.mail.Part;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.HostAuth;
import com.android.emailcommon.provider.EmailContent.Mailbox;
import com.android.emailcommon.utility.Utility;
import org.apache.commons.io.IOUtils;
@ -1259,7 +1260,7 @@ public class ImapStoreUnitTests extends InstrumentationTestCase {
list.add(f.getName());
}
MoreAsserts.assertEquals(
new String[] {"Drafts", "\u65E5\u672C\u8A9E", "INBOX"},
new String[] {"INBOX", "\u65E5\u672C\u8A9E", "Drafts"},
list.toArray(new String[0])
);
@ -2134,7 +2135,7 @@ public class ImapStoreUnitTests extends InstrumentationTestCase {
list.add(f.getName());
}
MoreAsserts.assertEquals(
new String[] {FOLDER_1, FOLDER_2, "INBOX"},
new String[] {"INBOX", FOLDER_2, FOLDER_1},
list.toArray(new String[0])
);
@ -2148,8 +2149,8 @@ public class ImapStoreUnitTests extends InstrumentationTestCase {
"* OK [UNSEEN 0]",
"* OK [UIDNEXT 1]",
getNextTag(true) + " OK [READ-WRITE] " + FOLDER_1});
folders[0].open(OpenMode.READ_WRITE, null);
folders[0].close(false);
folders[2].open(OpenMode.READ_WRITE, null);
folders[2].close(false);
expectNoop(mock, true);
mock.expect(getNextTag(false) + " SELECT \"" + FOLDER_2 + "\"", new String[] {
@ -2274,4 +2275,76 @@ public class ImapStoreUnitTests extends InstrumentationTestCase {
}
});
}
/** Creates a folder & mailbox */
private ImapFolder createFolder(long id, String displayName, String serverId, char delimiter) {
ImapFolder folder = new ImapFolder(null, serverId);
Mailbox mailbox = new Mailbox();
mailbox.mId = id;
mailbox.mDisplayName = displayName;
mailbox.mServerId = serverId;
mailbox.mDelimiter = delimiter;
mailbox.mFlags = 0xAAAAAAA8;
folder.mMailbox = mailbox;
return folder;
}
/** Tests creating folder hierarchies */
public void testCreateHierarchy() {
HashMap<String, ImapFolder> testMap = new HashMap<String, ImapFolder>();
// Create hierarchy
// |-INBOX
// | +-b
// |-a
// | |-b
// | |-c
// | +-d
// | +-b
// | +-b
// +-g
ImapFolder[] folders = {
createFolder(1L, "INBOX", "INBOX", '/'),
createFolder(2L, "b", "INBOX/b", '/'),
createFolder(3L, "a", "a", '/'),
createFolder(4L, "b", "a/b", '/'),
createFolder(5L, "c", "a/c", '/'),
createFolder(6L, "d", "a/d", '/'),
createFolder(7L, "b", "a/d/b", '/'),
createFolder(8L, "b", "a/d/b/b", '/'),
createFolder(9L, "g", "g", '/'),
};
for (ImapFolder folder : folders) {
testMap.put(folder.getName(), folder);
}
ImapStore.createHierarchy(testMap);
// 'INBOX'
assertEquals(-1L, folders[0].mMailbox.mParentKey);
assertEquals(0xAAAAAAAB, folders[0].mMailbox.mFlags);
// 'INBOX/b'
assertEquals(1L, folders[1].mMailbox.mParentKey);
assertEquals(0xAAAAAAA8, folders[1].mMailbox.mFlags);
// 'a'
assertEquals(-1L, folders[2].mMailbox.mParentKey);
assertEquals(0xAAAAAAAB, folders[2].mMailbox.mFlags);
// 'a/b'
assertEquals(3L, folders[3].mMailbox.mParentKey);
assertEquals(0xAAAAAAA8, folders[3].mMailbox.mFlags);
// 'a/c'
assertEquals(3L, folders[4].mMailbox.mParentKey);
assertEquals(0xAAAAAAA8, folders[4].mMailbox.mFlags);
// 'a/d'
assertEquals(3L, folders[5].mMailbox.mParentKey);
assertEquals(0xAAAAAAAB, folders[5].mMailbox.mFlags);
// 'a/d/b'
assertEquals(6L, folders[6].mMailbox.mParentKey);
assertEquals(0xAAAAAAAB, folders[6].mMailbox.mFlags);
// 'a/d/b/b'
assertEquals(7L, folders[7].mMailbox.mParentKey);
assertEquals(0xAAAAAAA8, folders[7].mMailbox.mFlags);
// 'g'
assertEquals(-1L, folders[8].mMailbox.mParentKey);
assertEquals(0xAAAAAAA8, folders[8].mMailbox.mFlags);
}
}

View File

@ -125,8 +125,13 @@ public class ProviderTestUtils extends Assert {
Context context, int type, char delimiter) {
Mailbox box = new Mailbox();
box.mDisplayName = name;
box.mServerId = "serverid-" + name;
int delimiterIndex = name.lastIndexOf(delimiter);
String displayName = name;
if (delimiterIndex > 0) {
displayName = name.substring(delimiterIndex + 1);
}
box.mDisplayName = displayName;
box.mServerId = name;
box.mParentServerId = "parent-serverid-" + name;
box.mParentKey = 4;
box.mAccountKey = accountId;

View File

@ -88,6 +88,41 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
* TODO: Database upgrade tests
*/
//////////////////////////////////////////////////////////
////// Utility methods
//////////////////////////////////////////////////////////
/** Sets the message count of all mailboxes to {@code -1}. */
private void setMinusOneToMessageCounts() {
ContentValues values = new ContentValues();
values.put(MailboxColumns.MESSAGE_COUNT, -1);
// EmailProvider.update() doesn't allow updating messageCount, so directly use the DB.
SQLiteDatabase db = getProvider().getDatabase(mMockContext);
db.update(Mailbox.TABLE_NAME, values, null, null);
}
/** Returns the number of messages in a mailbox. */
private int getMessageCount(long mailboxId) {
return Utility.getFirstRowInt(mMockContext,
ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
new String[] {MailboxColumns.MESSAGE_COUNT}, null, null, null, 0);
}
/** Creates a new message. */
private static Message createMessage(Context c, Mailbox b, boolean starred, boolean read,
int flagLoaded) {
Message message = ProviderTestUtils.setupMessage(
"1", b.mAccountKey, b.mId, true, false, c, starred, read);
message.mFlagLoaded = flagLoaded;
message.save(c);
return message;
}
//////////////////////////////////////////////////////////
////// The tests
//////////////////////////////////////////////////////////
/**
* Test simple account save/retrieve
*/
@ -312,21 +347,6 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
return Integer.valueOf(text);
}
/**
* Test simple mailbox save/retrieve
*/
public void testMailboxSave() {
Account account1 = ProviderTestUtils.setupAccount("mailbox-save", true, mMockContext);
long account1Id = account1.mId;
Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true,
mMockContext);
long box1Id = box1.mId;
Mailbox box2 = EmailContent.Mailbox.restoreMailboxWithId(mMockContext, box1Id);
ProviderTestUtils.assertMailboxEqual("testMailboxSave", box1, box2);
}
private static String[] expectedAttachmentNames =
new String[] {"attachment1.doc", "attachment2.xls", "attachment3"};
// The lengths need to be kept in ascending order
@ -937,41 +957,6 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
assertEquals(4, EmailContent.count(context, Message.DELETED_CONTENT_URI, null, null));
}
/**
* Test delete mailbox
*/
public void testMailboxDelete() {
Account account1 = ProviderTestUtils.setupAccount("mailbox-delete", true, mMockContext);
long account1Id = account1.mId;
Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext);
long box1Id = box1.mId;
Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mMockContext);
long box2Id = box2.mId;
String selection = EmailContent.MailboxColumns.ACCOUNT_KEY + "=?";
String[] selArgs = new String[] { String.valueOf(account1Id) };
// make sure there are two mailboxes
int numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs);
assertEquals(2, numBoxes);
// now delete one of them
Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box1Id);
mMockContext.getContentResolver().delete(uri, null, null);
// make sure there's only one mailbox now
numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs);
assertEquals(1, numBoxes);
// now delete the other one
uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2Id);
mMockContext.getContentResolver().delete(uri, null, null);
// make sure there are no mailboxes now
numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs);
assertEquals(0, numBoxes);
}
/**
* Test delete message
* TODO: body
@ -1731,90 +1716,6 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, count);
}
public void testFindMailboxOfType() {
final Context context = mMockContext;
// Create two accounts and a variety of mailbox types
Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context);
Mailbox acct1Inbox =
ProviderTestUtils.setupMailbox("Inbox1", acct1.mId, true, context, Mailbox.TYPE_INBOX);
Mailbox acct1Calendar
= ProviderTestUtils.setupMailbox("Cal1", acct1.mId, true, context, Mailbox.TYPE_CALENDAR);
Mailbox acct1Contacts =
ProviderTestUtils.setupMailbox("Con1", acct1.mId, true, context, Mailbox.TYPE_CONTACTS);
Account acct2 = ProviderTestUtils.setupAccount("acct1", true, context);
Mailbox acct2Inbox =
ProviderTestUtils.setupMailbox("Inbox2", acct2.mId, true, context, Mailbox.TYPE_INBOX);
Mailbox acct2Calendar =
ProviderTestUtils.setupMailbox("Cal2", acct2.mId, true, context, Mailbox.TYPE_CALENDAR);
Mailbox acct2Contacts =
ProviderTestUtils.setupMailbox("Con2", acct2.mId, true, context, Mailbox.TYPE_CONTACTS);
// Check that we can find them by type
assertEquals(acct1Inbox.mId,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX));
assertEquals(acct2Inbox.mId,
Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_INBOX));
assertEquals(acct1Calendar.mId,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR));
assertEquals(acct2Calendar.mId,
Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_CALENDAR));
assertEquals(acct1Contacts.mId,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS));
assertEquals(acct2Contacts.mId,
Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_CONTACTS));
// Check that nonexistent mailboxes are not returned
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_DRAFTS));
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_OUTBOX));
// delete account 1 and confirm no mailboxes are returned
context.getContentResolver().delete(
ContentUris.withAppendedId(Account.CONTENT_URI, acct1.mId), null, null);
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX));
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR));
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS));
}
public void testRestoreMailboxOfType() {
final Context context = mMockContext;
// Create two accounts and a variety of mailbox types
Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context);
Mailbox acct1Inbox =
ProviderTestUtils.setupMailbox("Inbox1", acct1.mId, true, context, Mailbox.TYPE_INBOX);
Mailbox acct1Calendar
= ProviderTestUtils.setupMailbox("Cal1", acct1.mId, true, context, Mailbox.TYPE_CALENDAR);
Mailbox acct1Contacts =
ProviderTestUtils.setupMailbox("Con1", acct1.mId, true, context, Mailbox.TYPE_CONTACTS);
Account acct2 = ProviderTestUtils.setupAccount("acct1", true, context);
Mailbox acct2Inbox =
ProviderTestUtils.setupMailbox("Inbox2", acct2.mId, true, context, Mailbox.TYPE_INBOX);
Mailbox acct2Calendar =
ProviderTestUtils.setupMailbox("Cal2", acct2.mId, true, context, Mailbox.TYPE_CALENDAR);
Mailbox acct2Contacts =
ProviderTestUtils.setupMailbox("Con2", acct2.mId, true, context, Mailbox.TYPE_CONTACTS);
// Check that we can find them by type
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Inbox,
Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Inbox,
Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_INBOX));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Calendar,
Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Calendar,
Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_CALENDAR));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Contacts,
Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Contacts,
Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_CONTACTS));
}
public void testAccountIsSecurityHold() {
final Context context = mMockContext;
Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context);
@ -1846,205 +1747,11 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
assertEquals(Account.FLAGS_VIBRATE_ALWAYS, a2a.mFlags);
}
/**
* @return the number of messages in a mailbox.
*/
private int getMessageCount(long mailboxId) {
return Utility.getFirstRowInt(mMockContext,
ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
new String[] {MailboxColumns.MESSAGE_COUNT}, null, null, null, 0);
}
/** Set -1 to the message count of all mailboxes for the recalculateMessageCount test. */
private void setMinusOneToMessageCounts() {
ContentValues values = new ContentValues();
values.put(MailboxColumns.MESSAGE_COUNT, -1);
// EmailProvider.update() doesn't allow updating messageCount, so directly use the DB.
SQLiteDatabase db = getProvider().getDatabase(mMockContext);
db.update(Mailbox.TABLE_NAME, values, null, null);
}
/**
* Test for the message count triggers (insert/delete/move mailbox), and also
* {@link EmailProvider#recalculateMessageCount}.
*
* It also covers:
* - {@link Mailbox#getMessageCountByMailboxType(Context, int)}
* - {@link Mailbox#getUnreadCountByAccountAndMailboxType(Context, long, int)}
* - {@link Mailbox#getUnreadCountByMailboxType(Context, int)}
* - {@link Message#getFavoriteMessageCount(Context)}
* - {@link Message#getFavoriteMessageCount(Context, long)}
*/
public void testMessageCount() {
final Context c = mMockContext;
// Create 2 accounts
Account a1 = ProviderTestUtils.setupAccount("holdflag-1", true, c);
Account a2 = ProviderTestUtils.setupAccount("holdflag-2", true, c);
// Create 2 mailboxes for each account
Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox b2 = ProviderTestUtils.setupMailbox("box2", a1.mId, true, c, Mailbox.TYPE_OUTBOX);
Mailbox b3 = ProviderTestUtils.setupMailbox("box3", a2.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox b4 = ProviderTestUtils.setupMailbox("box4", a2.mId, true, c, Mailbox.TYPE_OUTBOX);
Mailbox bt = ProviderTestUtils.setupMailbox("boxT", a2.mId, true, c, Mailbox.TYPE_TRASH);
// 0. Check the initial values, just in case.
assertEquals(0, getMessageCount(b1.mId));
assertEquals(0, getMessageCount(b2.mId));
assertEquals(0, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
assertEquals(0, getMessageCount(bt.mId));
assertEquals(0, Message.getFavoriteMessageCount(c));
assertEquals(0, Message.getFavoriteMessageCount(c, a1.mId));
assertEquals(0, Message.getFavoriteMessageCount(c, a2.mId));
assertEquals(0, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_TRASH));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_TRASH));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_TRASH));
// 1. Test for insert triggers.
// Create some messages
// b1 (account 1, inbox): 1 message, including 1 starred
Message m11 = createMessage(c, b1, true, false, Message.FLAG_LOADED_COMPLETE);
// b2 (account 1, outbox): 2 message, including 1 starred
Message m21 = createMessage(c, b2, false, false, Message.FLAG_LOADED_COMPLETE);
Message m22 = createMessage(c, b2, true, true, Message.FLAG_LOADED_COMPLETE);
// b3 (account 2, inbox): 3 message, including 1 starred
Message m31 = createMessage(c, b3, false, false, Message.FLAG_LOADED_COMPLETE);
Message m32 = createMessage(c, b3, false, false, Message.FLAG_LOADED_COMPLETE);
Message m33 = createMessage(c, b3, true, true, Message.FLAG_LOADED_COMPLETE);
// b4 (account 2, outbox) has no messages.
// bt (account 2, trash) has 3 messages, including 2 starred
Message mt1 = createMessage(c, bt, true, false, Message.FLAG_LOADED_COMPLETE);
Message mt2 = createMessage(c, bt, true, false, Message.FLAG_LOADED_COMPLETE);
Message mt3 = createMessage(c, bt, false, false, Message.FLAG_LOADED_COMPLETE);
// Check message counts
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(3, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
assertEquals(3, getMessageCount(bt.mId));
// Check the simple counting methods.
assertEquals(3, Message.getFavoriteMessageCount(c)); // excludes starred in trash
assertEquals(2, Message.getFavoriteMessageCount(c, a1.mId));
assertEquals(1, Message.getFavoriteMessageCount(c, a2.mId)); // excludes starred in trash
assertEquals(3, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_INBOX));
assertEquals(1, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_OUTBOX));
assertEquals(4, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_INBOX));
assertEquals(2, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_OUTBOX));
assertEquals(3, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_TRASH));
assertEquals(1, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_INBOX));
assertEquals(1, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_TRASH));
assertEquals(2, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_OUTBOX));
assertEquals(3, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_TRASH));
// 2. test for recalculateMessageCount.
// First, invalidate the message counts.
setMinusOneToMessageCounts();
assertEquals(-1, getMessageCount(b1.mId));
assertEquals(-1, getMessageCount(b2.mId));
assertEquals(-1, getMessageCount(b3.mId));
assertEquals(-1, getMessageCount(b4.mId));
// Batch update.
SQLiteDatabase db = getProvider().getDatabase(mMockContext);
EmailProvider.recalculateMessageCount(db);
// Check message counts
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(3, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
// 3. Check the "move mailbox" trigger.
// Move m32 (in mailbox 3) to mailbox 4.
ContentValues values = new ContentValues();
values.put(MessageColumns.MAILBOX_KEY, b4.mId);
getProvider().update(Message.CONTENT_URI, values, EmailContent.ID_SELECTION,
new String[] {"" + m32.mId});
// Check message counts
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(2, getMessageCount(b3.mId));
assertEquals(1, getMessageCount(b4.mId));
// 4. Check the delete trigger.
// Delete m11 (in mailbox 1)
getProvider().delete(Message.CONTENT_URI, EmailContent.ID_SELECTION,
new String[] {"" + m11.mId});
// Delete m21 (in mailbox 2)
getProvider().delete(Message.CONTENT_URI, EmailContent.ID_SELECTION,
new String[] {"" + m21.mId});
// Check message counts
assertEquals(0, getMessageCount(b1.mId));
assertEquals(1, getMessageCount(b2.mId));
assertEquals(2, getMessageCount(b3.mId));
assertEquals(1, getMessageCount(b4.mId));
// No such mailbox type.
assertEquals(0, Mailbox.getMessageCountByMailboxType(c, 99999));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, a1.mId, 99999));
assertEquals(0, Mailbox.getUnreadCountByMailboxType(c, 99999));
// No such account
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
99999, Mailbox.TYPE_INBOX));
}
private static Message createMessage(Context c, Mailbox b, boolean starred, boolean read) {
return ProviderTestUtils.setupMessage(
"1", b.mAccountKey, b.mId, true, true, c, starred, read);
}
private static Message createMessage(Context c, Mailbox b, boolean starred, boolean read,
int flagLoaded) {
Message message = ProviderTestUtils.setupMessage(
"1", b.mAccountKey, b.mId, true, false, c, starred, read);
message.mFlagLoaded = flagLoaded;
message.save(c);
return message;
}
public void testAccountIsEasAccount() {
Account account = new Account();
// No hostauth
@ -2093,46 +1800,6 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
assertEquals(-1, Account.getAccountIdForMessageId(c, 12345));
}
public void testGetMailboxForMessageId() {
final Context c = mMockContext;
Mailbox b1 = ProviderTestUtils.setupMailbox("box1", 1, true, c, Mailbox.TYPE_MAIL);
Mailbox b2 = ProviderTestUtils.setupMailbox("box2", 1, true, c, Mailbox.TYPE_MAIL);
Message m1 = createMessage(c, b1, false, false);
Message m2 = createMessage(c, b2, false, false);
ProviderTestUtils.assertMailboxEqual("x", b1, Mailbox.getMailboxForMessageId(c, m1.mId));
ProviderTestUtils.assertMailboxEqual("x", b2, Mailbox.getMailboxForMessageId(c, m2.mId));
}
public void testRestoreMailboxWithId() {
final Context c = mMockContext;
Mailbox testMailbox;
testMailbox = ProviderTestUtils.setupMailbox("box1", 1, true, c, Mailbox.TYPE_MAIL);
ProviderTestUtils.assertMailboxEqual(
"x", testMailbox, Mailbox.restoreMailboxWithId(c, testMailbox.mId));
testMailbox = ProviderTestUtils.setupMailbox("box2", 1, true, c, Mailbox.TYPE_MAIL);
ProviderTestUtils.assertMailboxEqual(
"x", testMailbox, Mailbox.restoreMailboxWithId(c, testMailbox.mId));
// Unknown IDs
assertNull(Mailbox.restoreMailboxWithId(c, 8));
assertNull(Mailbox.restoreMailboxWithId(c, -1));
assertNull(Mailbox.restoreMailboxWithId(c, Long.MAX_VALUE));
}
public void testRestoreMailboxForPath() {
final Context c = mMockContext;
Mailbox testMailbox;
testMailbox = ProviderTestUtils.setupMailbox("a/b/c/box", 1, true, c, Mailbox.TYPE_MAIL);
ProviderTestUtils.assertMailboxEqual(
"x", testMailbox, Mailbox.restoreMailboxForPath(c, 1, "a/b/c/box"));
// Same name, different account; no match
assertNull(Mailbox.restoreMailboxForPath(c, 2, "a/b/c/box"));
// Substring; no match
assertNull(Mailbox.restoreMailboxForPath(c, 1, "a/b/c"));
// Wild cards not supported; no match
assertNull(Mailbox.restoreMailboxForPath(c, 1, "a/b/c/%"));
}
public void testGetAccountForMessageId() {
final Context c = mMockContext;
Account a = ProviderTestUtils.setupAccount("acct", true, c);
@ -2158,67 +1825,6 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
assertEquals(-1, Account.getInboxId(c, 999999));
}
public void testGetMailboxType() {
final Context c = mMockContext;
Account a = ProviderTestUtils.setupAccount("acct1", true, c);
Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox bm = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_MAIL);
assertEquals(Mailbox.TYPE_INBOX, Mailbox.getMailboxType(c, bi.mId));
assertEquals(Mailbox.TYPE_MAIL, Mailbox.getMailboxType(c, bm.mId));
assertEquals(-1, Mailbox.getMailboxType(c, 999999)); // mailbox not found
}
public void testGetDisplayName() {
final Context c = mMockContext;
Account a = ProviderTestUtils.setupAccount("acct1", true, c);
Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox bm = ProviderTestUtils.setupMailbox("b2", a.mId, true, c, Mailbox.TYPE_MAIL);
assertEquals("b1", Mailbox.getDisplayName(c, bi.mId));
assertEquals("b2", Mailbox.getDisplayName(c, bm.mId));
assertEquals(null, Mailbox.getDisplayName(c, 999999)); // mailbox not found
}
public void testMailboxIsRefreshable() {
final Context c = mMockContext;
Account a = ProviderTestUtils.setupAccount("acct1", true, c);
Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox bm = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_MAIL);
Mailbox bd = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_DRAFTS);
Mailbox bo = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_OUTBOX);
assertTrue(Mailbox.isRefreshable(c, bi.mId));
assertTrue(Mailbox.isRefreshable(c, bm.mId));
assertFalse(Mailbox.isRefreshable(c, bd.mId));
assertFalse(Mailbox.isRefreshable(c, bo.mId));
// No such mailbox
assertFalse(Mailbox.isRefreshable(c, 9999999));
// Magic mailboxes can't be refreshed.
assertFalse(Mailbox.isRefreshable(c, Mailbox.QUERY_ALL_DRAFTS));
assertFalse(Mailbox.isRefreshable(c, Mailbox.QUERY_ALL_INBOXES));
}
public void testMailboxCanMoveFrom() {
final Context c = mMockContext;
Account a = ProviderTestUtils.setupAccount("acct1", true, c);
Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox bm = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_MAIL);
Mailbox bd = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_DRAFTS);
Mailbox bo = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_OUTBOX);
assertTrue(Mailbox.canMoveFrom(c, bi.mId));
assertTrue(Mailbox.canMoveFrom(c, bm.mId));
assertFalse(Mailbox.canMoveFrom(c, bd.mId));
assertFalse(Mailbox.canMoveFrom(c, bo.mId));
}
/**
* Check if update to {@link Account#RESET_NEW_MESSAGE_COUNT_URI} resets the new message count.
*/
@ -2375,27 +1981,6 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, Account.restoreAccountWithId(c, a1.mId).mNewMessageCount);
}
/**
* Check if update on MAILBOX_ID_ADD_TO_FIELD updates the cache properly.
*/
public void testUpdateCacheMailboxIdAddToField() {
final Context c = mMockContext;
Account a1 = ProviderTestUtils.setupAccount("a1", true, c);
Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c, Mailbox.TYPE_INBOX);
int start = Mailbox.restoreMailboxWithId(c, b1.mId).mSyncInterval;
// +1 to SYNC_INTERVAL
ContentValues cv = new ContentValues();
cv.put(EmailContent.FIELD_COLUMN_NAME, MailboxColumns.SYNC_INTERVAL);
cv.put(EmailContent.ADD_COLUMN_NAME, 1);
mProvider.update(ContentUris.withAppendedId(Mailbox.ADD_TO_FIELD_URI, a1.mId), cv,
null, null);
// Check
assertEquals(start + 1, Mailbox.restoreMailboxWithId(c, b1.mId).mSyncInterval);
}
/**
* Check that we're handling illegal uri's properly (by throwing an exception unless it's a
* query for an id of -1, in which case we return a zero-length cursor)
@ -2437,4 +2022,220 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, c.getCount());
c.close();
}
/**
* Verify {@link EmailProvider#recalculateMessageCount(android.database.sqlite.SQLiteDatabase)}
*/
public void testRecalculateMessageCounts() {
final Context c = mMockContext;
// Create accounts
Account a1 = ProviderTestUtils.setupAccount("holdflag-1", true, c);
Account a2 = ProviderTestUtils.setupAccount("holdflag-2", true, c);
// Create mailboxes for each account
Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox b2 = ProviderTestUtils.setupMailbox("box2", a1.mId, true, c, Mailbox.TYPE_OUTBOX);
Mailbox b3 = ProviderTestUtils.setupMailbox("box3", a2.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox b4 = ProviderTestUtils.setupMailbox("box4", a2.mId, true, c, Mailbox.TYPE_OUTBOX);
Mailbox bt = ProviderTestUtils.setupMailbox("boxT", a2.mId, true, c, Mailbox.TYPE_TRASH);
// Create some messages
// b1 (account 1, inbox): 1 message, including 1 starred
Message m11 = createMessage(c, b1, true, false, Message.FLAG_LOADED_COMPLETE);
// b2 (account 1, outbox): 2 message, including 1 starred
Message m21 = createMessage(c, b2, false, false, Message.FLAG_LOADED_COMPLETE);
Message m22 = createMessage(c, b2, true, true, Message.FLAG_LOADED_COMPLETE);
// b3 (account 2, inbox): 3 message, including 1 starred
Message m31 = createMessage(c, b3, false, false, Message.FLAG_LOADED_COMPLETE);
Message m32 = createMessage(c, b3, false, false, Message.FLAG_LOADED_COMPLETE);
Message m33 = createMessage(c, b3, true, true, Message.FLAG_LOADED_COMPLETE);
// b4 (account 2, outbox) has no messages.
// bt (account 2, trash) has 3 messages, including 2 starred
Message mt1 = createMessage(c, bt, true, false, Message.FLAG_LOADED_COMPLETE);
Message mt2 = createMessage(c, bt, true, false, Message.FLAG_LOADED_COMPLETE);
Message mt3 = createMessage(c, bt, false, false, Message.FLAG_LOADED_COMPLETE);
// Verifiy initial message counts
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(3, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
assertEquals(3, getMessageCount(bt.mId));
// Whew. The setup is done; now let's actually get to the test
// First, invalidate the message counts.
setMinusOneToMessageCounts();
assertEquals(-1, getMessageCount(b1.mId));
assertEquals(-1, getMessageCount(b2.mId));
assertEquals(-1, getMessageCount(b3.mId));
assertEquals(-1, getMessageCount(b4.mId));
assertEquals(-1, getMessageCount(bt.mId));
// Batch update.
SQLiteDatabase db = getProvider().getDatabase(mMockContext);
EmailProvider.recalculateMessageCount(db);
// Check message counts are valid again
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(3, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
assertEquals(3, getMessageCount(bt.mId));
}
/** Creates an account */
private Account createAccount(Context c, String name, HostAuth recvAuth, HostAuth sendAuth) {
Account account = ProviderTestUtils.setupAccount(name, false, c);
if (recvAuth != null) {
account.mHostAuthKeyRecv = recvAuth.mId;
if (sendAuth == null) {
account.mHostAuthKeySend = recvAuth.mId;
}
}
if (sendAuth != null) {
account.mHostAuthKeySend = sendAuth.mId;
}
account.save(c);
return account;
}
/** Creates a mailbox; redefine as we need version 17 mailbox values */
private Mailbox createMailbox(Context c, String displayName, String serverId, long parentKey,
long accountId) {
Mailbox box = new Mailbox();
box.mDisplayName = displayName;
box.mServerId = serverId;
box.mParentKey = parentKey;
box.mAccountKey = accountId;
// Don't care about the fields below ... set them for giggles
box.mType = Mailbox.TYPE_MAIL;
box.mDelimiter = '/';
box.mSyncKey = "sync-key";
box.mSyncLookback = 2;
box.mSyncInterval = EmailContent.Account.CHECK_INTERVAL_NEVER;
box.mSyncTime = 3;
box.mFlagVisible = true;
box.mFlags = 5;
box.mVisibleLimit = 6;
box.save(c);
return box;
}
/**
* Asserts equality between two mailboxes. We define this as we don't have implementations
* for Mailbox#equals().
*/
private void assertEquals(Mailbox expected, Mailbox actual) {
if (expected == null && actual == null) return;
assertTrue(expected != null && actual != null);
assertEqualsExceptServerId(expected, actual, expected.mServerId);
}
/**
* Asserts equality between the two mailboxes EXCEPT for the server id. The given server
* ID is the expected value.
*/
private void assertEqualsExceptServerId(Mailbox expected, Mailbox actual, String serverId) {
if (expected == null && actual == null) return;
assertTrue(expected != null && actual != null);
assertEquals(expected.mDisplayName, actual.mDisplayName);
assertEquals(serverId, actual.mServerId);
assertEquals(expected.mParentKey, actual.mParentKey);
assertEquals(expected.mAccountKey, actual.mAccountKey);
}
/** Verifies updating the DB from v17 to v18 works as expected */
public void testUpgradeFromVersion17ToVersion18() {
final Context c = mMockContext;
// Create accounts
Account a1 =createAccount(c, "exchange",
ProviderTestUtils.setupHostAuth("eas", "exchange.host.com", true, c),
null);
Account a2 = createAccount(c, "imap",
ProviderTestUtils.setupHostAuth("imap", "imap.host.com", true, c),
ProviderTestUtils.setupHostAuth("smtp", "smtp.host.com", true, c));
Account a3 = createAccount(c, "pop3",
ProviderTestUtils.setupHostAuth("pop3", "imap.host.com", true, c),
ProviderTestUtils.setupHostAuth("smtp", "smtp.host.com", true, c));
// Create mailboxes; some w/ valid parent IDs, others without
Mailbox b11 = createMailbox(c, "box1", "12", 0L, a1.mId);
Mailbox b12 = createMailbox(c, "box2", "67", -1L, a1.mId);
Mailbox b13 = createMailbox(c, "box3", "18", b12.mId, a1.mId);
Mailbox b21 = createMailbox(c, "box4", null, 0L, a2.mId);
Mailbox b22 = createMailbox(c, "box4/foo/bar", "will-be-replaced", 0L, a2.mId);
Mailbox b23 = createMailbox(c, "box5", null, -1L, a2.mId);
Mailbox b24 = createMailbox(c, "box6", "box5/box6", b23.mId, a2.mId);
Mailbox b31 = createMailbox(c, "box7", "12", 0L, a3.mId);
Mailbox b32 = createMailbox(c, "box8/foo/bar", "will-be-replaced", 0L, a3.mId);
Mailbox b33 = createMailbox(c, "box9", "box9", -1L, a3.mId);
Mailbox b34 = createMailbox(c, "boxA", "box9/boxA", b33.mId, a3.mId);
// Sanity check the mailboxes that were just added
Mailbox testMailbox;
testMailbox = Mailbox.restoreMailboxWithId(c, b11.mId);
assertEquals(b11, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b12.mId);
assertEquals(b12, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b13.mId);
assertEquals(b13, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b21.mId);
assertEqualsExceptServerId(b21, testMailbox, null);
testMailbox = Mailbox.restoreMailboxWithId(c, b22.mId);
assertEqualsExceptServerId(b22, testMailbox, "will-be-replaced");
testMailbox = Mailbox.restoreMailboxWithId(c, b23.mId);
assertEquals(b23, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b24.mId);
assertEquals(b24, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b31.mId);
assertEqualsExceptServerId(b31, testMailbox, "12");
testMailbox = Mailbox.restoreMailboxWithId(c, b32.mId);
assertEqualsExceptServerId(b32, testMailbox, "will-be-replaced");
testMailbox = Mailbox.restoreMailboxWithId(c, b33.mId);
assertEquals(b33, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b34.mId);
assertEquals(b34, testMailbox);
SQLiteDatabase db = getProvider().getDatabase(mMockContext);
EmailProvider.upgradeFromVersion17ToVersion18(db);
// Verify that only IMAP/POP3 mailboxes w/ a parent key of '0' are changed
// Exchange mailboxes; none should be changed
testMailbox = Mailbox.restoreMailboxWithId(c, b11.mId);
assertEquals(b11, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b12.mId);
assertEquals(b12, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b13.mId);
assertEquals(b13, testMailbox);
// IMAP mailboxes; only mailboxes w/ a parent id of '0' are changed
testMailbox = Mailbox.restoreMailboxWithId(c, b21.mId);
assertEqualsExceptServerId(b21, testMailbox, "box4");
testMailbox = Mailbox.restoreMailboxWithId(c, b22.mId);
assertEqualsExceptServerId(b22, testMailbox, "box4/foo/bar");
testMailbox = Mailbox.restoreMailboxWithId(c, b23.mId);
assertEquals(b23, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b24.mId);
assertEquals(b24, testMailbox);
// POP3 mailboxes; only mailboxes w/ a parent id of '0' are changed
testMailbox = Mailbox.restoreMailboxWithId(c, b31.mId);
assertEqualsExceptServerId(b31, testMailbox, "box7");
testMailbox = Mailbox.restoreMailboxWithId(c, b32.mId);
assertEqualsExceptServerId(b32, testMailbox, "box8/foo/bar");
testMailbox = Mailbox.restoreMailboxWithId(c, b33.mId);
assertEquals(b33, testMailbox);
testMailbox = Mailbox.restoreMailboxWithId(c, b34.mId);
assertEquals(b34, testMailbox);
}
}

View File

@ -0,0 +1,549 @@
/*
* Copyright (C) 2011 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.emailcommon.provider;
import com.android.email.provider.ContentCache;
import com.android.email.provider.EmailProvider;
import com.android.email.provider.ProviderTestUtils;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Mailbox;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.EmailContent.MessageColumns;
import com.android.emailcommon.utility.Utility;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.test.MoreAsserts;
import android.test.ProviderTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
/**
* Unit tests for the Mailbox inner class.
* These tests must be locally complete - no server(s) required.
*/
@SmallTest
public class MailboxTests extends ProviderTestCase2<EmailProvider> {
private static final String TEST_DISPLAY_NAME = "display-name";
private static final String TEST_PARENT_SERVER_ID = "parent-server-id";
private static final String TEST_SERVER_ID = "server-id";
private static final String TEST_SYNC_KEY = "sync-key";
private static final String TEST_SYNC_STATUS = "sync-status";
private Context mMockContext;
private EmailProvider mProvider;
public MailboxTests() {
super(EmailProvider.class, EmailContent.AUTHORITY);
}
@Override
public void setUp() throws Exception {
super.setUp();
mMockContext = getMockContext();
mProvider = getProvider();
// Invalidate all caches, since we reset the database for each test
ContentCache.invalidateAllCachesForTest();
}
//////////////////////////////////////////////////////////
////// Utility methods
//////////////////////////////////////////////////////////
/** Returns the number of messages in a mailbox. */
private int getMessageCount(long mailboxId) {
return Utility.getFirstRowInt(mMockContext,
ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
new String[] {MailboxColumns.MESSAGE_COUNT}, null, null, null, 0);
}
/** Creates a new message. */
private static Message createMessage(Context c, Mailbox b, boolean starred, boolean read,
int flagLoaded) {
Message message = ProviderTestUtils.setupMessage(
"1", b.mAccountKey, b.mId, true, false, c, starred, read);
message.mFlagLoaded = flagLoaded;
message.save(c);
return message;
}
//////////////////////////////////////////////////////////
////// The tests
//////////////////////////////////////////////////////////
/**
* Test simple mailbox save/retrieve
*/
public void testSave() {
final Context c = mMockContext;
Account account1 = ProviderTestUtils.setupAccount("mailbox-save", true, c);
long account1Id = account1.mId;
Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, c);
long box1Id = box1.mId;
Mailbox box2 = EmailContent.Mailbox.restoreMailboxWithId(c, box1Id);
ProviderTestUtils.assertMailboxEqual("testMailboxSave", box1, box2);
}
/**
* Test delete mailbox
*/
public void testDelete() {
final Context c = mMockContext;
Account account1 = ProviderTestUtils.setupAccount("mailbox-delete", true, c);
long account1Id = account1.mId;
Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, c);
long box1Id = box1.mId;
Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, c);
long box2Id = box2.mId;
String selection = EmailContent.MailboxColumns.ACCOUNT_KEY + "=?";
String[] selArgs = new String[] { String.valueOf(account1Id) };
// make sure there are two mailboxes
int numBoxes = EmailContent.count(c, Mailbox.CONTENT_URI, selection, selArgs);
assertEquals(2, numBoxes);
// now delete one of them
Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box1Id);
c.getContentResolver().delete(uri, null, null);
// make sure there's only one mailbox now
numBoxes = EmailContent.count(c, Mailbox.CONTENT_URI, selection, selArgs);
assertEquals(1, numBoxes);
// now delete the other one
uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2Id);
c.getContentResolver().delete(uri, null, null);
// make sure there are no mailboxes now
numBoxes = EmailContent.count(c, Mailbox.CONTENT_URI, selection, selArgs);
assertEquals(0, numBoxes);
}
public void testGetMailboxType() {
final Context c = mMockContext;
Account a = ProviderTestUtils.setupAccount("acct1", true, c);
Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox bm = ProviderTestUtils.setupMailbox("b2", a.mId, true, c, Mailbox.TYPE_MAIL);
assertEquals(Mailbox.TYPE_INBOX, Mailbox.getMailboxType(c, bi.mId));
assertEquals(Mailbox.TYPE_MAIL, Mailbox.getMailboxType(c, bm.mId));
assertEquals(-1, Mailbox.getMailboxType(c, 999999)); // mailbox not found
}
public void testGetDisplayName() {
final Context c = mMockContext;
Account a = ProviderTestUtils.setupAccount("acct1", true, c);
Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox bm = ProviderTestUtils.setupMailbox("b2", a.mId, true, c, Mailbox.TYPE_MAIL);
assertEquals("b1", Mailbox.getDisplayName(c, bi.mId));
assertEquals("b2", Mailbox.getDisplayName(c, bm.mId));
assertEquals(null, Mailbox.getDisplayName(c, 999999)); // mailbox not found
}
public void testIsRefreshable() {
final Context c = mMockContext;
Account a = ProviderTestUtils.setupAccount("acct1", true, c);
Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox bm = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_MAIL);
Mailbox bd = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_DRAFTS);
Mailbox bo = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_OUTBOX);
assertTrue(Mailbox.isRefreshable(c, bi.mId));
assertTrue(Mailbox.isRefreshable(c, bm.mId));
assertFalse(Mailbox.isRefreshable(c, bd.mId));
assertFalse(Mailbox.isRefreshable(c, bo.mId));
// No such mailbox
assertFalse(Mailbox.isRefreshable(c, 9999999));
// Magic mailboxes can't be refreshed.
assertFalse(Mailbox.isRefreshable(c, Mailbox.QUERY_ALL_DRAFTS));
assertFalse(Mailbox.isRefreshable(c, Mailbox.QUERY_ALL_INBOXES));
}
public void testCanMoveFrom() {
final Context c = mMockContext;
Account a = ProviderTestUtils.setupAccount("acct1", true, c);
Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox bm = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_MAIL);
Mailbox bd = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_DRAFTS);
Mailbox bo = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_OUTBOX);
assertTrue(Mailbox.canMoveFrom(c, bi.mId));
assertTrue(Mailbox.canMoveFrom(c, bm.mId));
assertFalse(Mailbox.canMoveFrom(c, bd.mId));
assertFalse(Mailbox.canMoveFrom(c, bo.mId));
}
public void testGetMailboxForMessageId() {
final Context c = mMockContext;
Mailbox b1 = ProviderTestUtils.setupMailbox("box1", 1, true, c, Mailbox.TYPE_MAIL);
Mailbox b2 = ProviderTestUtils.setupMailbox("box2", 1, true, c, Mailbox.TYPE_MAIL);
Message m1 = ProviderTestUtils.setupMessage("1", b1.mAccountKey, b1.mId,
true, true, c, false, false);
Message m2 = ProviderTestUtils.setupMessage("1", b2.mAccountKey, b2.mId,
true, true, c, false, false);
ProviderTestUtils.assertMailboxEqual("x", b1, Mailbox.getMailboxForMessageId(c, m1.mId));
ProviderTestUtils.assertMailboxEqual("x", b2, Mailbox.getMailboxForMessageId(c, m2.mId));
}
public void testRestoreMailboxWithId() {
final Context c = mMockContext;
Mailbox testMailbox;
testMailbox = ProviderTestUtils.setupMailbox("box1", 1, true, c, Mailbox.TYPE_MAIL);
ProviderTestUtils.assertMailboxEqual(
"x", testMailbox, Mailbox.restoreMailboxWithId(c, testMailbox.mId));
testMailbox = ProviderTestUtils.setupMailbox("box2", 1, true, c, Mailbox.TYPE_MAIL);
ProviderTestUtils.assertMailboxEqual(
"x", testMailbox, Mailbox.restoreMailboxWithId(c, testMailbox.mId));
// Unknown IDs
assertNull(Mailbox.restoreMailboxWithId(c, 8));
assertNull(Mailbox.restoreMailboxWithId(c, -1));
assertNull(Mailbox.restoreMailboxWithId(c, Long.MAX_VALUE));
}
public void testRestoreMailboxForPath() {
final Context c = mMockContext;
Mailbox testMailbox;
testMailbox = ProviderTestUtils.setupMailbox("a/b/c/box", 1, true, c, Mailbox.TYPE_MAIL);
ProviderTestUtils.assertMailboxEqual(
"x", testMailbox, Mailbox.restoreMailboxForPath(c, 1, "a/b/c/box"));
// Same name, different account; no match
assertNull(Mailbox.restoreMailboxForPath(c, 2, "a/b/c/box"));
// Substring; no match
assertNull(Mailbox.restoreMailboxForPath(c, 1, "a/b/c"));
// Wild cards not supported; no match
assertNull(Mailbox.restoreMailboxForPath(c, 1, "a/b/c/%"));
}
public void testFindMailboxOfType() {
final Context context = mMockContext;
// Create two accounts and a variety of mailbox types
Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context);
Mailbox acct1Inbox =
ProviderTestUtils.setupMailbox("Inbox1", acct1.mId, true, context, Mailbox.TYPE_INBOX);
Mailbox acct1Calendar =
ProviderTestUtils.setupMailbox("Cal1", acct1.mId, true, context, Mailbox.TYPE_CALENDAR);
Mailbox acct1Contacts =
ProviderTestUtils.setupMailbox("Con1", acct1.mId, true, context, Mailbox.TYPE_CONTACTS);
Account acct2 = ProviderTestUtils.setupAccount("acct1", true, context);
Mailbox acct2Inbox =
ProviderTestUtils.setupMailbox("Inbox2", acct2.mId, true, context, Mailbox.TYPE_INBOX);
Mailbox acct2Calendar =
ProviderTestUtils.setupMailbox("Cal2", acct2.mId, true, context, Mailbox.TYPE_CALENDAR);
Mailbox acct2Contacts =
ProviderTestUtils.setupMailbox("Con2", acct2.mId, true, context, Mailbox.TYPE_CONTACTS);
// Check that we can find them by type
assertEquals(acct1Inbox.mId,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX));
assertEquals(acct2Inbox.mId,
Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_INBOX));
assertEquals(acct1Calendar.mId,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR));
assertEquals(acct2Calendar.mId,
Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_CALENDAR));
assertEquals(acct1Contacts.mId,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS));
assertEquals(acct2Contacts.mId,
Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_CONTACTS));
// Check that nonexistent mailboxes are not returned
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_DRAFTS));
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_OUTBOX));
// delete account 1 and confirm no mailboxes are returned
context.getContentResolver().delete(
ContentUris.withAppendedId(Account.CONTENT_URI, acct1.mId), null, null);
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX));
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR));
assertEquals(Mailbox.NO_MAILBOX,
Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS));
}
public void testRestoreMailboxOfType() {
final Context context = getMockContext();
// Create two accounts and a variety of mailbox types
Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context);
Mailbox acct1Inbox =
ProviderTestUtils.setupMailbox("Inbox1", acct1.mId, true, context, Mailbox.TYPE_INBOX);
Mailbox acct1Calendar =
ProviderTestUtils.setupMailbox("Cal1", acct1.mId, true, context, Mailbox.TYPE_CALENDAR);
Mailbox acct1Contacts =
ProviderTestUtils.setupMailbox("Con1", acct1.mId, true, context, Mailbox.TYPE_CONTACTS);
Account acct2 =ProviderTestUtils.setupAccount("acct1", true, context);
Mailbox acct2Inbox =
ProviderTestUtils.setupMailbox("Inbox2", acct2.mId, true, context, Mailbox.TYPE_INBOX);
Mailbox acct2Calendar =
ProviderTestUtils.setupMailbox("Cal2", acct2.mId, true, context, Mailbox.TYPE_CALENDAR);
Mailbox acct2Contacts =
ProviderTestUtils.setupMailbox("Con2", acct2.mId, true, context, Mailbox.TYPE_CONTACTS);
// Check that we can find them by type
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Inbox,
Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Inbox,
Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_INBOX));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Calendar,
Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Calendar,
Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_CALENDAR));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Contacts,
Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS));
ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Contacts,
Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_CONTACTS));
}
/**
* Test for the message count triggers (insert/delete/move mailbox), and also
* {@link EmailProvider#recalculateMessageCount}.
*
* It also covers:
* - {@link Mailbox#getMessageCountByMailboxType(Context, int)}
* - {@link Mailbox#getUnreadCountByAccountAndMailboxType(Context, long, int)}
* - {@link Mailbox#getUnreadCountByMailboxType(Context, int)}
* - {@link Message#getFavoriteMessageCount(Context)}
* - {@link Message#getFavoriteMessageCount(Context, long)}
*/
public void testMessageCount() {
final Context c = mMockContext;
// Create 2 accounts
Account a1 = ProviderTestUtils.setupAccount("holdflag-1", true, c);
Account a2 = ProviderTestUtils.setupAccount("holdflag-2", true, c);
// Create 2 mailboxes for each account
Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox b2 = ProviderTestUtils.setupMailbox("box2", a1.mId, true, c, Mailbox.TYPE_OUTBOX);
Mailbox b3 = ProviderTestUtils.setupMailbox("box3", a2.mId, true, c, Mailbox.TYPE_INBOX);
Mailbox b4 = ProviderTestUtils.setupMailbox("box4", a2.mId, true, c, Mailbox.TYPE_OUTBOX);
Mailbox bt = ProviderTestUtils.setupMailbox("boxT", a2.mId, true, c, Mailbox.TYPE_TRASH);
// 0. Check the initial values, just in case.
assertEquals(0, getMessageCount(b1.mId));
assertEquals(0, getMessageCount(b2.mId));
assertEquals(0, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
assertEquals(0, getMessageCount(bt.mId));
assertEquals(0, Message.getFavoriteMessageCount(c));
assertEquals(0, Message.getFavoriteMessageCount(c, a1.mId));
assertEquals(0, Message.getFavoriteMessageCount(c, a2.mId));
assertEquals(0, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_TRASH));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_TRASH));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_TRASH));
// 1. Test for insert triggers.
// Create some messages
// b1 (account 1, inbox): 1 message, including 1 starred
Message m11 = createMessage(c, b1, true, false, Message.FLAG_LOADED_COMPLETE);
// b2 (account 1, outbox): 2 message, including 1 starred
Message m21 = createMessage(c, b2, false, false, Message.FLAG_LOADED_COMPLETE);
Message m22 = createMessage(c, b2, true, true, Message.FLAG_LOADED_COMPLETE);
// b3 (account 2, inbox): 3 message, including 1 starred
Message m31 = createMessage(c, b3, false, false, Message.FLAG_LOADED_COMPLETE);
Message m32 = createMessage(c, b3, false, false, Message.FLAG_LOADED_COMPLETE);
Message m33 = createMessage(c, b3, true, true, Message.FLAG_LOADED_COMPLETE);
// b4 (account 2, outbox) has no messages.
// bt (account 2, trash) has 3 messages, including 2 starred
Message mt1 = createMessage(c, bt, true, false, Message.FLAG_LOADED_COMPLETE);
Message mt2 = createMessage(c, bt, true, false, Message.FLAG_LOADED_COMPLETE);
Message mt3 = createMessage(c, bt, false, false, Message.FLAG_LOADED_COMPLETE);
// Check message counts
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(3, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
assertEquals(3, getMessageCount(bt.mId));
// Check the simple counting methods.
assertEquals(3, Message.getFavoriteMessageCount(c)); // excludes starred in trash
assertEquals(2, Message.getFavoriteMessageCount(c, a1.mId));
assertEquals(1, Message.getFavoriteMessageCount(c, a2.mId)); // excludes starred in trash
assertEquals(3, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_INBOX));
assertEquals(1, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_OUTBOX));
assertEquals(4, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_INBOX));
assertEquals(2, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_OUTBOX));
assertEquals(3, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_TRASH));
assertEquals(1, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_INBOX));
assertEquals(1, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_OUTBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a1.mId, Mailbox.TYPE_TRASH));
assertEquals(2, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_INBOX));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_OUTBOX));
assertEquals(3, Mailbox.getUnreadCountByAccountAndMailboxType(c,
a2.mId, Mailbox.TYPE_TRASH));
// 2. Check the "move mailbox" trigger.
// Move m32 (in mailbox 3) to mailbox 4.
ContentValues values = new ContentValues();
values.put(MessageColumns.MAILBOX_KEY, b4.mId);
getProvider().update(Message.CONTENT_URI, values, EmailContent.ID_SELECTION,
new String[] {"" + m32.mId});
// Check message counts
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(2, getMessageCount(b3.mId));
assertEquals(1, getMessageCount(b4.mId));
// 3. Check the delete trigger.
// Delete m11 (in mailbox 1)
getProvider().delete(Message.CONTENT_URI, EmailContent.ID_SELECTION,
new String[] {"" + m11.mId});
// Delete m21 (in mailbox 2)
getProvider().delete(Message.CONTENT_URI, EmailContent.ID_SELECTION,
new String[] {"" + m21.mId});
// Check message counts
assertEquals(0, getMessageCount(b1.mId));
assertEquals(1, getMessageCount(b2.mId));
assertEquals(2, getMessageCount(b3.mId));
assertEquals(1, getMessageCount(b4.mId));
// No such mailbox type.
assertEquals(0, Mailbox.getMessageCountByMailboxType(c, 99999));
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, a1.mId, 99999));
assertEquals(0, Mailbox.getUnreadCountByMailboxType(c, 99999));
// No such account
assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c,
99999, Mailbox.TYPE_INBOX));
}
/**
* Check if update on MAILBOX_ID_ADD_TO_FIELD updates the cache properly.
*/
public void testUpdateCacheMailboxIdAddToField() {
final Context c = mMockContext;
Account a1 = ProviderTestUtils.setupAccount("a1", true, c);
Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c, Mailbox.TYPE_INBOX);
int start = Mailbox.restoreMailboxWithId(c, b1.mId).mSyncInterval;
// +1 to SYNC_INTERVAL
ContentValues cv = new ContentValues();
cv.put(EmailContent.FIELD_COLUMN_NAME, MailboxColumns.SYNC_INTERVAL);
cv.put(EmailContent.ADD_COLUMN_NAME, 1);
mProvider.update(ContentUris.withAppendedId(Mailbox.ADD_TO_FIELD_URI, a1.mId), cv,
null, null);
// Check
assertEquals(start + 1, Mailbox.restoreMailboxWithId(c, b1.mId).mSyncInterval);
}
public void testGetHashes() {
final Context c = mMockContext;
Mailbox testMailbox;
testMailbox = new Mailbox();
testMailbox.mDisplayName = TEST_DISPLAY_NAME;
testMailbox.mParentServerId = TEST_PARENT_SERVER_ID;
testMailbox.mServerId = TEST_SERVER_ID;
testMailbox.mSyncKey = TEST_SYNC_KEY;
testMailbox.mSyncStatus = TEST_SYNC_STATUS;
testMailbox.mAccountKey = 1L;
testMailbox.mDelimiter = '/';
testMailbox.mFlags = 2;
testMailbox.mFlagVisible = true;
testMailbox.mParentKey = 3L;
testMailbox.mSyncInterval = 4;
testMailbox.mSyncLookback = 5;
testMailbox.mSyncTime = 6L;
testMailbox.mType = 7;
testMailbox.mVisibleLimit = 8;
testMailbox.save(c);
Object[] testHash;
testHash = new Object[] {
testMailbox.mId, TEST_DISPLAY_NAME, TEST_SERVER_ID,
TEST_PARENT_SERVER_ID, 1L /*mAccountKey*/, 7 /*mType */,
(int)'/' /*mDelimiter */, TEST_SYNC_KEY, 5 /*mSyncLookback*/,
4 /*mSyncInterval*/, 6L /*mSyncTime*/, true /*mFlagVisible*/, 2 /*mFlags*/,
8 /*mVisibleLimit*/, TEST_SYNC_STATUS, 3L /*mParentKey*/
};
MoreAsserts.assertEquals(testHash, testMailbox.getHashes());
// Verify null checks happen correctly
testMailbox.mDisplayName = null;
testMailbox.mParentServerId = null;
testMailbox.mServerId = null;
testMailbox.mSyncKey = null;
testMailbox.mSyncStatus = null;
testMailbox.mFlagVisible = false;
testHash = new Object[] {
testMailbox.mId, null /*mDisplayname*/, null /*mServerId*/,
null /*mParentServerId*/, 1L /*mAccountKey*/, 7 /*mType */,
(int)'/' /*mDelimiter */, null /*mSyncKey*/, 5 /*mSyncLookback*/,
4 /*mSyncInterval*/, 6L /*mSyncTime*/, false /*mFlagVisible*/, 2 /*mFlags*/,
8 /*mVisibleLimit*/, null /*mSyncStatus*/, 3L /*mParentKey*/
};
MoreAsserts.assertEquals(testHash, testMailbox.getHashes());
}
}