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 * @test 50 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest 51 * @run testng/othervm -DrunSecMngr=true stream.XMLStreamWriterTest.SurrogatesTest 52 * @run testng/othervm stream.XMLStreamWriterTest.SurrogatesTest 53 * @summary Check that XMLStreamWriter generates valid xml with surrogate pair 54 * used within element text 55 */ 56 57 @Listeners({jaxp.library.BasePolicy.class}) 58 public class SurrogatesTest { 59 60 // Test that valid surrogate characters can be written/readen by xml stream 61 // reader/writer 62 @Test(dataProvider = "validData") 63 public void xmlWithValidSurrogatesTest(String content) 64 throws Exception { 65 generateAndReadXml(content); 66 } 67 68 // Test that unbalanced surrogate character will 69 @Test(dataProvider = "invalidData", 70 expectedExceptions = XMLStreamException.class) 71 public void xmlWithUnbalancedSurrogatesTest(String content) 72 throws Exception { 73 generateAndReadXml(content); 74 } 75 76 // Generates xml content with XMLStreamWriter and read it to check 77 // for correctness of xml and generated data 78 void generateAndReadXml(String content) throws Exception { 79 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 80 XMLOutputFactory factory = XMLOutputFactory.newInstance(); 81 OutputStreamWriter streamWriter = new OutputStreamWriter(stream); 82 XMLStreamWriter writer = factory.createXMLStreamWriter(streamWriter); 83 84 // Generate xml with selected stream writer type 85 generateXML(writer, content); 86 String output = stream.toString(); 87 System.out.println("Generated xml: " + output); 88 // Read generated xml with StAX parser 89 readXML(output.getBytes(), content); 90 } 91 92 // Generates XML with provided xml stream writer. Provided string 93 // is inserted into xml twice: with usage of writeCharacters( String ) 94 // and writeCharacters( char [], int , int ) 95 private void generateXML(XMLStreamWriter writer, String sequence) 96 throws XMLStreamException { 97 char[] seqArr = sequence.toCharArray(); 98 writer.writeStartDocument(); 99 writer.writeStartElement("root"); 100 101 // Use writeCharacters( String ) to write characters 102 writer.writeStartElement("writeCharactersWithString"); 103 writer.writeCharacters(sequence); 104 writer.writeEndElement(); 105 106 // Use writeCharacters( char [], int , int ) to write characters 107 writer.writeStartElement("writeCharactersWithArray"); 108 writer.writeCharacters(seqArr, 0, seqArr.length); 109 writer.writeEndElement(); 110 111 // Close root element and document 112 writer.writeEndElement(); 113 writer.writeEndDocument(); 114 writer.flush(); 115 writer.close(); 116 } 117 118 // Reads generated XML data and check if it contains expected 119 // text in writeCharactersWithString and writeCharactersWithArray 120 // elements 121 private void readXML(byte[] xmlData, String expectedContent) 122 throws Exception { 123 InputStream stream = new ByteArrayInputStream(xmlData); 124 XMLInputFactory factory = XMLInputFactory.newInstance(); 125 XMLStreamReader xmlReader 126 = factory.createXMLStreamReader(stream); 127 boolean inTestElement = false; 128 StringBuilder sb = new StringBuilder(); 129 while (xmlReader.hasNext()) { 130 String ename; 131 switch (xmlReader.getEventType()) { 132 case XMLStreamConstants.START_ELEMENT: 133 ename = xmlReader.getLocalName(); 134 if (ename.equals("writeCharactersWithString") 135 || ename.equals("writeCharactersWithArray")) { 136 inTestElement = true; 137 } 138 break; 139 case XMLStreamConstants.END_ELEMENT: 140 ename = xmlReader.getLocalName(); 141 if (ename.equals("writeCharactersWithString") 142 || ename.equals("writeCharactersWithArray")) { 143 inTestElement = false; 144 String content = sb.toString(); 145 System.out.println(ename + " text:'" + content + "' expected:'" + expectedContent+"'"); 146 Assert.assertEquals(content, expectedContent); 147 sb.setLength(0); 148 } 149 break; 150 case XMLStreamConstants.CHARACTERS: 151 if (inTestElement) { 152 sb.append(xmlReader.getText()); 153 } 154 break; 155 } 156 xmlReader.next(); 157 } 158 } 159 160 @DataProvider(name = "validData") 161 public Object[][] getValidData() { 162 return new Object[][] { 163 {"Don't Worry Be \uD83D\uDE0A"}, 164 {"BMP characters \uE000\uFFFD"}, 165 {"Simple text"}, 166 }; 167 } 168 169 @DataProvider(name = "invalidData") 170 public Object[][] getInvalidData() { 171 return new Object[][] { 172 {"Unbalanced surrogate \uD83D"}, 173 {"Unbalanced surrogate \uD83Dis here"}, 174 {"Surrogate with followup BMP\uD83D\uFFF9"}, 175 }; 176 } 177 }