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.IOException;
  23 import java.nio.file.Files;
  24 import java.nio.file.Paths;
  25 import java.util.Arrays;
  26 import javax.xml.transform.Source;
  27 import javax.xml.transform.Transformer;
  28 import javax.xml.transform.TransformerException;
  29 import javax.xml.transform.TransformerFactory;
  30 import javax.xml.transform.stream.StreamResult;
  31 import javax.xml.transform.stream.StreamSource;
  32 import jaxp.library.JAXPFileBaseTest;
  33 import static jaxp.library.JAXPTestUtilities.filenameToURL;
  34 import static org.apache.qetest.trax.TraxConst.XML_DIR;
  35 import static jaxp.library.JAXPTestUtilities.getNextFile;
  36 import static org.testng.Assert.assertTrue;
  37 import org.testng.annotations.DataProvider;
  38 import org.testng.annotations.Test;
  39 
  40 /**
  41  * Functional test of various usages of parameters in transforms.
  42  */
  43 public class ParameterTest extends JAXPFileBaseTest {
  44     /**
  45      * Test XSL file.
  46      */
  47     private static final String XSLT_TEST_FILE = filenameToURL(XML_DIR + "ParameterTest.xsl");
  48 
  49     /**
  50      * Test XML file.
  51      */
  52     private static final String XML_TEST_FILE = filenameToURL(XML_DIR + "ParameterTest.xml");
  53 
  54     /**
  55      * Test XSL file.
  56      */
  57     private static final String SIMPLE_XSLT_TEST_FILE = filenameToURL(XML_DIR + "ParameterTest2.xsl");
  58 
  59     /**
  60      * Test XML file.
  61      */
  62     private static final String SIMPLE_XML_TEST_FILE = filenameToURL(XML_DIR + "ParameterTest2.xml");
  63 
  64     /**
  65      * Test Parameters.
  66      */
  67     private static final String[][] PARAMETERS
  68         = {
  69             {
  70                 "t1",
  71                 "'a'",
  72                 "<outt>false-notset,false-blank,false-a,false-1,'a'</outt>",
  73                 "(10)Select expr of a 'param' string"
  74             },
  75             {
  76                 "t1",
  77                 "a",
  78                 "<outt>false-notset,false-blank,true-a,false-1,a</outt>",
  79                 "(10a)Select expr of a param string"
  80             },
  81             {
  82                 "t1",
  83                 "'1'",
  84                 "<outt>false-notset,false-blank,false-a,false-1,'1'</outt>",
  85                 "(11)Select expr of a 'param' number"
  86             },
  87             {
  88                 "t1",
  89                 "1",
  90                 "<outt>false-notset,false-blank,false-a,true-1,1</outt>",
  91                 "(11a)Select expr of a param number"
  92             },
  93             {
  94                 "t1",
  95                 "''",
  96                 "<outt>false-notset,false-blank,false-a,false-1,''</outt>",
  97                 "(12)Select expr of a param 'blank' string"
  98             },
  99             {
 100                 "t1",
 101                 "",
 102                 "<outt>false-notset,true-blank,false-a,false-1,</outt>",
 103                 "(12a)Select expr of a param blank string"
 104             },
 105             {
 106                 "p1",
 107                 "'foo'",
 108                 "'foo','foo';",
 109                 "(13)Stylesheet with literal 'param' value"
 110             },
 111             {
 112                 "p1",
 113                 "foo",
 114                 "foo,foo;",
 115                 "(13a)Stylesheet with literal param value"
 116             },
 117             {
 118                 "p1",
 119                 "'bar'",
 120                 "'bar','bar';",
 121                 "(14)Stylesheet with replaced/another literal 'param' value"
 122             },
 123             {
 124                 "p1",
 125                 "bar",
 126                 "bar,bar;",
 127                 "(14a)Stylesheet with replaced/another literal param value"
 128             },
 129             {
 130                 "p2",
 131                 "'&lt;item&gt;bar&lt;/item&gt;'",
 132                 "'&amp;lt;item&amp;gt;bar&amp;lt;/item&amp;gt;','&amp;lt;item&amp;gt;bar&amp;lt;/item&amp;gt;'; GHI,<B>GHI</B>; </outp>",
 133                 "(15)Stylesheet with 'param' value with nodes"
 134             },
 135             {
 136                 "p2",
 137                 "&lt;item&gt;bar&lt;/item&gt;",
 138                 "&amp;lt;item&amp;gt;bar&amp;lt;/item&amp;gt;,&amp;lt;item&amp;gt;bar&amp;lt;/item&amp;gt;;",
 139                 "(15a)Stylesheet with param value with nodes"
 140             },
 141             {
 142                 "p3",
 143                 "'foo3'",
 144                 "DEF,<B>DEF</B>;",
 145                 "(16)Stylesheet with literal 'param' value in a template, is not passed"
 146             },
 147             {
 148                 "p3",
 149                 "foo3",
 150                 "DEF,<B>DEF</B>;",
 151                 "(16a)Stylesheet with literal param value in a template, is not passed"
 152             },
 153             {
 154                 "s1",
 155                 "'foos'",
 156                 "'foos','foos';",
 157                 "(17)Stylesheet with literal 'param' select"
 158             },
 159             {
 160                 "s1",
 161                 "foos",
 162                 "foos,foos;",
 163                 "(17a)Stylesheet with literal param select"
 164             },
 165             {
 166                 "s1",
 167                 "'bars'",
 168                 "<outs>'bars','bars'; s2val,s2val; s3val,s3val; </outs>",
 169                 "(18)Stylesheet with replaced/another literal 'param' select"
 170             },
 171             {
 172                 "s1",
 173                 "bars",
 174                 "<outs>bars,bars; s2val,s2val; s3val,s3val; </outs>",
 175                 "(18a)Stylesheet with replaced/another literal param select"
 176             },
 177             {
 178                 "s2",
 179                 "'&lt;item/&gt;'",
 180                 "'&amp;lt;item/&amp;gt;','&amp;lt;item/&amp;gt;'; s3val,s3val; </outs>",
 181                 "(19)Stylesheet with nodes(?) 'param' select"
 182             },
 183             {
 184                 "s2",
 185                 "&lt;item/&gt;",
 186                 "&amp;lt;item/&amp;gt;,&amp;lt;item/&amp;gt;; s3val,s3val; </outs>",
 187                 "(19a)Stylesheet with nodes(?) param select"
 188             }
 189     };
 190     
 191     @DataProvider
 192     public Object[][] parameters() {
 193         return Arrays.stream(PARAMETERS).map(ps -> new Object[]{
 194             ps[0], ps[1], new StreamSource(XML_TEST_FILE), 
 195             new StreamSource(XSLT_TEST_FILE), ps[2]
 196         }).toArray(Object[][]::new);
 197     }
 198 
 199     /**
 200      * Reuse the same transformer multiple times with parameters set.
 201      * @throws TransformerException If an unrecoverable error occurs during the 
 202      *         course of the transformation.
 203      * @throws IOException if any I/O operation error.
 204      */
 205     @Test
 206     public void reuseParametersTest() throws TransformerException, IOException {
 207         Transformer transformer = TransformerFactory.newInstance()
 208                 .newTemplates(new StreamSource(SIMPLE_XSLT_TEST_FILE))
 209                 .newTransformer();
 210         String outputFile1 = getNextFile(this.getClass());
 211         transformer.transform(new StreamSource(XML_TEST_FILE),
 212                 new StreamResult(outputFile1));
 213         // Verify the values are correct for no params set
 214         checkFileContains(outputFile1, "<globalVarAttr>ParameterTest.xml:</globalVarAttr>");
 215         String outputFile2 = getNextFile(this.getClass());
 216         transformer.transform(new StreamSource(SIMPLE_XML_TEST_FILE),
 217                 new StreamResult(outputFile2));
 218         // Do NOT call clear Parameters here; reuse the transformer
 219         checkFileContains(outputFile2, "<globalVarAttr>ParameterTest.xml:</globalVarAttr>");
 220         String outputFile3 = getNextFile(this.getClass());
 221         transformer.transform(new StreamSource(XML_TEST_FILE),
 222                 new StreamResult(outputFile3));
 223         // Do NOT call clearParameters here; reuse the transformer
 224         transformer.transform(new StreamSource(XML_TEST_FILE),
 225                 new StreamResult(outputFile3));
 226     }
 227 
 228     /**
 229      * Test setting a single string-valued parameter.
 230      * Uses the supplied Transformer and calls setParameter()
 231      * then transform(Source, Source), then uses the worker
 232      * method checkFileContains() to validate and output results.
 233      *
 234      * @param paramName simple name of parameter
 235      * @param paramVal String value of parameter
 236      * @param transformer object to use
 237      * @param xmlSource object to use in transform
 238      * @param checkString to look for in output file (logged)
 239      */
 240     private void testSetParam(String paramName, String paramVal,
 241             Transformer transformer, Source xmlSource, String checkString) 
 242             throws TransformerException, IOException {
 243         String outputFile = getNextFile(this.getClass());
 244 
 245         transformer.setParameter(paramName, paramVal);
 246         transformer.transform(xmlSource, new StreamResult(outputFile));
 247         assertTrue(checkFileContains(outputFile, checkString));
 248     }
 249 
 250     /**
 251      * Test setting a single string-valued parameter.
 252      * Creates a Transformer and calls setParameter()
 253      * then transform(Source, Source), then uses the worker
 254      * method checkFileContains() to validate and output results.
 255      *
 256      * @param paramName simple name of parameter
 257      * @param paramVal String value of parameter
 258      * @param xmlSource object to use in transform
 259      * @param xslStylesheet object to use in transform
 260      * @param checkString to look for in output file (logged)
 261      * @throws javax.xml.transform.TransformerConfigurationException
 262      * @throws IOException if any I/O operation error.
 263      */
 264     @Test(dataProvider = "parameters")
 265     public void testSetParam(String paramName, String paramVal, 
 266             Source xmlSource, Source xslStylesheet, String checkString) 
 267             throws TransformerException, IOException {
 268         testSetParam(paramName, paramVal,
 269             TransformerFactory.newInstance().newTransformer(xslStylesheet),
 270                 xmlSource, checkString);
 271     }
 272     
 273     /**
 274      * Setting various string-valued parameters and reusing transformers.
 275      * Creates one transformer first, then loops through array
 276      * of simple test data re-using transformer.
 277      * @throws IOException if any I/O operation error.
 278      * @throws TransformerException If an unrecoverable error occurs during the 
 279      *         course of the transformation.
 280      */
 281     @Test
 282     public void reuseTestParams() throws IOException, TransformerException {
 283         Transformer transformer = TransformerFactory.newInstance()
 284                 .newTemplates(new StreamSource(XSLT_TEST_FILE))
 285                 .newTransformer();
 286         String outputFile = getNextFile(this.getClass());
 287         transformer.transform(new StreamSource(XML_TEST_FILE),
 288                 new StreamResult(outputFile));
 289         transformer.clearParameters();
 290         // Verify each of the three kinds of params are correct
 291         assertTrue(checkFileContains(outputFile, "<outp>ABC,<B>ABC</B>; DEF,<B>DEF</B>; GHI,<B>GHI</B>; </outp>"));
 292         assertTrue(checkFileContains(outputFile, "<outs>s1val,s1val; s2val,s2val; s3val,s3val; </outs>"));
 293         assertTrue(checkFileContains(outputFile, "<outt>true-notset,false-blank,false-a,false-1,notset</outt>"));
 294         Arrays.stream(PARAMETERS).forEach(ps -> {
 295             try {
 296                 testSetParam(ps[0], ps[1], new StreamSource(XML_TEST_FILE),
 297                         new StreamSource(XSLT_TEST_FILE), ps[2]);
 298             } catch (TransformerException | IOException ex) {
 299                 throw new RuntimeException(ex);
 300             }
 301         });
 302     }
 303     
 304 
 305     
 306     /**
 307      * Checks if a file contains a certain string (all within one line).
 308      * We should really consider validating the entire output file, but
 309      * this is the important functionality, and it makes maintaining the
 310      * test and gold data easier (since it's all in this file).
 311      *
 312      * @param file local path/name of file to check.
 313      * @param checkStr String to look for in the file.
 314      * @return true if file contain checkStr
 315      *         false if file doesn't contain checkStr.
 316      * @throws IOException if any wrong with I/O operation.
 317      */
 318     protected boolean checkFileContains(String file, String checkStr) throws IOException {
 319         return Files.readAllLines(Paths.get(file)).stream()
 320                 .anyMatch(s -> s.contains(checkStr));
 321     }
 322 }