Loading core/java/com/android/internal/util/FastXmlSerializer.java +12 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -38,10 +39,10 @@ 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 "�", "", "", "", "", "", "", "", // 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 Loading Loading @@ -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)); Loading core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java +105 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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); } } Loading
core/java/com/android/internal/util/FastXmlSerializer.java +12 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -38,10 +39,10 @@ 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 "�", "", "", "", "", "", "", "", // 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 Loading Loading @@ -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)); Loading
core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java +105 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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); } }