2009-03-04 03:32:22 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2008 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.mail.store;
|
|
|
|
|
2010-05-17 20:13:56 +00:00
|
|
|
import com.android.email.Email;
|
2010-06-14 16:55:41 +00:00
|
|
|
import com.android.email.MockVendorPolicy;
|
2010-05-17 22:44:36 +00:00
|
|
|
import com.android.email.Utility;
|
2010-06-14 16:55:41 +00:00
|
|
|
import com.android.email.VendorPolicyLoader;
|
2009-03-04 03:32:22 +00:00
|
|
|
import com.android.email.mail.Transport;
|
2010-05-19 00:22:28 +00:00
|
|
|
import com.android.email.mail.store.ImapStore.ImapConnection;
|
2010-04-02 18:09:12 +00:00
|
|
|
import com.android.email.mail.store.ImapStore.ImapMessage;
|
2010-06-14 16:55:41 +00:00
|
|
|
import com.android.email.mail.store.imap.ImapResponse;
|
|
|
|
import com.android.email.mail.store.imap.ImapTestUtils;
|
2009-03-04 03:32:22 +00:00
|
|
|
import com.android.email.mail.transport.MockTransport;
|
2011-02-10 02:47:43 +00:00
|
|
|
import com.android.emailcommon.internet.MimeBodyPart;
|
|
|
|
import com.android.emailcommon.internet.MimeMultipart;
|
|
|
|
import com.android.emailcommon.internet.MimeUtility;
|
|
|
|
import com.android.emailcommon.internet.TextBody;
|
|
|
|
import com.android.emailcommon.mail.Address;
|
|
|
|
import com.android.emailcommon.mail.AuthenticationFailedException;
|
|
|
|
import com.android.emailcommon.mail.Body;
|
|
|
|
import com.android.emailcommon.mail.FetchProfile;
|
|
|
|
import com.android.emailcommon.mail.Flag;
|
|
|
|
import com.android.emailcommon.mail.Folder;
|
|
|
|
import com.android.emailcommon.mail.Message;
|
|
|
|
import com.android.emailcommon.mail.MessagingException;
|
|
|
|
import com.android.emailcommon.mail.Part;
|
|
|
|
import com.android.emailcommon.mail.Folder.FolderType;
|
|
|
|
import com.android.emailcommon.mail.Folder.OpenMode;
|
|
|
|
import com.android.emailcommon.mail.Message.RecipientType;
|
2009-03-04 03:32:22 +00:00
|
|
|
|
2010-05-17 22:44:36 +00:00
|
|
|
import org.apache.commons.io.IOUtils;
|
|
|
|
|
2010-06-14 16:55:41 +00:00
|
|
|
import android.os.Bundle;
|
2009-03-04 03:32:22 +00:00
|
|
|
import android.test.AndroidTestCase;
|
2010-02-01 23:53:46 +00:00
|
|
|
import android.test.MoreAsserts;
|
2009-03-04 03:32:22 +00:00
|
|
|
import android.test.suitebuilder.annotation.SmallTest;
|
2009-04-15 19:58:19 +00:00
|
|
|
|
2009-10-07 18:42:27 +00:00
|
|
|
import java.util.ArrayList;
|
2010-01-26 02:40:45 +00:00
|
|
|
import java.util.HashMap;
|
2010-05-20 00:23:23 +00:00
|
|
|
import java.util.regex.Pattern;
|
2009-03-04 03:32:22 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This is a series of unit tests for the ImapStore class. These tests must be locally
|
|
|
|
* complete - no server(s) required.
|
2009-10-07 18:42:27 +00:00
|
|
|
*
|
|
|
|
* To run these tests alone, use:
|
|
|
|
* $ runtest -c com.android.email.mail.store.ImapStoreUnitTests email
|
2010-05-18 20:41:14 +00:00
|
|
|
*
|
|
|
|
* TODO Check if callback is really called
|
2010-05-19 00:22:28 +00:00
|
|
|
* TODO test for BAD response in various places?
|
|
|
|
* TODO test for BYE response in various places?
|
2009-03-04 03:32:22 +00:00
|
|
|
*/
|
|
|
|
@SmallTest
|
|
|
|
public class ImapStoreUnitTests extends AndroidTestCase {
|
2010-04-02 18:09:12 +00:00
|
|
|
private final static String[] NO_REPLY = new String[0];
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2010-05-18 20:41:14 +00:00
|
|
|
/**
|
|
|
|
* Default folder name. In order to test for encoding, we use a non-ascii name.
|
|
|
|
*/
|
|
|
|
private final static String FOLDER_NAME = "\u65E5";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Folder name encoded in UTF-7.
|
|
|
|
*/
|
|
|
|
private final static String FOLDER_ENCODED = "&ZeU-";
|
|
|
|
|
2011-01-05 04:21:15 +00:00
|
|
|
private final static ImapResponse CAPABILITY_RESPONSE = ImapTestUtils.parseResponse(
|
2010-06-14 16:55:41 +00:00
|
|
|
"* CAPABILITY IMAP4rev1 STARTTLS");
|
|
|
|
|
2009-03-04 03:32:22 +00:00
|
|
|
/* These values are provided by setUp() */
|
|
|
|
private ImapStore mStore = null;
|
|
|
|
private ImapStore.ImapFolder mFolder = null;
|
2010-02-26 06:48:11 +00:00
|
|
|
|
|
|
|
private int mNextTag;
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2009-03-04 03:32:22 +00:00
|
|
|
/**
|
|
|
|
* Setup code. We generate a lightweight ImapStore and ImapStore.ImapFolder.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
protected void setUp() throws Exception {
|
|
|
|
super.setUp();
|
2010-05-17 20:13:56 +00:00
|
|
|
Email.setTempDirectory(getContext());
|
|
|
|
|
2009-03-04 03:32:22 +00:00
|
|
|
// These are needed so we can get at the inner classes
|
2009-03-27 00:05:25 +00:00
|
|
|
mStore = (ImapStore) ImapStore.newInstance("imap://user:password@server:999",
|
2009-04-14 03:07:56 +00:00
|
|
|
getContext(), null);
|
2010-05-18 20:41:14 +00:00
|
|
|
mFolder = (ImapStore.ImapFolder) mStore.getFolder(FOLDER_NAME);
|
2010-05-19 00:22:28 +00:00
|
|
|
mNextTag = 1;
|
2009-03-04 03:32:22 +00:00
|
|
|
}
|
|
|
|
|
2010-05-20 00:23:23 +00:00
|
|
|
public void testJoinMessageUids() throws Exception {
|
|
|
|
assertEquals("", ImapStore.joinMessageUids(new Message[] {}));
|
|
|
|
assertEquals("a", ImapStore.joinMessageUids(new Message[] {
|
|
|
|
mFolder.createMessage("a")
|
|
|
|
}));
|
|
|
|
assertEquals("a,XX", ImapStore.joinMessageUids(new Message[] {
|
|
|
|
mFolder.createMessage("a"),
|
|
|
|
mFolder.createMessage("XX"),
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2009-03-04 03:32:22 +00:00
|
|
|
/**
|
|
|
|
* Confirms simple non-SSL non-TLS login
|
|
|
|
*/
|
|
|
|
public void testSimpleLogin() throws MessagingException {
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2009-03-04 03:32:22 +00:00
|
|
|
MockTransport mockTransport = openAndInjectMockTransport();
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2009-03-04 03:32:22 +00:00
|
|
|
// try to open it
|
|
|
|
setupOpenFolder(mockTransport);
|
AI 146134: Add persistence API for remote stores & folders to use while
syncing. This provides a key-value store, per folder, that
can be used by network Stores to record persistent data such
as sync status, server keys, etc.
Note that, by definition, this only applies to remote folders
(e.g. IMAP, POP3). You'll see everywhere that LocalFolder is
passed null, and this is correct - LocalFolder *is* persistent
storage and does not need external help.
Note to reviewers: The core changes are Folder.java,
LocalStore.java, and LocalStoreUnitTests.java, so please give
them the bulk of your reviewer attention. The other files
are just following along with minor API changes. Of those,
the one worth close examination is MessagingController.java,
which is the only place in the system where remote Folders
are bonded with Local Folders and thus where this new API
comes into play.
Note to jham: Can you please take a look at
LocalStore.LocalFolder.setPersistentString() and recommend
better SQL foo than my primitive test-then-update-or-insert
logic, which is not transactional or threadsafe.
BUG=1786939
Automated import of CL 146134
2009-04-14 17:15:07 +00:00
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2009-03-04 03:32:22 +00:00
|
|
|
// TODO: inject specific facts in the initial folder SELECT and check them here
|
|
|
|
}
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2011-01-05 04:21:15 +00:00
|
|
|
/**
|
|
|
|
* Test simple login with failed authentication
|
|
|
|
*/
|
2010-05-19 00:22:28 +00:00
|
|
|
public void testLoginFailure() throws Exception {
|
|
|
|
MockTransport mockTransport = openAndInjectMockTransport();
|
2011-01-31 23:10:49 +00:00
|
|
|
expectLogin(mockTransport, false, false, new String[] {"* iD nIL", "oK"},
|
2011-01-05 04:21:15 +00:00
|
|
|
"nO authentication failed");
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
mStore.getConnection().open();
|
|
|
|
fail("Didn't throw AuthenticationFailedException");
|
|
|
|
} catch (AuthenticationFailedException expected) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-05 04:21:15 +00:00
|
|
|
/**
|
|
|
|
* Test simple TLS open
|
|
|
|
*/
|
|
|
|
public void testTlsOpen() throws MessagingException {
|
|
|
|
|
|
|
|
MockTransport mockTransport = openAndInjectMockTransport(Transport.CONNECTION_SECURITY_TLS,
|
|
|
|
false);
|
|
|
|
|
|
|
|
// try to open it, with STARTTLS
|
2011-01-31 23:10:49 +00:00
|
|
|
expectLogin(mockTransport, true, false,
|
2011-01-05 04:21:15 +00:00
|
|
|
new String[] {"* iD nIL", "oK"}, "oK user authenticated (Success)");
|
|
|
|
mockTransport.expect(
|
|
|
|
getNextTag(false) + " SELECT \"" + FOLDER_ENCODED + "\"", new String[] {
|
|
|
|
"* fLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)",
|
|
|
|
"* oK [pERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen \\*)]",
|
|
|
|
"* 0 eXISTS",
|
|
|
|
"* 0 rECENT",
|
|
|
|
"* OK [uNSEEN 0]",
|
|
|
|
"* OK [uIDNEXT 1]",
|
|
|
|
getNextTag(true) + " oK [" + "rEAD-wRITE" + "] " +
|
|
|
|
FOLDER_ENCODED + " selected. (Success)"});
|
|
|
|
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
assertTrue(mockTransport.isTlsStarted());
|
|
|
|
}
|
|
|
|
|
2010-01-26 02:40:45 +00:00
|
|
|
/**
|
|
|
|
* TODO: Test with SSL negotiation (faked)
|
|
|
|
* TODO: Test with SSL required but not supported
|
|
|
|
* TODO: Test with TLS required but not supported
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test the generation of the IMAP ID keys
|
2010-02-01 23:53:46 +00:00
|
|
|
*/
|
|
|
|
public void testImapIdBasic() {
|
|
|
|
// First test looks at operation of the outer API - we don't control any of the
|
|
|
|
// values; Just look for basic results.
|
|
|
|
|
|
|
|
// Strings we'll expect to find:
|
|
|
|
// name Android package name of the program
|
|
|
|
// os "android"
|
|
|
|
// os-version "version; build-id"
|
|
|
|
// vendor Vendor of the client/server
|
|
|
|
// x-android-device-model Model (Optional, so not tested here)
|
|
|
|
// x-android-net-operator Carrier (Unreliable, so not tested here)
|
|
|
|
// AGUID A device+account UID
|
2010-06-14 16:55:41 +00:00
|
|
|
String id = ImapStore.getImapId(getContext(), "user-name", "host-name",
|
2011-02-10 21:47:35 +00:00
|
|
|
CAPABILITY_RESPONSE.flatten());
|
2010-02-01 23:53:46 +00:00
|
|
|
HashMap<String, String> map = tokenizeImapId(id);
|
|
|
|
assertEquals(getContext().getPackageName(), map.get("name"));
|
|
|
|
assertEquals("android", map.get("os"));
|
|
|
|
assertNotNull(map.get("os-version"));
|
|
|
|
assertNotNull(map.get("vendor"));
|
|
|
|
assertNotNull(map.get("AGUID"));
|
|
|
|
|
|
|
|
// Next, use the inner API to confirm operation of a couple of
|
|
|
|
// variants for release and non-release devices.
|
|
|
|
|
|
|
|
// simple API check - non-REL codename, non-empty version
|
2010-05-20 00:23:23 +00:00
|
|
|
id = ImapStore.makeCommonImapId("packageName", "version", "codeName",
|
2010-02-01 23:53:46 +00:00
|
|
|
"model", "id", "vendor", "network-operator");
|
|
|
|
map = tokenizeImapId(id);
|
|
|
|
assertEquals("packageName", map.get("name"));
|
|
|
|
assertEquals("android", map.get("os"));
|
|
|
|
assertEquals("version; id", map.get("os-version"));
|
|
|
|
assertEquals("vendor", map.get("vendor"));
|
|
|
|
assertEquals(null, map.get("x-android-device-model"));
|
|
|
|
assertEquals("network-operator", map.get("x-android-mobile-net-operator"));
|
|
|
|
assertEquals(null, map.get("AGUID"));
|
|
|
|
|
|
|
|
// simple API check - codename is REL, so use model name.
|
|
|
|
// also test empty version => 1.0 and empty network operator
|
2010-05-20 00:23:23 +00:00
|
|
|
id = ImapStore.makeCommonImapId("packageName", "", "REL",
|
2010-02-01 23:53:46 +00:00
|
|
|
"model", "id", "vendor", "");
|
|
|
|
map = tokenizeImapId(id);
|
|
|
|
assertEquals("packageName", map.get("name"));
|
|
|
|
assertEquals("android", map.get("os"));
|
|
|
|
assertEquals("1.0; id", map.get("os-version"));
|
|
|
|
assertEquals("vendor", map.get("vendor"));
|
|
|
|
assertEquals("model", map.get("x-android-device-model"));
|
|
|
|
assertEquals(null, map.get("x-android-mobile-net-operator"));
|
|
|
|
assertEquals(null, map.get("AGUID"));
|
|
|
|
}
|
|
|
|
|
2010-06-14 16:55:41 +00:00
|
|
|
/**
|
|
|
|
* Test for the interaction between {@link ImapStore#getImapId} and a vendor policy.
|
|
|
|
*/
|
|
|
|
public void testImapIdWithVendorPolicy() {
|
|
|
|
try {
|
|
|
|
MockVendorPolicy.inject(getContext());
|
|
|
|
|
|
|
|
// Prepare mock result
|
|
|
|
Bundle result = new Bundle();
|
|
|
|
result.putString("getImapId", "\"test-key\" \"test-value\"");
|
|
|
|
MockVendorPolicy.mockResult = result;
|
|
|
|
|
|
|
|
// Invoke
|
|
|
|
String id = ImapStore.getImapId(getContext(), "user-name", "host-name",
|
2011-02-10 21:47:35 +00:00
|
|
|
ImapTestUtils.parseResponse("* CAPABILITY IMAP4rev1 XXX YYY Z").flatten());
|
2010-06-14 16:55:41 +00:00
|
|
|
|
|
|
|
// Check the result
|
|
|
|
assertEquals("test-value", tokenizeImapId(id).get("test-key"));
|
|
|
|
|
|
|
|
// Verify what's passed to the policy
|
|
|
|
assertEquals("getImapId", MockVendorPolicy.passedPolicy);
|
|
|
|
assertEquals("user-name", MockVendorPolicy.passedBundle.getString("getImapId.user"));
|
|
|
|
assertEquals("host-name", MockVendorPolicy.passedBundle.getString("getImapId.host"));
|
|
|
|
assertEquals("[CAPABILITY,IMAP4rev1,XXX,YYY,Z]",
|
|
|
|
MockVendorPolicy.passedBundle.getString("getImapId.capabilities"));
|
|
|
|
} finally {
|
|
|
|
VendorPolicyLoader.clearInstanceForTest();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-01 23:53:46 +00:00
|
|
|
/**
|
|
|
|
* Test of the internal generator for IMAP ID strings, specifically looking for proper
|
|
|
|
* filtering of illegal values. This is required because we cannot necessarily trust
|
|
|
|
* the external sources of some of this data (e.g. release labels).
|
2010-01-26 02:40:45 +00:00
|
|
|
*
|
2010-02-01 23:53:46 +00:00
|
|
|
* The (somewhat arbitrary) legal values are: a-z A-Z 0-9 - _ + = ; : . , / <space>
|
|
|
|
* The most important goal of the filters is to keep out control chars, (, ), and "
|
|
|
|
*/
|
|
|
|
public void testImapIdFiltering() {
|
2010-05-20 00:23:23 +00:00
|
|
|
String id = ImapStore.makeCommonImapId(
|
|
|
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
2010-02-01 23:53:46 +00:00
|
|
|
"0123456789", "codeName",
|
|
|
|
"model", "-_+=;:.,// ",
|
|
|
|
"v(e)n\"d\ro\nr", // look for bad chars stripped out, leaving OK chars
|
|
|
|
"()\""); // look for bad chars stripped out, leaving nothing
|
|
|
|
HashMap<String, String> map = tokenizeImapId(id);
|
|
|
|
|
|
|
|
assertEquals("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", map.get("name"));
|
|
|
|
assertEquals("0123456789; -_+=;:.,// ", map.get("os-version"));
|
|
|
|
assertEquals("vendor", map.get("vendor"));
|
|
|
|
assertNull(map.get("x-android-mobile-net-operator"));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test that IMAP ID uid's are per-username
|
2010-01-26 02:40:45 +00:00
|
|
|
*/
|
2010-02-01 23:53:46 +00:00
|
|
|
public void testImapIdDeviceId() throws MessagingException {
|
|
|
|
ImapStore store1a = (ImapStore) ImapStore.newInstance("imap://user1:password@server:999",
|
|
|
|
getContext(), null);
|
|
|
|
ImapStore store1b = (ImapStore) ImapStore.newInstance("imap://user1:password@server:999",
|
|
|
|
getContext(), null);
|
|
|
|
ImapStore store2 = (ImapStore) ImapStore.newInstance("imap://user2:password@server:999",
|
|
|
|
getContext(), null);
|
|
|
|
|
2011-02-10 21:47:35 +00:00
|
|
|
String capabilities = CAPABILITY_RESPONSE.flatten();
|
|
|
|
String id1a = ImapStore.getImapId(getContext(), "user1", "host-name", capabilities);
|
|
|
|
String id1b = ImapStore.getImapId(getContext(), "user1", "host-name", capabilities);
|
|
|
|
String id2 = ImapStore.getImapId(getContext(), "user2", "host-name", capabilities);
|
2010-02-01 23:53:46 +00:00
|
|
|
|
|
|
|
String uid1a = tokenizeImapId(id1a).get("AGUID");
|
|
|
|
String uid1b = tokenizeImapId(id1b).get("AGUID");
|
|
|
|
String uid2 = tokenizeImapId(id2).get("AGUID");
|
|
|
|
|
|
|
|
assertEquals(uid1a, uid1b);
|
|
|
|
MoreAsserts.assertNotEqual(uid1a, uid2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper to break an IMAP ID string into keys & values
|
|
|
|
* @param id the IMAP Id string (the part inside the parens)
|
|
|
|
* @return a map of key/value pairs
|
|
|
|
*/
|
|
|
|
private HashMap<String, String> tokenizeImapId(String id) {
|
2010-01-26 02:40:45 +00:00
|
|
|
// Instead of a true tokenizer, we'll use double-quote as the split.
|
2010-05-17 20:13:56 +00:00
|
|
|
// We can's use " " because there may be spaces inside the values.
|
2010-01-26 02:40:45 +00:00
|
|
|
String[] elements = id.split("\"");
|
|
|
|
HashMap<String, String> map = new HashMap<String, String>();
|
|
|
|
for (int i = 0; i < elements.length; ) {
|
|
|
|
// Because we split at quotes, we expect to find:
|
2010-02-01 23:53:46 +00:00
|
|
|
// [i] = null or one or more spaces
|
2010-01-26 02:40:45 +00:00
|
|
|
// [i+1] = key
|
|
|
|
// [i+2] = one or more spaces
|
|
|
|
// [i+3] = value
|
|
|
|
map.put(elements[i+1], elements[i+3]);
|
|
|
|
i += 4;
|
|
|
|
}
|
2010-02-01 23:53:46 +00:00
|
|
|
return map;
|
2010-01-26 02:40:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test non-NIL server response to IMAP ID. We should simply ignore it.
|
|
|
|
*/
|
|
|
|
public void testServerId() throws MessagingException {
|
|
|
|
MockTransport mockTransport = openAndInjectMockTransport();
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2010-01-26 02:40:45 +00:00
|
|
|
// try to open it
|
|
|
|
setupOpenFolder(mockTransport, new String[] {
|
|
|
|
"* ID (\"name\" \"Cyrus\" \"version\" \"1.5\"" +
|
|
|
|
" \"os\" \"sunos\" \"os-version\" \"5.5\"" +
|
|
|
|
" \"support-url\" \"mailto:cyrus-bugs+@andrew.cmu.edu\")",
|
2010-05-29 00:34:47 +00:00
|
|
|
"oK"}, "rEAD-wRITE");
|
2010-01-26 02:40:45 +00:00
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test OK response to IMAP ID with crummy text afterwards too.
|
|
|
|
*/
|
|
|
|
public void testImapIdOkParsing() throws MessagingException {
|
|
|
|
MockTransport mockTransport = openAndInjectMockTransport();
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2010-01-26 02:40:45 +00:00
|
|
|
// try to open it
|
|
|
|
setupOpenFolder(mockTransport, new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* iD nIL",
|
|
|
|
"oK [iD] bad-char-%"}, "rEAD-wRITE");
|
2010-01-26 02:40:45 +00:00
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
}
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2010-01-26 02:40:45 +00:00
|
|
|
/**
|
|
|
|
* Test BAD response to IMAP ID - also with bad parser chars
|
|
|
|
*/
|
|
|
|
public void testImapIdBad() throws MessagingException {
|
|
|
|
MockTransport mockTransport = openAndInjectMockTransport();
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2010-01-26 02:40:45 +00:00
|
|
|
// try to open it
|
|
|
|
setupOpenFolder(mockTransport, new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"bAD unknown command bad-char-%"}, "rEAD-wRITE");
|
2010-01-26 02:40:45 +00:00
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
}
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2011-01-31 23:10:49 +00:00
|
|
|
/**
|
|
|
|
* Confirm that when IMAP ID is not in capability, it is not sent/received.
|
|
|
|
* This supports RFC 2971 section 3, and is important because certain servers
|
|
|
|
* (e.g. imap.vodafone.net.nz) do not process the unexpected ID command properly.
|
|
|
|
*/
|
|
|
|
public void testImapIdNotSupported() throws MessagingException {
|
|
|
|
MockTransport mockTransport = openAndInjectMockTransport();
|
|
|
|
|
|
|
|
// try to open it
|
|
|
|
setupOpenFolder(mockTransport, null, "rEAD-wRITE");
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
}
|
|
|
|
|
2009-05-20 17:36:16 +00:00
|
|
|
/**
|
|
|
|
* Test small Folder functions that don't really do anything in Imap
|
|
|
|
*/
|
2011-02-10 21:47:35 +00:00
|
|
|
public void testSmallFolderFunctions() {
|
2009-08-27 06:12:02 +00:00
|
|
|
// getPermanentFlags() returns { Flag.DELETED, Flag.SEEN, Flag.FLAGGED }
|
2009-05-20 17:36:16 +00:00
|
|
|
Flag[] flags = mFolder.getPermanentFlags();
|
2009-08-27 06:12:02 +00:00
|
|
|
assertEquals(3, flags.length);
|
2009-05-20 17:36:16 +00:00
|
|
|
// TODO: Write flags into hashset and compare them to a hashset and compare them
|
|
|
|
assertEquals(Flag.DELETED, flags[0]);
|
|
|
|
assertEquals(Flag.SEEN, flags[1]);
|
2009-08-27 06:12:02 +00:00
|
|
|
assertEquals(Flag.FLAGGED, flags[2]);
|
2009-09-25 21:54:32 +00:00
|
|
|
|
|
|
|
// canCreate() returns true
|
|
|
|
assertTrue(mFolder.canCreate(FolderType.HOLDS_FOLDERS));
|
|
|
|
assertTrue(mFolder.canCreate(FolderType.HOLDS_MESSAGES));
|
2009-05-20 17:36:16 +00:00
|
|
|
}
|
|
|
|
|
2009-04-15 19:58:19 +00:00
|
|
|
/**
|
|
|
|
* Lightweight test to confirm that IMAP hasn't implemented any folder roles yet.
|
2010-05-17 20:13:56 +00:00
|
|
|
*
|
2009-04-15 19:58:19 +00:00
|
|
|
* TODO: Test this with multiple folders provided by mock server
|
2009-05-01 23:36:34 +00:00
|
|
|
* TODO: Implement XLIST and then support this
|
2009-04-15 19:58:19 +00:00
|
|
|
*/
|
|
|
|
public void testNoFolderRolesYet() {
|
2010-05-17 20:13:56 +00:00
|
|
|
assertEquals(Folder.FolderRole.UNKNOWN, mFolder.getRole());
|
2009-04-15 19:58:19 +00:00
|
|
|
}
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2009-05-01 23:36:34 +00:00
|
|
|
/**
|
|
|
|
* Lightweight test to confirm that IMAP isn't requesting structure prefetch.
|
|
|
|
*/
|
|
|
|
public void testNoStructurePrefetch() {
|
2010-05-17 20:13:56 +00:00
|
|
|
assertFalse(mStore.requireStructurePrefetch());
|
2009-05-01 23:36:34 +00:00
|
|
|
}
|
2010-05-17 20:13:56 +00:00
|
|
|
|
2009-05-01 23:36:34 +00:00
|
|
|
/**
|
|
|
|
* Lightweight test to confirm that IMAP is requesting sent-message-upload.
|
|
|
|
* TODO: Implement Gmail-specific cases and handle this server-side
|
|
|
|
*/
|
|
|
|
public void testSentUploadRequested() {
|
2010-05-17 20:13:56 +00:00
|
|
|
assertTrue(mStore.requireCopyMessageToSentFolder());
|
2009-05-01 23:36:34 +00:00
|
|
|
}
|
|
|
|
|
2009-03-04 03:32:22 +00:00
|
|
|
/**
|
|
|
|
* TODO: Test the process of opening and indexing a mailbox with one unread message in it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2010-05-17 20:13:56 +00:00
|
|
|
* TODO: Test the scenario where the transport is "open" but not really (e.g. server closed).
|
2009-03-04 03:32:22 +00:00
|
|
|
/**
|
|
|
|
* Set up a basic MockTransport. open it, and inject it into mStore
|
|
|
|
*/
|
|
|
|
private MockTransport openAndInjectMockTransport() {
|
2011-01-05 04:21:15 +00:00
|
|
|
return openAndInjectMockTransport(Transport.CONNECTION_SECURITY_NONE, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set up a MockTransport with security settings
|
|
|
|
*/
|
|
|
|
private MockTransport openAndInjectMockTransport(int connectionSecurity,
|
|
|
|
boolean trustAllCertificates) {
|
2009-03-04 03:32:22 +00:00
|
|
|
// Create mock transport and inject it into the ImapStore that's already set up
|
|
|
|
MockTransport mockTransport = new MockTransport();
|
2011-01-05 04:21:15 +00:00
|
|
|
mockTransport.setSecurity(connectionSecurity, trustAllCertificates);
|
2010-02-26 06:48:11 +00:00
|
|
|
mockTransport.setMockHost("mock.server.com");
|
2009-03-04 03:32:22 +00:00
|
|
|
mStore.setTransport(mockTransport);
|
|
|
|
return mockTransport;
|
|
|
|
}
|
2010-03-18 17:11:08 +00:00
|
|
|
|
2009-03-04 03:32:22 +00:00
|
|
|
/**
|
|
|
|
* Helper which stuffs the mock with enough strings to satisfy a call to ImapFolder.open()
|
2010-03-18 17:11:08 +00:00
|
|
|
*
|
2009-03-04 03:32:22 +00:00
|
|
|
* @param mockTransport the mock transport we're using
|
|
|
|
*/
|
|
|
|
private void setupOpenFolder(MockTransport mockTransport) {
|
2010-05-29 00:34:47 +00:00
|
|
|
setupOpenFolder(mockTransport, "rEAD-wRITE");
|
2010-03-18 17:11:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper which stuffs the mock with enough strings to satisfy a call to ImapFolder.open()
|
|
|
|
*
|
|
|
|
* @param mockTransport the mock transport we're using
|
|
|
|
*/
|
|
|
|
private void setupOpenFolder(MockTransport mockTransport, String readWriteMode) {
|
2010-01-26 02:40:45 +00:00
|
|
|
setupOpenFolder(mockTransport, new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* iD nIL", "oK"}, readWriteMode);
|
2010-01-26 02:40:45 +00:00
|
|
|
}
|
2010-03-18 17:11:08 +00:00
|
|
|
|
2010-01-26 02:40:45 +00:00
|
|
|
/**
|
|
|
|
* Helper which stuffs the mock with enough strings to satisfy a call to ImapFolder.open()
|
|
|
|
* Also allows setting a custom IMAP ID.
|
2010-02-26 06:48:11 +00:00
|
|
|
*
|
|
|
|
* Also sets mNextTag, an int, which is useful if there are additional commands to inject.
|
2010-03-18 17:11:08 +00:00
|
|
|
*
|
2010-01-26 02:40:45 +00:00
|
|
|
* @param mockTransport the mock transport we're using
|
2010-02-26 06:48:11 +00:00
|
|
|
* @param imapIdResponse the expected series of responses to the IMAP ID command. Non-final
|
|
|
|
* lines should be tagged with *. The final response should be untagged (the correct
|
2011-01-31 23:10:49 +00:00
|
|
|
* tag will be added at runtime). Pass "null" to test w/o IMAP ID.
|
2011-01-05 04:21:15 +00:00
|
|
|
* @param readWriteMode "READ-WRITE" or "READ-ONLY"
|
2010-01-26 02:40:45 +00:00
|
|
|
*/
|
2010-03-18 17:11:08 +00:00
|
|
|
private void setupOpenFolder(MockTransport mockTransport, String[] imapIdResponse,
|
|
|
|
String readWriteMode) {
|
2010-05-18 20:41:14 +00:00
|
|
|
expectLogin(mockTransport, imapIdResponse);
|
|
|
|
mockTransport.expect(
|
|
|
|
getNextTag(false) + " SELECT \"" + FOLDER_ENCODED + "\"", new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* fLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)",
|
|
|
|
"* oK [pERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen \\*)]",
|
|
|
|
"* 0 eXISTS",
|
|
|
|
"* 0 rECENT",
|
|
|
|
"* OK [uNSEEN 0]",
|
|
|
|
"* OK [uIDNEXT 1]",
|
|
|
|
getNextTag(true) + " oK [" + readWriteMode + "] " +
|
2010-05-18 20:41:14 +00:00
|
|
|
FOLDER_ENCODED + " selected. (Success)"});
|
|
|
|
}
|
|
|
|
|
2010-05-20 00:23:23 +00:00
|
|
|
private void expectLogin(MockTransport mockTransport) {
|
2010-05-29 00:34:47 +00:00
|
|
|
expectLogin(mockTransport, new String[] {"* iD nIL", "oK"});
|
2010-05-20 00:23:23 +00:00
|
|
|
}
|
|
|
|
|
2010-05-18 20:41:14 +00:00
|
|
|
private void expectLogin(MockTransport mockTransport, String[] imapIdResponse) {
|
2011-01-31 23:10:49 +00:00
|
|
|
expectLogin(mockTransport, false, (imapIdResponse != null), imapIdResponse,
|
|
|
|
"oK user authenticated (Success)");
|
2010-05-19 00:22:28 +00:00
|
|
|
}
|
|
|
|
|
2011-01-31 23:10:49 +00:00
|
|
|
private void expectLogin(MockTransport mockTransport, boolean startTls, boolean withId,
|
|
|
|
String[] imapIdResponse, String loginResponse) {
|
2010-02-26 06:48:11 +00:00
|
|
|
// inject boilerplate commands that match our typical login
|
2010-05-29 00:34:47 +00:00
|
|
|
mockTransport.expect(null, "* oK Imap 2000 Ready To Assist You");
|
2010-05-19 00:22:28 +00:00
|
|
|
|
2011-01-31 23:10:49 +00:00
|
|
|
expectCapability(mockTransport, withId);
|
2011-01-05 04:21:15 +00:00
|
|
|
|
|
|
|
// TLS (if expected)
|
|
|
|
if (startTls) {
|
|
|
|
mockTransport.expect(getNextTag(false) + " STARTTLS",
|
|
|
|
getNextTag(true) + " Ok starting TLS");
|
|
|
|
mockTransport.expectStartTls();
|
|
|
|
// After switching to TLS the client must re-query for capability
|
2011-01-31 23:10:49 +00:00
|
|
|
expectCapability(mockTransport, withId);
|
2011-01-05 04:21:15 +00:00
|
|
|
}
|
2010-05-19 00:22:28 +00:00
|
|
|
|
2011-01-05 04:21:15 +00:00
|
|
|
// ID
|
2011-01-31 23:10:49 +00:00
|
|
|
if (withId) {
|
|
|
|
String expectedNextTag = getNextTag(false);
|
|
|
|
// Fix the tag # of the ID response
|
|
|
|
String last = imapIdResponse[imapIdResponse.length-1];
|
|
|
|
last = expectedNextTag + " " + last;
|
|
|
|
imapIdResponse[imapIdResponse.length-1] = last;
|
|
|
|
mockTransport.expect(getNextTag(false) + " ID \\(.*\\)", imapIdResponse);
|
|
|
|
getNextTag(true); // Advance the tag for ID response.
|
|
|
|
}
|
2010-05-19 00:22:28 +00:00
|
|
|
|
2011-01-05 04:21:15 +00:00
|
|
|
// LOGIN
|
2010-05-19 00:22:28 +00:00
|
|
|
mockTransport.expect(getNextTag(false) + " LOGIN user \"password\"",
|
|
|
|
getNextTag(true) + " " + loginResponse);
|
2010-02-26 06:48:11 +00:00
|
|
|
}
|
|
|
|
|
2011-01-31 23:10:49 +00:00
|
|
|
private void expectCapability(MockTransport mockTransport, boolean withId) {
|
|
|
|
String capabilityList = withId
|
|
|
|
? "* cAPABILITY iMAP4rev1 sTARTTLS aUTH=gSSAPI lOGINDISABLED iD"
|
|
|
|
: "* cAPABILITY iMAP4rev1 sTARTTLS aUTH=gSSAPI lOGINDISABLED";
|
|
|
|
|
2011-01-05 04:21:15 +00:00
|
|
|
mockTransport.expect(getNextTag(false) + " CAPABILITY", new String[] {
|
2011-01-31 23:10:49 +00:00
|
|
|
capabilityList,
|
2011-01-05 04:21:15 +00:00
|
|
|
getNextTag(true) + " oK CAPABILITY completed"});
|
|
|
|
}
|
|
|
|
|
2010-05-20 00:23:23 +00:00
|
|
|
private void expectNoop(MockTransport mockTransport, boolean ok) {
|
2010-05-29 00:34:47 +00:00
|
|
|
String response = ok ? " oK success" : " nO timeout";
|
2010-05-20 00:23:23 +00:00
|
|
|
mockTransport.expect(getNextTag(false) + " NOOP",
|
|
|
|
new String[] {getNextTag(true) + response});
|
|
|
|
}
|
|
|
|
|
2010-02-26 06:48:11 +00:00
|
|
|
/**
|
|
|
|
* Return a tag for use in setting up expect strings. Typically this is called in pairs,
|
|
|
|
* first as getNextTag(false) when emitting the command, then as getNextTag(true) when
|
|
|
|
* emitting the final line of the expected response.
|
|
|
|
* @param advance true to increment mNextTag for the subsequence command
|
|
|
|
* @return a string containing the current tag
|
|
|
|
*/
|
|
|
|
public String getNextTag(boolean advance) {
|
|
|
|
if (advance) ++mNextTag;
|
|
|
|
return Integer.toString(mNextTag);
|
2009-03-04 03:32:22 +00:00
|
|
|
}
|
2010-03-18 17:11:08 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Test that servers reporting READ-WRITE mode are parsed properly
|
|
|
|
* Note: the READ_WRITE mode passed to folder.open() does not affect the test
|
|
|
|
*/
|
|
|
|
public void testReadWrite() throws MessagingException {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
2010-05-29 00:34:47 +00:00
|
|
|
setupOpenFolder(mock, "rEAD-WRITE");
|
2010-03-18 17:11:08 +00:00
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
assertEquals(OpenMode.READ_WRITE, mFolder.getMode());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test that servers reporting READ-ONLY mode are parsed properly
|
|
|
|
* Note: the READ_ONLY mode passed to folder.open() does not affect the test
|
|
|
|
*/
|
|
|
|
public void testReadOnly() throws MessagingException {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
2010-05-29 00:34:47 +00:00
|
|
|
setupOpenFolder(mock, "rEAD-ONLY");
|
2010-03-18 17:11:08 +00:00
|
|
|
mFolder.open(OpenMode.READ_ONLY, null);
|
|
|
|
assertEquals(OpenMode.READ_ONLY, mFolder.getMode());
|
|
|
|
}
|
|
|
|
|
2009-05-19 21:54:49 +00:00
|
|
|
/**
|
|
|
|
* Test for getUnreadMessageCount with quoted string in the middle of response.
|
|
|
|
*/
|
|
|
|
public void testGetUnreadMessageCountWithQuotedString() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
2010-05-18 20:41:14 +00:00
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " STATUS \"" + FOLDER_ENCODED + "\" \\(UNSEEN\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* sTATUS \"" + FOLDER_ENCODED + "\" (uNSEEN 2)",
|
|
|
|
getNextTag(true) + " oK STATUS completed"});
|
2009-05-19 21:54:49 +00:00
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
int unreadCount = mFolder.getUnreadMessageCount();
|
|
|
|
assertEquals("getUnreadMessageCount with quoted string", 2, unreadCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test for getUnreadMessageCount with literal string in the middle of response.
|
|
|
|
*/
|
|
|
|
public void testGetUnreadMessageCountWithLiteralString() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
2010-05-18 20:41:14 +00:00
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " STATUS \"" + FOLDER_ENCODED + "\" \\(UNSEEN\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* sTATUS {5}",
|
|
|
|
FOLDER_ENCODED + " (uNSEEN 10)",
|
|
|
|
getNextTag(true) + " oK STATUS completed"});
|
2009-05-19 21:54:49 +00:00
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
int unreadCount = mFolder.getUnreadMessageCount();
|
|
|
|
assertEquals("getUnreadMessageCount with literal string", 10, unreadCount);
|
|
|
|
}
|
2009-10-07 18:42:27 +00:00
|
|
|
|
2010-05-17 22:44:36 +00:00
|
|
|
public void testFetchFlagEnvelope() throws MessagingException {
|
|
|
|
final MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
final Message message = mFolder.createMessage("1");
|
|
|
|
|
|
|
|
final FetchProfile fp = new FetchProfile();
|
|
|
|
fp.add(FetchProfile.Item.FLAGS);
|
|
|
|
fp.add(FetchProfile.Item.ENVELOPE);
|
|
|
|
mock.expect(getNextTag(false) +
|
|
|
|
" UID FETCH 1 \\(UID FLAGS INTERNALDATE RFC822\\.SIZE BODY\\.PEEK\\[HEADER.FIELDS" +
|
|
|
|
" \\(date subject from content-type to cc message-id\\)\\]\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 9 fETCH (uID 1 rFC822.sIZE 120626 iNTERNALDATE \"17-may-2010 22:00:15 +0000\"" +
|
|
|
|
"fLAGS (\\Seen) bODY[hEADER.FIELDS (dAte sUbject fRom cOntent-type tO cC" +
|
|
|
|
" mEssage-id)]" +
|
2010-05-17 22:44:36 +00:00
|
|
|
" {279}",
|
|
|
|
"From: Xxxxxx Yyyyy <userxx@android.com>",
|
|
|
|
"Date: Mon, 17 May 2010 14:59:52 -0700",
|
|
|
|
"Message-ID: <x0000000000000000000000000000000000000000000000y@android.com>",
|
|
|
|
"Subject: ssubject",
|
|
|
|
"To: android.test01@android.com",
|
|
|
|
"Content-Type: multipart/mixed; boundary=a00000000000000000000000000b",
|
|
|
|
"",
|
|
|
|
")",
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2010-05-17 22:44:36 +00:00
|
|
|
});
|
|
|
|
mFolder.fetch(new Message[] { message }, fp, null);
|
|
|
|
|
|
|
|
assertEquals("android.test01@android.com", message.getHeader("to")[0]);
|
|
|
|
assertEquals("Xxxxxx Yyyyy <userxx@android.com>", message.getHeader("from")[0]);
|
|
|
|
assertEquals("multipart/mixed; boundary=a00000000000000000000000000b",
|
|
|
|
message.getHeader("Content-Type")[0]);
|
|
|
|
assertTrue(message.isSet(Flag.SEEN));
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
// TODO: Test NO response.
|
2010-05-17 22:44:36 +00:00
|
|
|
}
|
|
|
|
|
2010-05-20 00:23:23 +00:00
|
|
|
/**
|
|
|
|
* Test for fetching simple BODYSTRUCTURE.
|
|
|
|
*/
|
|
|
|
public void testFetchBodyStructureSimple() throws Exception {
|
2010-05-17 22:44:36 +00:00
|
|
|
final MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
final Message message = mFolder.createMessage("1");
|
|
|
|
|
|
|
|
final FetchProfile fp = new FetchProfile();
|
|
|
|
fp.add(FetchProfile.Item.STRUCTURE);
|
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODYSTRUCTURE\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 9 fETCH (uID 1 bODYSTRUCTURE (\"tEXT\" \"pLAIN\" nIL" +
|
|
|
|
" nIL nIL nIL 18 3 nIL nIL nIL))",
|
|
|
|
getNextTag(true) + " oK sUCCESS"
|
2010-05-17 22:44:36 +00:00
|
|
|
});
|
|
|
|
mFolder.fetch(new Message[] { message }, fp, null);
|
|
|
|
|
|
|
|
// Check mime structure...
|
2010-05-20 00:23:23 +00:00
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"text/plain"},
|
|
|
|
message.getHeader("Content-Type")
|
|
|
|
);
|
|
|
|
assertNull(message.getHeader("Content-Transfer-Encoding"));
|
|
|
|
assertNull(message.getHeader("Content-ID"));
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {";\n size=18"},
|
|
|
|
message.getHeader("Content-Disposition")
|
|
|
|
);
|
|
|
|
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"TEXT"},
|
|
|
|
message.getHeader("X-Android-Attachment-StoreData")
|
|
|
|
);
|
|
|
|
|
|
|
|
// TODO: Test NO response.
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test for fetching complex muiltipart BODYSTRUCTURE.
|
|
|
|
*/
|
|
|
|
public void testFetchBodyStructureMultipart() throws Exception {
|
|
|
|
final MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
final Message message = mFolder.createMessage("1");
|
|
|
|
|
|
|
|
final FetchProfile fp = new FetchProfile();
|
|
|
|
fp.add(FetchProfile.Item.STRUCTURE);
|
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODYSTRUCTURE\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 9 fETCH (uID 1 bODYSTRUCTURE ((\"tEXT\" \"pLAIN\" () {20}",
|
2010-05-20 00:23:23 +00:00
|
|
|
"long content id#@!@#" +
|
|
|
|
" NIL \"7BIT\" 18 3 NIL NIL NIL)" +
|
|
|
|
"(\"IMAGE\" \"PNG\" (\"NAME\" {10}",
|
|
|
|
"device.png) NIL NIL \"BASE64\" {6}",
|
2010-05-29 00:34:47 +00:00
|
|
|
"117840 NIL (\"aTTACHMENT\" (\"fILENAME\" \"device.png\")) NIL)" +
|
|
|
|
"(\"TEXT\" \"HTML\" () NIL NIL \"7BIT\" 100 NIL 123 (\"aTTACHMENT\"" +
|
|
|
|
"(\"fILENAME\" {15}",
|
2010-05-20 00:23:23 +00:00
|
|
|
"attachment.html \"SIZE\" 555)) NIL)" +
|
|
|
|
"((\"TEXT\" \"HTML\" NIL NIL \"BASE64\")(\"XXX\" \"YYY\"))" + // Nested
|
2010-05-29 00:34:47 +00:00
|
|
|
"\"mIXED\" (\"bOUNDARY\" \"00032556278a7005e40486d159ca\") NIL NIL))",
|
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2010-05-20 00:23:23 +00:00
|
|
|
});
|
|
|
|
mFolder.fetch(new Message[] { message }, fp, null);
|
|
|
|
|
|
|
|
// Check mime structure...
|
|
|
|
final Body body = message.getBody();
|
2010-05-17 22:44:36 +00:00
|
|
|
assertTrue(body instanceof MimeMultipart);
|
|
|
|
MimeMultipart mimeMultipart = (MimeMultipart) body;
|
2010-05-20 00:23:23 +00:00
|
|
|
assertEquals(4, mimeMultipart.getCount());
|
2010-05-17 22:44:36 +00:00
|
|
|
assertEquals("mixed", mimeMultipart.getSubTypeForTest());
|
|
|
|
|
2010-05-20 00:23:23 +00:00
|
|
|
final Part part1 = mimeMultipart.getBodyPart(0);
|
|
|
|
final Part part2 = mimeMultipart.getBodyPart(1);
|
|
|
|
final Part part3 = mimeMultipart.getBodyPart(2);
|
|
|
|
final Part part4 = mimeMultipart.getBodyPart(3);
|
2010-05-17 22:44:36 +00:00
|
|
|
assertTrue(part1 instanceof MimeBodyPart);
|
|
|
|
assertTrue(part2 instanceof MimeBodyPart);
|
2010-05-20 00:23:23 +00:00
|
|
|
assertTrue(part3 instanceof MimeBodyPart);
|
|
|
|
assertTrue(part4 instanceof MimeBodyPart);
|
2010-05-17 22:44:36 +00:00
|
|
|
|
2010-05-20 00:23:23 +00:00
|
|
|
final MimeBodyPart mimePart1 = (MimeBodyPart) part1; // text/plain
|
|
|
|
final MimeBodyPart mimePart2 = (MimeBodyPart) part2; // image/png
|
|
|
|
final MimeBodyPart mimePart3 = (MimeBodyPart) part3; // text/html
|
|
|
|
final MimeBodyPart mimePart4 = (MimeBodyPart) part4; // Nested
|
2010-05-17 22:44:36 +00:00
|
|
|
|
|
|
|
MoreAsserts.assertEquals(
|
2010-05-20 00:23:23 +00:00
|
|
|
new String[] {"1"},
|
|
|
|
part1.getHeader("X-Android-Attachment-StoreData")
|
2010-05-17 22:44:36 +00:00
|
|
|
);
|
|
|
|
MoreAsserts.assertEquals(
|
2010-05-20 00:23:23 +00:00
|
|
|
new String[] {"2"},
|
|
|
|
part2.getHeader("X-Android-Attachment-StoreData")
|
|
|
|
);
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"3"},
|
|
|
|
part3.getHeader("X-Android-Attachment-StoreData")
|
|
|
|
);
|
|
|
|
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"text/plain"},
|
2010-05-17 22:44:36 +00:00
|
|
|
part1.getHeader("Content-Type")
|
|
|
|
);
|
|
|
|
MoreAsserts.assertEquals(
|
2010-05-20 00:23:23 +00:00
|
|
|
new String[] {"image/png;\n NAME=\"device.png\""},
|
2010-05-17 22:44:36 +00:00
|
|
|
part2.getHeader("Content-Type")
|
|
|
|
);
|
|
|
|
MoreAsserts.assertEquals(
|
2010-05-20 00:23:23 +00:00
|
|
|
new String[] {"text/html"},
|
|
|
|
part3.getHeader("Content-Type")
|
2010-05-17 22:44:36 +00:00
|
|
|
);
|
2010-05-20 00:23:23 +00:00
|
|
|
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"long content id#@!@#"},
|
2010-05-17 22:44:36 +00:00
|
|
|
part1.getHeader("Content-ID")
|
|
|
|
);
|
2010-05-20 00:23:23 +00:00
|
|
|
assertNull(part2.getHeader("Content-ID"));
|
|
|
|
assertNull(part3.getHeader("Content-ID"));
|
2010-05-17 22:44:36 +00:00
|
|
|
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"7BIT"},
|
2010-05-20 00:23:23 +00:00
|
|
|
part1.getHeader("Content-Transfer-Encoding")
|
2010-05-17 22:44:36 +00:00
|
|
|
);
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"BASE64"},
|
2010-05-20 00:23:23 +00:00
|
|
|
part2.getHeader("Content-Transfer-Encoding")
|
2010-05-17 22:44:36 +00:00
|
|
|
);
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"7BIT"},
|
2010-05-20 00:23:23 +00:00
|
|
|
part3.getHeader("Content-Transfer-Encoding")
|
2010-05-17 22:44:36 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
MoreAsserts.assertEquals(
|
2010-05-20 00:23:23 +00:00
|
|
|
new String[] {";\n size=18"},
|
|
|
|
part1.getHeader("Content-Disposition")
|
2010-05-17 22:44:36 +00:00
|
|
|
);
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"attachment;\n filename=\"device.png\";\n size=117840"},
|
2010-05-20 00:23:23 +00:00
|
|
|
part2.getHeader("Content-Disposition")
|
2010-05-17 22:44:36 +00:00
|
|
|
);
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"attachment;\n filename=\"attachment.html\";\n size=\"555\""},
|
2010-05-20 00:23:23 +00:00
|
|
|
part3.getHeader("Content-Disposition")
|
2010-05-17 22:44:36 +00:00
|
|
|
);
|
|
|
|
|
2010-05-20 00:23:23 +00:00
|
|
|
// Check the nested parts.
|
|
|
|
final Body part4body = part4.getBody();
|
|
|
|
assertTrue(part4body instanceof MimeMultipart);
|
|
|
|
MimeMultipart mimeMultipartPart4 = (MimeMultipart) part4body;
|
|
|
|
assertEquals(2, mimeMultipartPart4.getCount());
|
2010-05-19 00:22:28 +00:00
|
|
|
|
2010-05-20 00:23:23 +00:00
|
|
|
final MimeBodyPart mimePart41 = (MimeBodyPart) mimeMultipartPart4.getBodyPart(0);
|
|
|
|
final MimeBodyPart mimePart42 = (MimeBodyPart) mimeMultipartPart4.getBodyPart(1);
|
|
|
|
|
|
|
|
MoreAsserts.assertEquals(new String[] {"4.1"},
|
|
|
|
mimePart41.getHeader("X-Android-Attachment-StoreData")
|
|
|
|
);
|
|
|
|
MoreAsserts.assertEquals(new String[] {"4.2"},
|
|
|
|
mimePart42.getHeader("X-Android-Attachment-StoreData")
|
|
|
|
);
|
2010-05-17 22:44:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void testFetchBodySane() throws MessagingException {
|
|
|
|
final MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
final Message message = mFolder.createMessage("1");
|
|
|
|
|
|
|
|
final FetchProfile fp = new FetchProfile();
|
|
|
|
fp.add(FetchProfile.Item.BODY_SANE);
|
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODY.PEEK\\[\\]<0.51200>\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 9 fETCH (uID 1 bODY[] {23}",
|
2010-05-17 22:44:36 +00:00
|
|
|
"from: a@b.com", // 15 bytes
|
|
|
|
"", // 2
|
|
|
|
"test", // 6
|
|
|
|
")",
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2010-05-17 22:44:36 +00:00
|
|
|
});
|
|
|
|
mFolder.fetch(new Message[] { message }, fp, null);
|
|
|
|
assertEquals("a@b.com", message.getHeader("from")[0]);
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
// TODO: Test NO response.
|
2010-05-17 22:44:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void testFetchBody() throws MessagingException {
|
|
|
|
final MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
final Message message = mFolder.createMessage("1");
|
|
|
|
|
|
|
|
final FetchProfile fp = new FetchProfile();
|
|
|
|
fp.add(FetchProfile.Item.BODY);
|
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODY.PEEK\\[\\]\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 9 fETCH (uID 1 bODY[] {23}",
|
2010-05-17 22:44:36 +00:00
|
|
|
"from: a@b.com", // 15 bytes
|
|
|
|
"", // 2
|
|
|
|
"test", // 6
|
|
|
|
")",
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2010-05-17 22:44:36 +00:00
|
|
|
});
|
|
|
|
mFolder.fetch(new Message[] { message }, fp, null);
|
|
|
|
assertEquals("a@b.com", message.getHeader("from")[0]);
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
// TODO: Test NO response.
|
2010-05-17 22:44:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void testFetchAttachment() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
final Message message = mFolder.createMessage("1");
|
|
|
|
|
|
|
|
final FetchProfile fp = new FetchProfile();
|
|
|
|
fp.add(FetchProfile.Item.STRUCTURE);
|
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODYSTRUCTURE\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 9 fETCH (uID 1 bODYSTRUCTURE ((\"tEXT\" \"PLAIN\" (\"cHARSET\" \"iSO-8859-1\")" +
|
|
|
|
" CID nIL \"7bIT\" 18 3 NIL NIL NIL)" +
|
2010-05-17 22:44:36 +00:00
|
|
|
"(\"IMAGE\" \"PNG\"" +
|
2010-05-29 00:34:47 +00:00
|
|
|
" (\"nAME\" \"device.png\") NIL NIL \"bASE64\" 117840 NIL (\"aTTACHMENT\"" +
|
|
|
|
"(\"fILENAME\" \"device.png\")) NIL)" +
|
|
|
|
"\"mIXED\"))",
|
2010-05-17 22:44:36 +00:00
|
|
|
getNextTag(true) + " OK SUCCESS"
|
|
|
|
});
|
|
|
|
mFolder.fetch(new Message[] { message }, fp, null);
|
|
|
|
|
|
|
|
// Check mime structure, and get the second part.
|
|
|
|
Body body = message.getBody();
|
|
|
|
assertTrue(body instanceof MimeMultipart);
|
|
|
|
MimeMultipart mimeMultipart = (MimeMultipart) body;
|
|
|
|
assertEquals(2, mimeMultipart.getCount());
|
|
|
|
|
|
|
|
Part part1 = mimeMultipart.getBodyPart(1);
|
|
|
|
assertTrue(part1 instanceof MimeBodyPart);
|
|
|
|
MimeBodyPart mimePart1 = (MimeBodyPart) part1;
|
|
|
|
|
|
|
|
// Fetch the second part
|
|
|
|
fp.clear();
|
|
|
|
fp.add(mimePart1);
|
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODY.PEEK\\[2\\]\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 9 fETCH (uID 1 bODY[2] {4}",
|
2010-05-17 22:44:36 +00:00
|
|
|
"YWJj)", // abc in base64
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2010-05-17 22:44:36 +00:00
|
|
|
});
|
|
|
|
mFolder.fetch(new Message[] { message }, fp, null);
|
|
|
|
|
|
|
|
assertEquals("abc",
|
|
|
|
Utility.fromUtf8(IOUtils.toByteArray(mimePart1.getBody().getInputStream())));
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
// TODO: Test NO response.
|
2010-05-17 22:44:36 +00:00
|
|
|
}
|
|
|
|
|
2009-10-07 18:42:27 +00:00
|
|
|
/**
|
|
|
|
* Test for proper operations on servers that return "NIL" for empty message bodies.
|
|
|
|
*/
|
|
|
|
public void testNilMessage() throws MessagingException {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
// Prepare to pull structure and peek body text - this is like the "large message"
|
|
|
|
// loop in MessagingController.synchronizeMailboxGeneric()
|
|
|
|
FetchProfile fp = new FetchProfile();fp.clear();
|
|
|
|
fp.add(FetchProfile.Item.STRUCTURE);
|
|
|
|
Message message1 = mFolder.createMessage("1");
|
2010-02-26 06:48:11 +00:00
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODYSTRUCTURE\\)", new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 1 fETCH (uID 1 bODYSTRUCTURE (tEXT pLAIN nIL nIL nIL 7bIT 0 0 nIL nIL nIL))",
|
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2009-10-07 18:42:27 +00:00
|
|
|
});
|
|
|
|
mFolder.fetch(new Message[] { message1 }, fp, null);
|
|
|
|
|
|
|
|
// The expected result for an empty body is:
|
|
|
|
// * 1 FETCH (UID 1 BODY[TEXT] {0})
|
|
|
|
// But some servers are returning NIL for the empty body:
|
|
|
|
// * 1 FETCH (UID 1 BODY[TEXT] NIL)
|
|
|
|
// Because this breaks our little parser, fetch() skips over empty parts.
|
|
|
|
// The rest of this test is confirming that this is the case.
|
|
|
|
|
2010-02-26 06:48:11 +00:00
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODY.PEEK\\[TEXT\\]\\)", new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 1 fETCH (uID 1 bODY[tEXT] nIL)",
|
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2009-10-07 18:42:27 +00:00
|
|
|
});
|
|
|
|
ArrayList<Part> viewables = new ArrayList<Part>();
|
|
|
|
ArrayList<Part> attachments = new ArrayList<Part>();
|
|
|
|
MimeUtility.collectParts(message1, viewables, attachments);
|
|
|
|
assertTrue(viewables.size() == 1);
|
|
|
|
Part emptyBodyPart = viewables.get(0);
|
|
|
|
fp.clear();
|
|
|
|
fp.add(emptyBodyPart);
|
|
|
|
mFolder.fetch(new Message[] { message1 }, fp, null);
|
|
|
|
|
|
|
|
// If this wasn't working properly, there would be an attempted interpretation
|
|
|
|
// of the empty part's NIL and possibly a crash.
|
|
|
|
|
|
|
|
// If this worked properly, the "empty" body can now be retrieved
|
|
|
|
viewables = new ArrayList<Part>();
|
|
|
|
attachments = new ArrayList<Part>();
|
|
|
|
MimeUtility.collectParts(message1, viewables, attachments);
|
|
|
|
assertTrue(viewables.size() == 1);
|
|
|
|
emptyBodyPart = viewables.get(0);
|
|
|
|
String text = MimeUtility.getTextFromPart(emptyBodyPart);
|
|
|
|
assertNull(text);
|
|
|
|
}
|
2010-02-24 01:29:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Confirm the IMAP parser won't crash when seeing an excess FETCH response line without UID.
|
|
|
|
*
|
|
|
|
* <p>We've observed that the secure.emailsrvr.com email server returns an excess FETCH response
|
|
|
|
* for a UID FETCH command. These excess responses doesn't have the UID field in it, even
|
|
|
|
* though we request, which led the response parser to crash. We fixed it by ignoring response
|
|
|
|
* lines that don't have UID. This test is to make sure this case.
|
|
|
|
*/
|
|
|
|
public void testExcessFetchResult() throws MessagingException {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
// Create a message, and make sure it's not "SEEN".
|
|
|
|
Message message1 = mFolder.createMessage("1");
|
|
|
|
assertFalse(message1.isSet(Flag.SEEN));
|
|
|
|
|
|
|
|
FetchProfile fp = new FetchProfile();
|
|
|
|
fp.clear();
|
|
|
|
fp.add(FetchProfile.Item.FLAGS);
|
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID FLAGS\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 1 fETCH (uID 1 fLAGS (\\Seen))",
|
|
|
|
"* 2 fETCH (fLAGS (\\Seen))",
|
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2010-02-24 01:29:24 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// Shouldn't crash
|
|
|
|
mFolder.fetch(new Message[] { message1 }, fp, null);
|
|
|
|
|
|
|
|
// And the message is "SEEN".
|
|
|
|
assertTrue(message1.isSet(Flag.SEEN));
|
|
|
|
}
|
2010-04-02 18:09:12 +00:00
|
|
|
|
|
|
|
|
2010-05-21 01:19:12 +00:00
|
|
|
private ImapMessage prepareForAppendTest(MockTransport mock, String response) throws Exception {
|
|
|
|
ImapMessage message = (ImapMessage) mFolder.createMessage("initial uid");
|
2010-04-02 18:09:12 +00:00
|
|
|
message.setFrom(new Address("me@test.com"));
|
|
|
|
message.setRecipient(RecipientType.TO, new Address("you@test.com"));
|
|
|
|
message.setMessageId("<message.id@test.com>");
|
|
|
|
message.setFlagDirectlyForTest(Flag.SEEN, true);
|
|
|
|
message.setBody(new TextBody("Test Body"));
|
|
|
|
|
|
|
|
// + go ahead
|
|
|
|
// * 12345 EXISTS
|
|
|
|
// OK [APPENDUID 627684530 17] (Success)
|
|
|
|
|
2010-05-18 20:41:14 +00:00
|
|
|
mock.expect(getNextTag(false) +
|
2010-05-29 00:34:47 +00:00
|
|
|
" APPEND \\\"" + FOLDER_ENCODED + "\\\" \\(\\\\SEEN\\) \\{166\\}",
|
|
|
|
new String[] {"+ gO aHead"});
|
2010-04-02 18:09:12 +00:00
|
|
|
|
|
|
|
mock.expectLiterally("From: me@test.com", NO_REPLY);
|
|
|
|
mock.expectLiterally("To: you@test.com", NO_REPLY);
|
|
|
|
mock.expectLiterally("Message-ID: <message.id@test.com>", NO_REPLY);
|
|
|
|
mock.expectLiterally("Content-Type: text/plain;", NO_REPLY);
|
|
|
|
mock.expectLiterally(" charset=utf-8", NO_REPLY);
|
|
|
|
mock.expectLiterally("Content-Transfer-Encoding: base64", NO_REPLY);
|
|
|
|
mock.expectLiterally("", NO_REPLY);
|
|
|
|
mock.expectLiterally("VGVzdCBCb2R5", NO_REPLY);
|
|
|
|
mock.expectLiterally("", new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 7 eXISTS",
|
2010-05-21 01:19:12 +00:00
|
|
|
getNextTag(true) + " " + response
|
2010-04-02 18:09:12 +00:00
|
|
|
});
|
2010-05-21 01:19:12 +00:00
|
|
|
return message;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test for APPEND when the response has APPENDUID.
|
|
|
|
*/
|
|
|
|
public void testAppendMessages() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
2010-05-29 00:34:47 +00:00
|
|
|
ImapMessage message = prepareForAppendTest(mock, "oK [aPPENDUID 1234567 13] (Success)");
|
2010-04-02 18:09:12 +00:00
|
|
|
|
|
|
|
mFolder.appendMessages(new Message[] {message});
|
|
|
|
|
|
|
|
assertEquals("13", message.getUid());
|
|
|
|
assertEquals(7, mFolder.getMessageCount());
|
2010-05-21 01:19:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test for APPEND when the response doesn't have APPENDUID.
|
|
|
|
*/
|
|
|
|
public void testAppendMessagesNoAppendUid() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
ImapMessage message = prepareForAppendTest(mock, "OK Success");
|
|
|
|
|
|
|
|
mock.expectLiterally(
|
|
|
|
getNextTag(false) + " UID SEARCH (HEADER MESSAGE-ID <message.id@test.com>)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* sEARCH 321",
|
|
|
|
getNextTag(true) + " oK success"
|
2010-05-21 01:19:12 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
mFolder.appendMessages(new Message[] {message});
|
|
|
|
|
|
|
|
assertEquals("321", message.getUid());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test for append failure.
|
|
|
|
*
|
|
|
|
* We don't check the response for APPEND. We just SEARCH for the message-id to get the UID.
|
|
|
|
* If append has failed, the SEARCH command returns no UID, and the UID of the message is left
|
|
|
|
* unset.
|
|
|
|
*/
|
|
|
|
public void testAppendFailure() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
ImapMessage message = prepareForAppendTest(mock, "NO No space left on the server.");
|
|
|
|
assertEquals("initial uid", message.getUid());
|
|
|
|
|
|
|
|
mock.expectLiterally(
|
|
|
|
getNextTag(false) + " UID SEARCH (HEADER MESSAGE-ID <message.id@test.com>)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* sEARCH", // not found
|
|
|
|
getNextTag(true) + " oK Search completed."
|
2010-05-21 01:19:12 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
mFolder.appendMessages(new Message[] {message});
|
2010-05-19 00:22:28 +00:00
|
|
|
|
2010-05-21 01:19:12 +00:00
|
|
|
// Shouldn't have changed
|
|
|
|
assertEquals("initial uid", message.getUid());
|
2010-04-02 18:09:12 +00:00
|
|
|
}
|
2010-05-18 20:41:14 +00:00
|
|
|
|
2011-02-10 21:47:35 +00:00
|
|
|
public void testGetAllFolders() throws Exception {
|
2010-05-18 20:41:14 +00:00
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
2010-05-20 00:23:23 +00:00
|
|
|
expectLogin(mock);
|
2010-05-18 20:41:14 +00:00
|
|
|
|
2011-02-10 21:47:35 +00:00
|
|
|
expectNoop(mock, true);
|
2010-05-18 20:41:14 +00:00
|
|
|
mock.expect(getNextTag(false) + " LIST \"\" \"\\*\"",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* lIST (\\HAsNoChildren) \"/\" \"inbox\"",
|
|
|
|
"* lIST (\\hAsnochildren) \"/\" \"Drafts\"",
|
|
|
|
"* lIST (\\nOselect) \"/\" \"no select\"",
|
|
|
|
"* lIST (\\HAsNoChildren) \"/\" \"&ZeVnLIqe-\"", // Japanese folder name
|
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
2011-02-10 21:47:35 +00:00
|
|
|
Folder[] folders = mStore.getAllFolders();
|
2010-05-18 20:41:14 +00:00
|
|
|
|
|
|
|
ArrayList<String> list = new ArrayList<String>();
|
|
|
|
for (Folder f : folders) {
|
|
|
|
list.add(f.getName());
|
|
|
|
}
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"Drafts", "\u65E5\u672C\u8A9E", "INBOX"},
|
|
|
|
list.toArray(new String[0])
|
|
|
|
);
|
|
|
|
|
|
|
|
// TODO test with path prefix
|
2010-05-19 00:22:28 +00:00
|
|
|
// TODO: Test NO response.
|
2010-05-18 20:41:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void testEncodeFolderName() {
|
2011-02-10 21:47:35 +00:00
|
|
|
// null prefix
|
|
|
|
assertEquals("",
|
|
|
|
ImapStore.encodeFolderName("", null));
|
|
|
|
assertEquals("a",
|
|
|
|
ImapStore.encodeFolderName("a", null));
|
|
|
|
assertEquals("XYZ",
|
|
|
|
ImapStore.encodeFolderName("XYZ", null));
|
|
|
|
assertEquals("&ZeVnLIqe-",
|
|
|
|
ImapStore.encodeFolderName("\u65E5\u672C\u8A9E", null));
|
|
|
|
assertEquals("!&ZeVnLIqe-!",
|
|
|
|
ImapStore.encodeFolderName("!\u65E5\u672C\u8A9E!", null));
|
|
|
|
// empty prefix (same as a null prefix)
|
|
|
|
assertEquals("",
|
|
|
|
ImapStore.encodeFolderName("", ""));
|
|
|
|
assertEquals("a",
|
|
|
|
ImapStore.encodeFolderName("a", ""));
|
|
|
|
assertEquals("XYZ",
|
|
|
|
ImapStore.encodeFolderName("XYZ", ""));
|
|
|
|
assertEquals("&ZeVnLIqe-",
|
|
|
|
ImapStore.encodeFolderName("\u65E5\u672C\u8A9E", ""));
|
|
|
|
assertEquals("!&ZeVnLIqe-!",
|
|
|
|
ImapStore.encodeFolderName("!\u65E5\u672C\u8A9E!", ""));
|
|
|
|
// defined prefix
|
|
|
|
assertEquals("[Gmail]/",
|
|
|
|
ImapStore.encodeFolderName("", "[Gmail]/"));
|
|
|
|
assertEquals("[Gmail]/a",
|
|
|
|
ImapStore.encodeFolderName("a", "[Gmail]/"));
|
|
|
|
assertEquals("[Gmail]/XYZ",
|
|
|
|
ImapStore.encodeFolderName("XYZ", "[Gmail]/"));
|
|
|
|
assertEquals("[Gmail]/&ZeVnLIqe-",
|
|
|
|
ImapStore.encodeFolderName("\u65E5\u672C\u8A9E", "[Gmail]/"));
|
|
|
|
assertEquals("[Gmail]/!&ZeVnLIqe-!",
|
|
|
|
ImapStore.encodeFolderName("!\u65E5\u672C\u8A9E!", "[Gmail]/"));
|
|
|
|
// Add prefix to special mailbox "INBOX" [case insensitive), no affect
|
|
|
|
assertEquals("INBOX",
|
|
|
|
ImapStore.encodeFolderName("INBOX", "[Gmail]/"));
|
|
|
|
assertEquals("inbox",
|
|
|
|
ImapStore.encodeFolderName("inbox", "[Gmail]/"));
|
|
|
|
assertEquals("InBoX",
|
|
|
|
ImapStore.encodeFolderName("InBoX", "[Gmail]/"));
|
2010-05-18 20:41:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void testDecodeFolderName() {
|
2011-02-10 21:47:35 +00:00
|
|
|
// null prefix
|
|
|
|
assertEquals("",
|
|
|
|
ImapStore.decodeFolderName("", null));
|
|
|
|
assertEquals("a",
|
|
|
|
ImapStore.decodeFolderName("a", null));
|
|
|
|
assertEquals("XYZ",
|
|
|
|
ImapStore.decodeFolderName("XYZ", null));
|
|
|
|
assertEquals("\u65E5\u672C\u8A9E",
|
|
|
|
ImapStore.decodeFolderName("&ZeVnLIqe-", null));
|
|
|
|
assertEquals("!\u65E5\u672C\u8A9E!",
|
|
|
|
ImapStore.decodeFolderName("!&ZeVnLIqe-!", null));
|
|
|
|
// empty prefix (same as a null prefix)
|
|
|
|
assertEquals("",
|
|
|
|
ImapStore.decodeFolderName("", ""));
|
|
|
|
assertEquals("a",
|
|
|
|
ImapStore.decodeFolderName("a", ""));
|
|
|
|
assertEquals("XYZ",
|
|
|
|
ImapStore.decodeFolderName("XYZ", ""));
|
|
|
|
assertEquals("\u65E5\u672C\u8A9E",
|
|
|
|
ImapStore.decodeFolderName("&ZeVnLIqe-", ""));
|
|
|
|
assertEquals("!\u65E5\u672C\u8A9E!",
|
|
|
|
ImapStore.decodeFolderName("!&ZeVnLIqe-!", ""));
|
|
|
|
// defined prefix; prefix found, prefix removed
|
|
|
|
assertEquals("",
|
|
|
|
ImapStore.decodeFolderName("[Gmail]/", "[Gmail]/"));
|
|
|
|
assertEquals("a",
|
|
|
|
ImapStore.decodeFolderName("[Gmail]/a", "[Gmail]/"));
|
|
|
|
assertEquals("XYZ",
|
|
|
|
ImapStore.decodeFolderName("[Gmail]/XYZ", "[Gmail]/"));
|
|
|
|
assertEquals("\u65E5\u672C\u8A9E",
|
|
|
|
ImapStore.decodeFolderName("[Gmail]/&ZeVnLIqe-", "[Gmail]/"));
|
|
|
|
assertEquals("!\u65E5\u672C\u8A9E!",
|
|
|
|
ImapStore.decodeFolderName("[Gmail]/!&ZeVnLIqe-!", "[Gmail]/"));
|
|
|
|
// defined prefix; prefix not found, no affect
|
|
|
|
assertEquals("INBOX/",
|
|
|
|
ImapStore.decodeFolderName("INBOX/", "[Gmail]/"));
|
|
|
|
assertEquals("INBOX/a",
|
|
|
|
ImapStore.decodeFolderName("INBOX/a", "[Gmail]/"));
|
|
|
|
assertEquals("INBOX/XYZ",
|
|
|
|
ImapStore.decodeFolderName("INBOX/XYZ", "[Gmail]/"));
|
|
|
|
assertEquals("INBOX/\u65E5\u672C\u8A9E",
|
|
|
|
ImapStore.decodeFolderName("INBOX/&ZeVnLIqe-", "[Gmail]/"));
|
|
|
|
assertEquals("INBOX/!\u65E5\u672C\u8A9E!",
|
|
|
|
ImapStore.decodeFolderName("INBOX/!&ZeVnLIqe-!", "[Gmail]/"));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void testEnsurePrefixIsValid() {
|
|
|
|
// Test mPathSeparator == null
|
|
|
|
mStore.mPathSeparator = null;
|
|
|
|
mStore.mPathPrefix = null;
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertNull(mStore.mPathPrefix);
|
|
|
|
|
|
|
|
mStore.mPathPrefix = "";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("", mStore.mPathPrefix);
|
|
|
|
|
|
|
|
mStore.mPathPrefix = "foo";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("foo", mStore.mPathPrefix);
|
|
|
|
|
|
|
|
mStore.mPathPrefix = "foo.";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("foo.", mStore.mPathPrefix);
|
|
|
|
|
|
|
|
// Test mPathSeparator == ""
|
|
|
|
mStore.mPathSeparator = "";
|
|
|
|
mStore.mPathPrefix = null;
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertNull(mStore.mPathPrefix);
|
|
|
|
|
|
|
|
mStore.mPathPrefix = "";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("", mStore.mPathPrefix);
|
|
|
|
|
|
|
|
mStore.mPathPrefix = "foo";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("foo", mStore.mPathPrefix);
|
|
|
|
|
|
|
|
mStore.mPathPrefix = "foo.";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("foo.", mStore.mPathPrefix);
|
|
|
|
|
|
|
|
// Test mPathSeparator is non-empty
|
|
|
|
mStore.mPathSeparator = ".";
|
|
|
|
mStore.mPathPrefix = null;
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertNull(mStore.mPathPrefix);
|
|
|
|
|
|
|
|
mStore.mPathPrefix = "";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("", mStore.mPathPrefix);
|
|
|
|
|
|
|
|
mStore.mPathPrefix = "foo";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("foo.", mStore.mPathPrefix);
|
|
|
|
|
|
|
|
// Trailing separator; path separator NOT appended
|
|
|
|
mStore.mPathPrefix = "foo.";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("foo.", mStore.mPathPrefix);
|
|
|
|
|
|
|
|
// Trailing punctuation has no affect; path separator still appended
|
|
|
|
mStore.mPathPrefix = "foo/";
|
|
|
|
mStore.ensurePrefixIsValid();
|
|
|
|
assertEquals("foo/.", mStore.mPathPrefix);
|
2010-05-18 20:41:14 +00:00
|
|
|
}
|
|
|
|
|
2010-05-20 00:23:23 +00:00
|
|
|
public void testOpen() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
expectLogin(mock);
|
|
|
|
|
|
|
|
final Folder folder = mStore.getFolder("test");
|
|
|
|
|
|
|
|
// Not exist
|
|
|
|
mock.expect(getNextTag(false) + " SELECT \\\"test\\\"",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " nO no such mailbox"
|
2010-05-20 00:23:23 +00:00
|
|
|
});
|
|
|
|
try {
|
|
|
|
folder.open(OpenMode.READ_WRITE, null);
|
|
|
|
fail();
|
|
|
|
} catch (MessagingException expected) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// READ-WRITE
|
|
|
|
expectNoop(mock, true); // Need it because we reuse the connection.
|
|
|
|
mock.expect(getNextTag(false) + " SELECT \\\"test\\\"",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 1 eXISTS",
|
|
|
|
getNextTag(true) + " oK [rEAD-wRITE]"
|
2010-05-20 00:23:23 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
folder.open(OpenMode.READ_WRITE, null);
|
|
|
|
assertTrue(folder.exists());
|
|
|
|
assertEquals(1, folder.getMessageCount());
|
|
|
|
assertEquals(OpenMode.READ_WRITE, folder.getMode());
|
|
|
|
|
|
|
|
assertTrue(folder.isOpen());
|
|
|
|
folder.close(false);
|
|
|
|
assertFalse(folder.isOpen());
|
|
|
|
|
|
|
|
// READ-ONLY
|
|
|
|
expectNoop(mock, true); // Need it because we reuse the connection.
|
|
|
|
mock.expect(getNextTag(false) + " SELECT \\\"test\\\"",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 2 eXISTS",
|
|
|
|
getNextTag(true) + " oK [rEAD-oNLY]"
|
2010-05-20 00:23:23 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
folder.open(OpenMode.READ_WRITE, null);
|
|
|
|
assertTrue(folder.exists());
|
|
|
|
assertEquals(2, folder.getMessageCount());
|
|
|
|
assertEquals(OpenMode.READ_ONLY, folder.getMode());
|
|
|
|
|
|
|
|
// Try to re-open as read-write. Should send SELECT again.
|
|
|
|
expectNoop(mock, true); // Need it because we reuse the connection.
|
|
|
|
mock.expect(getNextTag(false) + " SELECT \\\"test\\\"",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* 15 eXISTS",
|
|
|
|
getNextTag(true) + " oK selected"
|
2010-05-20 00:23:23 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
folder.open(OpenMode.READ_WRITE, null);
|
|
|
|
assertTrue(folder.exists());
|
|
|
|
assertEquals(15, folder.getMessageCount());
|
|
|
|
assertEquals(OpenMode.READ_WRITE, folder.getMode());
|
|
|
|
}
|
2010-05-19 00:22:28 +00:00
|
|
|
|
2010-05-18 20:41:14 +00:00
|
|
|
public void testExists() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
2010-05-20 00:23:23 +00:00
|
|
|
expectLogin(mock);
|
2010-05-18 20:41:14 +00:00
|
|
|
|
|
|
|
// Folder exists
|
|
|
|
Folder folder = mStore.getFolder("\u65E5\u672C\u8A9E");
|
|
|
|
mock.expect(getNextTag(false) + " STATUS \\\"&ZeVnLIqe-\\\" \\(UIDVALIDITY\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* sTATUS \"&ZeVnLIqe-\" (mESSAGES 10)",
|
|
|
|
getNextTag(true) + " oK SUCCESS"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
assertTrue(folder.exists());
|
|
|
|
|
|
|
|
// Connection verification
|
2010-05-20 00:23:23 +00:00
|
|
|
expectNoop(mock, true);
|
2010-05-18 20:41:14 +00:00
|
|
|
|
|
|
|
// Doesn't exist
|
|
|
|
folder = mStore.getFolder("no such folder");
|
|
|
|
mock.expect(getNextTag(false) + " STATUS \\\"no such folder\\\" \\(UIDVALIDITY\\)",
|
|
|
|
new String[] {
|
|
|
|
getNextTag(true) + " NO No such folder!"
|
|
|
|
});
|
|
|
|
|
|
|
|
assertFalse(folder.exists());
|
|
|
|
}
|
|
|
|
|
|
|
|
public void testCreate() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
2010-05-20 00:23:23 +00:00
|
|
|
expectLogin(mock);
|
2010-05-18 20:41:14 +00:00
|
|
|
|
|
|
|
// Success
|
|
|
|
Folder folder = mStore.getFolder("\u65E5\u672C\u8A9E");
|
|
|
|
|
|
|
|
assertTrue(folder.canCreate(FolderType.HOLDS_MESSAGES));
|
|
|
|
|
|
|
|
mock.expect(getNextTag(false) + " CREATE \\\"&ZeVnLIqe-\\\"",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " oK Success"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
assertTrue(folder.create(FolderType.HOLDS_MESSAGES));
|
|
|
|
|
|
|
|
// Connection verification
|
2010-05-20 00:23:23 +00:00
|
|
|
expectNoop(mock, true);
|
2010-05-18 20:41:14 +00:00
|
|
|
|
|
|
|
// Failure
|
|
|
|
mock.expect(getNextTag(false) + " CREATE \\\"&ZeVnLIqe-\\\"",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " nO Can't create folder"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
assertFalse(folder.create(FolderType.HOLDS_MESSAGES));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void testCopy() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
Folder folderTo = mStore.getFolder("\u65E5\u672C\u8A9E");
|
|
|
|
Message[] messages = new Message[] {
|
|
|
|
mFolder.createMessage("11"),
|
|
|
|
mFolder.createMessage("12"),
|
|
|
|
};
|
|
|
|
|
|
|
|
mock.expect(getNextTag(false) + " UID COPY 11\\,12 \\\"&ZeVnLIqe-\\\"",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " oK copy completed"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
mFolder.copyMessages(messages, folderTo, null);
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
// TODO: Test NO response. (src message not found)
|
2010-05-18 20:41:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void testGetUnreadMessageCount() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
mock.expect(getNextTag(false) + " STATUS \\\"" + FOLDER_ENCODED + "\\\" \\(UNSEEN\\)",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* sTATUS \"" + FOLDER_ENCODED + "\" (X 1 uNSEEN 123)",
|
|
|
|
getNextTag(true) + " oK copy completed"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
assertEquals(123, mFolder.getUnreadMessageCount());
|
|
|
|
}
|
|
|
|
|
|
|
|
public void testExpunge() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
mock.expect(getNextTag(false) + " EXPUNGE",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " oK success"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
mFolder.expunge();
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
// TODO: Test NO response. (permission denied)
|
2010-05-18 20:41:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void testSetFlags() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
Message[] messages = new Message[] {
|
|
|
|
mFolder.createMessage("11"),
|
|
|
|
mFolder.createMessage("12"),
|
|
|
|
};
|
|
|
|
|
|
|
|
// Set
|
|
|
|
mock.expect(
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(false) + " UID STORE 11\\,12 \\+FLAGS.SILENT \\(\\\\FLAGGED \\\\SEEN\\)",
|
2010-05-18 20:41:14 +00:00
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " oK success"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
mFolder.setFlags(messages, new Flag[] {Flag.FLAGGED, Flag.SEEN}, true);
|
|
|
|
|
|
|
|
// Clear
|
|
|
|
mock.expect(
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(false) + " UID STORE 11\\,12 \\-FLAGS.SILENT \\(\\\\DELETED\\)",
|
2010-05-18 20:41:14 +00:00
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " oK success"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
mFolder.setFlags(messages, new Flag[] {Flag.DELETED}, false);
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
// TODO: Test NO response. (src message not found)
|
2010-05-18 20:41:14 +00:00
|
|
|
}
|
|
|
|
|
2010-08-11 21:39:45 +00:00
|
|
|
public void testSearchForUids() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
// Single results
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH X",
|
|
|
|
new String[] {
|
|
|
|
"* sEARCH 1",
|
|
|
|
getNextTag(true) + " oK success"
|
|
|
|
});
|
|
|
|
MoreAsserts.assertEquals(new String[] {
|
|
|
|
"1"
|
|
|
|
}, mFolder.searchForUids("X"));
|
|
|
|
|
|
|
|
// Multiple results, including SEARCH with no UIDs.
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH UID 123",
|
|
|
|
new String[] {
|
|
|
|
"* sEARCH 123 4 567",
|
|
|
|
"* search",
|
|
|
|
"* sEARCH 0",
|
|
|
|
"* SEARCH",
|
|
|
|
"* sEARCH 100 200 300",
|
|
|
|
getNextTag(true) + " oK success"
|
|
|
|
});
|
|
|
|
MoreAsserts.assertEquals(new String[] {
|
|
|
|
"123", "4", "567", "0", "100", "200", "300"
|
|
|
|
}, mFolder.searchForUids("UID 123"));
|
|
|
|
|
|
|
|
// NO result
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH SOME CRITERIA",
|
|
|
|
new String[] {
|
|
|
|
getNextTag(true) + " nO not found"
|
|
|
|
});
|
|
|
|
MoreAsserts.assertEquals(new String[] {
|
|
|
|
}, mFolder.searchForUids("SOME CRITERIA"));
|
|
|
|
|
|
|
|
// OK result, but result is empty. (Probably against RFC)
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH SOME CRITERIA",
|
|
|
|
new String[] {
|
|
|
|
getNextTag(true) + " oK success"
|
|
|
|
});
|
|
|
|
MoreAsserts.assertEquals(new String[] {
|
|
|
|
}, mFolder.searchForUids("SOME CRITERIA"));
|
|
|
|
|
|
|
|
// OK result with empty search response.
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH SOME CRITERIA",
|
|
|
|
new String[] {
|
|
|
|
"* search",
|
|
|
|
getNextTag(true) + " oK success"
|
|
|
|
});
|
|
|
|
MoreAsserts.assertEquals(new String[] {
|
|
|
|
}, mFolder.searchForUids("SOME CRITERIA"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-18 20:41:14 +00:00
|
|
|
public void testGetMessage() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
// Found
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH UID 123",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* sEARCH 123",
|
|
|
|
getNextTag(true) + " oK success"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
assertEquals("123", mFolder.getMessage("123").getUid());
|
|
|
|
|
|
|
|
// Not found
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH UID 123",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " nO not found"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
assertNull(mFolder.getMessage("123"));
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Test for getMessages(int, int, MessageRetrievalListener) */
|
|
|
|
public void testGetMessages1() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
// Found
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH 3:5 NOT DELETED",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* sEARCH 3 4",
|
|
|
|
getNextTag(true) + " oK success"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
checkMessageUids(new String[] {"3", "4"}, mFolder.getMessages(3, 5, null));
|
|
|
|
|
|
|
|
// Not found
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH 3:5 NOT DELETED",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
getNextTag(true) + " nO not found"
|
2010-05-18 20:41:14 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
checkMessageUids(new String[] {}, mFolder.getMessages(3, 5, null));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test for getMessages(String[] uids, MessageRetrievalListener) where uids != null.
|
|
|
|
* (testGetMessages3() covers the case where uids == null.)
|
|
|
|
*/
|
|
|
|
public void testGetMessages2() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
// No command will be sent
|
|
|
|
checkMessageUids(new String[] {"3", "4", "5"},
|
|
|
|
mFolder.getMessages(new String[] {"3", "4", "5"}, null));
|
|
|
|
|
|
|
|
checkMessageUids(new String[] {},
|
|
|
|
mFolder.getMessages(new String[] {}, null));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test for getMessages(MessageRetrievalListener), which is the same as
|
|
|
|
* getMessages(String[] uids, MessageRetrievalListener) where uids == null.
|
|
|
|
*/
|
|
|
|
public void testGetMessages3() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
mock.expect(
|
|
|
|
getNextTag(false) + " UID SEARCH 1:\\* NOT DELETED",
|
|
|
|
new String[] {
|
2010-05-29 00:34:47 +00:00
|
|
|
"* sEARCH 3 4 5",
|
2010-05-18 20:41:14 +00:00
|
|
|
getNextTag(true) + " OK success"
|
|
|
|
});
|
|
|
|
checkMessageUids(new String[] {"3", "4", "5"},
|
|
|
|
mFolder.getMessages(null));
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void checkMessageUids(String[] expectedUids, Message[] actualMessages) {
|
|
|
|
ArrayList<String> list = new ArrayList<String>();
|
|
|
|
for (Message m : actualMessages) {
|
|
|
|
list.add(m.getUid());
|
|
|
|
}
|
|
|
|
MoreAsserts.assertEquals(expectedUids, list.toArray(new String[0]) );
|
|
|
|
}
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
/**
|
2011-01-05 04:21:15 +00:00
|
|
|
* Test for {@link ImapStore#getConnection}
|
2010-05-19 00:22:28 +00:00
|
|
|
*/
|
|
|
|
public void testGetConnection() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
|
|
|
|
// Start: No pooled connections.
|
|
|
|
assertEquals(0, mStore.getConnectionPoolForTest().size());
|
|
|
|
|
|
|
|
// Get 1st connection.
|
|
|
|
final ImapConnection con1 = mStore.getConnection();
|
|
|
|
assertNotNull(con1);
|
|
|
|
assertEquals(0, mStore.getConnectionPoolForTest().size()); // Pool size not changed.
|
|
|
|
assertFalse(con1.isTransportOpenForTest()); // Transport not open yet.
|
|
|
|
|
|
|
|
// Open con1
|
2010-05-20 00:23:23 +00:00
|
|
|
expectLogin(mock);
|
2010-05-19 00:22:28 +00:00
|
|
|
con1.open();
|
|
|
|
assertTrue(con1.isTransportOpenForTest());
|
|
|
|
|
|
|
|
// Get 2nd connection.
|
|
|
|
final ImapConnection con2 = mStore.getConnection();
|
|
|
|
assertNotNull(con2);
|
|
|
|
assertEquals(0, mStore.getConnectionPoolForTest().size()); // Pool size not changed.
|
|
|
|
assertFalse(con2.isTransportOpenForTest()); // Transport not open yet.
|
|
|
|
|
|
|
|
// con1 != con2
|
|
|
|
assertNotSame(con1, con2);
|
|
|
|
|
|
|
|
// Open con2
|
2010-05-20 00:23:23 +00:00
|
|
|
expectLogin(mock);
|
2010-05-19 00:22:28 +00:00
|
|
|
con2.open();
|
|
|
|
assertTrue(con1.isTransportOpenForTest());
|
|
|
|
|
|
|
|
// Now we have two open connections: con1 and con2
|
|
|
|
|
|
|
|
// Save con1 in the pool.
|
|
|
|
mStore.poolConnection(con1);
|
|
|
|
assertEquals(1, mStore.getConnectionPoolForTest().size());
|
|
|
|
|
|
|
|
// Get another connection. Should get con1, after verifying the connection.
|
2010-05-29 00:34:47 +00:00
|
|
|
mock.expect(getNextTag(false) + " NOOP", new String[] {getNextTag(true) + " oK success"});
|
2010-05-19 00:22:28 +00:00
|
|
|
|
|
|
|
final ImapConnection con1b = mStore.getConnection();
|
|
|
|
assertEquals(0, mStore.getConnectionPoolForTest().size()); // No connections left in pool
|
|
|
|
assertSame(con1, con1b);
|
|
|
|
assertTrue(con1.isTransportOpenForTest()); // We opened it.
|
|
|
|
|
|
|
|
// Save con2.
|
|
|
|
mStore.poolConnection(con2);
|
|
|
|
assertEquals(1, mStore.getConnectionPoolForTest().size());
|
|
|
|
|
|
|
|
// Try to get connection, but this time, connection gets closed.
|
2010-05-29 00:34:47 +00:00
|
|
|
mock.expect(getNextTag(false) + " NOOP", new String[] {getNextTag(true) + "* bYE bye"});
|
2010-05-19 00:22:28 +00:00
|
|
|
final ImapConnection con3 = mStore.getConnection();
|
|
|
|
assertNotNull(con3);
|
|
|
|
assertEquals(0, mStore.getConnectionPoolForTest().size()); // No connections left in pool
|
|
|
|
|
|
|
|
// It should be a new connection.
|
|
|
|
assertNotSame(con1, con3);
|
|
|
|
assertNotSame(con2, con3);
|
|
|
|
}
|
2010-05-20 00:23:23 +00:00
|
|
|
|
|
|
|
public void testCheckSettings() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
|
|
|
|
expectLogin(mock);
|
|
|
|
mStore.checkSettings();
|
|
|
|
|
2011-01-31 23:10:49 +00:00
|
|
|
expectLogin(mock, false, false,
|
|
|
|
new String[] {"* iD nIL", "oK"}, "nO authentication failed");
|
2010-05-20 00:23:23 +00:00
|
|
|
try {
|
|
|
|
mStore.checkSettings();
|
|
|
|
fail();
|
|
|
|
} catch (MessagingException expected) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compatibility tests...
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Getting an ALERT with a % mark in the message, which crashed the old parser.
|
|
|
|
*/
|
|
|
|
public void testQuotaAlert() throws Exception {
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
expectLogin(mock);
|
|
|
|
|
|
|
|
// Success
|
|
|
|
Folder folder = mStore.getFolder("INBOX");
|
|
|
|
|
|
|
|
// The following response was copied from an actual bug...
|
|
|
|
mock.expect(getNextTag(false) + " SELECT \"INBOX\"", new String[] {
|
|
|
|
"* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen NonJunk $Forwarded Junk" +
|
|
|
|
" $Label4 $Label1 $Label2 $Label3 $Label5 $MDNSent Old)",
|
|
|
|
"* OK [PERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen NonJunk" +
|
|
|
|
" $Forwarded Junk $Label4 $Label1 $Label2 $Label3 $Label5 $MDNSent Old \\*)]",
|
|
|
|
"* 6406 EXISTS",
|
|
|
|
"* 0 RECENT",
|
|
|
|
"* OK [UNSEEN 5338]",
|
|
|
|
"* OK [UIDVALIDITY 1055957975]",
|
|
|
|
"* OK [UIDNEXT 449625]",
|
|
|
|
"* NO [ALERT] Mailbox is at 98% of quota",
|
|
|
|
getNextTag(true) + " OK [READ-WRITE] Completed"});
|
|
|
|
folder.open(OpenMode.READ_WRITE, null); // shouldn't crash.
|
|
|
|
assertEquals(6406, folder.getMessageCount());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Apparently some servers send a size in the wrong format. e.g. 123E
|
|
|
|
*/
|
|
|
|
public void testFetchBodyStructureMalformed() throws Exception {
|
|
|
|
final MockTransport mock = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mock);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
final Message message = mFolder.createMessage("1");
|
|
|
|
|
|
|
|
final FetchProfile fp = new FetchProfile();
|
|
|
|
fp.add(FetchProfile.Item.STRUCTURE);
|
|
|
|
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODYSTRUCTURE\\)",
|
|
|
|
new String[] {
|
|
|
|
"* 9 FETCH (UID 1 BODYSTRUCTURE (\"TEXT\" \"PLAIN\" ()" +
|
|
|
|
" NIL NIL NIL 123E 3))", // 123E isn't a number!
|
|
|
|
getNextTag(true) + " OK SUCCESS"
|
|
|
|
});
|
|
|
|
mFolder.fetch(new Message[] { message }, fp, null);
|
|
|
|
|
|
|
|
// Check mime structure...
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {"text/plain"},
|
|
|
|
message.getHeader("Content-Type")
|
|
|
|
);
|
|
|
|
assertNull(message.getHeader("Content-Transfer-Encoding"));
|
|
|
|
assertNull(message.getHeader("Content-ID"));
|
|
|
|
|
|
|
|
// Doesn't have size=xxx
|
|
|
|
assertNull(message.getHeader("Content-Disposition"));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Folder name with special chars in it.
|
|
|
|
*
|
|
|
|
* Gmail puts the folder name in the OK response, which crashed the old parser if there's a
|
|
|
|
* special char in the folder name.
|
|
|
|
*/
|
|
|
|
public void testFolderNameWithSpecialChars() throws Exception {
|
|
|
|
final String FOLDER_1 = "@u88**%_St";
|
|
|
|
final String FOLDER_1_QUOTED = Pattern.quote(FOLDER_1);
|
|
|
|
final String FOLDER_2 = "folder test_06";
|
|
|
|
|
|
|
|
MockTransport mock = openAndInjectMockTransport();
|
|
|
|
expectLogin(mock);
|
|
|
|
|
|
|
|
// List folders.
|
2011-02-10 21:47:35 +00:00
|
|
|
expectNoop(mock, true);
|
2010-05-20 00:23:23 +00:00
|
|
|
mock.expect(getNextTag(false) + " LIST \"\" \"\\*\"",
|
|
|
|
new String[] {
|
2011-02-10 21:47:35 +00:00
|
|
|
"* LIST () \"/\" \"" + FOLDER_1 + "\"",
|
|
|
|
"* LIST () \"/\" \"" + FOLDER_2 + "\"",
|
|
|
|
getNextTag(true) + " OK SUCCESS"
|
|
|
|
});
|
|
|
|
final Folder[] folders = mStore.getAllFolders();
|
2010-05-20 00:23:23 +00:00
|
|
|
|
|
|
|
ArrayList<String> list = new ArrayList<String>();
|
|
|
|
for (Folder f : folders) {
|
|
|
|
list.add(f.getName());
|
|
|
|
}
|
|
|
|
MoreAsserts.assertEquals(
|
|
|
|
new String[] {FOLDER_1, FOLDER_2, "INBOX"},
|
|
|
|
list.toArray(new String[0])
|
|
|
|
);
|
|
|
|
|
|
|
|
// Try to open the folders.
|
|
|
|
expectNoop(mock, true);
|
|
|
|
mock.expect(getNextTag(false) + " SELECT \"" + FOLDER_1_QUOTED + "\"", new String[] {
|
|
|
|
"* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)",
|
|
|
|
"* OK [PERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen \\*)]",
|
|
|
|
"* 0 EXISTS",
|
|
|
|
"* 0 RECENT",
|
|
|
|
"* OK [UNSEEN 0]",
|
|
|
|
"* OK [UIDNEXT 1]",
|
|
|
|
getNextTag(true) + " OK [READ-WRITE] " + FOLDER_1});
|
|
|
|
folders[0].open(OpenMode.READ_WRITE, null);
|
|
|
|
folders[0].close(false);
|
|
|
|
|
|
|
|
expectNoop(mock, true);
|
|
|
|
mock.expect(getNextTag(false) + " SELECT \"" + FOLDER_2 + "\"", new String[] {
|
|
|
|
"* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)",
|
|
|
|
"* OK [PERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen \\*)]",
|
|
|
|
"* 0 EXISTS",
|
|
|
|
"* 0 RECENT",
|
|
|
|
"* OK [UNSEEN 0]",
|
|
|
|
"* OK [UIDNEXT 1]",
|
|
|
|
getNextTag(true) + " OK [READ-WRITE] " + FOLDER_2});
|
|
|
|
folders[1].open(OpenMode.READ_WRITE, null);
|
|
|
|
folders[1].close(false);
|
|
|
|
}
|
2010-08-05 23:43:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Callback for {@link #runAndExpectMessagingException}.
|
|
|
|
*/
|
|
|
|
private interface RunAndExpectMessagingExceptionTarget {
|
|
|
|
public void run(MockTransport mockTransport) throws Exception;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set up the usual mock transport, open the folder,
|
|
|
|
* run {@link RunAndExpectMessagingExceptionTarget} and make sure a {@link MessagingException}
|
|
|
|
* is thrown.
|
|
|
|
*/
|
|
|
|
private void runAndExpectMessagingException(RunAndExpectMessagingExceptionTarget target)
|
|
|
|
throws Exception {
|
|
|
|
try {
|
|
|
|
final MockTransport mockTransport = openAndInjectMockTransport();
|
|
|
|
setupOpenFolder(mockTransport);
|
|
|
|
mFolder.open(OpenMode.READ_WRITE, null);
|
|
|
|
|
|
|
|
target.run(mockTransport);
|
|
|
|
|
|
|
|
fail("MessagingException expected.");
|
|
|
|
} catch (MessagingException expected) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure that IOExceptions are always converted to MessagingException.
|
|
|
|
*/
|
|
|
|
public void testFetchIOException() throws Exception {
|
|
|
|
runAndExpectMessagingException(new RunAndExpectMessagingExceptionTarget() {
|
|
|
|
public void run(MockTransport mockTransport) throws Exception {
|
|
|
|
mockTransport.expectIOException();
|
|
|
|
|
|
|
|
final Message message = mFolder.createMessage("1");
|
|
|
|
final FetchProfile fp = new FetchProfile();
|
|
|
|
fp.add(FetchProfile.Item.STRUCTURE);
|
|
|
|
|
|
|
|
mFolder.fetch(new Message[] { message }, fp, null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure that IOExceptions are always converted to MessagingException.
|
|
|
|
*/
|
|
|
|
public void testUnreadMessageCountIOException() throws Exception {
|
|
|
|
runAndExpectMessagingException(new RunAndExpectMessagingExceptionTarget() {
|
|
|
|
public void run(MockTransport mockTransport) throws Exception {
|
|
|
|
mockTransport.expectIOException();
|
|
|
|
|
|
|
|
mFolder.getUnreadMessageCount();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure that IOExceptions are always converted to MessagingException.
|
|
|
|
*/
|
|
|
|
public void testCopyMessagesIOException() throws Exception {
|
|
|
|
runAndExpectMessagingException(new RunAndExpectMessagingExceptionTarget() {
|
|
|
|
public void run(MockTransport mockTransport) throws Exception {
|
|
|
|
mockTransport.expectIOException();
|
|
|
|
|
|
|
|
final Message message = mFolder.createMessage("1");
|
|
|
|
final Folder folder = mStore.getFolder("test");
|
|
|
|
|
|
|
|
mFolder.copyMessages(new Message[] { message }, folder, null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure that IOExceptions are always converted to MessagingException.
|
|
|
|
*/
|
|
|
|
public void testSearchForUidsIOException() throws Exception {
|
|
|
|
runAndExpectMessagingException(new RunAndExpectMessagingExceptionTarget() {
|
|
|
|
public void run(MockTransport mockTransport) throws Exception {
|
|
|
|
mockTransport.expectIOException();
|
|
|
|
|
|
|
|
mFolder.getMessage("uid");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure that IOExceptions are always converted to MessagingException.
|
|
|
|
*/
|
|
|
|
public void testExpungeIOException() throws Exception {
|
|
|
|
runAndExpectMessagingException(new RunAndExpectMessagingExceptionTarget() {
|
|
|
|
public void run(MockTransport mockTransport) throws Exception {
|
|
|
|
mockTransport.expectIOException();
|
|
|
|
|
|
|
|
mFolder.expunge();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure that IOExceptions are always converted to MessagingException.
|
|
|
|
*/
|
|
|
|
public void testOpenIOException() throws Exception {
|
|
|
|
runAndExpectMessagingException(new RunAndExpectMessagingExceptionTarget() {
|
|
|
|
public void run(MockTransport mockTransport) throws Exception {
|
|
|
|
mockTransport.expectIOException();
|
|
|
|
final Folder folder = mStore.getFolder("test");
|
|
|
|
folder.open(OpenMode.READ_WRITE, null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2009-03-04 03:32:22 +00:00
|
|
|
}
|