1 /*
   2  * Copyright (c) 2014, 2017, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package transform;
  25 
  26 import static jaxp.library.JAXPTestUtilities.getSystemProperty;
  27 
  28 import java.io.ByteArrayInputStream;
  29 import java.io.ByteArrayOutputStream;
  30 import java.io.IOException;
  31 import java.io.StringWriter;
  32 
  33 import javax.xml.parsers.DocumentBuilderFactory;
  34 import javax.xml.parsers.ParserConfigurationException;
  35 import javax.xml.parsers.SAXParserFactory;
  36 import javax.xml.stream.XMLInputFactory;
  37 import javax.xml.stream.XMLStreamException;
  38 import javax.xml.transform.Source;
  39 import javax.xml.transform.Transformer;
  40 import javax.xml.transform.TransformerConfigurationException;
  41 import javax.xml.transform.TransformerException;
  42 import javax.xml.transform.TransformerFactory;
  43 import javax.xml.transform.TransformerFactoryConfigurationError;
  44 import javax.xml.transform.dom.DOMResult;
  45 import javax.xml.transform.dom.DOMSource;
  46 import javax.xml.transform.sax.SAXSource;
  47 import javax.xml.transform.stax.StAXSource;
  48 import javax.xml.transform.stream.StreamResult;
  49 
  50 import org.testng.Assert;
  51 import org.testng.AssertJUnit;
  52 import org.testng.annotations.DataProvider;
  53 import org.testng.annotations.Listeners;
  54 import org.testng.annotations.Test;
  55 import org.w3c.dom.Document;
  56 import org.w3c.dom.Element;
  57 import org.w3c.dom.Node;
  58 import org.w3c.dom.NodeList;
  59 import org.xml.sax.ContentHandler;
  60 import org.xml.sax.DTDHandler;
  61 import org.xml.sax.EntityResolver;
  62 import org.xml.sax.ErrorHandler;
  63 import org.xml.sax.InputSource;
  64 import org.xml.sax.SAXException;
  65 import org.xml.sax.SAXNotRecognizedException;
  66 import org.xml.sax.SAXNotSupportedException;
  67 import org.xml.sax.XMLReader;
  68 import org.xml.sax.helpers.AttributesImpl;
  69 
  70 import transform.util.TransformerTestTemplate;
  71 
  72 /*
  73  * @test
  74  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  75  * @run testng/othervm -DrunSecMngr=true transform.TransformerTest
  76  * @run testng/othervm transform.TransformerTest
  77  * @summary Transformer Tests
  78  * @bug 6272879 6305029 6505031 8150704 8162598 8169112 8169631 8169772
  79  */
  80 @Listeners({jaxp.library.FilePolicy.class})
  81 public class TransformerTest {
  82 
  83     // some global constants
  84     private static final String LINE_SEPARATOR =
  85         getSystemProperty("line.separator");
  86 
  87     private static final String NAMESPACES =
  88         "http://xml.org/sax/features/namespaces";
  89 
  90     private static final String NAMESPACE_PREFIXES =
  91         "http://xml.org/sax/features/namespace-prefixes";
  92 
  93     public static class Test6272879 extends TransformerTestTemplate {
  94 
  95         private static String XSL_INPUT =
  96             "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR +
  97             "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" + LINE_SEPARATOR +
  98             "<xsl:output method=\"xml\" indent=\"no\" encoding=\"ISO-8859-1\"/>" + LINE_SEPARATOR +
  99             "<xsl:template match=\"/\">" + LINE_SEPARATOR +
 100             "<xsl:element name=\"TransformateurXML\">" + LINE_SEPARATOR +
 101             "  <xsl:for-each select=\"XMLUtils/test\">" + LINE_SEPARATOR +
 102             "  <xsl:element name=\"test2\">" + LINE_SEPARATOR +
 103             "    <xsl:element name=\"valeur2\">" + LINE_SEPARATOR +
 104             "      <xsl:attribute name=\"attribut2\">" + LINE_SEPARATOR +
 105             "        <xsl:value-of select=\"valeur/@attribut\"/>" + LINE_SEPARATOR +
 106             "      </xsl:attribute>" + LINE_SEPARATOR +
 107             "      <xsl:value-of select=\"valeur\"/>" + LINE_SEPARATOR +
 108             "    </xsl:element>" + LINE_SEPARATOR +
 109             "  </xsl:element>" + LINE_SEPARATOR +
 110             "  </xsl:for-each>" + LINE_SEPARATOR +
 111             "</xsl:element>" + LINE_SEPARATOR +
 112             "</xsl:template>" + LINE_SEPARATOR +
 113             "</xsl:stylesheet>";
 114 
 115         private static String XML_INPUT =
 116             "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR +
 117             // "<!DOCTYPE XMLUtils [" + LINE_SEPARATOR +
 118             // "<!ELEMENT XMLUtils (test*)>" + LINE_SEPARATOR +
 119             // "<!ELEMENT test (valeur*)>" + LINE_SEPARATOR +
 120             // "<!ELEMENT valeur (#PCDATA)>" + LINE_SEPARATOR +
 121             // "<!ATTLIST valeur attribut CDATA #REQUIRED>]>" +
 122             // LINE_SEPARATOR +
 123             "<XMLUtils>" + LINE_SEPARATOR +
 124             "  <test>" + LINE_SEPARATOR +
 125             "    <valeur attribut=\"Attribut 1\">Valeur 1</valeur>" + LINE_SEPARATOR +
 126             "  </test>" + LINE_SEPARATOR +
 127             "  <test>" + LINE_SEPARATOR +
 128             "    <valeur attribut=\"Attribut 2\">Valeur 2</valeur>" + LINE_SEPARATOR +
 129             "  </test>" + LINE_SEPARATOR +
 130             "</XMLUtils>";
 131 
 132         public Test6272879() {
 133             super(XSL_INPUT, XML_INPUT);
 134         }
 135 
 136         /*
 137          * @bug 6272879
 138          * @summary Test for JDK-6272879
 139          *          DomResult had truncated Strings in some places
 140          */
 141         @Test
 142         public void run() throws TransformerException, ClassNotFoundException, InstantiationException,
 143             IllegalAccessException, ClassCastException
 144         {
 145             // print input
 146             printSnippet("Stylesheet:", getXsl());
 147             printSnippet("Source before transformation:", getSourceXml());
 148 
 149             // transform to DOM result
 150             Transformer t = getTransformer();
 151             DOMResult result = new DOMResult();
 152             t.transform(getStreamSource(), result);
 153 
 154             // print output
 155             printSnippet("Result after transformation:", prettyPrintDOMResult(result));
 156 
 157             // do some assertions
 158             Document document = (Document)result.getNode();
 159             NodeList nodes = document.getElementsByTagName("valeur2");
 160             for (int i = 0; i < nodes.getLength(); i++) {
 161                 Node node = nodes.item(i);
 162                 AssertJUnit.assertEquals("Node value mismatch",
 163                                          "Valeur " + (i + 1),
 164                                          node.getFirstChild().getNodeValue());
 165                 AssertJUnit.assertEquals("Node attribute mismatch",
 166                                          "Attribut " + (i + 1),
 167                                          node.getAttributes().item(0).getNodeValue());
 168             }
 169         }
 170     }
 171 
 172     public static class Test6305029 extends TransformerTestTemplate {
 173 
 174         private static String XML_INPUT =
 175             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<prefix:localName xmlns:prefix=\"namespaceUri\"/>";
 176 
 177         // custom XMLReader representing XML_INPUT
 178         private class MyXMLReader implements XMLReader {
 179             private boolean namespaces = true;
 180             private boolean namespacePrefixes = false;
 181             private EntityResolver resolver;
 182             private DTDHandler dtdHandler;
 183             private ContentHandler contentHandler;
 184             private ErrorHandler errorHandler;
 185 
 186             public boolean getFeature(final String name) throws SAXNotRecognizedException, SAXNotSupportedException {
 187                 if (name.equals(NAMESPACES)) {
 188                     return namespaces;
 189                 } else if (name.equals(NAMESPACE_PREFIXES)) {
 190                     return namespacePrefixes;
 191                 } else {
 192                     throw new SAXNotRecognizedException();
 193                 }
 194             }
 195 
 196             public void setFeature(final String name, final boolean value) throws SAXNotRecognizedException, SAXNotSupportedException {
 197                 if (name.equals(NAMESPACES)) {
 198                     namespaces = value;
 199                 } else if (name.equals(NAMESPACE_PREFIXES)) {
 200                     namespacePrefixes = value;
 201                 } else {
 202                     throw new SAXNotRecognizedException();
 203                 }
 204             }
 205 
 206             public Object getProperty(final String name) throws SAXNotRecognizedException, SAXNotSupportedException {
 207                 return null;
 208             }
 209 
 210             public void setProperty(final String name, final Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
 211             }
 212 
 213             public void setEntityResolver(final EntityResolver theResolver) {
 214                 this.resolver = theResolver;
 215             }
 216 
 217             public EntityResolver getEntityResolver() {
 218                 return resolver;
 219             }
 220 
 221             public void setDTDHandler(final DTDHandler theHandler) {
 222                 dtdHandler = theHandler;
 223             }
 224 
 225             public DTDHandler getDTDHandler() {
 226                 return dtdHandler;
 227             }
 228 
 229             public void setContentHandler(final ContentHandler handler) {
 230                 contentHandler = handler;
 231             }
 232 
 233             public ContentHandler getContentHandler() {
 234                 return contentHandler;
 235             }
 236 
 237             public void setErrorHandler(final ErrorHandler handler) {
 238                 errorHandler = handler;
 239             }
 240 
 241             public ErrorHandler getErrorHandler() {
 242                 return errorHandler;
 243             }
 244 
 245             public void parse(final InputSource input) throws IOException, SAXException {
 246                 parse();
 247             }
 248 
 249             public void parse(final String systemId) throws IOException, SAXException {
 250                 parse();
 251             }
 252 
 253             private void parse() throws SAXException {
 254                 contentHandler.startDocument();
 255                 contentHandler.startPrefixMapping("prefix", "namespaceUri");
 256 
 257                 AttributesImpl atts = new AttributesImpl();
 258                 if (namespacePrefixes) {
 259                     atts.addAttribute("", "xmlns:prefix", "xmlns:prefix", "CDATA", "namespaceUri");
 260                 }
 261 
 262                 contentHandler.startElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : "", atts);
 263                 contentHandler.endElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : "");
 264                 contentHandler.endPrefixMapping("prefix");
 265                 contentHandler.endDocument();
 266             }
 267         }
 268 
 269         public Test6305029() {
 270             super(null, XML_INPUT);
 271         }
 272 
 273         /*
 274          * @bug 6305029
 275          * @summary Test for JDK-6305029
 276          *          Test identity transformation
 277          */
 278         @Test
 279         public void run() throws TransformerFactoryConfigurationError, TransformerException {
 280             // get Identity transformer
 281             Transformer t = getTransformer();
 282 
 283             // test SAXSource from custom XMLReader
 284             SAXSource saxSource = new SAXSource(new MyXMLReader(), new InputSource());
 285             StringWriter resultWriter = new StringWriter();
 286             t.transform(saxSource, new StreamResult(resultWriter));
 287             String resultString = resultWriter.toString();
 288             printSnippet("Result after transformation from custom SAXSource:", resultString);
 289             AssertJUnit.assertEquals("Identity transform of SAXSource", getSourceXml(), resultString);
 290 
 291             // test StreamSource
 292             printSnippet("Source before transformation of StreamSource:", getSourceXml());
 293             resultWriter = new StringWriter();
 294             t.transform(getStreamSource(), new StreamResult(resultWriter));
 295             resultString = resultWriter.toString();
 296             printSnippet("Result after transformation of StreamSource:", resultString);
 297             AssertJUnit.assertEquals("Identity transform of StreamSource", getSourceXml(), resultString);
 298         }
 299     }
 300 
 301     public static class Test6505031 extends TransformerTestTemplate {
 302 
 303         public Test6505031() throws IOException {
 304             super();
 305             setXsl(fromInputStream(getClass().getResourceAsStream("transform.xsl")));
 306             setSourceXml(fromInputStream(getClass().getResourceAsStream("template.xml")));
 307         }
 308 
 309         /*
 310          * @bug 6505031
 311          * @summary Test transformer parses keys and their values coming from different xml documents.
 312          */
 313         @Test
 314         public void run() throws TransformerFactoryConfigurationError, TransformerException {
 315             Transformer t = getTransformer();
 316             t.setParameter("config", getClass().getResource("config.xml").toString());
 317             t.setParameter("mapsFile", getClass().getResource("maps.xml").toString());
 318             StringWriter resultWriter = new StringWriter();
 319             t.transform(getStreamSource(), new StreamResult(resultWriter));
 320             String resultString = resultWriter.toString();
 321             Assert.assertTrue(resultString.contains("map1key1value") && resultString.contains("map2key1value"));
 322         }
 323     }
 324 
 325     public static class Test8169631 extends TransformerTestTemplate {
 326 
 327         private static String XSL_INPUT =
 328             "<?xml version=\"1.0\"?>" + LINE_SEPARATOR +
 329             "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" + LINE_SEPARATOR +
 330             "  <xsl:template match=\"/\">" + LINE_SEPARATOR +
 331             "    <xsl:variable name=\"Counter\" select=\"count(//row)\"/>" + LINE_SEPARATOR +
 332             "    <xsl:variable name=\"AttribCounter\" select=\"count(//@attrib)\"/>" + LINE_SEPARATOR +
 333             "    <Counter><xsl:value-of select=\"$Counter\"/></Counter>" + LINE_SEPARATOR +
 334             "    <AttribCounter><xsl:value-of select=\"$AttribCounter\"/></AttribCounter>" + LINE_SEPARATOR +
 335             "  </xsl:template>" + LINE_SEPARATOR +
 336             "</xsl:stylesheet>" + LINE_SEPARATOR;
 337 
 338         private static String XML_INPUT =
 339             "<?xml version=\"1.0\"?>" + LINE_SEPARATOR +
 340             "<envelope xmlns=\"http://www.sap.com/myns\" xmlns:sap=\"http://www.sap.com/myns\">" + LINE_SEPARATOR +
 341             "  <sap:row sap:attrib=\"a\">1</sap:row>" + LINE_SEPARATOR +
 342             "  <row attrib=\"b\">2</row>" + LINE_SEPARATOR +
 343             "  <row sap:attrib=\"c\">3</row>" + LINE_SEPARATOR +
 344             "</envelope>" + LINE_SEPARATOR;
 345 
 346         public Test8169631() {
 347             super(XSL_INPUT, XML_INPUT);
 348         }
 349 
 350         /**
 351          * Utility method to print out transformation result and check values.
 352          *
 353          * @param type
 354          * Text describing type of transformation
 355          * @param result
 356          * Resulting output of transformation
 357          * @param elementCount
 358          * Counter of elements to check
 359          * @param attribCount
 360          * Counter of attributes to check
 361          */
 362         private void verifyResult(String type, String result, int elementCount,
 363                                   int attribCount)
 364         {
 365             printSnippet("Result of transformation from " + type + ":",
 366                          result);
 367             Assert.assertEquals(
 368                 result.contains("<Counter>" + elementCount + "</Counter>"),
 369                 true, "Result of transformation from " + type +
 370                 " should have count of " + elementCount + " elements.");
 371             Assert.assertEquals(
 372                 result.contains("<AttribCounter>" + attribCount +
 373                 "</AttribCounter>"), true, "Result of transformation from " +
 374                 type + " should have count of "+ attribCount + " attributes.");
 375         }
 376 
 377         @DataProvider(name = "testdata8169631")
 378         public Object[][] testData()
 379             throws TransformerConfigurationException, SAXException, IOException,
 380             ParserConfigurationException, XMLStreamException
 381         {
 382             // get Transformers
 383             TransformerFactory tf = TransformerFactory.newInstance();
 384             Transformer t = getTransformer(tf);
 385             Transformer tFromTemplates = getTemplates(tf).newTransformer();
 386 
 387             // get DOMSource objects
 388             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 389             DOMSource domSourceWithoutNS = getDOMSource(dbf);
 390             dbf.setNamespaceAware(true);
 391             DOMSource domSourceWithNS = getDOMSource(dbf);
 392 
 393             // get SAXSource objects
 394             SAXParserFactory spf = SAXParserFactory.newInstance();
 395             SAXSource saxSourceWithoutNS = getSAXSource(spf);
 396             spf.setNamespaceAware(true);
 397             SAXSource saxSourceWithNS = getSAXSource(spf);
 398 
 399             // get StAXSource objects
 400             XMLInputFactory xif = XMLInputFactory.newInstance();
 401             StAXSource staxSourceWithNS = getStAXSource(xif);
 402 
 403             // print XML/XSL snippets to ease understanding of result
 404             printSnippet("Source:", getSourceXml());
 405             printSnippet("Stylesheet:", getXsl());
 406 
 407             return new Object[][] {
 408                 // test StreamSource input with all transformers
 409                 // namespace awareness is set by transformer
 410                 {t, getStreamSource(), "StreamSource with namespace support", 0, 1},
 411                 {tFromTemplates, getStreamSource(), "StreamSource with namespace support using templates", 0, 1},
 412                 // now test DOMSource, SAXSource and StAXSource
 413                 // with rotating use of created transformers
 414                 // namespace awareness is set by source objects
 415                 {t, domSourceWithNS, "DOMSource with namespace support", 0, 1},
 416                 {t, domSourceWithoutNS, "DOMSource without namespace support", 3, 3},
 417                 {tFromTemplates, saxSourceWithNS, "SAXSource with namespace support", 0, 1},
 418                 {tFromTemplates, saxSourceWithoutNS, "SAXSource without namespace support", 3, 3},
 419                 {t, staxSourceWithNS, "StAXSource with namespace support", 0, 1}
 420             };
 421         }
 422 
 423         /*
 424          * @bug 8169631
 425          * @summary Test combinations of namespace awareness settings on
 426          *          XSL transformations
 427          */
 428         @Test(dataProvider = "testdata8169631")
 429         public void run(Transformer t, Source s, String label, int elementcount, int attributecount)
 430             throws TransformerException
 431         {
 432             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 433             t.transform(s, new StreamResult(baos));
 434             verifyResult(label, baos.toString(), elementcount, attributecount);
 435         }
 436     }
 437 
 438     public static class Test8150704 extends TransformerTestTemplate {
 439 
 440         public Test8150704() {
 441             super();
 442         }
 443 
 444         @DataProvider(name = "testdata8150704")
 445         public Object[][] testData() {
 446             return new Object[][] {
 447                 {"Bug8150704-1.xsl", "Bug8150704-1.xml", "Bug8150704-1.ref"},
 448                 {"Bug8150704-2.xsl", "Bug8150704-2.xml", "Bug8150704-2.ref"}
 449             };
 450         }
 451 
 452         /*
 453          * @bug 8150704
 454          * @summary Test that XSL transformation with lots of temporary result
 455          *          trees will not run out of DTM IDs.
 456          */
 457         @Test(dataProvider = "testdata8150704")
 458         public void run(String xsl, String xml, String ref) throws IOException, TransformerException {
 459             System.out.println("Testing transformation of " + xml + "...");
 460             setXsl(fromInputStream(getClass().getResourceAsStream(xsl)));
 461             setSourceXml(fromInputStream(getClass().getResourceAsStream(xml)));
 462             Transformer t = getTransformer();
 463             StringWriter resultWriter = new StringWriter();
 464             t.transform(getStreamSource(), new StreamResult(resultWriter));
 465             String resultString = resultWriter.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n").trim();
 466             String reference = fromInputStream(getClass().getResourceAsStream(ref)).trim();
 467             Assert.assertEquals(resultString, reference, "Output of transformation of " + xml + " does not match reference");
 468             System.out.println("Passed.");
 469         }
 470     }
 471 
 472     public static class Test8162598 extends TransformerTestTemplate {
 473 
 474         private static String XSL_INPUT =
 475             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + LINE_SEPARATOR +
 476             "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" + LINE_SEPARATOR +
 477             "    <xsl:template match=\"/\">" + LINE_SEPARATOR +
 478             "        <root xmlns=\"ns1\">" + LINE_SEPARATOR +
 479             "            <xsl:call-template name=\"transform\"/>" + LINE_SEPARATOR +
 480             "        </root>" + LINE_SEPARATOR +
 481             "    </xsl:template>" + LINE_SEPARATOR +
 482             "    <xsl:template name=\"transform\">" + LINE_SEPARATOR +
 483             "        <test1 xmlns=\"ns2\"><b xmlns=\"ns2\"><c xmlns=\"\"></c></b></test1>" + LINE_SEPARATOR +
 484             "        <test2 xmlns=\"ns1\"><b xmlns=\"ns2\"><c xmlns=\"\"></c></b></test2>" + LINE_SEPARATOR +
 485             "        <test3><b><c xmlns=\"\"></c></b></test3>" + LINE_SEPARATOR +
 486             "        <test4 xmlns=\"\"><b><c xmlns=\"\"></c></b></test4>" + LINE_SEPARATOR +
 487             "        <test5 xmlns=\"ns1\"><b><c xmlns=\"\"></c></b></test5>" + LINE_SEPARATOR +
 488             "        <test6 xmlns=\"\"/>" + LINE_SEPARATOR +
 489             "    </xsl:template>" + LINE_SEPARATOR +
 490             "</xsl:stylesheet>";
 491 
 492         private static String XML_INPUT =
 493             "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aaa></aaa>" + LINE_SEPARATOR;
 494 
 495         public Test8162598() {
 496             super(XSL_INPUT, XML_INPUT);
 497         }
 498 
 499         /**
 500          * Utility method for testBug8162598().
 501          * Provides a convenient way to check/assert the expected namespaces
 502          * of a Node and its siblings.
 503          *
 504          * @param test
 505          * The node to check
 506          * @param nstest
 507          * Expected namespace of the node
 508          * @param nsb
 509          * Expected namespace of the first sibling
 510          * @param nsc
 511          * Expected namespace of the first sibling of the first sibling
 512          */
 513         private void checkNodeNS(Node test, String nstest, String nsb, String nsc) {
 514             String testNodeName = test.getNodeName();
 515             if (nstest == null) {
 516                 Assert.assertNull(test.getNamespaceURI(), "unexpected namespace for " + testNodeName);
 517             } else {
 518                 Assert.assertEquals(test.getNamespaceURI(), nstest, "unexpected namespace for " + testNodeName);
 519             }
 520             Node b = test.getChildNodes().item(0);
 521             if (nsb == null) {
 522                 Assert.assertNull(b.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b");
 523             } else {
 524                 Assert.assertEquals(b.getNamespaceURI(), nsb, "unexpected namespace for " + testNodeName + "->b");
 525             }
 526             Node c = b.getChildNodes().item(0);
 527             if (nsc == null) {
 528                 Assert.assertNull(c.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b->c");
 529             } else {
 530                 Assert.assertEquals(c.getNamespaceURI(), nsc, "unexpected namespace for " + testNodeName + "->b->c");
 531             }
 532         }
 533 
 534         /*
 535          * @bug 8162598
 536          * @summary Test XSLTC handling of namespaces, especially empty namespace
 537          *          definitions to reset the default namespace
 538          */
 539         @Test
 540         public void run()  throws Exception {
 541             // print input
 542             printSnippet("Source:", getSourceXml());
 543             printSnippet("Stylesheet:", getXsl());
 544 
 545             // transform to DOM result
 546             Transformer t = getTransformer();
 547             DOMResult result = new DOMResult();
 548             t.transform(getStreamSource(), result);
 549 
 550             // print output
 551             printSnippet("Result after transformation:", prettyPrintDOMResult(result));
 552 
 553             // do some verifications
 554             Document document = (Document)result.getNode();
 555             checkNodeNS(document.getElementsByTagName("test1").item(0), "ns2", "ns2", null);
 556             checkNodeNS(document.getElementsByTagName("test2").item(0), "ns1", "ns2", null);
 557             checkNodeNS(document.getElementsByTagName("test3").item(0), null, null, null);
 558             checkNodeNS(document.getElementsByTagName("test4").item(0), null, null, null);
 559             checkNodeNS(document.getElementsByTagName("test5").item(0), "ns1", "ns1", null);
 560             Assert.assertNull(document.getElementsByTagName("test6").item(0).getNamespaceURI(),
 561                 "unexpected namespace for test6");
 562         }
 563     }
 564 
 565     public static class Test8169112 extends TransformerTestTemplate{
 566 
 567         public static String XML_INPUT =
 568             "<?xml version=\"1.0\"?><DOCROOT/>";
 569 
 570         public Test8169112() throws IOException {
 571             super();
 572             setXsl(fromInputStream(getClass().getResourceAsStream("Bug8169112.xsl")));
 573             setSourceXml(XML_INPUT);
 574         }
 575 
 576         /**
 577          * @throws TransformerException
 578          * @bug 8169112
 579          * @summary Test compilation of large xsl file with outlining.
 580          *
 581          * This test merely compiles a large xsl file and tests if its bytecode
 582          * passes verification by invoking the transform() method for
 583          * dummy content. The test succeeds if no Exception is thrown
 584          */
 585         @Test
 586         public void run() throws TransformerException {
 587             Transformer t = getTransformer();
 588             t.transform(getStreamSource(), new StreamResult(new ByteArrayOutputStream()));
 589         }
 590     }
 591 
 592     public static class Test8169772 extends TransformerTestTemplate {
 593 
 594         public Test8169772() {
 595             super();
 596         }
 597 
 598         private Document getDOMWithBadElement() throws SAXException, IOException, ParserConfigurationException {
 599             // create a small DOM
 600             Document doc = DocumentBuilderFactory.newInstance().
 601                 newDocumentBuilder().parse(
 602                     new ByteArrayInputStream(
 603                         "<?xml version=\"1.0\"?><DOCROOT/>".getBytes()
 604                     )
 605                 );
 606 
 607             // insert a bad element
 608             Element e = doc.createElement("ERROR");
 609             e.appendChild(doc.createTextNode(null));
 610             doc.getDocumentElement().appendChild(e);
 611 
 612             return doc;
 613         }
 614 
 615         /**
 616          * @throws ParserConfigurationException
 617          * @throws IOException
 618          * @throws SAXException
 619          * @throws TransformerException
 620          * @bug 8169772
 621          * @summary Test transformation of DOM with null valued text node
 622          *
 623          * This test would throw a NullPointerException during transform when the
 624          * fix was not present.
 625          */
 626         @Test
 627         public void run() throws SAXException, IOException, ParserConfigurationException, TransformerException {
 628             Transformer t = getTransformer();
 629             StringWriter resultWriter = new StringWriter();
 630             DOMSource d = new DOMSource(getDOMWithBadElement().getDocumentElement());
 631             t.transform(d, new StreamResult(resultWriter));
 632             printSnippet("Transformation result (DOM with null text node):", resultWriter.toString());
 633         }
 634     }
 635 }