MimeUtilityTest.java revision 2193962ca2b3157e79f731736afa2a0c972e778a
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.emailcommon.internet; 18 19import com.android.emailcommon.internet.MimeBodyPart; 20import com.android.emailcommon.internet.MimeHeader; 21import com.android.emailcommon.internet.MimeUtility; 22import com.android.emailcommon.internet.TextBody; 23import com.android.emailcommon.mail.BodyPart; 24import com.android.emailcommon.mail.Message; 25import com.android.emailcommon.mail.MessageTestUtils; 26import com.android.emailcommon.mail.MessagingException; 27import com.android.emailcommon.mail.Part; 28import com.android.emailcommon.mail.MessageTestUtils.MessageBuilder; 29import com.android.emailcommon.mail.MessageTestUtils.MultipartBuilder; 30 31import android.test.suitebuilder.annotation.SmallTest; 32 33import junit.framework.TestCase; 34 35/** 36 * This is a series of unit tests for the MimeUtility class. These tests must be locally 37 * complete - no server(s) required. 38 */ 39@SmallTest 40public class MimeUtilityTest extends TestCase { 41 42 /** up arrow, down arrow, left arrow, right arrow */ 43 private final String SHORT_UNICODE = "\u2191\u2193\u2190\u2192"; 44 private final String SHORT_UNICODE_ENCODED = "=?UTF-8?B?4oaR4oaT4oaQ4oaS?="; 45 46 /** dollar and euro sign */ 47 private final String PADDED2_UNICODE = "$\u20AC"; 48 private final String PADDED2_UNICODE_ENCODED = "=?UTF-8?B?JOKCrA==?="; 49 private final String PADDED1_UNICODE = "$$\u20AC"; 50 private final String PADDED1_UNICODE_ENCODED = "=?UTF-8?B?JCTigqw=?="; 51 private final String PADDED0_UNICODE = "$$$\u20AC"; 52 private final String PADDED0_UNICODE_ENCODED = "=?UTF-8?B?JCQk4oKs?="; 53 54 /** a string without any unicode */ 55 private final String SHORT_PLAIN = "abcd"; 56 57 /** long subject which will be split into two MIME/Base64 chunks */ 58 private final String LONG_UNICODE_SPLIT = 59 "$" + 60 "\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC" + 61 "\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC"; 62 private final String LONG_UNICODE_SPLIT_ENCODED = 63 "=?UTF-8?B?JOKCrOKCrOKCrOKCrOKCrOKCrOKCrOKCrA==?=" + "\r\n " + 64 "=?UTF-8?B?4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs4oKs?="; 65 66 /** strings that use supplemental characters and really stress encode/decode */ 67 // actually it's U+10400 68 private final String SHORT_SUPPLEMENTAL = "\uD801\uDC00"; 69 private final String SHORT_SUPPLEMENTAL_ENCODED = "=?UTF-8?B?8JCQgA==?="; 70 private final String LONG_SUPPLEMENTAL = SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + 71 SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + 72 SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL; 73 private final String LONG_SUPPLEMENTAL_ENCODED = 74 "=?UTF-8?B?8JCQgPCQkIDwkJCA8JCQgA==?=" + "\r\n " + 75 "=?UTF-8?B?8JCQgPCQkIDwkJCA8JCQgPCQkIDwkJCA?="; 76 private final String LONG_SUPPLEMENTAL_2 = "a" + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + 77 SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + 78 SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL + SHORT_SUPPLEMENTAL; 79 private final String LONG_SUPPLEMENTAL_ENCODED_2 = 80 "=?UTF-8?B?YfCQkIDwkJCA8JCQgPCQkIA=?=" + "\r\n " + 81 "=?UTF-8?B?8JCQgPCQkIDwkJCA8JCQgPCQkIDwkJCA?="; 82 // Earth is U+1D300. 83 private final String LONG_SUPPLEMENTAL_QP = 84 "*Monogram for Earth \uD834\uDF00. Monogram for Human \u268b."; 85 private final String LONG_SUPPLEMENTAL_QP_ENCODED = 86 "=?UTF-8?Q?*Monogram_for_Earth_?=" + "\r\n " + 87 "=?UTF-8?Q?=F0=9D=8C=80._Monogram_for_Human_=E2=9A=8B.?="; 88 89 /** a typical no-param header */ 90 private final String HEADER_NO_PARAMETER = 91 "header"; 92 /** a typical multi-param header */ 93 private final String HEADER_MULTI_PARAMETER = 94 "header; Param1Name=Param1Value; Param2Name=Param2Value"; 95 /** a multi-param header with quoting */ 96 private final String HEADER_QUOTED_MULTI_PARAMETER = 97 "header; Param1Name=\"Param1Value\"; Param2Name=\"Param2Value\""; 98 /** a malformed header we're seeing in production servers */ 99 private final String HEADER_MALFORMED_PARAMETER = 100 "header; Param1Name=Param1Value; filename"; 101 102 /** 103 * a string generated by google calendar that contains two interesting gotchas: 104 * 1. Uses windows-1252 encoding, and en-dash recoded appropriately (\u2013 / =96) 105 * 2. Because the first encoded char requires '=XX' encoding, we create an "internal" 106 * "?=" that the decoder must correctly skip over. 107 **/ 108 private final String CALENDAR_SUBJECT_UNICODE = 109 "=?windows-1252?Q?=5BReminder=5D_test_=40_Fri_Mar_20_10=3A30am_=96_11am_=28andro?=" + 110 "\r\n\t" + 111 "=?windows-1252?Q?id=2Etr=40gmail=2Ecom=29?="; 112 private final String CALENDAR_SUBJECT_PLAIN = 113 "[Reminder] test @ Fri Mar 20 10:30am \u2013 11am (android.tr@gmail.com)"; 114 115 /** 116 * Some basic degenerate strings designed to exercise error handling in the decoder 117 */ 118 private final String CALENDAR_DEGENERATE_UNICODE_1 = 119 "=?windows-1252?Q=5B?="; 120 private final String CALENDAR_DEGENERATE_UNICODE_2 = 121 "=?windows-1252Q?=5B?="; 122 private final String CALENDAR_DEGENERATE_UNICODE_3 = 123 "=?windows-1252?="; 124 private final String CALENDAR_DEGENERATE_UNICODE_4 = 125 "=?windows-1252"; 126 127 /** 128 * Test that decode/unfold is efficient when it can be 129 */ 130 public void testEfficientUnfoldAndDecode() { 131 String result1 = MimeUtility.unfold(SHORT_PLAIN); 132 String result2 = MimeUtility.decode(SHORT_PLAIN); 133 String result3 = MimeUtility.unfoldAndDecode(SHORT_PLAIN); 134 135 assertSame(SHORT_PLAIN, result1); 136 assertSame(SHORT_PLAIN, result2); 137 assertSame(SHORT_PLAIN, result3); 138 } 139 140 // TODO: more tests for unfold(String s) 141 142 /** 143 * Test that decode is working for simple strings 144 */ 145 public void testDecodeSimple() { 146 String result1 = MimeUtility.decode(SHORT_UNICODE_ENCODED); 147 assertEquals(SHORT_UNICODE, result1); 148 } 149 150 // TODO: tests for decode(String s) 151 152 /** 153 * Test that unfoldAndDecode is working for simple strings 154 */ 155 public void testUnfoldAndDecodeSimple() { 156 String result1 = MimeUtility.unfoldAndDecode(SHORT_UNICODE_ENCODED); 157 assertEquals(SHORT_UNICODE, result1); 158 } 159 160 /** 161 * test decoding complex string from google calendar that has two gotchas for the decoder. 162 * also tests a couple of degenerate cases that should "fail" decoding and pass through. 163 */ 164 public void testComplexDecode() { 165 String result1 = MimeUtility.unfoldAndDecode(CALENDAR_SUBJECT_UNICODE); 166 assertEquals(CALENDAR_SUBJECT_PLAIN, result1); 167 168 // These degenerate cases should "fail" and return the same string 169 String degenerate1 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_1); 170 assertEquals("degenerate case 1", CALENDAR_DEGENERATE_UNICODE_1, degenerate1); 171 String degenerate2 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_2); 172 assertEquals("degenerate case 2", CALENDAR_DEGENERATE_UNICODE_2, degenerate2); 173 String degenerate3 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_3); 174 assertEquals("degenerate case 3", CALENDAR_DEGENERATE_UNICODE_3, degenerate3); 175 String degenerate4 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_4); 176 assertEquals("degenerate case 4", CALENDAR_DEGENERATE_UNICODE_4, degenerate4); 177 } 178 179 // TODO: more tests for unfoldAndDecode(String s) 180 181 /** 182 * Test that fold/encode is efficient when it can be 183 */ 184 public void testEfficientFoldAndEncode() { 185 String result1 = MimeUtility.foldAndEncode(SHORT_PLAIN); 186 String result2 = MimeUtility.foldAndEncode2(SHORT_PLAIN, 10); 187 String result3 = MimeUtility.fold(SHORT_PLAIN, 10); 188 189 assertSame(SHORT_PLAIN, result1); 190 assertSame(SHORT_PLAIN, result2); 191 assertSame(SHORT_PLAIN, result3); 192 } 193 194 /** 195 * Test about base64 padding variety. 196 */ 197 public void testPaddingOfFoldAndEncode2() { 198 String result1 = MimeUtility.foldAndEncode2(PADDED2_UNICODE, 0); 199 String result2 = MimeUtility.foldAndEncode2(PADDED1_UNICODE, 0); 200 String result3 = MimeUtility.foldAndEncode2(PADDED0_UNICODE, 0); 201 202 assertEquals("padding 2", PADDED2_UNICODE_ENCODED, result1); 203 assertEquals("padding 1", PADDED1_UNICODE_ENCODED, result2); 204 assertEquals("padding 0", PADDED0_UNICODE_ENCODED, result3); 205 } 206 207 // TODO: more tests for foldAndEncode(String s) 208 209 /** 210 * Test that foldAndEncode2 is working for simple strings 211 */ 212 public void testFoldAndEncode2() { 213 String result1 = MimeUtility.foldAndEncode2(SHORT_UNICODE, 10); 214 assertEquals(SHORT_UNICODE_ENCODED, result1); 215 } 216 217 /** 218 * Test that foldAndEncode2 is working for long strings which needs splitting. 219 */ 220 public void testFoldAndEncode2WithLongSplit() { 221 String result = MimeUtility.foldAndEncode2(LONG_UNICODE_SPLIT, "Subject: ".length()); 222 223 assertEquals("long string", LONG_UNICODE_SPLIT_ENCODED, result); 224 } 225 226 /** 227 * Tests of foldAndEncode2 that involve supplemental characters (UTF-32) 228 * 229 * Note that the difference between LONG_SUPPLEMENTAL and LONG_SUPPLEMENTAL_2 is the 230 * insertion of a single character at the head of the string. This is intended to disrupt 231 * the code that splits the long string into multiple encoded words, and confirm that it 232 * properly applies the breaks between UTF-32 code points. 233 */ 234 public void testFoldAndEncode2Supplemental() { 235 String result1 = MimeUtility.foldAndEncode2(SHORT_SUPPLEMENTAL, "Subject: ".length()); 236 String result2 = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL, "Subject: ".length()); 237 String result3 = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL_2, "Subject: ".length()); 238 assertEquals("short supplemental", SHORT_SUPPLEMENTAL_ENCODED, result1); 239 assertEquals("long supplemental", LONG_SUPPLEMENTAL_ENCODED, result2); 240 assertEquals("long supplemental 2", LONG_SUPPLEMENTAL_ENCODED_2, result3); 241 } 242 243 /** 244 * Tests of foldAndEncode2 that involve supplemental characters (UTF-32) 245 * 246 * Note that the difference between LONG_SUPPLEMENTAL and LONG_SUPPLEMENTAL_QP is that 247 * the former will be encoded as base64 but the latter will be encoded as quoted printable. 248 */ 249 public void testFoldAndEncode2SupplementalQuotedPrintable() { 250 String result = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL_QP, "Subject: ".length()); 251 assertEquals("long supplement quoted printable", 252 LONG_SUPPLEMENTAL_QP_ENCODED, result); 253 } 254 255 // TODO: more tests for foldAndEncode2(String s) 256 // TODO: more tests for fold(String s, int usedCharacters) 257 258 /** 259 * Basic tests of getHeaderParameter() 260 * 261 * Typical header value: multipart/mixed; boundary="----E5UGTXUQQJV80DR8SJ88F79BRA4S8K" 262 * 263 * Function spec says: 264 * if header is null: return null 265 * if name is null: if params, return first param. else return full field 266 * else: if param is found (case insensitive) return it 267 * else return null 268 */ 269 public void testGetHeaderParameter() { 270 // if header is null, return null 271 assertNull("null header check", MimeUtility.getHeaderParameter(null, "name")); 272 273 // if name is null, return first param or full header 274 // NOTE: The docs are wrong - it returns the header (no params) in that case 275// assertEquals("null name first param per docs", "Param1Value", 276// MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, null)); 277 assertEquals("null name first param per code", "header", 278 MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, null)); 279 assertEquals("null name full header", HEADER_NO_PARAMETER, 280 MimeUtility.getHeaderParameter(HEADER_NO_PARAMETER, null)); 281 282 // find name 283 assertEquals("get 1st param", "Param1Value", 284 MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param1Name")); 285 assertEquals("get 2nd param", "Param2Value", 286 MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param2Name")); 287 assertEquals("get missing param", null, 288 MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param3Name")); 289 290 // case insensitivity 291 assertEquals("get 2nd param all LC", "Param2Value", 292 MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "param2name")); 293 assertEquals("get 2nd param all UC", "Param2Value", 294 MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "PARAM2NAME")); 295 296 // quoting 297 assertEquals("get 1st param", "Param1Value", 298 MimeUtility.getHeaderParameter(HEADER_QUOTED_MULTI_PARAMETER, "Param1Name")); 299 assertEquals("get 2nd param", "Param2Value", 300 MimeUtility.getHeaderParameter(HEADER_QUOTED_MULTI_PARAMETER, "Param2Name")); 301 302 // Don't fail when malformed 303 assertEquals("malformed filename param", null, 304 MimeUtility.getHeaderParameter(HEADER_MALFORMED_PARAMETER, "filename")); 305 } 306 307 // TODO: tests for findFirstPartByMimeType(Part part, String mimeType) 308 309 /** Tests for findPartByContentId(Part part, String contentId) */ 310 public void testFindPartByContentIdTestCase() throws MessagingException, Exception { 311 final String cid1 = "cid.1@android.com"; 312 final Part cid1bp = MessageTestUtils.bodyPart("image/gif", cid1); 313 final String cid2 = "cid.2@android.com"; 314 final Part cid2bp = MessageTestUtils.bodyPart("image/gif", "<" + cid2 + ">"); 315 316 final Message msg1 = new MessageBuilder() 317 .setBody(new MultipartBuilder("multipart/related") 318 .addBodyPart(MessageTestUtils.bodyPart("text/html", null)) 319 .addBodyPart((BodyPart)cid1bp) 320 .build()) 321 .build(); 322 // found cid1 part 323 final Part actual1_1 = MimeUtility.findPartByContentId(msg1, cid1); 324 assertEquals("could not found expected content-id part", cid1bp, actual1_1); 325 326 final Message msg2 = new MessageBuilder() 327 .setBody(new MultipartBuilder("multipart/mixed") 328 .addBodyPart(MessageTestUtils.bodyPart("image/tiff", "cid.4@android.com")) 329 .addBodyPart(new MultipartBuilder("multipart/related") 330 .addBodyPart(new MultipartBuilder("multipart/alternative") 331 .addBodyPart(MessageTestUtils.bodyPart("text/plain", null)) 332 .addBodyPart(MessageTestUtils.bodyPart("text/html", null)) 333 .buildBodyPart()) 334 .addBodyPart((BodyPart)cid1bp) 335 .buildBodyPart()) 336 .addBodyPart(MessageTestUtils.bodyPart("image/gif", "cid.3@android.com")) 337 .addBodyPart((BodyPart)cid2bp) 338 .build()) 339 .build(); 340 // found cid1 part 341 final Part actual2_1 = MimeUtility.findPartByContentId(msg2, cid1); 342 assertEquals("found part from related multipart", cid1bp, actual2_1); 343 344 // found cid2 part 345 final Part actual2_2 = MimeUtility.findPartByContentId(msg2, cid2); 346 assertEquals("found part from mixed multipart", cid2bp, actual2_2); 347 } 348 349 /** Tests for getTextFromPart(Part part) */ 350 public void testGetTextFromPartContentTypeCase() throws MessagingException { 351 final String theText = "This is the text of the part"; 352 TextBody tb = new TextBody(theText); 353 MimeBodyPart p = new MimeBodyPart(); 354 355 // 1. test basic text/plain mode 356 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/plain"); 357 p.setBody(tb); 358 String gotText = MimeUtility.getTextFromPart(p); 359 assertEquals(theText, gotText); 360 361 // 2. mixed case is OK 362 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/PLAIN"); 363 p.setBody(tb); 364 gotText = MimeUtility.getTextFromPart(p); 365 assertEquals(theText, gotText); 366 367 // 3. wildcards OK 368 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/other"); 369 p.setBody(tb); 370 gotText = MimeUtility.getTextFromPart(p); 371 assertEquals(theText, gotText); 372 } 373 374 /** Test for usage of Content-Type in getTextFromPart(Part part). 375 * 376 * For example 'Content-Type: text/html; charset=utf-8' 377 * 378 * If the body part has no mime-type, refuses to parse content as text. 379 * If the mime-type does not match text/*, it will not get parsed. 380 * Then, the charset parameter is used, with a default of ASCII. 381 * 382 * This test works by using a string that is valid Unicode, and is also 383 * valid when decoded from UTF-8 bytes into Windows-1252 (so that 384 * auto-detection is not possible), and checks that the correct conversion 385 * was made, based on the Content-Type header. 386 * 387 */ 388 public void testContentTypeCharset() throws MessagingException { 389 final String UNICODE_EXPECT = "This is some happy unicode text \u263a"; 390 // What you get if you encode to UTF-8 (\xe2\x98\xba) and reencode with Windows-1252 391 final String WINDOWS1252_EXPECT = "This is some happy unicode text \u00e2\u02dc\u00ba"; 392 TextBody tb = new TextBody(UNICODE_EXPECT); 393 MimeBodyPart p = new MimeBodyPart(); 394 395 String gotText, mimeType, charset; 396 // TEST 0: Standard Content-Type header; no extraneous spaces or fields 397 p.setBody(tb); 398 // We call setHeader after setBody, since setBody overwrites Content-Type 399 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/html; charset=utf-8"); 400 gotText = MimeUtility.getTextFromPart(p); 401 assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 402 assertEquals(UNICODE_EXPECT, gotText); 403 404 p.setBody(tb); 405 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/html; charset=windows-1252"); 406 gotText = MimeUtility.getTextFromPart(p); 407 assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 408 assertEquals(WINDOWS1252_EXPECT, gotText); 409 410 // TEST 1: Extra fields and quotes in Content-Type (from RFC 2045) 411 p.setBody(tb); 412 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 413 "text/html; prop1 = \"test\"; charset = \"utf-8\"; prop2 = \"test\""); 414 gotText = MimeUtility.getTextFromPart(p); 415 assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 416 assertEquals(UNICODE_EXPECT, gotText); 417 418 p.setBody(tb); 419 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 420 "text/html; prop1 = \"test\"; charset = \"windows-1252\"; prop2 = \"test\""); 421 gotText = MimeUtility.getTextFromPart(p); 422 assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 423 assertEquals(WINDOWS1252_EXPECT, gotText); 424 425 // TEST 2: Mixed case in Content-Type header: 426 // RFC 2045 says that content types, subtypes and parameter names 427 // are case-insensitive. 428 429 p.setBody(tb); 430 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/HtmL ; CHARseT=utf-8"); 431 gotText = MimeUtility.getTextFromPart(p); 432 assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 433 assertEquals(UNICODE_EXPECT, gotText); 434 435 p.setBody(tb); 436 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/HtmL ; CHARseT=windows-1252"); 437 gotText = MimeUtility.getTextFromPart(p); 438 assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 439 assertEquals(WINDOWS1252_EXPECT, gotText); 440 441 // TEST 3: Comments in Content-Type header field (from RFC 2045) 442 // Thunderbird permits comments after the end of a parameter, as in this example. 443 // Not something that I have seen in the real world outside RFC 2045. 444 445 p.setBody(tb); 446 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 447 "text/html; charset=utf-8 (Plain text)"); 448 gotText = MimeUtility.getTextFromPart(p); 449 assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 450 // Note: This test does not pass. 451 //assertEquals(UNICODE_EXPECT, gotText); 452 453 p.setBody(tb); 454 p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 455 "text/html; charset=windows-1252 (Plain text)"); 456 gotText = MimeUtility.getTextFromPart(p); 457 assertTrue(MimeUtility.mimeTypeMatches(p.getMimeType(), "text/html")); 458 // Note: These tests does not pass. 459 //assertEquals(WINDOWS1252_EXPECT, gotText); 460 } 461 462 /** Tests for various aspects of mimeTypeMatches(String mimeType, String matchAgainst) */ 463 public void testMimeTypeMatches() { 464 // 1. No match 465 assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "TEXT/PLAIN")); 466 467 // 2. Match 468 assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/plain")); 469 470 // 3. Match (mixed case) 471 assertTrue(MimeUtility.mimeTypeMatches("text/plain", "TEXT/PLAIN")); 472 assertTrue(MimeUtility.mimeTypeMatches("TEXT/PLAIN", "text/plain")); 473 474 // 4. Match (wildcards) 475 assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/plain")); 476 assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/*")); 477 assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/*")); 478 479 // 5. No Match (wildcards) 480 assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "*/plain")); 481 assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "text/*")); 482 } 483 484 /** Tests for various aspects of mimeTypeMatches(String mimeType, String[] matchAgainst) */ 485 public void testMimeTypeMatchesArray() { 486 // 1. Zero-length array 487 String[] arrayZero = new String[0]; 488 assertFalse(MimeUtility.mimeTypeMatches("text/plain", arrayZero)); 489 490 // 2. Single entry, no match 491 String[] arrayOne = new String[] { "text/plain" }; 492 assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayOne)); 493 494 // 3. Single entry, match 495 assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayOne)); 496 497 // 4. Multi entry, no match 498 String[] arrayTwo = new String[] { "text/plain", "match/this" }; 499 assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayTwo)); 500 501 // 5. Multi entry, match first 502 assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayTwo)); 503 504 // 6. Multi entry, match not first 505 assertTrue(MimeUtility.mimeTypeMatches("match/this", arrayTwo)); 506 } 507 508 // TODO: tests for decodeBody(InputStream in, String contentTransferEncoding) 509 // TODO: tests for collectParts(Part part, ArrayList<Part> viewables, ArrayList<Part> attachments) 510 511} 512