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
24package transform;
25
26import static jaxp.library.JAXPTestUtilities.getSystemProperty;
27
28import java.io.ByteArrayInputStream;
29import java.io.ByteArrayOutputStream;
30import java.io.IOException;
31import java.io.StringWriter;
32
33import javax.xml.parsers.DocumentBuilderFactory;
34import javax.xml.parsers.ParserConfigurationException;
35import javax.xml.parsers.SAXParserFactory;
36import javax.xml.stream.XMLInputFactory;
37import javax.xml.stream.XMLStreamException;
38import javax.xml.transform.Source;
39import javax.xml.transform.Transformer;
40import javax.xml.transform.TransformerConfigurationException;
41import javax.xml.transform.TransformerException;
42import javax.xml.transform.TransformerFactory;
43import javax.xml.transform.TransformerFactoryConfigurationError;
44import javax.xml.transform.dom.DOMResult;
45import javax.xml.transform.dom.DOMSource;
46import javax.xml.transform.sax.SAXSource;
47import javax.xml.transform.stax.StAXSource;
48import javax.xml.transform.stream.StreamResult;
49
50import org.testng.Assert;
51import org.testng.AssertJUnit;
52import org.testng.annotations.DataProvider;
53import org.testng.annotations.Listeners;
54import org.testng.annotations.Test;
55import org.w3c.dom.Document;
56import org.w3c.dom.Element;
57import org.w3c.dom.Node;
58import org.w3c.dom.NodeList;
59import org.xml.sax.ContentHandler;
60import org.xml.sax.DTDHandler;
61import org.xml.sax.EntityResolver;
62import org.xml.sax.ErrorHandler;
63import org.xml.sax.InputSource;
64import org.xml.sax.SAXException;
65import org.xml.sax.SAXNotRecognizedException;
66import org.xml.sax.SAXNotSupportedException;
67import org.xml.sax.XMLReader;
68import org.xml.sax.helpers.AttributesImpl;
69
70import 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})
81public 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}
636