From af6724527e564d35dd27ac35e24dbced554792e5 Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Fri, 2 Apr 2010 11:09:12 -0700 Subject: [PATCH] Added a test for IMAP APPEND It's a preliminary change for IMAP bug fixes. Also, - Fixed a potential bug in ImapFolder.setFlags where it'd throw StringIndexOutOfBoundsException if flags is empty. - Added a generic flag to proguard.flags so that now all methods with the "ForTest" sufix are automatically preserved. Turned out it wasn't needed for this CL, but it should come in handy someday. Bug 2538076 Change-Id: I49a08afc196c7b7f1f30477dfc38ac5381045d84 --- proguard.flags | 5 ++- src/com/android/email/mail/Message.java | 10 ++++- .../android/email/mail/store/ImapStore.java | 25 ++++++----- .../email/mail/store/ImapStoreUnitTests.java | 44 +++++++++++++++++++ .../email/mail/transport/MockTransport.java | 21 +++++++-- 5 files changed, 89 insertions(+), 16 deletions(-) diff --git a/proguard.flags b/proguard.flags index be627dbbf..bbffc8a54 100644 --- a/proguard.flags +++ b/proguard.flags @@ -26,6 +26,10 @@ # Keep names that are used only by unit tests +-keep class ** { + *** *ForTest(...); +} + -keepclasseswithmembers class com.android.email.GroupMessagingListener { *** removeListener(com.android.email.MessagingListener); } @@ -168,4 +172,3 @@ -keep class org.apache.james.mime4j.message.Message { *; } - diff --git a/src/com/android/email/mail/Message.java b/src/com/android/email/mail/Message.java index 8906caf30..b23633786 100644 --- a/src/com/android/email/mail/Message.java +++ b/src/com/android/email/mail/Message.java @@ -117,7 +117,11 @@ public abstract class Message implements Part, Body { return getFlagSet().toArray(new Flag[] {}); } - public void setFlag(Flag flag, boolean set) throws MessagingException { + /** + * Set/clear a flag directly, without involving overrides of {@link #setFlag} in subclasses. + * Only used for testing. + */ + public final void setFlagDirectlyForTest(Flag flag, boolean set) throws MessagingException { if (set) { getFlagSet().add(flag); } else { @@ -125,6 +129,10 @@ public abstract class Message implements Part, Body { } } + public void setFlag(Flag flag, boolean set) throws MessagingException { + setFlagDirectlyForTest(flag, set); + } + /** * This method calls setFlag(Flag, boolean) * @param flags diff --git a/src/com/android/email/mail/store/ImapStore.java b/src/com/android/email/mail/store/ImapStore.java index 9ec912cfe..b4feb1658 100644 --- a/src/com/android/email/mail/store/ImapStore.java +++ b/src/com/android/email/mail/store/ImapStore.java @@ -1265,22 +1265,26 @@ public class ImapStore extends Store { uidList.append(messages[i].getUid()); } - StringBuilder flagList = new StringBuilder(); - for (int i = 0, count = flags.length; i < count; i++) { - Flag flag = flags[i]; - if (flag == Flag.SEEN) { - flagList.append(" \\Seen"); - } else if (flag == Flag.DELETED) { - flagList.append(" \\Deleted"); - } else if (flag == Flag.FLAGGED) { - flagList.append(" \\Flagged"); + String allFlags = ""; + if (flags.length > 0) { + StringBuilder flagList = new StringBuilder(); + for (int i = 0, count = flags.length; i < count; i++) { + Flag flag = flags[i]; + if (flag == Flag.SEEN) { + flagList.append(" \\Seen"); // TODO this can be a field of Flag... + } else if (flag == Flag.DELETED) { + flagList.append(" \\Deleted"); + } else if (flag == Flag.FLAGGED) { + flagList.append(" \\Flagged"); + } } + allFlags = flagList.substring(1); } try { mConnection.executeSimpleCommand(String.format("UID STORE %s %sFLAGS.SILENT (%s)", uidList, value ? "+" : "-", - flagList.substring(1))); // Remove the first space + allFlags)); } catch (IOException ioe) { throw ioExceptionHandler(mConnection, ioe); @@ -1513,6 +1517,7 @@ public class ImapStore extends Store { this.mSize = size; } + @Override public void parse(InputStream in) throws IOException, MessagingException { super.parse(in); } diff --git a/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java b/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java index 3223099b8..661fe5c1b 100644 --- a/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java +++ b/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java @@ -16,6 +16,7 @@ package com.android.email.mail.store; +import com.android.email.mail.Address; import com.android.email.mail.FetchProfile; import com.android.email.mail.Flag; import com.android.email.mail.Folder; @@ -25,8 +26,11 @@ import com.android.email.mail.Part; import com.android.email.mail.Transport; import com.android.email.mail.Folder.FolderType; import com.android.email.mail.Folder.OpenMode; +import com.android.email.mail.Message.RecipientType; import com.android.email.mail.internet.BinaryTempFileBody; import com.android.email.mail.internet.MimeUtility; +import com.android.email.mail.internet.TextBody; +import com.android.email.mail.store.ImapStore.ImapMessage; import com.android.email.mail.transport.DiscourseLogger; import com.android.email.mail.transport.MockTransport; @@ -48,6 +52,7 @@ import java.util.Locale; */ @SmallTest public class ImapStoreUnitTests extends AndroidTestCase { + private final static String[] NO_REPLY = new String[0]; /* These values are provided by setUp() */ private ImapStore mStore = null; @@ -555,4 +560,43 @@ public class ImapStoreUnitTests extends AndroidTestCase { // And the message is "SEEN". assertTrue(message1.isSet(Flag.SEEN)); } + + public void testAppendMessages() throws Exception { + MockTransport mock = openAndInjectMockTransport(); + setupOpenFolder(mock); + mFolder.open(OpenMode.READ_WRITE, null); + + ImapMessage message = (ImapMessage) mFolder.createMessage("1"); + message.setFrom(new Address("me@test.com")); + message.setRecipient(RecipientType.TO, new Address("you@test.com")); + message.setMessageId(""); + message.setFlagDirectlyForTest(Flag.SEEN, true); + message.setBody(new TextBody("Test Body")); + + // + go ahead + // * 12345 EXISTS + // OK [APPENDUID 627684530 17] (Success) + + mock.expect(getNextTag(false) + " APPEND \\\"INBOX\\\" \\(\\\\Seen\\) \\{166\\}", + new String[] {"+ go ahead"}); + + mock.expectLiterally("From: me@test.com", NO_REPLY); + mock.expectLiterally("To: you@test.com", NO_REPLY); + mock.expectLiterally("Message-ID: ", 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[] { + "* 7 EXISTS", + getNextTag(true) + " OK [APPENDUID 1234567 13] (Success)" + }); + + mFolder.appendMessages(new Message[] {message}); + mock.close(); + + assertEquals("13", message.getUid()); + assertEquals(7, mFolder.getMessageCount()); + } } diff --git a/tests/src/com/android/email/mail/transport/MockTransport.java b/tests/src/com/android/email/mail/transport/MockTransport.java index 3e72cee0a..b1cc3b462 100644 --- a/tests/src/com/android/email/mail/transport/MockTransport.java +++ b/tests/src/com/android/email/mail/transport/MockTransport.java @@ -26,6 +26,9 @@ import java.io.OutputStream; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; +import java.util.regex.Pattern; + +import junit.framework.Assert; /** * This is a mock Transport that is used to test protocols that use MailTransport. @@ -115,7 +118,15 @@ public class MockTransport implements Transport { Transaction pair = new Transaction(pattern, responses); mPairs.add(pair); } - + + /** + * Same as {@link #expect(String, String[])}, but the first arg is taken literally, rather than + * as a regexp. + */ + public void expectLiterally(String literal, String[] responses) { + expect("^" + Pattern.quote(literal) + "$", responses); + } + /** * Tell the Mock Transport that we expect it to be closed. This will preserve * the remaining entries in the expect() stream and allow us to "ride over" the close (which @@ -192,7 +203,7 @@ public class MockTransport implements Transport { } public OutputStream getOutputStream() { - SmtpSenderUnitTests.assertTrue(mOpen); + Assert.assertTrue(mOpen); return new MockOutputStream(); } @@ -302,9 +313,11 @@ public class MockTransport implements Transport { Log.d(LOG_TAG, ">>> " + s); } SmtpSenderUnitTests.assertTrue(mOpen); - SmtpSenderUnitTests.assertTrue("Overflow writing to MockTransport", 0 != mPairs.size()); + SmtpSenderUnitTests.assertTrue("Overflow writing to MockTransport: Getting " + s, + 0 != mPairs.size()); Transaction pair = mPairs.remove(0); - SmtpSenderUnitTests.assertTrue("Unexpected string written to MockTransport", + SmtpSenderUnitTests.assertTrue("Unexpected string written to MockTransport: Actual=" + s + + " Expected=" + pair.mPattern, pair.mPattern != null && s.matches(pair.mPattern)); if (pair.mResponses != null) { sendResponse(pair.mResponses);