From 29f0638f4d12db2e42fce7b8a74495d6f368417e Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Wed, 11 Aug 2010 14:39:45 -0700 Subject: [PATCH] DO NOT MERGE: Handle multiple IMAP SEARCH results. Apparently IMAP servers may return multiple SEARCH responses for a single SEARCH command, and we need to handle all of them. Before the IMAP rework there was 3 methods that issued the SEARCH command. Two of them ware doing it right, but the other wasn't, which was what I copied from, unfortunately! In case you're wondering, originally the test for this method was done through upper methods, e.g. getMessage(). Bug 2911647 Backport of Ia50072944d5b01c1e59541c3a966067b13910cc4 Change-Id: Iab5d3fa21e403f2e1043990112154fbb72322b02 --- .../android/email/mail/store/ImapStore.java | 14 ++--- .../email/mail/store/ImapStoreUnitTests.java | 61 +++++++++++++++++++ 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/com/android/email/mail/store/ImapStore.java b/src/com/android/email/mail/store/ImapStore.java index c2557fa11..7e2bc8679 100644 --- a/src/com/android/email/mail/store/ImapStore.java +++ b/src/com/android/email/mail/store/ImapStore.java @@ -744,7 +744,7 @@ public class ImapStore extends Store { throw new Error("ImapStore.delete() not yet implemented"); } - private String[] searchForUids(String searchCriteria) + /* package */ String[] searchForUids(String searchCriteria) throws MessagingException { checkOpen(); List responses; @@ -758,29 +758,23 @@ public class ImapStore extends Store { throw ioExceptionHandler(mConnection, ioe); } // S: * SEARCH 2 3 6 + final ArrayList uids = new ArrayList(); for (ImapResponse response : responses) { if (!response.isDataResponse(0, ImapConstants.SEARCH)) { continue; } // Found SEARCH response data - final int count = response.size() - 1; - if (count <= 0) { - return Utility.EMPTY_STRINGS; // ... but no UIDs in it! Return empty array. - } - - ArrayList ret = new ArrayList(count); for (int i = 1; i < response.size(); i++) { ImapString s = response.getStringOrEmpty(i); if (s.isString()) { - ret.add(s.getString()); + uids.add(s.getString()); } } - return ret.toArray(Utility.EMPTY_STRINGS); } + return uids.toArray(Utility.EMPTY_STRINGS); } finally { mConnection.destroyResponses(); } - return Utility.EMPTY_STRINGS; } @Override diff --git a/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java b/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java index 6d6113ac2..fbdbfbe30 100644 --- a/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java +++ b/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java @@ -1264,6 +1264,67 @@ public class ImapStoreUnitTests extends AndroidTestCase { // TODO: Test NO response. (src message not found) } + 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")); + } + + public void testGetMessage() throws Exception { MockTransport mock = openAndInjectMockTransport(); setupOpenFolder(mock);