Merge "Make FastXmlSerializer more suitable to persist arbitrary strings" into nyc-dev
This commit is contained in:
@@ -28,6 +28,7 @@ import java.nio.CharBuffer;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.CharsetEncoder;
|
import java.nio.charset.CharsetEncoder;
|
||||||
import java.nio.charset.CoderResult;
|
import java.nio.charset.CoderResult;
|
||||||
|
import java.nio.charset.CodingErrorAction;
|
||||||
import java.nio.charset.IllegalCharsetNameException;
|
import java.nio.charset.IllegalCharsetNameException;
|
||||||
import java.nio.charset.UnsupportedCharsetException;
|
import java.nio.charset.UnsupportedCharsetException;
|
||||||
|
|
||||||
@@ -38,14 +39,14 @@ import java.nio.charset.UnsupportedCharsetException;
|
|||||||
*/
|
*/
|
||||||
public class FastXmlSerializer implements XmlSerializer {
|
public class FastXmlSerializer implements XmlSerializer {
|
||||||
private static final String ESCAPE_TABLE[] = new String[] {
|
private static final String ESCAPE_TABLE[] = new String[] {
|
||||||
null, null, null, null, null, null, null, null, // 0-7
|
"�", "", "", "", "", "", "", "", // 0-7
|
||||||
null, null, null, null, null, null, null, null, // 8-15
|
"", "	", " ", "", "", " ", "", "", // 8-15
|
||||||
null, null, null, null, null, null, null, null, // 16-23
|
"", "", "", "", "", "", "", "", // 16-23
|
||||||
null, null, null, null, null, null, null, null, // 24-31
|
"", "", "", "", "", "", "", "", // 24-31
|
||||||
null, null, """, null, null, null, "&", null, // 32-39
|
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, // 40-47
|
||||||
null, null, null, null, null, null, null, null, // 48-55
|
null, null, null, null, null, null, null, null, // 48-55
|
||||||
null, null, null, null, "<", null, ">", null, // 56-63
|
null, null, null, null, "<", null, ">", null, // 56-63
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final int BUFFER_LEN = 8192;
|
private static final int BUFFER_LEN = 8192;
|
||||||
@@ -310,7 +311,9 @@ public class FastXmlSerializer implements XmlSerializer {
|
|||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if (true) {
|
if (true) {
|
||||||
try {
|
try {
|
||||||
mCharset = Charset.forName(encoding).newEncoder();
|
mCharset = Charset.forName(encoding).newEncoder()
|
||||||
|
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||||
|
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||||
} catch (IllegalCharsetNameException e) {
|
} catch (IllegalCharsetNameException e) {
|
||||||
throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
|
throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
|
||||||
encoding).initCause(e));
|
encoding).initCause(e));
|
||||||
|
|||||||
@@ -16,16 +16,32 @@
|
|||||||
|
|
||||||
package com.android.internal.util;
|
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 junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlSerializer;
|
import org.xmlpull.v1.XmlSerializer;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link FastXmlSerializer}
|
* Tests for {@link FastXmlSerializer}
|
||||||
*/
|
*/
|
||||||
|
@SmallTest
|
||||||
public class FastXmlSerializerTest extends TestCase {
|
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 {
|
public void testEmptyText() throws Exception {
|
||||||
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
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"
|
assertEquals("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
|
||||||
+ "<string name=\"meow\"></string>\n", stream.toString());
|
+ "<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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user