From 6d487f722c1b9af161c08baab694357f3ffcf4e8 Mon Sep 17 00:00:00 2001 From: aefimov Date: Mon, 24 Oct 2016 17:02:34 +0300 Subject: [PATCH] 8167179: Make XSL generated namespace prefixes local to transformation process Reviewed-by: joehw --- .../8167179/NamespacePrefixTest.java | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 test/javax/xml/jaxp/transform/8167179/NamespacePrefixTest.java diff --git a/test/javax/xml/jaxp/transform/8167179/NamespacePrefixTest.java b/test/javax/xml/jaxp/transform/8167179/NamespacePrefixTest.java new file mode 100644 index 000000000..62446419b --- /dev/null +++ b/test/javax/xml/jaxp/transform/8167179/NamespacePrefixTest.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2016, 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. + */ + +import java.io.StringReader; +import java.io.StringWriter; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.xml.transform.Source; +import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.testng.annotations.Test; +import static org.testng.Assert.assertTrue; + +/* + * @test + * @bug 8167179 + * @run testng/othervm NamespacePrefixTest + * @summary This class tests the generation of namespace prefixes + */ +public class NamespacePrefixTest { + + @Test + public void testReuseTemplates() throws Exception { + final TransformerFactory tf = TransformerFactory.newInstance(); + final Source xslsrc = new StreamSource(new StringReader(XSL)); + final Templates tmpl = tf.newTemplates(xslsrc); + for (int i = 0; i < TRANSF_COUNT; i++) { + checkResult(doTransformation(tmpl.newTransformer())); + } + } + + @Test + public void testReuseTransformer() throws Exception { + final TransformerFactory tf = TransformerFactory.newInstance(); + final Source xslsrc = new StreamSource(new StringReader(XSL)); + final Transformer t = tf.newTransformer(xslsrc); + for (int i = 0; i < TRANSF_COUNT; i++) { + checkResult(doTransformation(t)); + } + } + + @Test + public void testConcurrentTransformations() throws Exception { + final TransformerFactory tf = TransformerFactory.newInstance(); + final Source xslsrc = new StreamSource(new StringReader(XSL)); + final Templates tmpl = tf.newTemplates(xslsrc); + concurrentTestPassed.set(true); + + // Execute multiple TestWorker tasks + for (int id = 0; id < THREADS_COUNT; id++) { + EXECUTOR.execute(new TransformerThread(tmpl.newTransformer(), id)); + } + // Initiate shutdown of previously submitted task + EXECUTOR.shutdown(); + // Wait for termination of submitted tasks + if (!EXECUTOR.awaitTermination(THREADS_COUNT, TimeUnit.SECONDS)) { + // If not all tasks terminates during the time out force them to shutdown + EXECUTOR.shutdownNow(); + } + // Check if all transformation threads generated the correct namespace prefix + assertTrue(concurrentTestPassed.get()); + } + + // Do one transformation with the provided transformer + private static String doTransformation(Transformer t) throws Exception { + StringWriter resWriter = new StringWriter(); + Source xmlSrc = new StreamSource(new StringReader(XML)); + t.transform(xmlSrc, new StreamResult(resWriter)); + return resWriter.toString(); + } + + // Check if the transformation result string contains the + // element with the exact namespace prefix generated. + private static void checkResult(String result) { + // Check prefix of 'Element2' element, it should always be the same + assertTrue(result.contains(EXPECTED_CONTENT)); + } + + // Check if the transformation result string contains the element with + // the exact namespace prefix generated by current thread. + // If the expected prefix is not found and there was no failures observed by + // other test threads then mark concurrent test as failed. + private static void checkThreadResult(String result, int id) { + boolean res = result.contains(EXPECTED_CONTENT); + System.out.printf("%d: transformation result: %s%n", id, res ? "Pass" : "Fail"); + if (!res) { + System.out.printf("%d result:%s%n", id, result); + } + concurrentTestPassed.compareAndSet(true, res); + } + + // TransformerThread task that does the transformation similar + // to testReuseTransformer test method + private class TransformerThread implements Runnable { + + private final Transformer transformer; + private final int id; + + TransformerThread(Transformer transformer, int id) { + this.transformer = transformer; + this.id = id; + } + + @Override + public void run() { + try { + System.out.printf("%d: waiting for barrier%n", id); + //Synchronize startup of all tasks + BARRIER.await(); + System.out.printf("%d: starting transformation%n", id); + checkThreadResult(doTransformation(transformer), id); + } catch (Exception ex) { + throw new RuntimeException("TransformerThread " + id + " failed", ex); + } + } + } + + // Number of subsequent transformations + private static final int TRANSF_COUNT = 10; + + // Number of transformer threads running concurently + private static final int THREADS_COUNT = 10; + + // Variable for storing the concurrent transformation test result. It is + // updated by transformer threads + private static final AtomicBoolean concurrentTestPassed = new AtomicBoolean(true); + + // Cyclic barrier for threads startup synchronization + private static final CyclicBarrier BARRIER = new CyclicBarrier(THREADS_COUNT); + + // Thread pool + private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool(); + + // XSL that transforms XML and produces unique namespace prefixes for each element + private final static String XSL = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + // Simple XML content with root and two child elements + private final static String XML = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + // With thread local namespace prefix index each transformation result should + // be the same and contain the same prefix for Element2 + private final static String EXPECTED_CONTENT = ""; + +} -- GitLab