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