MimeUtilityTest.java revision 2193962ca2b3157e79f731736afa2a0c972e778a
196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/*
296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * you may not use this file except in compliance with the License.
696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * You may obtain a copy of the License at
796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
1096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * See the License for the specific language governing permissions and
1496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * limitations under the License.
1596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */
1696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
172193962ca2b3157e79f731736afa2a0c972e778aMarc Blankpackage com.android.emailcommon.internet;
1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
192193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.MimeBodyPart;
202193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.MimeHeader;
212193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.MimeUtility;
222193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.TextBody;
232193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.BodyPart;
242193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Message;
252193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.MessageTestUtils;
262193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.MessagingException;
272193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Part;
282193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.MessageTestUtils.MessageBuilder;
292193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.MessageTestUtils.MultipartBuilder;
3096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
3196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.test.suitebuilder.annotation.SmallTest;
3296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
3396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport junit.framework.TestCase;
3496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/**
3696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is a series of unit tests for the MimeUtility class.  These tests must be locally
3796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * complete - no server(s) required.
3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */
3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project@SmallTest
4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpublic class MimeUtilityTest extends TestCase {
4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
428aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /** up arrow, down arrow, left arrow, right arrow */
438aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    private final String SHORT_UNICODE = "\u2191\u2193\u2190\u2192";
448aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    private final String SHORT_UNICODE_ENCODED = "=?UTF-8?B?4oaR4oaT4oaQ4oaS?=";
458aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
46d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    /** dollar and euro sign */
47d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    private final String PADDED2_UNICODE = "$\u20AC";
48d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    private final String PADDED2_UNICODE_ENCODED = "=?UTF-8?B?JOKCrA==?=";
49d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    private final String PADDED1_UNICODE = "$$\u20AC";
50d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    private final String PADDED1_UNICODE_ENCODED = "=?UTF-8?B?JCTigqw=?=";
51d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    private final String PADDED0_UNICODE = "$$$\u20AC";
52d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    private final String PADDED0_UNICODE_ENCODED = "=?UTF-8?B?JCQk4oKs?=";
53d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka
548aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /** a string without any unicode */
558aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    private final String SHORT_PLAIN = "abcd";
568aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
5744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    /** long subject which will be split into two MIME/Base64 chunks */
5844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String LONG_UNICODE_SPLIT =
5944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "$" +
6044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC" +
6144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC";
6244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String LONG_UNICODE_SPLIT_ENCODED =
6344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "=?UTF-8?B?JOKCrOKCrOKCrOKCrOKCrOKCrOKCrOKCrA==?=" + "\r\n " +
6444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "=?UTF-8?B?4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs?=";
6544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka
6644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    /** strings that use supplemental characters and really stress encode/decode */
6744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    // actually it's U+10400
6844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String SHORT_SUPPLEMENTAL = "\uD801\uDC00";
6944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String SHORT_SUPPLEMENTAL_ENCODED = "=?UTF-8?B?8JCQgA==?=";
7044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String LONG_SUPPLEMENTAL = SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL +
7144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL +
7244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL;
7344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String LONG_SUPPLEMENTAL_ENCODED =
7444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "=?UTF-8?B?8JCQgPCQkIDwkJCA8JCQgA==?=" + "\r\n " +
7544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "=?UTF-8?B?8JCQgPCQkIDwkJCA8JCQgPCQkIDwkJCA?=";
7644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String LONG_SUPPLEMENTAL_2 = "a" + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL +
7744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL +
7844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL;
7944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String LONG_SUPPLEMENTAL_ENCODED_2 =
8044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "=?UTF-8?B?YfCQkIDwkJCA8JCQgPCQkIA=?=" + "\r\n " +
8144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "=?UTF-8?B?8JCQgPCQkIDwkJCA8JCQgPCQkIDwkJCA?=";
8244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    // Earth is U+1D300.
8344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String LONG_SUPPLEMENTAL_QP =
8444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "*Monogram for Earth \uD834\uDF00. Monogram for Human \u268b.";
8544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    private final String LONG_SUPPLEMENTAL_QP_ENCODED =
8644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "=?UTF-8?Q?*Monogram_for_Earth_?=" + "\r\n " +
8744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        "=?UTF-8?Q?=F0=9D=8C=80._Monogram_for_Human_=E2=9A=8B.?=";
8844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka
898aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /** a typical no-param header */
9087fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler    private final String HEADER_NO_PARAMETER =
918aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project            "header";
928aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /** a typical multi-param header */
9387fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler    private final String HEADER_MULTI_PARAMETER =
948aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project            "header; Param1Name=Param1Value; Param2Name=Param2Value";
9587fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler    /** a multi-param header with quoting */
9687fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler    private final String HEADER_QUOTED_MULTI_PARAMETER =
9787fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler            "header; Param1Name=\"Param1Value\"; Param2Name=\"Param2Value\"";
9887fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler    /** a malformed header we're seeing in production servers */
9987fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler    private final String HEADER_MALFORMED_PARAMETER =
10087fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler            "header; Param1Name=Param1Value; filename";
101f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler
102f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    /**
103f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     * a string generated by google calendar that contains two interesting gotchas:
104f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     * 1.  Uses windows-1252 encoding, and en-dash recoded appropriately (\u2013 / =96)
105f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     * 2.  Because the first encoded char requires '=XX' encoding, we create an "internal"
106f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     *     "?=" that the decoder must correctly skip over.
107f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     **/
108f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    private final String CALENDAR_SUBJECT_UNICODE =
109f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        "=?windows-1252?Q?=5BReminder=5D_test_=40_Fri_Mar_20_10=3A30am_=96_11am_=28andro?=" +
110f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        "\r\n\t" +
111f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        "=?windows-1252?Q?id=2Etr=40gmail=2Ecom=29?=";
112f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    private final String CALENDAR_SUBJECT_PLAIN =
113f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        "[Reminder] test @ Fri Mar 20 10:30am \u2013 11am (android.tr@gmail.com)";
114f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler
115f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    /**
116f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     * Some basic degenerate strings designed to exercise error handling in the decoder
117f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     */
118f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    private final String CALENDAR_DEGENERATE_UNICODE_1 =
119f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        "=?windows-1252?Q=5B?=";
120f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    private final String CALENDAR_DEGENERATE_UNICODE_2 =
121f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        "=?windows-1252Q?=5B?=";
122f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    private final String CALENDAR_DEGENERATE_UNICODE_3 =
123f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        "=?windows-1252?=";
124f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    private final String CALENDAR_DEGENERATE_UNICODE_4 =
125f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        "=?windows-1252";
1268aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
1278aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /**
1288aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     * Test that decode/unfold is efficient when it can be
1298aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     */
1308aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    public void testEfficientUnfoldAndDecode() {
1318aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        String result1 = MimeUtility.unfold(SHORT_PLAIN);
1328aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        String result2 = MimeUtility.decode(SHORT_PLAIN);
1338aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        String result3 = MimeUtility.unfoldAndDecode(SHORT_PLAIN);
1348aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
1358aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertSame(SHORT_PLAIN, result1);
1368aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertSame(SHORT_PLAIN, result2);
1378aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertSame(SHORT_PLAIN, result3);
1388aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    }
1398aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
1408aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    // TODO:  more tests for unfold(String s)
1418aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
1428aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /**
1438aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     * Test that decode is working for simple strings
1448aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     */
1458aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    public void testDecodeSimple() {
1468aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        String result1 = MimeUtility.decode(SHORT_UNICODE_ENCODED);
1478aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertEquals(SHORT_UNICODE, result1);
1488aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    }
1498aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
15096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    // TODO:  tests for decode(String s)
1518aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
1528aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /**
1538aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     * Test that unfoldAndDecode is working for simple strings
1548aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     */
1558aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    public void testUnfoldAndDecodeSimple() {
1568aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        String result1 = MimeUtility.unfoldAndDecode(SHORT_UNICODE_ENCODED);
1578aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertEquals(SHORT_UNICODE, result1);
1588aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    }
1598aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
160f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    /**
161f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     * test decoding complex string from google calendar that has two gotchas for the decoder.
162f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     * also tests a couple of degenerate cases that should "fail" decoding and pass through.
163f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler     */
164f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    public void testComplexDecode() {
165f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        String result1 = MimeUtility.unfoldAndDecode(CALENDAR_SUBJECT_UNICODE);
166f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        assertEquals(CALENDAR_SUBJECT_PLAIN, result1);
167f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler
168f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        // These degenerate cases should "fail" and return the same string
169f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        String degenerate1 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_1);
170f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        assertEquals("degenerate case 1", CALENDAR_DEGENERATE_UNICODE_1, degenerate1);
171f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        String degenerate2 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_2);
172f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        assertEquals("degenerate case 2", CALENDAR_DEGENERATE_UNICODE_2, degenerate2);
173f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        String degenerate3 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_3);
174f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        assertEquals("degenerate case 3", CALENDAR_DEGENERATE_UNICODE_3, degenerate3);
175f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        String degenerate4 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_4);
176f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler        assertEquals("degenerate case 4", CALENDAR_DEGENERATE_UNICODE_4, degenerate4);
177f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    }
178f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler
179f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler    // TODO:  more tests for unfoldAndDecode(String s)
1808aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
1818aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /**
1828aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     * Test that fold/encode is efficient when it can be
1838aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     */
1848aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    public void testEfficientFoldAndEncode() {
1858aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        String result1 = MimeUtility.foldAndEncode(SHORT_PLAIN);
1868aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        String result2 = MimeUtility.foldAndEncode2(SHORT_PLAIN, 10);
1878aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        String result3 = MimeUtility.fold(SHORT_PLAIN, 10);
1888aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
1898aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertSame(SHORT_PLAIN, result1);
1908aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertSame(SHORT_PLAIN, result2);
1918aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertSame(SHORT_PLAIN, result3);
1928aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    }
1938aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
194d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    /**
195d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka     * Test about base64 padding variety.
196d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka     */
197d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    public void testPaddingOfFoldAndEncode2() {
198d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka        String result1 = MimeUtility.foldAndEncode2(PADDED2_UNICODE, 0);
199d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka        String result2 = MimeUtility.foldAndEncode2(PADDED1_UNICODE, 0);
200d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka        String result3 = MimeUtility.foldAndEncode2(PADDED0_UNICODE, 0);
201d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka
202d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka        assertEquals("padding 2", PADDED2_UNICODE_ENCODED, result1);
203d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka        assertEquals("padding 1", PADDED1_UNICODE_ENCODED, result2);
204d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka        assertEquals("padding 0", PADDED0_UNICODE_ENCODED, result3);
205d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka    }
206d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka
2078aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    // TODO:  more tests for foldAndEncode(String s)
2088aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
2098aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /**
2108aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     * Test that foldAndEncode2 is working for simple strings
2118aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     */
2128aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    public void testFoldAndEncode2() {
2138aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        String result1 = MimeUtility.foldAndEncode2(SHORT_UNICODE, 10);
2148aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertEquals(SHORT_UNICODE_ENCODED, result1);
2158aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    }
2168aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
21744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    /**
21844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     * Test that foldAndEncode2 is working for long strings which needs splitting.
21944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     */
22044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    public void testFoldAndEncode2WithLongSplit() {
22144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        String result = MimeUtility.foldAndEncode2(LONG_UNICODE_SPLIT, "Subject: ".length());
22244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka
22344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        assertEquals("long string", LONG_UNICODE_SPLIT_ENCODED, result);
22444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    }
22544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka
22644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    /**
22744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     * Tests of foldAndEncode2 that involve supplemental characters (UTF-32)
22844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     *
22944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     * Note that the difference between LONG_SUPPLEMENTAL and LONG_SUPPLEMENTAL_2 is the
23044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     * insertion of a single character at the head of the string. This is intended to disrupt
23144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     * the code that splits the long string into multiple encoded words, and confirm that it
23244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     * properly applies the breaks between UTF-32 code points.
23344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     */
23444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    public void testFoldAndEncode2Supplemental() {
23544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        String result1 = MimeUtility.foldAndEncode2(SHORT_SUPPLEMENTAL, "Subject: ".length());
23644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        String result2 = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL, "Subject: ".length());
23744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        String result3 = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL_2, "Subject: ".length());
23844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        assertEquals("short supplemental", SHORT_SUPPLEMENTAL_ENCODED, result1);
23944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        assertEquals("long supplemental", LONG_SUPPLEMENTAL_ENCODED, result2);
24044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        assertEquals("long supplemental 2", LONG_SUPPLEMENTAL_ENCODED_2, result3);
24144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    }
24244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka
24344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    /**
24444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     * Tests of foldAndEncode2 that involve supplemental characters (UTF-32)
24544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     *
24644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     * Note that the difference between LONG_SUPPLEMENTAL and LONG_SUPPLEMENTAL_QP is that
24744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     * the former will be encoded as base64 but the latter will be encoded as quoted printable.
24844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka     */
24944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    public void testFoldAndEncode2SupplementalQuotedPrintable() {
25044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        String result = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL_QP, "Subject: ".length());
25144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka        assertEquals("long supplement quoted printable",
25244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka                     LONG_SUPPLEMENTAL_QP_ENCODED, result);
25344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka    }
25444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka
2558aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    // TODO:  more tests for foldAndEncode2(String s)
2568aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    // TODO:  more tests for fold(String s, int usedCharacters)
2578aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
2588aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    /**
2598aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     * Basic tests of getHeaderParameter()
2608aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     *
2618aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     * Typical header value:  multipart/mixed; boundary="----E5UGTXUQQJV80DR8SJ88F79BRA4S8K"
2628aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     *
2638aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     * Function spec says:
2648aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     *  if header is null:  return null
2658aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     *  if name is null:    if params, return first param.  else return full field
2668aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     *  else:               if param is found (case insensitive) return it
2678aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     *                        else return null
2688aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project     */
2698aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    public void testGetHeaderParameter() {
2708aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        // if header is null, return null
2718aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        assertNull("null header check", MimeUtility.getHeaderParameter(null, "name"));
2728aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
2738aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        // if name is null, return first param or full header
2748aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        // NOTE:  The docs are wrong - it returns the header (no params) in that case
2758aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project//      assertEquals("null name first param per docs", "Param1Value",
2768aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project//              MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, null));
27787fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("null name first param per code", "header",
2788aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, null));
27987fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("null name full header", HEADER_NO_PARAMETER,
2808aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project                MimeUtility.getHeaderParameter(HEADER_NO_PARAMETER, null));
2818aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
2828aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        // find name
28387fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("get 1st param", "Param1Value",
2848aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param1Name"));
28587fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("get 2nd param", "Param2Value",
2868aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param2Name"));
28787fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("get missing param", null,
2888aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param3Name"));
2898aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
2908aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project        // case insensitivity
29187fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("get 2nd param all LC", "Param2Value",
2928aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "param2name"));
29387fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("get 2nd param all UC", "Param2Value",
2948aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "PARAM2NAME"));
29587fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler
29687fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        // quoting
29787fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("get 1st param", "Param1Value",
29887fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler                MimeUtility.getHeaderParameter(HEADER_QUOTED_MULTI_PARAMETER, "Param1Name"));
29987fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("get 2nd param", "Param2Value",
30087fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler                MimeUtility.getHeaderParameter(HEADER_QUOTED_MULTI_PARAMETER, "Param2Name"));
30187fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler
30287fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        // Don't fail when malformed
30387fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler        assertEquals("malformed filename param", null,
30487fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler                MimeUtility.getHeaderParameter(HEADER_MALFORMED_PARAMETER, "filename"));
3058aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project    }
3068aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project
30796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    // TODO:  tests for findFirstPartByMimeType(Part part, String mimeType)
3083469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project
3093469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project    /** Tests for findPartByContentId(Part part, String contentId) */
3103469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project    public void testFindPartByContentIdTestCase() throws MessagingException, Exception {
3113469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        final String cid1 = "cid.1@android.com";
3123469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        final Part cid1bp = MessageTestUtils.bodyPart("image/gif", cid1);
3133469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        final String cid2 = "cid.2@android.com";
3143469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        final Part cid2bp = MessageTestUtils.bodyPart("image/gif", "<" + cid2 + ">");
3153469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project
3163469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        final Message msg1 = new MessageBuilder()
3173469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project            .setBody(new MultipartBuilder("multipart/related")
3183469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                 .addBodyPart(MessageTestUtils.bodyPart("text/html", null))
3193469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                 .addBodyPart((BodyPart)cid1bp)
3203469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                 .build())
3213469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project            .build();
3223469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        // found cid1 part
3233469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        final Part actual1_1 = MimeUtility.findPartByContentId(msg1, cid1);
3243469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertEquals("could not found expected content-id part", cid1bp, actual1_1);
3253469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project
3263469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        final Message msg2 = new MessageBuilder()
3273469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project            .setBody(new MultipartBuilder("multipart/mixed")
3283469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                .addBodyPart(MessageTestUtils.bodyPart("image/tiff", "cid.4@android.com"))
3293469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                .addBodyPart(new MultipartBuilder("multipart/related")
3303469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                    .addBodyPart(new MultipartBuilder("multipart/alternative")
3313469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                        .addBodyPart(MessageTestUtils.bodyPart("text/plain", null))
3323469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                        .addBodyPart(MessageTestUtils.bodyPart("text/html", null))
3333469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                        .buildBodyPart())
3343469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                    .addBodyPart((BodyPart)cid1bp)
3353469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                    .buildBodyPart())
3363469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                .addBodyPart(MessageTestUtils.bodyPart("image/gif", "cid.3@android.com"))
3373469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                .addBodyPart((BodyPart)cid2bp)
3383469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project                .build())
3393469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project            .build();
3403469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        // found cid1 part
3413469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        final Part actual2_1 = MimeUtility.findPartByContentId(msg2, cid1);
3423469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertEquals("found part from related multipart", cid1bp, actual2_1);
3433469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project
3443469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        // found cid2 part
3453469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        final Part actual2_2 = MimeUtility.findPartByContentId(msg2, cid2);
3463469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertEquals("found part from mixed multipart", cid2bp, actual2_2);
3473469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project    }
34896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
34996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /** Tests for getTextFromPart(Part part) */
35096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testGetTextFromPartContentTypeCase() throws MessagingException {
35196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        final String theText = "This is the text of the part";
35296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        TextBody tb = new TextBody(theText);
35396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MimeBodyPart p = new MimeBodyPart();
35496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
35596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 1. test basic text/plain mode
35696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/plain");
35796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        p.setBody(tb);
35896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String gotText = MimeUtility.getTextFromPart(p);
35996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(theText, gotText);
36096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
36196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 2. mixed case is OK
36296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/PLAIN");
36396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        p.setBody(tb);
36496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        gotText = MimeUtility.getTextFromPart(p);
36596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(theText, gotText);
36696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
36796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 3. wildcards OK
36896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/other");
36996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        p.setBody(tb);
37096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        gotText = MimeUtility.getTextFromPart(p);
37196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(theText, gotText);
37296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
3732517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
3742517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn    /** Test for usage of Content-Type in getTextFromPart(Part part).
3752517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *
3762517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     * For example 'Content-Type: text/html; charset=utf-8'
3772517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *
3782517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *  If the body part has no mime-type, refuses to parse content as text.
3792517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *  If the mime-type does not match text/*, it will not get parsed.
3802517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *  Then, the charset parameter is used, with a default of ASCII.
3812517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *
3822517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *  This test works by using a string that is valid Unicode, and is also
3832517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *  valid when decoded from UTF-8 bytes into Windows-1252 (so that
3842517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *  auto-detection is not possible), and checks that the correct conversion
3852517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *  was made, based on the Content-Type header.
3862517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     *
3872517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn     */
3882517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn    public void testContentTypeCharset() throws MessagingException {
3892517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        final String UNICODE_EXPECT = "This is some happy unicode text \u263a";
3902517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // What you get if you encode to UTF-8 (\xe2\x98\xba) and reencode with Windows-1252
3912517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        final String WINDOWS1252_EXPECT = "This is some happy unicode text \u00e2\u02dc\u00ba";
3922517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        TextBody tb = new TextBody(UNICODE_EXPECT);
3932517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        MimeBodyPart p = new MimeBodyPart();
3942517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
3952517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        String gotText, mimeType, charset;
3962517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // TEST 0: Standard Content-Type header; no extraneous spaces or fields
3972517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setBody(tb);
3982517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // We call setHeader after setBody, since setBody overwrites Content-Type
3992517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/html; charset=utf-8");
4002517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        gotText = MimeUtility.getTextFromPart(p);
4012517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html"));
4022517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertEquals(UNICODE_EXPECT, gotText);
4032517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
4042517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setBody(tb);
4052517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/html; charset=windows-1252");
4062517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        gotText = MimeUtility.getTextFromPart(p);
4072517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html"));
4082517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertEquals(WINDOWS1252_EXPECT, gotText);
4092517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
4102517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // TEST 1: Extra fields and quotes in Content-Type (from RFC 2045)
4112517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setBody(tb);
4122517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
4132517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn                    "text/html; prop1 = \"test\"; charset = \"utf-8\"; prop2 = \"test\"");
4142517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        gotText = MimeUtility.getTextFromPart(p);
4152517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html"));
4162517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertEquals(UNICODE_EXPECT, gotText);
4172517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
4182517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setBody(tb);
4192517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
4202517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn                    "text/html; prop1 = \"test\"; charset = \"windows-1252\"; prop2 = \"test\"");
4212517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        gotText = MimeUtility.getTextFromPart(p);
4222517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html"));
4232517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertEquals(WINDOWS1252_EXPECT, gotText);
4242517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
4252517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // TEST 2: Mixed case in Content-Type header:
4262517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // RFC 2045 says that content types, subtypes and parameter names
4272517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // are case-insensitive.
4282517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
4292517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setBody(tb);
4302517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/HtmL ; CHARseT=utf-8");
4312517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        gotText = MimeUtility.getTextFromPart(p);
4322517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html"));
4332517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertEquals(UNICODE_EXPECT, gotText);
4342517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
4352517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setBody(tb);
4362517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/HtmL ; CHARseT=windows-1252");
4372517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        gotText = MimeUtility.getTextFromPart(p);
4382517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html"));
4392517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertEquals(WINDOWS1252_EXPECT, gotText);
4402517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
4412517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // TEST 3: Comments in Content-Type header field (from RFC 2045)
4422517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // Thunderbird permits comments after the end of a parameter, as in this example.
4432517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // Not something that I have seen in the real world outside RFC 2045.
4442517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
4452517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setBody(tb);
4462517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
4472517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn                    "text/html; charset=utf-8 (Plain text)");
4482517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        gotText = MimeUtility.getTextFromPart(p);
4492517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html"));
4502517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // Note: This test does not pass.
4512517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        //assertEquals(UNICODE_EXPECT, gotText);
4522517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn
4532517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setBody(tb);
4542517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
4552517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn                    "text/html; charset=windows-1252 (Plain text)");
4562517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        gotText = MimeUtility.getTextFromPart(p);
4572517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html"));
4582517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        // Note: These tests does not pass.
4592517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn        //assertEquals(WINDOWS1252_EXPECT, gotText);
4602517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn    }
46196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
46296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /** Tests for various aspects of mimeTypeMatches(String mimeType, String matchAgainst) */
46396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testMimeTypeMatches() {
46496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 1. No match
46596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "TEXT/PLAIN"));
46696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
46796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 2. Match
46896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/plain"));
46996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
47096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 3. Match (mixed case)
47196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "TEXT/PLAIN"));
47296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(MimeUtility.mimeTypeMatches("TEXT/PLAIN", "text/plain"));
47396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
47496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 4. Match (wildcards)
47596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/plain"));
47696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/*"));
47796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/*"));
47896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
47996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 5. No Match (wildcards)
48096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "*/plain"));
48196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "text/*"));
48296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
48396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
48496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /** Tests for various aspects of mimeTypeMatches(String mimeType, String[] matchAgainst) */
48596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testMimeTypeMatchesArray() {
48696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 1. Zero-length array
48796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String[] arrayZero = new String[0];
48896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(MimeUtility.mimeTypeMatches("text/plain", arrayZero));
48996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
49096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 2. Single entry, no match
49196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String[] arrayOne = new String[] { "text/plain" };
49296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayOne));
49396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
49496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 3. Single entry, match
49596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayOne));
49696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
49796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 4. Multi entry, no match
49896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String[] arrayTwo = new String[] { "text/plain", "match/this" };
49996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayTwo));
50096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
50196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 5. Multi entry, match first
50296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayTwo));
50396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
50496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // 6. Multi entry, match not first
50596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(MimeUtility.mimeTypeMatches("match/this", arrayTwo));
50696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
50796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
50896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    // TODO:  tests for decodeBody(InputStream in, String contentTransferEncoding)
50996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    // TODO:  tests for collectParts(Part part, ArrayList<Part> viewables, ArrayList<Part> attachments)
5103469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project
51196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project}
512