test/jaxp/javax/xml/jaxp/unittest/transform/ErrorListenerTest.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
child 58679 9c3209ff7550
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/transform/ErrorListenerTest.java	Thu Oct 17 20:53:35 2019 +0100
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package transform;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+
+/*
+ * @test
+ * @bug 8157830 8228854
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm transform.ErrorListenerTest
+ * @summary Verifies that ErrorListeners are handled properly
+ */
+public class ErrorListenerTest {
+    static final int SYSTEM_ERR = 1;
+    static final int SYSTEM_OUT = 2;
+    static final String ERR_STDERR = "Msg sent to stderr";
+    static final String ERR_STDOUT = "Msg sent to stdout";
+
+    static final private String INVALID_STYLESHEET = "xxx";
+    static final private String SYSTEM_ID = "http://openjdk_java_net/xsl/dummy.xsl";
+
+    final private String INCLUDE_NOT_EXIST = "<?xml version=\"1.1\" encoding=\"UTF-8\"?>" +
+        "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" +
+        "    <xsl:import href=\"NOSUCHFILE.xsl\"/>" +
+        "</xsl:stylesheet>";
+
+    final private String VAR_UNDEFINED = "<?xml version=\"1.1\" encoding=\"ISO-8859-1\"?>" +
+        "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
+        "    <xsl:template match=\"/\"> " +
+        "        <test1><xsl:apply-templates select=\"$ids\"/></test1>" +
+        "        <test2><xsl:apply-templates select=\"$dummy//ids/id\"/></test2>" +
+        "    </xsl:template>" +
+        "</xsl:stylesheet>";
+    final private String XSL_DOC_FUNCTION = "<?xml version=\"1.1\" encoding=\"ISO-8859-1\"?>" +
+        "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
+        "    <xsl:output method=\"xml\" indent=\"yes\"/>" +
+        "    <xsl:variable name=\"ids\" select=\"//ids//id\"/>" +
+        "    <xsl:variable name=\"dummy\" select=\"document('NOSUCHFILE.xml')\"/>" +
+        "    <xsl:template match=\"/\"> " +
+        "        <test1><xsl:apply-templates select=\"$ids\"/></test1>" +
+        "        <test2><xsl:apply-templates select=\"$dummy//ids/id\"/></test2>" +
+        "    </xsl:template>" +
+        "    <xsl:template match=\"id\">" +
+        "        <xsl:variable name=\"entity\" select=\"id(@value)\"/> " +
+        "        <must-be-one><xsl:value-of select=\"count($entity)\"/></must-be-one>" +
+        "    </xsl:template>" +
+        "</xsl:stylesheet>";
+    final private String XML_DOC_FUNCTION = "<?xml version=\"1.1\" encoding=\"ISO-8859-1\" standalone=\"no\"?>" +
+        "<organization2>" +
+        "    <company id=\"xca\" count=\"2\">" +
+        "        <department id=\"xda\"/>" +
+        "    </company>" +
+        "    <company id=\"xcb\" count=\"0\"/>" +
+        "    <company id=\"xcc\" count=\"5\"/>" +
+        "    <ids>" +
+        "        <id value=\"xca\"/>" +
+        "        <id value=\"xcb\"/>" +
+        "    </ids>" +
+        "</organization2>";
+
+    PrintStream originalErr, originalOut;
+    List<String> testMsgs = new ArrayList<>();
+
+    @BeforeClass
+    public void setUpClass() throws Exception {
+        // save the PrintStream
+        originalErr = System.err;
+        originalOut = System.out;
+    }
+
+    @AfterClass
+    protected void tearDown() throws Exception {
+        // set back to the original
+        System.setErr(originalErr);
+        System.setOut(originalOut);
+        // print out test messages
+        testMsgs.stream().forEach((msg) -> {
+            System.out.println(msg);
+        });
+    }
+
+    /*
+       DataProvider: for ErrorListenner tests
+       Data: xsl, xml, setListener(true/false), output channel(stderr/stdout),
+             expected console output, expected listener output
+     */
+    @DataProvider(name = "testCreatingTransformer")
+    public Object[][] getTransformer() {
+        return new Object[][]{
+            /*
+             * Verifies that the default implementation does not print out
+             * warnings and errors to stderr.
+             */
+            {INCLUDE_NOT_EXIST, false, ""},
+            {VAR_UNDEFINED, false, ""},
+            /*
+             * Verifies that the registered listener is used.
+             */
+            {INCLUDE_NOT_EXIST, true, "NOSUCHFILE.xsl"},
+            {VAR_UNDEFINED, true, "'ids' is undefined"},
+            /*
+             * The original test for JDK8157830
+             * Verifies that when an ErrorListener is registered, parser errors
+             * are passed onto the listener without other output.
+            */
+            {INVALID_STYLESHEET, true, "Content is not allowed in prolog"},
+        };
+    }
+    /*
+       DataProvider: for ErrorListenner tests
+       Data: xsl, xml, setListener(true/false), output channel(stderr/stdout),
+             expected console output, expected listener output
+     */
+    @DataProvider(name = "testTransform")
+    public Object[][] getTransform() {
+        return new Object[][]{
+            /*
+             * Verifies that the default implementation does not print out
+             * warnings and errors to stderr.
+             */
+            {XSL_DOC_FUNCTION, XML_DOC_FUNCTION, false, ""},
+            /*
+             * Verifies that the default implementation does not print out
+             * warnings and errors to stderr.
+             */
+            {XSL_DOC_FUNCTION, XML_DOC_FUNCTION, true, "NOSUCHFILE.xml"}
+        };
+    }
+
+    /*
+       DataProvider: for ErrorListenner tests
+       Data: xsl, xml, setListener(true/false), expected listener output
+     */
+    @DataProvider(name = "testEncoding")
+    public Object[][] getData() {
+        return new Object[][]{
+            {"<foo><bar></bar></foo>", false, ""},
+            {"<foo><bar></bar></foo>", true, "'dummy' is not supported"}
+        };
+    }
+
+    /**
+     * Verifies that ErrorListeners are properly set and propagated, or the
+     * default ErrorListener does not send messages to stderr/stdout.
+     *
+     * @param xsl the stylesheet
+     * @param setListener a flag indicating whether a listener should be set
+     * @param msgL the expected listener output
+     * @throws Exception if the test fails
+     */
+    @Test(dataProvider = "testCreatingTransformer")
+    public void testTransformer(String xsl, boolean setListener, String msgL)
+            throws Exception {
+        ErrListener listener = setListener ? new ErrListener("test") : null;
+        String msgConsole = getTransformerErr("testTransformer", xsl, listener);
+        evalResult(listener, msgConsole, setListener, msgL);
+    }
+
+    /**
+     * Verifies that ErrorListeners are properly set and propagated, or the
+     * default ErrorListener does not send messages to stderr/stdout.
+     *
+     * @param xsl the stylesheet
+     * @param xml the XML
+     * @param setListener a flag indicating whether a listener should be set
+     * @param msgL the expected listener output
+     * @throws Exception if the test fails
+     */
+    //@Test(dataProvider = "testTransform")
+    public void testTransform(String xsl, String xml, boolean setListener, String msgL)
+            throws Exception {
+        ErrListener listener = setListener ? new ErrListener("test") : null;
+        Transformer t = getTransformer("testDocFunc", xsl, listener);
+        String msgConsole = transform("testDocFunc", xml, t);
+        evalResult(listener, msgConsole, setListener, msgL);
+    }
+
+    /**
+     * Verifies that the default implementation does not print out warnings and
+     * errors to the console when an invalid encoding is set.
+     *
+     * @throws Exception if the test fails
+     */
+    //@Test(dataProvider = "testEncoding")
+    public void testEncoding(String xml, boolean setListener, String msgL)
+            throws Exception {
+        ErrListener listener = setListener ? new ErrListener("test") : null;
+        Transformer t = TransformerFactory.newInstance().newTransformer();
+        if (setListener) {
+            t.setErrorListener(listener);
+        }
+        t.setOutputProperty(OutputKeys.ENCODING, "dummy");
+        String msgConsole = transform("testEncoding", "<foo><bar></bar></foo>", t);
+        evalResult(listener, msgConsole, setListener, msgL);
+    }
+
+    private void evalResult(ErrListener l, String m, boolean setListener, String msgL)
+            throws Exception{
+        Assert.assertTrue(!m.contains(ERR_STDERR), "no output to stderr");
+        Assert.assertTrue(!m.contains(ERR_STDOUT), "no output to stdout");
+        if (setListener) {
+            testMsgs.add("l.errMsg=" + l.errMsg);
+            testMsgs.add("evalResult.msgL=" + msgL);
+            Assert.assertTrue(l.errMsg.contains(msgL),
+                    "The registered listener shall be used.");
+        }
+    }
+
+    /**
+     * Obtains a Transformer.
+     *
+     * @param test the name of the test
+     * @param xsl the stylesheet
+     * @param setListener a flag indicating whether to set a listener
+     * @return the Transformer, null if error occurs
+     * @throws Exception
+     */
+    private Transformer getTransformer(String test, String xsl, ErrorListener listener)
+            throws Exception {
+        Transformer f = null;
+        InputSource source = new InputSource(new ByteArrayInputStream(xsl.getBytes()));
+        TransformerFactory factory = TransformerFactory.newInstance();
+        if (listener != null) {
+            factory.setErrorListener(listener);
+        }
+
+        try {
+            f = factory.newTransformer(new SAXSource(source));
+            if (listener != null) {
+                f.setErrorListener(listener);
+            }
+        } catch (TransformerConfigurationException e) {
+            testMsgs.add(test + "::catch: " + e.getMessage());
+        }
+
+        return f;
+    }
+
+    /**
+     * Attempts to capture messages sent to stderr/stdout during the creation
+     * of a Transformer.
+     *
+     * @param test the name of the test
+     * @param xsl the stylesheet
+     * @param setListener a flag indicating whether to set a listener
+     * @return message sent to stderr/stdout, null if none
+     * @throws Exception
+     */
+    private String getTransformerErr(String test, String xsl, ErrorListener listener)
+            throws Exception {
+        InputStream is = new ByteArrayInputStream(xsl.getBytes());
+        InputSource source = new InputSource(is);
+
+        ByteArrayOutputStream baos1 = setOutput(SYSTEM_ERR);
+        ByteArrayOutputStream baos2 = setOutput(SYSTEM_OUT);
+
+        TransformerFactory factory = TransformerFactory.newInstance();
+        if (listener != null) {
+            factory.setErrorListener(listener);
+        }
+
+        try {
+            factory.newTransformer(new SAXSource(source));
+        } catch (TransformerConfigurationException e) {
+            testMsgs.add(test + "::catch: " + e.getMessage());
+        }
+        reset();
+        String msg = !"".equals(baos1.toString()) ? ERR_STDERR : "";
+        msg = !"".equals(baos2.toString()) ? msg + ERR_STDOUT : msg;
+        return msg;
+    }
+
+    /**
+     * Transforms an XML file. Attempts to capture stderr/stdout as the Transformer
+     * may direct messages to stdout.
+     *
+     * @param test the name of the test
+     * @param xml the XML file
+     * @param t the Transformer
+     * @param type the flag indicating which output channel to capture
+     * @return message sent to stdout, null if none
+     * @throws Exception
+     */
+    private String transform(String test, String xml, Transformer t)
+            throws Exception {
+        StreamSource source = new StreamSource(new StringReader(xml));
+        StreamResult result = new StreamResult(new StringWriter());
+        ByteArrayOutputStream baos1 = setOutput(SYSTEM_ERR);
+        ByteArrayOutputStream baos2 = setOutput(SYSTEM_OUT);
+        try {
+            t.transform(source, result);
+        } catch (Exception e) {
+            testMsgs.add(test + "::catch: " + e.getMessage());
+        }
+        reset();
+        String msg = !"".equals(baos1.toString()) ? ERR_STDERR : "";
+        msg = !"".equals(baos2.toString()) ? msg + ERR_STDOUT : msg;
+        return msg;
+    }
+
+    private ByteArrayOutputStream setOutput(int type) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(baos);
+        if (type == SYSTEM_ERR) {
+            System.setErr(ps);
+        } else {
+            System.setOut(ps);
+        }
+        return baos;
+    }
+
+    private void reset() {
+        System.setErr(originalErr);
+        System.setOut(originalOut);
+    }
+
+    class ErrListener implements ErrorListener {
+        String testName;
+        String errMsg = "";
+        ErrListener(String test) {
+            testName = test;
+        }
+
+        @Override
+        public void error(TransformerException e)
+                throws TransformerException {
+            errMsg = errMsg + "#error: " + e.getMessage();
+        }
+
+        @Override
+        public void fatalError(TransformerException e)
+                throws TransformerException {
+            errMsg = errMsg + "#fatalError: " + e.getMessage();
+        }
+
+        @Override
+        public void warning(TransformerException e)
+                throws TransformerException {
+            errMsg = errMsg + "#warning: " + e.getMessage();
+        }
+    }
+}