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
This commit is contained in:
Makoto Onuki 2010-08-11 14:39:45 -07:00
parent 8aa79ba695
commit 29f0638f4d
2 changed files with 65 additions and 10 deletions

View File

@ -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<ImapResponse> responses;
@ -758,29 +758,23 @@ public class ImapStore extends Store {
throw ioExceptionHandler(mConnection, ioe);
}
// S: * SEARCH 2 3 6
final ArrayList<String> uids = new ArrayList<String>();
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<String> ret = new ArrayList<String>(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

View File

@ -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);