1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package libcore.xml; 18 19import java.io.ByteArrayOutputStream; 20import java.io.IOException; 21import java.io.StringWriter; 22import junit.framework.TestCase; 23import org.kxml2.io.KXmlSerializer; 24import org.w3c.dom.Document; 25import org.w3c.dom.NodeList; 26import org.xmlpull.v1.XmlSerializer; 27import static tests.support.Support_Xml.domOf; 28 29public final class KxmlSerializerTest extends TestCase { 30 private static final String NAMESPACE = null; 31 32 public void testWhitespaceInAttributeValue() throws Exception { 33 StringWriter stringWriter = new StringWriter(); 34 XmlSerializer serializer = new KXmlSerializer(); 35 serializer.setOutput(stringWriter); 36 serializer.startDocument("UTF-8", null); 37 serializer.startTag(NAMESPACE, "a"); 38 serializer.attribute(NAMESPACE, "cr", "\r"); 39 serializer.attribute(NAMESPACE, "lf", "\n"); 40 serializer.attribute(NAMESPACE, "tab", "\t"); 41 serializer.attribute(NAMESPACE, "space", " "); 42 serializer.endTag(NAMESPACE, "a"); 43 serializer.endDocument(); 44 assertXmlEquals("<a cr=\" \" lf=\" \" tab=\"	\" space=\" \" />", 45 stringWriter.toString()); 46 } 47 48 public void testWriteDocument() throws Exception { 49 StringWriter stringWriter = new StringWriter(); 50 XmlSerializer serializer = new KXmlSerializer(); 51 serializer.setOutput(stringWriter); 52 serializer.startDocument("UTF-8", null); 53 serializer.startTag(NAMESPACE, "foo"); 54 serializer.attribute(NAMESPACE, "quux", "abc"); 55 serializer.startTag(NAMESPACE, "bar"); 56 serializer.endTag(NAMESPACE, "bar"); 57 serializer.startTag(NAMESPACE, "baz"); 58 serializer.endTag(NAMESPACE, "baz"); 59 serializer.endTag(NAMESPACE, "foo"); 60 serializer.endDocument(); 61 assertXmlEquals("<foo quux=\"abc\"><bar /><baz /></foo>", stringWriter.toString()); 62 } 63 64 // http://code.google.com/p/android/issues/detail?id=21250 65 public void testWriteSpecialCharactersInText() throws Exception { 66 StringWriter stringWriter = new StringWriter(); 67 XmlSerializer serializer = new KXmlSerializer(); 68 serializer.setOutput(stringWriter); 69 serializer.startDocument("UTF-8", null); 70 serializer.startTag(NAMESPACE, "foo"); 71 serializer.text("5'8\", 5 < 6 & 7 > 3!"); 72 serializer.endTag(NAMESPACE, "foo"); 73 serializer.endDocument(); 74 assertXmlEquals("<foo>5'8\", 5 < 6 & 7 > 3!</foo>", stringWriter.toString()); 75 } 76 77 private void assertXmlEquals(String expectedXml, String actualXml) throws Exception { 78 String declaration = "<?xml version='1.0' encoding='UTF-8' ?>"; 79 assertEquals(declaration + expectedXml, actualXml); 80 } 81 82 private static XmlSerializer newSerializer() throws IOException { 83 ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 84 XmlSerializer serializer = new KXmlSerializer(); 85 serializer.setOutput(bytesOut, "UTF-8"); 86 serializer.startDocument("UTF-8", null); 87 return serializer; 88 } 89 90 public void testInvalidCharactersInText() throws IOException { 91 XmlSerializer serializer = newSerializer(); 92 serializer.startTag(NAMESPACE, "root"); 93 for (int ch = 0; ch <= 0xffff; ++ch) { 94 final String s = Character.toString((char) ch); 95 if (isValidXmlCodePoint(ch)) { 96 serializer.text("a" + s + "b"); 97 } else { 98 try { 99 serializer.text("a" + s + "b"); 100 fail(s); 101 } catch (IllegalArgumentException expected) { 102 } 103 } 104 } 105 serializer.endTag(NAMESPACE, "root"); 106 } 107 108 public void testInvalidCharactersInAttributeValues() throws IOException { 109 XmlSerializer serializer = newSerializer(); 110 serializer.startTag(NAMESPACE, "root"); 111 for (int ch = 0; ch <= 0xffff; ++ch) { 112 final String s = Character.toString((char) ch); 113 if (isValidXmlCodePoint(ch)) { 114 serializer.attribute(NAMESPACE, "a", "a" + s + "b"); 115 } else { 116 try { 117 serializer.attribute(NAMESPACE, "a", "a" + s + "b"); 118 fail(s); 119 } catch (IllegalArgumentException expected) { 120 } 121 } 122 } 123 serializer.endTag(NAMESPACE, "root"); 124 } 125 126 public void testInvalidCharactersInCdataSections() throws IOException { 127 XmlSerializer serializer = newSerializer(); 128 serializer.startTag(NAMESPACE, "root"); 129 for (int ch = 0; ch <= 0xffff; ++ch) { 130 final String s = Character.toString((char) ch); 131 if (isValidXmlCodePoint(ch)) { 132 serializer.cdsect("a" + s + "b"); 133 } else { 134 try { 135 serializer.cdsect("a" + s + "b"); 136 fail(s); 137 } catch (IllegalArgumentException expected) { 138 } 139 } 140 } 141 serializer.endTag(NAMESPACE, "root"); 142 } 143 144 public void testCdataWithTerminatorInside() throws Exception { 145 StringWriter writer = new StringWriter(); 146 XmlSerializer serializer = new KXmlSerializer(); 147 serializer.setOutput(writer); 148 serializer.startDocument("UTF-8", null); 149 serializer.startTag(NAMESPACE, "p"); 150 serializer.cdsect("a]]>b"); 151 serializer.endTag(NAMESPACE, "p"); 152 serializer.endDocument(); 153 // Adjacent CDATA sections aren't merged, so let's stick them together ourselves... 154 Document doc = domOf(writer.toString()); 155 NodeList children = doc.getFirstChild().getChildNodes(); 156 String text = ""; 157 for (int i = 0; i < children.getLength(); ++i) { 158 text += children.item(i).getNodeValue(); 159 } 160 assertEquals("a]]>b", text); 161 } 162 163 private static boolean isValidXmlCodePoint(int c) { 164 // http://www.w3.org/TR/REC-xml/#charsets 165 return (c >= 0x20 && c <= 0xd7ff) || (c == 0x9) || (c == 0xa) || (c == 0xd) || 166 (c >= 0xe000 && c <= 0xfffd) || (c >= 0x10000 && c <= 0x10ffff); 167 } 168} 169