1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package org.apache.qetest.trax;
  21 
  22 import java.io.FileOutputStream;
  23 import java.io.IOException;
  24 import java.nio.charset.Charset;
  25 import java.nio.charset.StandardCharsets;
  26 import java.util.Properties;
  27 import javax.xml.transform.OutputKeys;
  28 import javax.xml.transform.Templates;
  29 import javax.xml.transform.Transformer;
  30 import javax.xml.transform.TransformerConfigurationException;
  31 import javax.xml.transform.TransformerException;
  32 import javax.xml.transform.TransformerFactory;
  33 import javax.xml.transform.stream.StreamResult;
  34 import javax.xml.transform.stream.StreamSource;
  35 import jaxp.library.JAXPFileBaseTest;
  36 import static jaxp.library.JAXPTestUtilities.compareWithGold;
  37 import static jaxp.library.JAXPTestUtilities.filenameToURL;
  38 import static org.apache.qetest.trax.TraxConst.GOLDEN_DIR;
  39 import static org.apache.qetest.trax.TraxConst.XML_DIR;
  40 import static jaxp.library.JAXPTestUtilities.getNextFile;
  41 import static org.testng.Assert.assertEquals;
  42 import static org.testng.Assert.assertNotNull;
  43 import static org.testng.Assert.assertNull;
  44 import static org.testng.Assert.assertTrue;
  45 import org.testng.annotations.DataProvider;
  46 import org.testng.annotations.Test;
  47 
  48 /**
  49  * Basic API coverage test for the Transformer class of TRAX.
  50  * This test focuses on coverage testing for the API's, and
  51  * very brief functional testing.
  52  */
  53 public class TransformerAPITest extends JAXPFileBaseTest {
  54      /** 
  55       * Parameter names from TransformerAPIParam.xsl  
  56       */
  57     private static final String PARAM1S = "param1s";
  58     
  59     /** 
  60       * Parameter names from TransformerAPIParam.xsl  
  61       */
  62     private static final String PARAM3S = "param3s";
  63     
  64     /** 
  65      * Parameter names from TransformerAPIParam.xsl  
  66      */
  67     private static final String PARAM1N = "param1n";
  68     
  69     /**
  70      * TransformerFactory for creating Transfomer.
  71      */
  72     private final TransformerFactory factory;
  73     
  74     /**
  75      * Initiate Transformer factory.
  76      */
  77     public TransformerAPITest() {
  78         factory = TransformerFactory.newInstance();
  79     }
  80     
  81     /** 
  82      * Known outputFormat values from TransformerAPIOutputFormat.xsl .
  83      */
  84     private static final String METHOD_VALUE = "xml";
  85     private static final String VERSION_VALUE ="123.45";
  86     private static final String ENCODING_VALUE ="UTF-16";
  87     private static final String STANDALONE_VALUE = "yes";
  88     private static final String DOCTYPE_PUBLIC_VALUE = "this-is-doctype-public";
  89     private static final String DOCTYPE_SYSTEM_VALUE = "this-is-doctype-system";
  90     private static final String CDATA_SECTION_ELEMENTS_VALUE = "cdataHere ";
  91     private static final String INDENT_VALUE  =  "yes";
  92     private static final String MEDIA_TYPE_VALUE = "text/test/xml";
  93     private static final String OMIT_XML_DECLARATION_VALUE = "yes";
  94     
  95     /**
  96      * Basic API coverage tests for Transformer API.
  97      * 
  98      * @throws TransformerConfigurationException When it is not possible to 
  99      *         create a Transformer instance.
 100      * @throws IOException if any I/O operation error.
 101      * @throws TransformerException If an unrecoverable error occurs during the 
 102      *         course of the transformation. 
 103      */
 104     @Test
 105     public void testCase1() throws TransformerConfigurationException, 
 106             IOException, TransformerException {
 107         String xmlFile = filenameToURL(XML_DIR + "TransformerAPIParam.xml");
 108         String xslFile = filenameToURL(XML_DIR + "TransformerAPIParam.xsl");
 109         String goldFile= GOLDEN_DIR + "TransformerAPIParam.out";
 110 
 111         Transformer identityTransformer = factory.newTransformer();
 112         Templates templates = factory.newTemplates(new StreamSource(xslFile));
 113         assertNull(identityTransformer.getParameter("This-param-does-not-exist"));
 114 
 115         identityTransformer.setParameter("foo", "bar");
 116         assertNotNull(identityTransformer.getParameter("foo"));
 117 
 118         Transformer transformer = templates.newTransformer();
 119         // Default Transformer should not have any parameters.
 120         assertNull(transformer.getParameter("This-param-does-not-exist"));
 121         // Including params in the stylesheet, Javadoc says "This method does
 122         // not return a default parameter value, which cannot be determined 
 123         // until the node context is evaluated during the transformation process".
 124         assertNull(transformer.getParameter(PARAM1S));
 125 
 126         // Verify simple set/get of a single parameter - Integer
 127         transformer.setParameter(PARAM3S, 1234);
 128         assertEquals(transformer.getParameter(PARAM3S), 1234);
 129 
 130         transformer.setParameter(PARAM3S, 99);   // Had bug can't re-set
 131         assertEquals(transformer.getParameter(PARAM3S), 99);
 132         
 133         // Verify simple re-set/get of a single parameter - now a new String
 134         transformer.setParameter(PARAM3S, "new value3s");
 135         assertEquals(transformer.getParameter(PARAM3S), "new value3s");
 136         
 137         transformer.setParameter(PARAM1S, "'test-param-1s'"); // note single quotes
 138         transformer.setParameter(PARAM1N, 1234);
 139         
 140         
 141         // Verify basic params actually affect transformation
 142         //   Use the transformer we set the params onto above!
 143         String outputFile = getNextFile(this.getClass());
 144         try (FileOutputStream fos = new FileOutputStream(outputFile);) {
 145             transformer.transform(new StreamSource(xmlFile),
 146                             new StreamResult(fos));
 147         }
 148         assertTrue(compareWithGold(goldFile, outputFile));
 149         assertEquals(transformer.getParameter(PARAM1S), "'test-param-1s'");
 150         assertEquals(transformer.getParameter(PARAM1N), 1234);
 151     }
 152     
 153     /**
 154      * API coverage test of Transformer.set/getOutputProperty().
 155      * 
 156      * @param xslFile XSLT file we will use.
 157      * @param xmlFile XML test file.
 158      * @param goldFile golden validation file.
 159      * @param expectedProperties expected result.
 160      * @throws TransformerException When it is not possible to create a 
 161      *         Transformer instance or an unrecoverable error occurs during
 162      *         the course of the transformation..
 163      * @throws IOException if an I/O error occurs reading from the file or a 
 164      *         malformed or unmappable byte sequence is read.
 165      */
 166     @Test(dataProvider="propertiesDataProvider")
 167     public void testCase2(String xslFile, String xmlFile, String goldFile,
 168             String[] expectedProperties) throws TransformerException, IOException {
 169         Transformer transformer = factory.newTemplates(new StreamSource(xslFile)).newTransformer();
 170         Properties props = transformer.getOutputProperties();
 171         // Default uses UTF8 as encoding.
 172         Charset cs = StandardCharsets.UTF_8;
 173         for(int i = 0; i < expectedProperties.length; i = i + 2) {
 174             assertEquals(props.get(expectedProperties[i]), 
 175                     expectedProperties[i + 1]);
 176             if(expectedProperties[i].equals(OutputKeys.ENCODING)) {
 177                 cs = Charset.forName(expectedProperties[i + 1]);
 178             }
 179         }
 180         // Always do set/get testing on default Transformer.
 181         Transformer defaultTransformer = factory.newTransformer();
 182         defaultTransformer.setOutputProperty(OutputKeys.METHOD, "text");
 183         assertEquals(defaultTransformer.getOutputProperty(OutputKeys.METHOD), "text"); 
 184         
 185         String outputFile = getNextFile(this.getClass());
 186         transformer.transform(new StreamSource(xmlFile), new StreamResult(outputFile));
 187         assertTrue(compareWithGold(goldFile, outputFile, cs));
 188     }
 189     
 190     /**
 191      * Data provider for testCase2.
 192      * 
 193      * @return an array that has parameters XSL file,XML file, golden validation
 194      *         file, expected properties.
 195      */
 196     @DataProvider
 197     public Object[][] propertiesDataProvider(){
 198         return new Object[][]{
 199             {XML_DIR + "identity.xsl",
 200                 XML_DIR + "identity.xml", 
 201                 GOLDEN_DIR + "identity.out",
 202                 new String[]{OutputKeys.METHOD, null,
 203                     OutputKeys.INDENT, null}},
 204             {XML_DIR + "TransformerAPIVar.xsl",
 205                 XML_DIR + "TransformerAPIVar.xml", 
 206                 GOLDEN_DIR + "TransformerAPIVar.out",
 207                 new String[]{OutputKeys.METHOD, "xml", OutputKeys.INDENT, "no"}},
 208             {XML_DIR + "TransformerAPIOutputFormat.xsl",
 209                 XML_DIR + "TransformerAPIOutputFormat.xml", 
 210                 GOLDEN_DIR + "TransformerAPIOutputFormatUTF16.out",
 211                 new String[]{                    
 212                     OutputKeys.METHOD, METHOD_VALUE,
 213                     OutputKeys.VERSION, VERSION_VALUE,
 214                     OutputKeys.ENCODING, ENCODING_VALUE,
 215                     OutputKeys.STANDALONE, STANDALONE_VALUE,
 216                     OutputKeys.DOCTYPE_PUBLIC, DOCTYPE_PUBLIC_VALUE,
 217                     OutputKeys.DOCTYPE_SYSTEM, DOCTYPE_SYSTEM_VALUE, 
 218                     OutputKeys.CDATA_SECTION_ELEMENTS, CDATA_SECTION_ELEMENTS_VALUE,
 219                     OutputKeys.INDENT, INDENT_VALUE,
 220                     OutputKeys.MEDIA_TYPE, MEDIA_TYPE_VALUE,
 221                     OutputKeys.OMIT_XML_DECLARATION, OMIT_XML_DECLARATION_VALUE}},
 222             {XML_DIR + "TransformerAPIHTMLFormat.xsl",
 223                 XML_DIR + "TransformerAPIHTMLFormat.xml",
 224                 GOLDEN_DIR + "TransformerAPIHTMLFormat.out",
 225                 new String[]{
 226                     OutputKeys.METHOD, "html", OutputKeys.INDENT, null}}
 227         };
 228     }
 229     
 230     /**
 231      * API coverage test of Transformer.set/getOutputProperties()
 232      *
 233      * @throws TransformerConfigurationException Thrown in case of 
 234      *         ServiceConfigurationError service configuration error or if the
 235      *         implementation is not available or cannot be instantiated. 
 236      */
 237     @Test
 238     public void testCase3() throws TransformerConfigurationException {
 239         Transformer identityTransformer = factory.newTransformer();
 240         assertNotNull(factory.newTemplates(new StreamSource(XML_DIR + "TransformerAPIOutputFormat.xsl")));
 241         assertNotNull(identityTransformer.getOutputProperties());
 242         identityTransformer.setOutputProperties(new Properties());
 243         assertEquals(identityTransformer.getOutputProperties(), new Properties());
 244     }
 245 
 246     /**
 247      * Data provider for re-use Transformer test.
 248      * 
 249      * @return an array that has parameters XSL file,XML file, golden validation
 250      *         file.
 251      */ 
 252     @DataProvider
 253     public Object[][] reuseTranfomerOnSameXMLProvider() {
 254         return new Object[][]{
 255             {XML_DIR + "identity.xsl",
 256                 XML_DIR + "identity.xml",
 257                 GOLDEN_DIR + "identity.out"}, 
 258             {XML_DIR + "TransformerAPIVar.xsl",
 259                 XML_DIR + "TransformerAPIVar.xml",
 260                 GOLDEN_DIR + "TransformerAPIVar.out"}, 
 261             {XML_DIR + "TransformerAPIVar.xsl",
 262                 XML_DIR + "TransformerAPIVar2.xml",
 263                 GOLDEN_DIR + "TransformerAPIVar2.out"}
 264         };
 265     }
 266     
 267     /**
 268      * TRAX Transformer: cover transform() API and multiple Transformations from
 269      * single transformer on same XML file with same style-sheet file.
 270      * 
 271      * @param xslFile XSLT file we will use.
 272      * @param xmlFile XML test file.
 273      * @param goldFile golden validation file.
 274      * @throws TransformerException When it is not possible to create a 
 275      *         Transformer instance or an unrecoverable error occurs during
 276      *         the course of the transformation..
 277      * @throws IOException if an I/O error occurs reading from the file or a 
 278      *         malformed or unmappable byte sequence is read.
 279      */
 280     @Test(dataProvider = "reuseTranfomerOnSameXMLProvider")
 281     public void reuseTransformerSameXMLTest(String xslFile, String xmlFile, 
 282             String goldFile) throws IOException, TransformerException {
 283         Transformer reuseTransformer = factory.newTransformer(new StreamSource(xslFile));
 284         String outputFile = getNextFile(this.getClass());
 285 
 286         // Re-use the transformer multiple times on XML file.
 287         reuseTransformer.transform(new StreamSource(xmlFile),
 288                                   new StreamResult(outputFile));
 289         assertTrue(compareWithGold(goldFile, outputFile));
 290         reuseTransformer.transform(new StreamSource(xmlFile),
 291                                   new StreamResult(outputFile));
 292         assertTrue(compareWithGold(goldFile, outputFile));
 293     }
 294 
 295     /**
 296      * Data provider for re-use Transformer test.
 297      * Note: same style-sheet should be transformed two different XML files.
 298      * 
 299      * @return an array that has parameters XSL file,two XML files and two 
 300      *         golden validation files.
 301      */ 
 302     @DataProvider
 303     public Object[][] reuseTranfomerOnDiffXMLProvider() {
 304         return new Object[][]{ 
 305             {XML_DIR + "TransformerAPIVar.xsl",
 306                 XML_DIR + "TransformerAPIVar.xml",
 307                 GOLDEN_DIR + "TransformerAPIVar.out",
 308                 XML_DIR + "TransformerAPIVar2.xml",
 309                 GOLDEN_DIR + "TransformerAPIVar2.out"}
 310         };
 311     }
 312 
 313     /**
 314      * TRAX Transformer: cover transform() API and multiple Transformations from
 315      * single transformer on same XML file.
 316      * 
 317      * @param xslFile XSLT file we will use.
 318      * @param xmlFile1 First XML test file to be transformed.
 319      * @param goldFile1 golden validation file for xmlFile1.
 320      * @param xmlFile2 Second XML test file to be transformed.
 321      * @param goldFile2 golden validation file for xmlFile2.
 322      * @throws TransformerException When it is not possible to create a 
 323      *         Transformer instance or an unrecoverable error occurs during
 324      *         the course of the transformation..
 325      * @throws IOException if an I/O error occurs reading from the file or a 
 326      *         malformed or unmappable byte sequence is read.
 327      */
 328     @Test(dataProvider = "reuseTranfomerOnDiffXMLProvider")
 329     public void reuseTransformerDiffXMLTest(String xslFile, String xmlFile1,
 330             String goldFile1, String xmlFile2, String goldFile2) 
 331             throws IOException, TransformerException {
 332         Transformer reuseTransformer = factory.newTransformer(new StreamSource(xslFile));
 333 
 334         // Transform first xml file and validate it.
 335         String outputFile1 = getNextFile(this.getClass());
 336         reuseTransformer.transform(new StreamSource(xmlFile1),
 337                                   new StreamResult(outputFile1));
 338         assertTrue(compareWithGold(goldFile1, outputFile1));
 339         
 340         // Transform second xml file and validate it.
 341         String outputFile2 = getNextFile(this.getClass());
 342         reuseTransformer.transform(new StreamSource(xmlFile2),
 343                                   new StreamResult(outputFile2));
 344         assertTrue(compareWithGold(goldFile2, outputFile2));
 345 
 346         // Transform first xml file and validate it again.
 347         String outputFile3 = getNextFile(this.getClass());
 348         reuseTransformer.transform(new StreamSource(xmlFile1),
 349                                   new StreamResult(outputFile3));
 350         assertTrue(compareWithGold(goldFile1, outputFile3));
 351     }
 352     
 353     /**
 354      * Negative test on getOutputProperty. IllegalArgumentException If the 
 355      * property is not supported.
 356      * 
 357      * @param notSupportedProperty an invalid property name.
 358      * @throws TransformerConfigurationException Thrown in case of 
 359      *         ServiceConfigurationError service configuration error or if the
 360      *         implementation is not available or cannot be instantiated. 
 361      */
 362     @Test(dataProvider = "bogusProperties", expectedExceptions = IllegalArgumentException.class)
 363     public void bogusPropertyName(String notSupportedProperty) 
 364             throws TransformerConfigurationException{
 365         Transformer transformer = factory.newTransformer();
 366         transformer.getOutputProperty(notSupportedProperty);
 367     }
 368     
 369     /**
 370      * Data provider for bogusPropertyName negative tests.
 371      * 
 372      * @return a parameters array that contains all invalid properties name. 
 373      */
 374     @DataProvider
 375     public Object[][] bogusProperties() {
 376         return new Object[][]{
 377             {"bogus-name"},
 378             {"bogus-{name}"}
 379         };
 380     }
 381 }