replicant-packages_apps_Email/tests/src/com/android/email/mail/store/imap/ImapResponseParserTest.java

402 lines
14 KiB
Java

/*
* Copyright (C) 2010 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.imap;
import static com.android.email.mail.store.imap.ImapTestUtils.assertElement;
import static com.android.email.mail.store.imap.ImapTestUtils.buildList;
import static com.android.email.mail.store.imap.ImapTestUtils.buildResponse;
import static com.android.email.mail.store.imap.ImapTestUtils.createFixedLengthInputStream;
import com.android.email.Email;
import com.android.email.Utility;
import com.android.email.mail.store.imap.ImapMemoryLiteral;
import com.android.email.mail.store.imap.ImapResponse;
import com.android.email.mail.store.imap.ImapResponseParser;
import com.android.email.mail.store.imap.ImapSimpleString;
import com.android.email.mail.store.imap.ImapString;
import com.android.email.mail.store.imap.ImapTempFileLiteral;
import com.android.email.mail.store.imap.ImapResponseParser.ByeException;
import com.android.email.mail.transport.DiscourseLogger;
import com.android.emailcommon.mail.MessagingException;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@SmallTest
public class ImapResponseParserTest extends AndroidTestCase {
private static ImapResponseParser generateParser(int literalKeepInMemoryThreshold,
String responses) {
return new ImapResponseParser(new ByteArrayInputStream(Utility.toAscii(responses)),
new DiscourseLogger(4), literalKeepInMemoryThreshold);
}
@Override
protected void setUp() throws Exception {
super.setUp();
Email.setTempDirectory(getContext());
}
public void testExpect() throws Exception {
final ImapResponseParser p = generateParser(100000, "abc");
p.expect('a');
p.expect('b');
try {
p.expect('C');
fail();
} catch (IOException e) {
// OK
}
}
public void testreadUntil() throws Exception {
final ImapResponseParser p = generateParser(100000, "!ab!c!!def!");
assertEquals("", p.readUntil('!'));
assertEquals("ab", p.readUntil('!'));
assertEquals("c", p.readUntil('!'));
assertEquals("", p.readUntil('!'));
assertEquals("def", p.readUntil('!'));
}
public void testBasic() throws Exception {
ImapResponse r;
final ImapResponseParser p = generateParser(100000,
"* STATUS \"INBOX\" (UNSEEN 2)\r\n" +
"100 OK STATUS completed\r\n" +
"+ continuation request+(\r\n" +
"* STATUS {5}\r\n" +
"IN%OX (UNSEEN 10) \"a b c\"\r\n" +
"101 OK STATUS completed %!(\r\n" +
"102 OK 1\r\n" +
"* 1 FETCH\r\n" +
"103 OK\r\n" + // shortest OK
"* a\r\n" // shortest response
);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("STATUS"),
new ImapSimpleString("INBOX"),
buildList(
new ImapSimpleString("UNSEEN"),
new ImapSimpleString("2")
)
), r);
r = p.readResponse();
assertElement(buildResponse("100", false,
new ImapSimpleString("OK"),
new ImapSimpleString("STATUS completed") // one string
), r);
r = p.readResponse();
assertElement(buildResponse(null, true,
new ImapSimpleString("continuation request+(") // one string
), r);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("STATUS"),
new ImapMemoryLiteral(createFixedLengthInputStream("IN%OX")),
buildList(
new ImapSimpleString("UNSEEN"),
new ImapSimpleString("10")
),
new ImapSimpleString("a b c")
), r);
r = p.readResponse();
assertElement(buildResponse("101", false,
new ImapSimpleString("OK"),
new ImapSimpleString("STATUS completed %!(") // one string
), r);
r = p.readResponse();
assertElement(buildResponse("102", false,
new ImapSimpleString("OK"),
new ImapSimpleString("1")
), r);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("1"),
new ImapSimpleString("FETCH")
), r);
r = p.readResponse();
assertElement(buildResponse("103", false,
new ImapSimpleString("OK")
), r);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("a")
), r);
}
public void testNil() throws Exception {
ImapResponse r;
final ImapResponseParser p = generateParser(100000,
"* nil nil NIL \"NIL\" {3}\r\n" +
"NIL\r\n"
);
r = p.readResponse();
assertElement(buildResponse(null, false,
ImapString.EMPTY,
ImapString.EMPTY,
ImapString.EMPTY,
new ImapSimpleString("NIL"),
new ImapMemoryLiteral(createFixedLengthInputStream("NIL"))
), r);
}
public void testBareLf() throws Exception {
ImapResponse r;
// Threshold = 3 bytes: use in memory literal.
ImapResponseParser p = generateParser(3,
"* a b\n" + // Bare LF -- should be treated like CRLF
"* x y\r\n"
);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("a"),
new ImapSimpleString("b")
), r);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("x"),
new ImapSimpleString("y")
), r);
}
public void testLiteral() throws Exception {
ImapResponse r;
// Threshold = 3 bytes: use in memory literal.
ImapResponseParser p = generateParser(3,
"* test {3}\r\n" +
"ABC\r\n"
);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("test"),
new ImapMemoryLiteral(createFixedLengthInputStream("ABC"))
), r);
// Threshold = 2 bytes: use temp file literal.
p = generateParser(2,
"* test {3}\r\n" +
"ABC\r\n"
);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("test"),
new ImapTempFileLiteral(createFixedLengthInputStream("ABC"))
), r);
// 2 literals in a line
p = generateParser(0,
"* test {3}\r\n" +
"ABC {4}\r\n" +
"wxyz\r\n"
);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("test"),
new ImapTempFileLiteral(createFixedLengthInputStream("ABC")),
new ImapTempFileLiteral(createFixedLengthInputStream("wxyz"))
), r);
}
public void testAlert() throws Exception {
ImapResponse r;
final ImapResponseParser p = generateParser(100000,
"* OK [ALERT]\r\n" + // No message
"* OK [ALERT] alert ( message ) %*\r\n" +
"* OK [ABC] not alert\r\n"
);
r = p.readResponse();
assertTrue(r.isOk());
assertTrue(r.getAlertTextOrEmpty().isEmpty());
r = p.readResponse();
assertTrue(r.isOk());
assertEquals("alert ( message ) %*", r.getAlertTextOrEmpty().getString());
r = p.readResponse();
assertTrue(r.isOk());
assertTrue(r.getAlertTextOrEmpty().isEmpty());
}
/**
* If a [ appears in the middle of a string, the following string until the next ']' will
* be considered a part of the string.
*/
public void testBracket() throws Exception {
ImapResponse r;
final ImapResponseParser p = generateParser(100000,
"* AAA BODY[HEADER.FIELDS (\"DATE\" \"SUBJECT\")]\r\n" +
"* BBB B[a b c]d e f\r\n"
);
r = p.readResponse();
assertEquals("BODY[HEADER.FIELDS (\"DATE\" \"SUBJECT\")]",
r.getStringOrEmpty(1).getString());
r = p.readResponse();
assertEquals("B[a b c]d", r.getStringOrEmpty(1).getString());
}
public void testNest() throws Exception {
ImapResponse r;
final ImapResponseParser p = generateParser(100000,
"* A (a B () DEF) (a (ab)) ((() ())) ((a) ab) ((x y ZZ) () [] [A B] (A B C))" +
" ([abc] a[abc])\r\n"
);
r = p.readResponse();
assertElement(buildResponse(null, false,
new ImapSimpleString("A"),
buildList(
new ImapSimpleString("a"),
new ImapSimpleString("B"),
buildList(),
new ImapSimpleString("DEF")
),
buildList(
new ImapSimpleString("a"),
buildList(
new ImapSimpleString("ab")
)
),
buildList(
buildList(
buildList(),
buildList()
)
),
buildList(
buildList(
new ImapSimpleString("a")
),
new ImapSimpleString("ab")
),
buildList(
buildList(
new ImapSimpleString("x"),
new ImapSimpleString("y"),
new ImapSimpleString("ZZ")
),
buildList(),
buildList(),
buildList(
new ImapSimpleString("A"),
new ImapSimpleString("B")
),
buildList(
new ImapSimpleString("A"),
new ImapSimpleString("B"),
new ImapSimpleString("C")
)
),
buildList(
buildList(
new ImapSimpleString("abc")
),
new ImapSimpleString("a[abc]")
)
), r);
}
/**
* Parser shouldn't crash for any response. Should just throw IO/MessagingException.
*/
public void testMalformedResponse() throws Exception {
expectMessagingException("");
expectMessagingException("\r");
expectMessagingException("\r\n");
expectMessagingException("*\r\n");
expectMessagingException("1\r\n");
expectMessagingException("* \r\n");
expectMessagingException("1 \r\n");
expectMessagingException("* A (\r\n");
expectMessagingException("* A )\r\n");
expectMessagingException("* A (()\r\n");
expectMessagingException("* A ())\r\n");
expectMessagingException("* A [\r\n");
expectMessagingException("* A ]\r\n");
expectMessagingException("* A [[]\r\n");
expectMessagingException("* A []]\r\n");
expectMessagingException("* A ([)]\r\n");
expectMessagingException("* A");
expectMessagingException("* {3}");
expectMessagingException("* {3}\r\nab");
}
private static void expectMessagingException(String response) throws Exception {
final ImapResponseParser p = generateParser(100000, response);
try {
p.readResponse();
fail("Didn't throw Exception: response='" + response + "'");
} catch (MessagingException ok) {
return;
} catch (IOException ok) {
return;
}
}
// Compatibility tests...
/**
* OK response with a long message that contains special chars. (including tabs)
*/
public void testOkWithLongMessage() throws Exception {
ImapResponse r;
final ImapResponseParser p = generateParser(100000,
"* OK [CAPABILITY IMAP4 IMAP4rev1 LITERAL+ ID STARTTLS AUTH=PLAIN AUTH=LOGIN" +
"AUTH=CRAM-MD5] server.domain.tld\tCyrus IMAP4 v2.3.8-OS X Server 10.5:"
+" \t\t\t9F33 server ready %%\r\n");
assertTrue(p.readResponse().isOk());
}
/** Make sure literals and strings are interchangeable. */
public void testLiteralStringConversion() throws Exception {
ImapResponse r;
final ImapResponseParser p = generateParser(100000,
"* XXX {5}\r\n" +
"a b c\r\n");
assertEquals("a b c", p.readResponse().getStringOrEmpty(1).getString());
}
public void testByeReceived() throws Exception {
final ImapResponseParser p = generateParser(100000,
"* BYE Autologout timer; idle for too long\r\n");
try {
p.readResponse();
fail("Didn't throw ByeException");
} catch (ByeException ok) {
}
}
}