FileDocCategorySizeDatePackage
MimeUtilityTest.javaAPI DocAndroid 1.5 API18433Wed May 06 22:42:46 BST 2009com.android.email.mail.internet

MimeUtilityTest

public class MimeUtilityTest extends TestCase
This is a series of unit tests for the MimeUtility class. These tests must be locally complete - no server(s) required.

Fields Summary
private final String
SHORT_UNICODE
up arrow, down arrow, left arrow, right arrow
private final String
SHORT_UNICODE_ENCODED
private final String
PADDED2_UNICODE
dollar and euro sign
private final String
PADDED2_UNICODE_ENCODED
private final String
PADDED1_UNICODE
private final String
PADDED1_UNICODE_ENCODED
private final String
PADDED0_UNICODE
private final String
PADDED0_UNICODE_ENCODED
private final String
SHORT_PLAIN
a string without any unicode
private final String
LONG_UNICODE_SPLIT
long subject which will be split into two MIME/Base64 chunks
private final String
LONG_UNICODE_SPLIT_ENCODED
private final String
SHORT_SUPPLEMENTAL
strings that use supplemental characters and really stress encode/decode
private final String
SHORT_SUPPLEMENTAL_ENCODED
private final String
LONG_SUPPLEMENTAL
private final String
LONG_SUPPLEMENTAL_ENCODED
private final String
LONG_SUPPLEMENTAL_2
private final String
LONG_SUPPLEMENTAL_ENCODED_2
private final String
LONG_SUPPLEMENTAL_QP
private final String
LONG_SUPPLEMENTAL_QP_ENCODED
private final String
HEADER_NO_PARAMETER
a typical no-param header
private final String
HEADER_MULTI_PARAMETER
a typical multi-param header
private final String
CALENDAR_SUBJECT_UNICODE
a string generated by google calendar that contains two interesting gotchas: 1. Uses windows-1252 encoding, and en-dash recoded appropriately (\u2013 / =96) 2. Because the first encoded char requires '=XX' encoding, we create an "internal" "?=" that the decoder must correctly skip over.
private final String
CALENDAR_SUBJECT_PLAIN
private final String
CALENDAR_DEGENERATE_UNICODE_1
Some basic degenerate strings designed to exercise error handling in the decoder
private final String
CALENDAR_DEGENERATE_UNICODE_2
private final String
CALENDAR_DEGENERATE_UNICODE_3
private final String
CALENDAR_DEGENERATE_UNICODE_4
Constructors Summary
Methods Summary
public voidtestComplexDecode()
test decoding complex string from google calendar that has two gotchas for the decoder. also tests a couple of degenerate cases that should "fail" decoding and pass through.

        String result1 = MimeUtility.unfoldAndDecode(CALENDAR_SUBJECT_UNICODE);
        assertEquals(CALENDAR_SUBJECT_PLAIN, result1);
        
        // These degenerate cases should "fail" and return the same string
        String degenerate1 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_1);
        assertEquals("degenerate case 1", CALENDAR_DEGENERATE_UNICODE_1, degenerate1);
        String degenerate2 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_2);
        assertEquals("degenerate case 2", CALENDAR_DEGENERATE_UNICODE_2, degenerate2);
        String degenerate3 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_3);
        assertEquals("degenerate case 3", CALENDAR_DEGENERATE_UNICODE_3, degenerate3);
        String degenerate4 = MimeUtility.unfoldAndDecode(CALENDAR_DEGENERATE_UNICODE_4);
        assertEquals("degenerate case 4", CALENDAR_DEGENERATE_UNICODE_4, degenerate4);
    
public voidtestDecodeSimple()
Test that decode is working for simple strings

        String result1 = MimeUtility.decode(SHORT_UNICODE_ENCODED);
        assertEquals(SHORT_UNICODE, result1);
    
public voidtestEfficientFoldAndEncode()
Test that fold/encode is efficient when it can be

        String result1 = MimeUtility.foldAndEncode(SHORT_PLAIN);
        String result2 = MimeUtility.foldAndEncode2(SHORT_PLAIN, 10);
        String result3 = MimeUtility.fold(SHORT_PLAIN, 10);
        
        assertSame(SHORT_PLAIN, result1);
        assertSame(SHORT_PLAIN, result2);
        assertSame(SHORT_PLAIN, result3);
    
