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 3339121c758dcc919b5fde4c893d488916e26d3140Todd Kennedyimport java.util.ArrayList; 3439121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy 3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport junit.framework.TestCase; 3696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 3796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/** 3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is a series of unit tests for the MimeUtility class. These tests must be locally 3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * complete - no server(s) required. 4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project@SmallTest 4296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpublic class MimeUtilityTest extends TestCase { 4396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 448aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** up arrow, down arrow, left arrow, right arrow */ 458aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project private final String SHORT_UNICODE = "\u2191\u2193\u2190\u2192"; 468aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project private final String SHORT_UNICODE_ENCODED = "=?UTF-8?B?4oaR4oaT4oaQ4oaS?="; 477037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 48d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka /** dollar and euro sign */ 49d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka private final String PADDED2_UNICODE = "$\u20AC"; 50d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka private final String PADDED2_UNICODE_ENCODED = "=?UTF-8?B?JOKCrA==?="; 51d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka private final String PADDED1_UNICODE = "$$\u20AC"; 52d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka private final String PADDED1_UNICODE_ENCODED = "=?UTF-8?B?JCTigqw=?="; 53d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka private final String PADDED0_UNICODE = "$$$\u20AC"; 54d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka private final String PADDED0_UNICODE_ENCODED = "=?UTF-8?B?JCQk4oKs?="; 55d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka 568aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** a string without any unicode */ 578aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project private final String SHORT_PLAIN = "abcd"; 587037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 5944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka /** long subject which will be split into two MIME/Base64 chunks */ 6044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String LONG_UNICODE_SPLIT = 6144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka "$" + 6244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka "\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC" + 6344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka "\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC"; 6444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String LONG_UNICODE_SPLIT_ENCODED = 6544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka "=?UTF-8?B?JOKCrOKCrOKCrOKCrOKCrOKCrOKCrOKCrA==?=" + "\r\n " + 6644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka "=?UTF-8?B?4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs?="; 6744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka 6844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka /** strings that use supplemental characters and really stress encode/decode */ 6944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka // actually it's U+10400 7044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String SHORT_SUPPLEMENTAL = "\uD801\uDC00"; 7144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String SHORT_SUPPLEMENTAL_ENCODED = "=?UTF-8?B?8JCQgA==?="; 7244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String LONG_SUPPLEMENTAL = SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + 7344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + 7444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL; 7544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String LONG_SUPPLEMENTAL_ENCODED = 767037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie "=?UTF-8?B?8JCQgPCQkIDwkJCA8JCQgA==?=" + "\r\n " + 7744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka "=?UTF-8?B?8JCQgPCQkIDwkJCA8JCQgPCQkIDwkJCA?="; 7844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String LONG_SUPPLEMENTAL_2 = "a" + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + 7944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + 8044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL; 8144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String LONG_SUPPLEMENTAL_ENCODED_2 = 8244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka "=?UTF-8?B?YfCQkIDwkJCA8JCQgPCQkIA=?=" + "\r\n " + 837037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie "=?UTF-8?B?8JCQgPCQkIDwkJCA8JCQgPCQkIDwkJCA?="; 8444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka // Earth is U+1D300. 8544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String LONG_SUPPLEMENTAL_QP = 867037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie "*Monogram for Earth \uD834\uDF00. Monogram for Human \u268b."; 8744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka private final String LONG_SUPPLEMENTAL_QP_ENCODED = 8844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka "=?UTF-8?Q?*Monogram_for_Earth_?=" + "\r\n " + 8944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka "=?UTF-8?Q?=F0=9D=8C=80._Monogram_for_Human_=E2=9A=8B.?="; 9044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka 918aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** a typical no-param header */ 9287fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler private final String HEADER_NO_PARAMETER = 938aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project "header"; 948aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** a typical multi-param header */ 9587fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler private final String HEADER_MULTI_PARAMETER = 968aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project "header; Param1Name=Param1Value; Param2Name=Param2Value"; 9787fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler /** a multi-param header with quoting */ 9887fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler private final String HEADER_QUOTED_MULTI_PARAMETER = 9987fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler "header; Param1Name=\"Param1Value\"; Param2Name=\"Param2Value\""; 10087fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler /** a malformed header we're seeing in production servers */ 10187fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler private final String HEADER_MALFORMED_PARAMETER = 10287fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler "header; Param1Name=Param1Value; filename"; 1037037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 104f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler /** 105f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler * a string generated by google calendar that contains two interesting gotchas: 106f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler * 1. Uses windows-1252 encoding, and en-dash recoded appropriately (\u2013 / =96) 107f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler * 2. Because the first encoded char requires '=XX' encoding, we create an "internal" 108f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler * "?=" that the decoder must correctly skip over. 109f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler **/ 1107037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie private final String CALENDAR_SUBJECT_UNICODE = 111f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler "=?windows-1252?Q?=5BReminder=5D_test_=40_Fri_Mar_20_10=3A30am_=96_11am_=28andro?=" + 112f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler "\r\n\t" + 113f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler "=?windows-1252?Q?id=2Etr=40gmail=2Ecom=29?="; 114f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler private final String CALENDAR_SUBJECT_PLAIN = 115f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler "[Reminder] test @ Fri Mar 20 10:30am \u2013 11am (android.tr@gmail.com)"; 1167037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 117f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler /** 118f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler * Some basic degenerate strings designed to exercise error handling in the decoder 119f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler */ 120f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler private final String CALENDAR_DEGENERATE_UNICODE_1 = 121f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler "=?windows-1252?Q=5B?="; 122f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler private final String CALENDAR_DEGENERATE_UNICODE_2 = 123f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler "=?windows-1252Q?=5B?="; 124f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler private final String CALENDAR_DEGENERATE_UNICODE_3 = 125f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler "=?windows-1252?="; 126f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler private final String CALENDAR_DEGENERATE_UNICODE_4 = 127f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler "=?windows-1252"; 1288aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project 1298aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** 1308aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * Test that decode/unfold is efficient when it can be 1318aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project */ 1328aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project public void testEfficientUnfoldAndDecode() { 1338aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project String result1 = MimeUtility.unfold(SHORT_PLAIN); 1348aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project String result2 = MimeUtility.decode(SHORT_PLAIN); 1358aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project String result3 = MimeUtility.unfoldAndDecode(SHORT_PLAIN); 1367037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 1378aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertSame(SHORT_PLAIN, result1); 1388aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertSame(SHORT_PLAIN, result2); 1398aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertSame(SHORT_PLAIN, result3); 1408aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project } 1418aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project 1428aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project // TODO: more tests for unfold(String s) 1437037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 1448aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** 1458aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * Test that decode is working for simple strings 1468aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project */ 1478aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project public void testDecodeSimple() { 1488aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project String result1 = MimeUtility.decode(SHORT_UNICODE_ENCODED); 1498aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertEquals(SHORT_UNICODE, result1); 1508aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project } 1517037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 15296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // TODO: tests for decode(String s) 1538aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project 1548aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** 1558aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * Test that unfoldAndDecode is working for simple strings 1568aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project */ 1578aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project public void testUnfoldAndDecodeSimple() { 1588aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project String result1 = MimeUtility.unfoldAndDecode(SHORT_UNICODE_ENCODED); 1598aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertEquals(SHORT_UNICODE, result1); 1608aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project } 1617037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 162f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler /** 163f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler * test decoding complex string from google calendar that has two gotchas for the decoder. 164f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler * also tests a couple of degenerate cases that should "fail" decoding and pass through. 165f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler */ 166f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler public void testComplexDecode() { 167f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler String result1 = MimeUtility.unfoldAndDecode(CALENDAR_SUBJECT_UNICODE); 168f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler assertEquals(CALENDAR_SUBJECT_PLAIN, result1); 1697037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 170f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler // These degenerate cases should "fail" and return the same string 171f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler String degenerate1 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_1); 172f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler assertEquals("degenerate case 1", CALENDAR_DEGENERATE_UNICODE_1, degenerate1); 173f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler String degenerate2 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_2); 174f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler assertEquals("degenerate case 2", CALENDAR_DEGENERATE_UNICODE_2, degenerate2); 175f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler String degenerate3 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_3); 176f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler assertEquals("degenerate case 3", CALENDAR_DEGENERATE_UNICODE_3, degenerate3); 177f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler String degenerate4 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_4); 178f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler assertEquals("degenerate case 4", CALENDAR_DEGENERATE_UNICODE_4, degenerate4); 179f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler } 1807037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 181f7eead207407c25b41fe622e9bd4f29a2b50ee7bAndy Stadler // TODO: more tests for unfoldAndDecode(String s) 1828aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project 1838aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** 1848aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * Test that fold/encode is efficient when it can be 1858aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project */ 1868aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project public void testEfficientFoldAndEncode() { 1878aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project String result1 = MimeUtility.foldAndEncode(SHORT_PLAIN); 1888aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project String result2 = MimeUtility.foldAndEncode2(SHORT_PLAIN, 10); 1898aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project String result3 = MimeUtility.fold(SHORT_PLAIN, 10); 1907037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 1918aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertSame(SHORT_PLAIN, result1); 1928aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertSame(SHORT_PLAIN, result2); 1938aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertSame(SHORT_PLAIN, result3); 1948aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project } 1958aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project 196d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka /** 197d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka * Test about base64 padding variety. 198d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka */ 199d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka public void testPaddingOfFoldAndEncode2() { 200d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka String result1 = MimeUtility.foldAndEncode2(PADDED2_UNICODE, 0); 201d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka String result2 = MimeUtility.foldAndEncode2(PADDED1_UNICODE, 0); 202d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka String result3 = MimeUtility.foldAndEncode2(PADDED0_UNICODE, 0); 2037037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 204d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka assertEquals("padding 2", PADDED2_UNICODE_ENCODED, result1); 205d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka assertEquals("padding 1", PADDED1_UNICODE_ENCODED, result2); 206d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka assertEquals("padding 0", PADDED0_UNICODE_ENCODED, result3); 207d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka } 208d351a92869438d937b84c27b026803a92923d1dbTadashi Takaoka 2098aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project // TODO: more tests for foldAndEncode(String s) 2108aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project 2118aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** 2128aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * Test that foldAndEncode2 is working for simple strings 2138aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project */ 2148aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project public void testFoldAndEncode2() { 2158aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project String result1 = MimeUtility.foldAndEncode2(SHORT_UNICODE, 10); 2168aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertEquals(SHORT_UNICODE_ENCODED, result1); 2178aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project } 2187037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 21944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka /** 22044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * Test that foldAndEncode2 is working for long strings which needs splitting. 22144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka */ 22244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka public void testFoldAndEncode2WithLongSplit() { 2237037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie String result = MimeUtility.foldAndEncode2(LONG_UNICODE_SPLIT, "Subject: ".length()); 22444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka 22544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka assertEquals("long string", LONG_UNICODE_SPLIT_ENCODED, result); 22644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka } 2277037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 22844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka /** 22944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * Tests of foldAndEncode2 that involve supplemental characters (UTF-32) 23044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * 23144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * Note that the difference between LONG_SUPPLEMENTAL and LONG_SUPPLEMENTAL_2 is the 23244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * insertion of a single character at the head of the string. This is intended to disrupt 23344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * the code that splits the long string into multiple encoded words, and confirm that it 23444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * properly applies the breaks between UTF-32 code points. 23544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka */ 23644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka public void testFoldAndEncode2Supplemental() { 23744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka String result1 = MimeUtility.foldAndEncode2(SHORT_SUPPLEMENTAL, "Subject: ".length()); 23844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka String result2 = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL, "Subject: ".length()); 23944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka String result3 = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL_2, "Subject: ".length()); 24044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka assertEquals("short supplemental", SHORT_SUPPLEMENTAL_ENCODED, result1); 24144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka assertEquals("long supplemental", LONG_SUPPLEMENTAL_ENCODED, result2); 24244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka assertEquals("long supplemental 2", LONG_SUPPLEMENTAL_ENCODED_2, result3); 24344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka } 24444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka 24544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka /** 24644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * Tests of foldAndEncode2 that involve supplemental characters (UTF-32) 24744cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * 24844cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * Note that the difference between LONG_SUPPLEMENTAL and LONG_SUPPLEMENTAL_QP is that 24944cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka * the former will be encoded as base64 but the latter will be encoded as quoted printable. 25044cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka */ 25144cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka public void testFoldAndEncode2SupplementalQuotedPrintable() { 25244cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka String result = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL_QP, "Subject: ".length()); 25344cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka assertEquals("long supplement quoted printable", 25444cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka LONG_SUPPLEMENTAL_QP_ENCODED, result); 25544cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka } 25644cf2e2882d9d96e6f515c36334cac5ae8e2c305Tadashi Takaoka 2578aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project // TODO: more tests for foldAndEncode2(String s) 2588aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project // TODO: more tests for fold(String s, int usedCharacters) 2597037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 2608aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project /** 2618aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * Basic tests of getHeaderParameter() 2627037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie * 2638aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * Typical header value: multipart/mixed; boundary="----E5UGTXUQQJV80DR8SJ88F79BRA4S8K" 2647037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie * 2658aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * Function spec says: 2668aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * if header is null: return null 2678aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * if name is null: if params, return first param. else return full field 2688aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * else: if param is found (case insensitive) return it 2698aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project * else return null 2708aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project */ 2718aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project public void testGetHeaderParameter() { 2728aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project // if header is null, return null 2738aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project assertNull("null header check", MimeUtility.getHeaderParameter(null, "name")); 2747037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 2758aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project // if name is null, return first param or full header 2768aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project // NOTE: The docs are wrong - it returns the header (no params) in that case 2777037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie// assertEquals("null name first param per docs", "Param1Value", 2788aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project// MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, null)); 27987fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("null name first param per code", "header", 2808aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, null)); 28187fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("null name full header", HEADER_NO_PARAMETER, 2828aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project MimeUtility.getHeaderParameter(HEADER_NO_PARAMETER, null)); 2837037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 2847037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie // find name 28587fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("get 1st param", "Param1Value", 2868aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param1Name")); 28787fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("get 2nd param", "Param2Value", 2888aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param2Name")); 28987fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("get missing param", null, 2908aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param3Name")); 2917037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 2928aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project // case insensitivity 29387fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("get 2nd param all LC", "Param2Value", 2948aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "param2name")); 29587fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("get 2nd param all UC", "Param2Value", 2968aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "PARAM2NAME")); 29787fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler 29887fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler // quoting 29987fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("get 1st param", "Param1Value", 30087fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler MimeUtility.getHeaderParameter(HEADER_QUOTED_MULTI_PARAMETER, "Param1Name")); 30187fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("get 2nd param", "Param2Value", 30287fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler MimeUtility.getHeaderParameter(HEADER_QUOTED_MULTI_PARAMETER, "Param2Name")); 30387fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler 30487fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler // Don't fail when malformed 30587fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler assertEquals("malformed filename param", null, 30687fcd03a1b266d3f6030347143f242b1eb524cf8Andrew Stadler MimeUtility.getHeaderParameter(HEADER_MALFORMED_PARAMETER, "filename")); 3078aeb922462694d22f42c5890e5434e9de9dc3987The Android Open Source Project } 3087037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 30996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // TODO: tests for findFirstPartByMimeType(Part part, String mimeType) 3103469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 3113469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project /** Tests for findPartByContentId(Part part, String contentId) */ 3127037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie public void brokentestCollectParts() throws MessagingException, Exception { 31339121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy // golden cases; these will marked as attachments 31439121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final String cid1 = "<i_12e8248b4f0874cb>"; 31539121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final Part cid1bp = MessageTestUtils.bodyPart("image/gif; name=\"im1.gif\"", cid1); 31639121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final String cid2 = "<ii_12e8248b4f0874cb>"; 31739121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final Part cid2bp = MessageTestUtils.bodyPart("image/gif", cid2); 31839121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy cid2bp.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "inline; filename=\"im2.gif\""); 31939121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final String cid3 = "<iii_12e8248b4f0874cb>"; 32039121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final Part cid3bp = MessageTestUtils.bodyPart("image/gif", cid3); 32139121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy cid3bp.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "attachment; filename=\"im3.gif\""); 32239121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy // error cases; these will NOT be marked as attachments 32339121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final String cid4 = "<iv_12e8248b4f0874cb>"; 32439121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final Part cid4bp = MessageTestUtils.bodyPart("image/gif", cid4); // no name attr 32539121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final String cid5 = "<v_12e8248b4f0874cb>"; 32639121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final Part cid5bp = MessageTestUtils.bodyPart("image/gif", cid5); 32739121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy cid5bp.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "inline"); // no filename attr 32839121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy 32939121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy // Default content disposition 33039121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> view1 = new ArrayList<Part>(); 33139121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> attach1 = new ArrayList<Part>(); 33239121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy MimeUtility.collectParts(cid1bp, view1, attach1); 33339121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy assertEquals(1, attach1.size()); 33439121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy assertEquals(attach1.get(0), cid1bp); 33539121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy 33639121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy // Explicit content disposition of "inline" 33739121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> view2 = new ArrayList<Part>(); 33839121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> attach2 = new ArrayList<Part>(); 33939121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy MimeUtility.collectParts(cid2bp, view2, attach2); 34039121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy assertEquals(1, attach2.size()); 34139121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy assertEquals(attach2.get(0), cid2bp); 34239121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy 34339121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy // Explicit content disposition of "attachment" 34439121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> view3 = new ArrayList<Part>(); 34539121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> attach3 = new ArrayList<Part>(); 34639121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy MimeUtility.collectParts(cid3bp, view3, attach3); 34739121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy assertEquals(1, attach3.size()); 34839121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy assertEquals(attach3.get(0), cid3bp); 34939121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy 35039121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy // Default content disposition; missing name attribute on content-type 35139121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> view4 = new ArrayList<Part>(); 35239121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> attach4 = new ArrayList<Part>(); 35339121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy MimeUtility.collectParts(cid4bp, view4, attach4); 35439121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy assertEquals(0, attach4.size()); 35539121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy 35639121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy // Content disposition of "inline"; missing filename attribute 35739121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> view5 = new ArrayList<Part>(); 35839121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy final ArrayList<Part> attach5 = new ArrayList<Part>(); 35939121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy MimeUtility.collectParts(cid5bp, view5, attach5); 36039121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy assertEquals(0, attach5.size()); 36139121c758dcc919b5fde4c893d488916e26d3140Todd Kennedy } 3627037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 36396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** Tests for getTextFromPart(Part part) */ 36496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void testGetTextFromPartContentTypeCase() throws MessagingException { 36596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project final String theText = "This is the text of the part"; 36696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project TextBody tb = new TextBody(theText); 36796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MimeBodyPart p = new MimeBodyPart(); 3687037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 36996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 1. test basic text/plain mode 37096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/plain"); 37196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project p.setBody(tb); 37296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String gotText = MimeUtility.getTextFromPart(p); 37396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertEquals(theText, gotText); 3747037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 37596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 2. mixed case is OK 37696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/PLAIN"); 37796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project p.setBody(tb); 37896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project gotText = MimeUtility.getTextFromPart(p); 37996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertEquals(theText, gotText); 3807037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 38196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 3. wildcards OK 38296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/other"); 38396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project p.setBody(tb); 38496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project gotText = MimeUtility.getTextFromPart(p); 38596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertEquals(theText, gotText); 38696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 3872517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 3882517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn /** Test for usage of Content-Type in getTextFromPart(Part part). 3897037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie * 3902517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * For example 'Content-Type: text/html; charset=utf-8' 3917037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie * 3922517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * If the body part has no mime-type, refuses to parse content as text. 3932517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * If the mime-type does not match text/*, it will not get parsed. 3942517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * Then, the charset parameter is used, with a default of ASCII. 3952517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * 3962517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * This test works by using a string that is valid Unicode, and is also 3972517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * valid when decoded from UTF-8 bytes into Windows-1252 (so that 3982517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * auto-detection is not possible), and checks that the correct conversion 3992517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * was made, based on the Content-Type header. 4007037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie * 4012517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn */ 4022517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn public void testContentTypeCharset() throws MessagingException { 4032517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn final String UNICODE_EXPECT = "This is some happy unicode text \u263a"; 4042517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // What you get if you encode to UTF-8 (\xe2\x98\xba) and reencode with Windows-1252 4052517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn final String WINDOWS1252_EXPECT = "This is some happy unicode text \u00e2\u02dc\u00ba"; 4062517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn TextBody tb = new TextBody(UNICODE_EXPECT); 4072517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn MimeBodyPart p = new MimeBodyPart(); 4082517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4092517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn String gotText, mimeType, charset; 4102517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // TEST 0: Standard Content-Type header; no extraneous spaces or fields 4112517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setBody(tb); 4122517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // We call setHeader after setBody, since setBody overwrites Content-Type 4132517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/html; charset=utf-8"); 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, "text/html; charset=windows-1252"); 4202517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn gotText = MimeUtility.getTextFromPart(p); 4212517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 4222517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertEquals(WINDOWS1252_EXPECT, gotText); 4232517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4242517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // TEST 1: Extra fields and quotes in Content-Type (from RFC 2045) 4252517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setBody(tb); 4262517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 4272517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "text/html; prop1 = \"test\"; charset = \"utf-8\"; prop2 = \"test\""); 4282517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn gotText = MimeUtility.getTextFromPart(p); 4292517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 4302517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertEquals(UNICODE_EXPECT, gotText); 4312517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4322517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setBody(tb); 4332517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 4342517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "text/html; prop1 = \"test\"; charset = \"windows-1252\"; prop2 = \"test\""); 4352517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn gotText = MimeUtility.getTextFromPart(p); 4362517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 4372517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertEquals(WINDOWS1252_EXPECT, gotText); 4382517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4392517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // TEST 2: Mixed case in Content-Type header: 4402517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // RFC 2045 says that content types, subtypes and parameter names 4412517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // are case-insensitive. 4422517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4432517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setBody(tb); 4442517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/HtmL ; CHARseT=utf-8"); 4452517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn gotText = MimeUtility.getTextFromPart(p); 4462517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 4472517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertEquals(UNICODE_EXPECT, gotText); 4482517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4492517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setBody(tb); 4502517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/HtmL ; CHARseT=windows-1252"); 4512517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn gotText = MimeUtility.getTextFromPart(p); 4522517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 4532517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertEquals(WINDOWS1252_EXPECT, gotText); 4542517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4552517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // TEST 3: Comments in Content-Type header field (from RFC 2045) 4562517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // Thunderbird permits comments after the end of a parameter, as in this example. 4572517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // Not something that I have seen in the real world outside RFC 2045. 4582517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4592517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setBody(tb); 4602517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 4612517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "text/html; charset=utf-8 (Plain text)"); 4622517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn gotText = MimeUtility.getTextFromPart(p); 4632517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 4642517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // Note: This test does not pass. 4652517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn //assertEquals(UNICODE_EXPECT, gotText); 4662517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4672517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setBody(tb); 4682517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 4692517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "text/html; charset=windows-1252 (Plain text)"); 4702517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn gotText = MimeUtility.getTextFromPart(p); 4712517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 4722517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // Note: These tests does not pass. 4732517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn //assertEquals(WINDOWS1252_EXPECT, gotText); 4742517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn } 4757037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 47696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** Tests for various aspects of mimeTypeMatches(String mimeType, String matchAgainst) */ 47796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void testMimeTypeMatches() { 47896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 1. No match 47996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "TEXT/PLAIN")); 4807037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 48196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 2. Match 48296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/plain")); 4837037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 48496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 3. Match (mixed case) 48596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertTrue(MimeUtility.mimeTypeMatches("text/plain", "TEXT/PLAIN")); 48696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertTrue(MimeUtility.mimeTypeMatches("TEXT/PLAIN", "text/plain")); 4877037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 48896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 4. Match (wildcards) 48996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/plain")); 49096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/*")); 49196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/*")); 4927037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 49396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 5. No Match (wildcards) 49496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "*/plain")); 49596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "text/*")); 49696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 4977037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 49896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** Tests for various aspects of mimeTypeMatches(String mimeType, String[] matchAgainst) */ 49996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void testMimeTypeMatchesArray() { 50096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 1. Zero-length array 50196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String[] arrayZero = new String[0]; 50296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertFalse(MimeUtility.mimeTypeMatches("text/plain", arrayZero)); 5037037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 50496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 2. Single entry, no match 50596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String[] arrayOne = new String[] { "text/plain" }; 50696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayOne)); 5077037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 50896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 3. Single entry, match 50996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayOne)); 5107037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 51196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 4. Multi entry, no match 51296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String[] arrayTwo = new String[] { "text/plain", "match/this" }; 51396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayTwo)); 5147037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 51596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 5. Multi entry, match first 51696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayTwo)); 5177037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie 51896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // 6. Multi entry, match not first 51996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertTrue(MimeUtility.mimeTypeMatches("match/this", arrayTwo)); 52096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 52196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 5227037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie // TODO: tests for decodeBody(InputStream in, String contentTransferEncoding) 52396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // TODO: tests for collectParts(Part part, ArrayList<Part> viewables, ArrayList<Part> attachments) 5243469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 52596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project} 526