13029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey/* 23029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project 33029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * 43029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 53029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * you may not use this file except in compliance with the License. 63029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * You may obtain a copy of the License at 73029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * 83029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 93029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * 103029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 113029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 123029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * See the License for the specific language governing permissions and 143029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * limitations under the License. 153029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey */ 163029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey 173029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkeypackage com.android.internal.util; 183029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey 193ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onukiimport android.test.suitebuilder.annotation.LargeTest; 203ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onukiimport android.test.suitebuilder.annotation.SmallTest; 213ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onukiimport android.util.Log; 223ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onukiimport android.util.Xml; 233ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 243029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkeyimport junit.framework.TestCase; 253029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey 263ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onukiimport org.xmlpull.v1.XmlPullParser; 273029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer; 283029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey 293ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onukiimport java.io.ByteArrayInputStream; 303029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkeyimport java.io.ByteArrayOutputStream; 313ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onukiimport java.nio.charset.StandardCharsets; 323029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey 333029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey/** 343029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey * Tests for {@link FastXmlSerializer} 353029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey */ 363ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki@SmallTest 373029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkeypublic class FastXmlSerializerTest extends TestCase { 383ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki private static final String TAG = "FastXmlSerializerTest"; 393ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 403ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH TRUE. 413ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 423ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki private static final String ROOT_TAG = "root"; 433ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki private static final String ATTR = "attr"; 443ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 453029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey public void testEmptyText() throws Exception { 463029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey final ByteArrayOutputStream stream = new ByteArrayOutputStream(); 473029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey 483029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey final XmlSerializer out = new FastXmlSerializer(); 493029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey out.setOutput(stream, "utf-8"); 503029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey out.startDocument(null, true); 513029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 523029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey 533029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey out.startTag(null, "string"); 543029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey out.attribute(null, "name", "meow"); 553029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey out.text(""); 563029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey out.endTag(null, "string"); 573029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey 583029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey out.endDocument(); 593029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey 603029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey assertEquals("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" 61733fc6b6f9af33bae047e8296b9fc9d341f4f202Mitchell Wills + "<string name=\"meow\"></string>\n", stream.toString()); 623029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey } 633ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 643ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki private boolean checkPreserved(String description, String str) { 653ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki boolean ok = true; 663ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki byte[] data; 673ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { 683ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki final XmlSerializer out = new FastXmlSerializer(); 693ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki out.setOutput(baos, StandardCharsets.UTF_16.name()); 703ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki out.startDocument(null, true); 713ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 723ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki out.startTag(null, ROOT_TAG); 733ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki out.attribute(null, ATTR, str); 743ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki out.text(str); 753ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki out.endTag(null, ROOT_TAG); 763ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 773ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki out.endDocument(); 783ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki baos.flush(); 793ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki data = baos.toByteArray(); 803ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } catch (Exception e) { 813ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki Log.e(TAG, "Unable to serialize: " + description, e); 823ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki return false; 833ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 843ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 853ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki if (ENABLE_DUMP) { 863ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki Log.d(TAG, "Dump:"); 873ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki Log.d(TAG, new String(data)); 883ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 893ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 903ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki try (final ByteArrayInputStream baos = new ByteArrayInputStream(data)) { 913ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki XmlPullParser parser = Xml.newPullParser(); 923ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki parser.setInput(baos, StandardCharsets.UTF_16.name()); 933ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 943ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki int type; 953ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki String tag = null; 963ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 973ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki if (type == XmlPullParser.START_TAG) { 983ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki tag = parser.getName(); 993ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki if (ROOT_TAG.equals(tag)) { 1003ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki String read = parser.getAttributeValue(null, ATTR); 1013ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki if (!str.equals(read)) { 1023ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki Log.e(TAG, "Attribute not preserved: " + description 1033ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki + " input=\"" + str + "\", but read=\"" + read + "\""); 1043ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki ok = false; 1053ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1063ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1073ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1083ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki if (type == XmlPullParser.TEXT && ROOT_TAG.equals(tag)) { 1093ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki String read = parser.getText(); 1103ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki if (!str.equals(parser.getText())) { 1113ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki Log.e(TAG, "Text not preserved: " + description 1123ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki + " input=\"" + str + "\", but read=\"" + read + "\""); 1133ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki ok = false; 1143ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1153ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1163ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1173ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } catch (Exception e) { 1183ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki Log.e(TAG, "Unable to parse: " + description, e); 1193ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki return false; 1203ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1213ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki return ok; 1223ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1233ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 1243ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki private boolean check(String description, String str) throws Exception { 1253ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki boolean ok = false; 1263ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki ok |= checkPreserved(description, str); 1273ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki ok |= checkPreserved(description + " wrapped with spaces" ," " + str + " "); 1283ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki return ok; 1293ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1303ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 1313ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki @LargeTest 1323ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki public void testAllCharacters() throws Exception { 1333ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki boolean ok = true; 1343ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki for (int i = 0; i < 0xffff; i++) { 1353ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki if (0xd800 <= i && i <= 0xdfff) { 1363ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki // Surrogate pair characters. 1373ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki continue; 1383ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1393ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki ok &= check("char: " + i, String.valueOf((char) i)); 1403ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1413ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki // Dangling surrogate pairs. We can't preserve them. 1423ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki assertFalse(check("+ud800", "\ud800")); 1433ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki assertFalse(check("+udc00", "\udc00")); 1443ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki 1453ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki for (int i = 0xd800; i < 0xdc00; i ++) { 1463ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki for (int j = 0xdc00; j < 0xe000; j++) { 1473ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki ok &= check("char: " + i, String.valueOf((char) i) + String.valueOf((char) j)); 1483ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1493ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1503ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki assertTrue("Some tests failed. See logcat for details.", ok); 1513ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki } 1523029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey} 153