public voidtestEfficientUnfoldAndDecode()
Test that decode/unfold is efficient when it can be


                  
       
        String result1 = MimeUtility.unfold(SHORT_PLAIN);
        String result2 = MimeUtility.decode(SHORT_PLAIN);
        String result3 = MimeUtility.unfoldAndDecode(SHORT_PLAIN);
        
        assertSame(SHORT_PLAIN, result1);
        assertSame(SHORT_PLAIN, result2);
        assertSame(SHORT_PLAIN, result3);
    
public voidtestFindPartByContentIdTestCase()
Tests for findPartByContentId(Part part, String contentId)

        final String cid1 = "cid.1@android.com";
        final Part cid1bp = MessageTestUtils.bodyPart("image/gif", cid1);
        final String cid2 = "cid.2@android.com";
        final Part cid2bp = MessageTestUtils.bodyPart("image/gif", "<" + cid2 + ">");

        final Message msg1 = new MessageBuilder()
            .setBody(new MultipartBuilder("multipart/related")
                 .addBodyPart(MessageTestUtils.bodyPart("text/html", null))
                 .addBodyPart((BodyPart)cid1bp)
                 .build())
            .build();
        // found cid1 part
        final Part actual1_1 = MimeUtility.findPartByContentId(msg1, cid1);
        assertEquals("could not found expected content-id part", cid1bp, actual1_1);

        final Message msg2 = new MessageBuilder()
            .setBody(new MultipartBuilder("multipart/mixed")
                .addBodyPart(MessageTestUtils.bodyPart("image/tiff", "cid.4@android.com"))
                .addBodyPart(new MultipartBuilder("multipart/related")
                    .addBodyPart(new MultipartBuilder("multipart/alternative")
                        .addBodyPart(MessageTestUtils.bodyPart("text/plain", null))
                        .addBodyPart(MessageTestUtils.bodyPart("text/html", null))
                        .buildBodyPart())
                    .addBodyPart((BodyPart)cid1bp)
                    .buildBodyPart())
                .addBodyPart(MessageTestUtils.bodyPart("image/gif", "cid.3@android.com"))
                .addBodyPart((BodyPart)cid2bp)
                .build())
            .build();
        // found cid1 part
        final Part actual2_1 = MimeUtility.findPartByContentId(msg2, cid1);
        assertEquals("found part from related multipart", cid1bp, actual2_1);

        // found cid2 part
        final Part actual2_2 = MimeUtility.findPartByContentId(msg2, cid2);
        assertEquals("found part from mixed multipart", cid2bp, actual2_2);
    
public voidtestFoldAndEncode2()
Test that foldAndEncode2 is working for simple strings

        String result1 = MimeUtility.foldAndEncode2(SHORT_UNICODE, 10);
        assertEquals(SHORT_UNICODE_ENCODED, result1);
    
public voidtestFoldAndEncode2Supplemental()
Tests of foldAndEncode2 that involve supplemental characters (UTF-32) Note that the difference between LONG_SUPPLEMENTAL and LONG_SUPPLEMENTAL_2 is the insertion of a single character at the head of the string. This is intended to disrupt the code that splits the long string into multiple encoded words, and confirm that it properly applies the breaks between UTF-32 code points.

        String result1 = MimeUtility.foldAndEncode2(SHORT_SUPPLEMENTAL, "Subject: ".length());
        String result2 = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL, "Subject: ".length());
        String result3 = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL_2, "Subject: ".length());
        assertEquals("short supplemental", SHORT_SUPPLEMENTAL_ENCODED, result1);
        assertEquals("long supplemental", LONG_SUPPLEMENTAL_ENCODED, result2);
        assertEquals("long supplemental 2", LONG_SUPPLEMENTAL_ENCODED_2, result3);
    
public voidtestFoldAndEncode2SupplementalQuotedPrintable()
Tests of foldAndEncode2 that involve supplemental characters (UTF-32) Note that the difference between LONG_SUPPLEMENTAL and LONG_SUPPLEMENTAL_QP is that the former will be encoded as base64 but the latter will be encoded as quoted printable.

        String result = MimeUtility.foldAndEncode2(LONG_SUPPLEMENTAL_QP, "Subject: ".length());
        assertEquals("long supplement quoted printable",
                     LONG_SUPPLEMENTAL_QP_ENCODED, result);
    
public voidtestFoldAndEncode2WithLongSplit()
Test that foldAndEncode2 is working for long strings which needs splitting.

        String result = MimeUtility.foldAndEncode2(LONG_UNICODE_SPLIT, "Subject: ".length()); 

        assertEquals("long string", LONG_UNICODE_SPLIT_ENCODED, result);
    
