1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package stream.XMLStreamWriterTest; 27 28 import java.io.ByteArrayInputStream; 29 import java.io.ByteArrayOutputStream; 30 import java.io.InputStream; 31 import java.io.OutputStreamWriter; 32 33 import javax.xml.stream.XMLInputFactory; 34 import javax.xml.stream.XMLOutputFactory; 35 import javax.xml.stream.XMLStreamConstants; 36 import javax.xml.stream.XMLStreamException; 37 import javax.xml.stream.XMLStreamReader; 38 import javax.xml.stream.XMLStreamWriter; 39 40 import org.testng.Assert; 41 import org.testng.annotations.Listeners; 42 import org.testng.annotations.Test; 43 import org.testng.annotations.DataProvider; 44 45 /* 46 * @test 47 * @bug 8145974 48 * @modules javax.xml 49 * @summary Check that XMLStreamWriter generates valid xml with surrogate pair 50 * used within element text 51 */ 52 53 @Listeners({jaxp.library.BasePolicy.class}) 54 public class SurrogatesTest { 55 56 // Test that valid surrogate characters can be written/readen by xml stream 57 // reader/writer 58 @Test(dataProvider = "validData") 59 public void xmlWithValidSurrogatesTest(String content) 60 throws Exception { 61 generateAndReadXml(content); 62 } 63 64 // Test that unbalanced surrogate character will 65 @Test(dataProvider = "invalidData", 66 expectedExceptions = XMLStreamException.class) 67 public void xmlWithUnbalancedSurrogatesTest(String content) 68 throws Exception { 69 generateAndReadXml(content); 70 } 71 72 // Generates xml content with XMLStreamWriter and read it to check 73 // for correctness of xml and generated data 74 void generateAndReadXml(String content) throws Exception { 75 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 76 XMLOutputFactory factory = XMLOutputFactory.newInstance(); 77 OutputStreamWriter streamWriter = new OutputStreamWriter(stream); 78 XMLStreamWriter writer = factory.createXMLStreamWriter(streamWriter); 79 80 // Generate xml with selected stream writer type 81 generateXML(writer, content); 82 String output = stream.toString(); 83 System.out.println("Generated xml: " + output); 84 // Read generated xml with StAX parser 85 readXML(output.getBytes(), content); 86 } 87 88 // Generates XML with provided xml stream writer. Provided string 89 // is inserted into xml twice: with usage of writeCharacters( String ) 90 // and writeCharacters( char [], int , int ) 91 private void generateXML(XMLStreamWriter writer, String sequence) 92 throws XMLStreamException { 93 char[] seqArr = sequence.toCharArray(); 94 writer.writeStartDocument(); 95 writer.writeStartElement("root"); 96 97 // Use writeCharacters( String ) to write characters 98 writer.writeStartElement("writeCharactersWithString"); 99 writer.writeCharacters(sequence); 100 writer.writeEndElement(); 101 102 // Use writeCharacters( char [], int , int ) to write characters 103 writer.writeStartElement("writeCharactersWithArray"); 104 writer.writeCharacters(seqArr, 0, seqArr.length); 105 writer.writeEndElement(); 106 107 // Close root element and document 108 writer.writeEndElement(); 109 writer.writeEndDocument(); 110 writer.flush(); 111 writer.close(); 112 } 113 114 // Reads generated XML data and check if it contains expected 115 // text in writeCharactersWithString and writeCharactersWithArray 116 // elements 117 private void readXML(byte[] xmlData, String expectedContent) 118 throws Exception { 119 InputStream stream = new ByteArrayInputStream(xmlData); 120 XMLInputFactory factory = XMLInputFactory.newInstance(); 121 XMLStreamReader xmlReader 122 = factory.createXMLStreamReader(stream); 123 boolean inTestElement = false; 124 StringBuilder sb = new StringBuilder(); 125 while (xmlReader.hasNext()) { 126 String ename; 127 switch (xmlReader.getEventType()) { 128 case XMLStreamConstants.START_ELEMENT: 129 ename = xmlReader.getLocalName(); 130 if (ename.equals("writeCharactersWithString") 131 || ename.equals("writeCharactersWithArray")) { 132 inTestElement = true; 133 } 134 break; 135 case XMLStreamConstants.END_ELEMENT: 136 ename = xmlReader.getLocalName(); 137 if (ename.equals("writeCharactersWithString") 138 || ename.equals("writeCharactersWithArray")) { 139 inTestElement = false; 140 String content = sb.toString(); 141 System.out.println(ename + " text:'" + content + "' expected:'" + expectedContent+"'"); 142 Assert.assertEquals(content, expectedContent); 143 sb.setLength(0); 144 } 145 break; 146 case XMLStreamConstants.CHARACTERS: 147 if (inTestElement) { 148 sb.append(xmlReader.getText()); 149 } 150 break; 151 } 152 xmlReader.next(); 153 } 154 } 155 156 @DataProvider(name = "validData") 157 Object[][] getValidData() { 158 return new Object[][] { 159 {"Don't Worry Be \uD83D\uDE0A"}, 160 {"BMP characters \uE000\uFFFD"}, 161 {"Simple text"}, 162 }; 163 } 164 165 @DataProvider(name = "invalidData") 166 Object[][] getInvalidData() { 167 return new Object[][] { 168 {"Unbalanced surrogate \uD83D"}, 169 {"Unbalanced surrogate \uD83Dis here"}, 170 {"Surrogate with followup BMP\uD83D\uFFF9"}, 171 }; 172 } 173 }