diff options
| -rw-r--r-- | core/java/com/android/internal/util/FastXmlSerializer.java | 21 | ||||
| -rw-r--r-- | core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java | 105 | 
2 files changed, 117 insertions, 9 deletions
diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java index 7a040801a9a5..3c1d2d6ce581 100644 --- a/core/java/com/android/internal/util/FastXmlSerializer.java +++ b/core/java/com/android/internal/util/FastXmlSerializer.java @@ -28,6 +28,7 @@ import java.nio.CharBuffer;  import java.nio.charset.Charset;  import java.nio.charset.CharsetEncoder;  import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction;  import java.nio.charset.IllegalCharsetNameException;  import java.nio.charset.UnsupportedCharsetException; @@ -38,14 +39,14 @@ import java.nio.charset.UnsupportedCharsetException;   */  public class FastXmlSerializer implements XmlSerializer {      private static final String ESCAPE_TABLE[] = new String[] { -        null,     null,     null,     null,     null,     null,     null,     null,  // 0-7 -        null,     null,     null,     null,     null,     null,     null,     null,  // 8-15 -        null,     null,     null,     null,     null,     null,     null,     null,  // 16-23 -        null,     null,     null,     null,     null,     null,     null,     null,  // 24-31 -        null,     null,     """, null,     null,     null,     "&",  null,  // 32-39 -        null,     null,     null,     null,     null,     null,     null,     null,  // 40-47 -        null,     null,     null,     null,     null,     null,     null,     null,  // 48-55 -        null,     null,     null,     null,     "<",   null,     ">",   null,  // 56-63 +        "�",   "",   "",   "",  "",    "",   "",  "",  // 0-7 +        "",   "	",   "
",  "", "",   "
",  "", "", // 8-15 +        "",  "",  "",  "", "",   "",  "", "", // 16-23 +        "",  "",  "",  "", "",   "",  "", "", // 24-31 +        null,     null,     """, null,     null,     null,     "&",  null,   // 32-39 +        null,     null,     null,     null,     null,     null,     null,     null,   // 40-47 +        null,     null,     null,     null,     null,     null,     null,     null,   // 48-55 +        null,     null,     null,     null,     "<",   null,     ">",   null,   // 56-63      };      private static final int BUFFER_LEN = 8192; @@ -310,7 +311,9 @@ public class FastXmlSerializer implements XmlSerializer {              throw new IllegalArgumentException();          if (true) {              try { -                mCharset = Charset.forName(encoding).newEncoder(); +                mCharset = Charset.forName(encoding).newEncoder() +                        .onMalformedInput(CodingErrorAction.REPLACE) +                        .onUnmappableCharacter(CodingErrorAction.REPLACE);              } catch (IllegalCharsetNameException e) {                  throw (UnsupportedEncodingException) (new UnsupportedEncodingException(                          encoding).initCause(e)); diff --git a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java index 5f36c2d0c29b..3cef33621a01 100644 --- a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java +++ b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java @@ -16,16 +16,32 @@  package com.android.internal.util; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; +import android.util.Xml; +  import junit.framework.TestCase; +import org.xmlpull.v1.XmlPullParser;  import org.xmlpull.v1.XmlSerializer; +import java.io.ByteArrayInputStream;  import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets;  /**   * Tests for {@link FastXmlSerializer}   */ +@SmallTest  public class FastXmlSerializerTest extends TestCase { +    private static final String TAG = "FastXmlSerializerTest"; + +    private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH TRUE. + +    private static final String ROOT_TAG = "root"; +    private static final String ATTR = "attr"; +      public void testEmptyText() throws Exception {          final ByteArrayOutputStream stream = new ByteArrayOutputStream(); @@ -44,4 +60,93 @@ public class FastXmlSerializerTest extends TestCase {          assertEquals("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"                  + "<string name=\"meow\"></string>\n", stream.toString());      } + +    private boolean checkPreserved(String description, String str) { +        boolean ok = true; +        byte[] data; +        try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { +            final XmlSerializer out = new FastXmlSerializer(); +            out.setOutput(baos, StandardCharsets.UTF_16.name()); +            out.startDocument(null, true); + +            out.startTag(null, ROOT_TAG); +            out.attribute(null, ATTR, str); +            out.text(str); +            out.endTag(null, ROOT_TAG); + +            out.endDocument(); +            baos.flush(); +            data = baos.toByteArray(); +        } catch (Exception e) { +            Log.e(TAG, "Unable to serialize: " + description, e); +            return false; +        } + +        if (ENABLE_DUMP) { +            Log.d(TAG, "Dump:"); +            Log.d(TAG, new String(data)); +        } + +        try (final ByteArrayInputStream baos = new ByteArrayInputStream(data)) { +            XmlPullParser parser = Xml.newPullParser(); +            parser.setInput(baos, StandardCharsets.UTF_16.name()); + +            int type; +            String tag = null; +            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { +                if (type == XmlPullParser.START_TAG) { +                    tag = parser.getName(); +                    if (ROOT_TAG.equals(tag)) { +                        String read = parser.getAttributeValue(null, ATTR); +                        if (!str.equals(read)) { +                            Log.e(TAG, "Attribute not preserved: " + description +                                    + " input=\"" + str + "\", but read=\"" + read + "\""); +                            ok = false; +                        } +                    } +                } +                if (type == XmlPullParser.TEXT && ROOT_TAG.equals(tag)) { +                    String read = parser.getText(); +                    if (!str.equals(parser.getText())) { +                        Log.e(TAG, "Text not preserved: " + description +                                + " input=\"" + str + "\", but read=\"" + read + "\""); +                        ok = false; +                    } +                } +            } +        } catch (Exception e) { +            Log.e(TAG, "Unable to parse: " + description, e); +            return false; +        } +        return ok; +    } + +    private boolean check(String description, String str) throws Exception { +        boolean ok = false; +        ok |= checkPreserved(description, str); +        ok |= checkPreserved(description + " wrapped with spaces" ,"  " + str + "  "); +        return ok; +    } + +    @LargeTest +    public void testAllCharacters() throws Exception { +        boolean ok = true; +        for (int i = 0; i < 0xffff; i++) { +            if (0xd800 <= i && i <= 0xdfff) { +                // Surrogate pair characters. +                continue; +            } +            ok &= check("char: " + i, String.valueOf((char) i)); +        } +        // Dangling surrogate pairs. We can't preserve them. +        assertFalse(check("+ud800", "\ud800")); +        assertFalse(check("+udc00", "\udc00")); + +        for (int i = 0xd800; i < 0xdc00; i ++) { +            for (int j = 0xdc00; j < 0xe000; j++) { +                ok &= check("char: " + i, String.valueOf((char) i) + String.valueOf((char) j)); +            } +        } +        assertTrue("Some tests failed.  See logcat for details.", ok); +    }  }  |