public voidtestGetHeaderParameter()
Basic tests of getHeaderParameter() Typical header value: multipart/mixed; boundary="----E5UGTXUQQJV80DR8SJ88F79BRA4S8K" Function spec says: if header is null: return null if name is null: if params, return first param. else return full field else: if param is found (case insensitive) return it else return null

        // if header is null, return null
        assertNull("null header check", MimeUtility.getHeaderParameter(null, "name"));
        
        // if name is null, return first param or full header
        // NOTE:  The docs are wrong - it returns the header (no params) in that case
//      assertEquals("null name first param per docs", "Param1Value", 
//              MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, null));
        assertEquals("null name first param per code", "header", 
                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, null));
        assertEquals("null name full header", HEADER_NO_PARAMETER, 
                MimeUtility.getHeaderParameter(HEADER_NO_PARAMETER, null));
        
        // find name 
        assertEquals("get 1st param", "Param1Value", 
                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param1Name"));
        assertEquals("get 2nd param", "Param2Value", 
                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param2Name"));
        assertEquals("get missing param", null, 
                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "Param3Name"));
        
        // case insensitivity
        assertEquals("get 2nd param all LC", "Param2Value", 
                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "param2name"));
        assertEquals("get 2nd param all UC", "Param2Value", 
                MimeUtility.getHeaderParameter(HEADER_MULTI_PARAMETER, "PARAM2NAME"));
    
public voidtestGetTextFromPartContentTypeCase()
Tests for getTextFromPart(Part part)

        final String theText = "This is the text of the part";
        TextBody tb = new TextBody(theText);
        MimeBodyPart p = new MimeBodyPart();
        
        // 1. test basic text/plain mode
        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/plain");
        p.setBody(tb);
        String gotText = MimeUtility.getTextFromPart(p);
        assertEquals(theText, gotText);
        
        // 2. mixed case is OK
        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/PLAIN");
        p.setBody(tb);
        gotText = MimeUtility.getTextFromPart(p);
        assertEquals(theText, gotText);
        
        // 3. wildcards OK
        p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/other");
        p.setBody(tb);
        gotText = MimeUtility.getTextFromPart(p);
        assertEquals(theText, gotText);
    
public voidtestMimeTypeMatches()
Tests for various aspects of mimeTypeMatches(String mimeType, String matchAgainst)

        // 1. No match
        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "TEXT/PLAIN"));
        
        // 2. Match
        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/plain"));
        
        // 3. Match (mixed case)
        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "TEXT/PLAIN"));
        assertTrue(MimeUtility.mimeTypeMatches("TEXT/PLAIN", "text/plain"));
        
        // 4. Match (wildcards)
        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/plain"));
        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/*"));
        assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/*"));
        
        // 5. No Match (wildcards)
        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "*/plain"));
        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "text/*"));
    
public voidtestMimeTypeMatchesArray()
Tests for various aspects of mimeTypeMatches(String mimeType, String[] matchAgainst)

        // 1. Zero-length array
        String[] arrayZero = new String[0];
        assertFalse(MimeUtility.mimeTypeMatches("text/plain", arrayZero));
        
        // 2. Single entry, no match
        String[] arrayOne = new String[] { "text/plain" };
        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayOne));
        
        // 3. Single entry, match
        assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayOne));
        
        // 4. Multi entry, no match
        String[] arrayTwo = new String[] { "text/plain", "match/this" };
        assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayTwo));
        
        // 5. Multi entry, match first
        assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayTwo));
        
        // 6. Multi entry, match not first
        assertTrue(MimeUtility.mimeTypeMatches("match/this", arrayTwo));
    
public voidtestPaddingOfFoldAndEncode2()
Test about base64 padding variety.

        String result1 = MimeUtility.foldAndEncode2(PADDED2_UNICODE, 0);
        String result2 = MimeUtility.foldAndEncode2(PADDED1_UNICODE, 0);
        String result3 = MimeUtility.foldAndEncode2(PADDED0_UNICODE, 0);
        
        assertEquals("padding 2", PADDED2_UNICODE_ENCODED, result1);
        assertEquals("padding 1", PADDED1_UNICODE_ENCODED, result2);
        assertEquals("padding 0", PADDED0_UNICODE_ENCODED, result3);
    
public voidtestUnfoldAndDecodeSimple()
Test that unfoldAndDecode is working for simple strings

        String result1 = MimeUtility.unfoldAndDecode(SHORT_UNICODE_ENCODED);
        assertEquals(SHORT_UNICODE, result1);