1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id$ 20 */ 21 22 /* 23 * 24 * ParameterTest.java 25 * 26 */ 27 package org.apache.qetest.trax; 28 29 import android.platform.test.annotations.FlakyTest; 30 import java.io.BufferedReader; 31 import java.io.File; 32 import java.io.FileInputStream; 33 import java.io.IOException; 34 import java.io.InputStreamReader; 35 import java.util.Properties; 36 37 import javax.xml.transform.Source; 38 import javax.xml.transform.Templates; 39 import javax.xml.transform.Transformer; 40 import javax.xml.transform.TransformerFactory; 41 import javax.xml.transform.stream.StreamResult; 42 import javax.xml.transform.stream.StreamSource; 43 44 import org.apache.qetest.FileBasedTest; 45 import org.apache.qetest.Logger; 46 import org.apache.qetest.OutputNameManager; 47 import org.apache.qetest.QetestUtils; 48 import org.apache.qetest.xsl.XSLTestfileInfo; 49 import org.apache.xml.utils.DefaultErrorHandler; 50 import org.junit.Test; 51 52 //------------------------------------------------------------------------- 53 54 /** 55 * Functional test of various usages of parameters in transforms. 56 * @author shane_curcuru@lotus.com 57 * @version $Id$ 58 */ 59 public class ParameterTest extends FileBasedTest 60 { 61 62 /** 63 * Provides nextName(), currentName() functionality for tests 64 * that may produce any number of output files. 65 */ 66 protected OutputNameManager outNames; 67 68 /** Information about an xsl/xml file pair for transforming. */ 69 protected XSLTestfileInfo paramTest = new XSLTestfileInfo(); 70 71 /** Information about an xsl/xml file pair for transforming. */ 72 protected XSLTestfileInfo paramTest2 = new XSLTestfileInfo(); 73 74 /** Subdirectory under test\tests\api for our xsl/xml files. */ 75 public static final String TRAX_SUBDIR = "trax"; 76 77 78 /** Just initialize test name, comment, numTestCases. */ ParameterTest()79 public ParameterTest() 80 { 81 numTestCases = 3; // REPLACE_num 82 testName = "ParameterTest"; 83 testComment = "Functional test of various usages of parameters in transforms"; 84 } 85 86 87 /** 88 * Initialize this test - Set names of xml/xsl test files, etc. 89 * 90 * @param p Properties to initialize from (if needed) 91 * @return false if we should abort the test; true otherwise 92 */ doTestFileInit(Properties p)93 public boolean doTestFileInit(Properties p) 94 { 95 File outSubDir = new File(outputDir + File.separator + TRAX_SUBDIR); 96 if (!outSubDir.mkdirs()) 97 reporter.logWarningMsg("Could not create output dir: " + outSubDir); 98 // Initialize an output name manager to that dir with .out extension 99 outNames = new OutputNameManager(outputDir + File.separator + TRAX_SUBDIR 100 + File.separator + testName, ".out"); 101 102 String testBasePath = inputDir 103 + File.separator 104 + TRAX_SUBDIR 105 + File.separator; 106 String goldBasePath = goldDir 107 + File.separator 108 + TRAX_SUBDIR 109 + File.separator; 110 111 paramTest.inputName = QetestUtils.filenameToURL(testBasePath + "ParameterTest.xsl"); 112 paramTest.xmlName = QetestUtils.filenameToURL(testBasePath + "ParameterTest.xml"); 113 114 paramTest2.inputName = QetestUtils.filenameToURL(testBasePath + "ParameterTest2.xsl"); 115 paramTest2.xmlName = QetestUtils.filenameToURL(testBasePath + "ParameterTest2.xml"); 116 return true; 117 } 118 119 120 /** Array of test data for parameter testing. */ 121 protected String paramTests[][] = 122 { 123 // { paramName to test, 124 // paramValue to test 125 // expected output string, 126 // description of the test 127 // } 128 { 129 "t1", 130 "'a'", 131 "<outt>false-notset,false-blank,false-a,false-1,'a'</outt>", 132 "(10)Select expr of a 'param' string" 133 }, 134 { 135 "t1", 136 "a", 137 "<outt>false-notset,false-blank,true-a,false-1,a</outt>", 138 "(10a)Select expr of a param string" 139 }, 140 { 141 "t1", 142 "'1'", 143 "<outt>false-notset,false-blank,false-a,false-1,'1'</outt>", 144 "(11)Select expr of a 'param' number" 145 }, 146 { 147 "t1", 148 "1", 149 "<outt>false-notset,false-blank,false-a,true-1,1</outt>", 150 "(11a)Select expr of a param number" 151 }, 152 { 153 "t1", 154 "''", 155 "<outt>false-notset,false-blank,false-a,false-1,''</outt>", 156 "(12)Select expr of a param 'blank' string" 157 }, 158 { 159 "t1", 160 "", 161 "<outt>false-notset,true-blank,false-a,false-1,</outt>", 162 "(12a)Select expr of a param blank string" 163 }, 164 /*{ 165 "t1", 166 null, 167 "<outt>false-notset,false-blank,false-a,false-1,</outt>", 168 "(12b)Select expr of a null" 169 },*/ 170 { 171 "p1", 172 "'foo'", 173 "'foo','foo';", 174 "(13)Stylesheet with literal 'param' value" 175 }, 176 { 177 "p1", 178 "foo", 179 "foo,foo;", 180 "(13a)Stylesheet with literal param value" 181 }, 182 { 183 "p1", 184 "'bar'", 185 "'bar','bar';", 186 "(14)Stylesheet with replaced/another literal 'param' value" 187 }, 188 { 189 "p1", 190 "bar", 191 "bar,bar;", 192 "(14a)Stylesheet with replaced/another literal param value" 193 }, 194 { 195 "p2", 196 "'<item>bar</item>'", 197 "'&lt;item&gt;bar&lt;/item&gt;','&lt;item&gt;bar&lt;/item&gt;'; GHI,<B>GHI</B>; </outp>", 198 "(15)Stylesheet with 'param' value with nodes" 199 }, 200 { 201 "p2", 202 "<item>bar</item>", 203 "&lt;item&gt;bar&lt;/item&gt;,&lt;item&gt;bar&lt;/item&gt;;", 204 "(15a)Stylesheet with param value with nodes" 205 }, 206 { 207 "p3", 208 "'foo3'", 209 "GHI,<B>GHI</B>;", 210 "(16)Stylesheet with literal 'param' value in a template, is not passed" 211 }, 212 { 213 "p3", 214 "foo3", 215 "GHI,<B>GHI</B>;", 216 "(16a)Stylesheet with literal param value in a template, is not passed" 217 }, 218 { 219 "s1", 220 "'foos'", 221 "'foos','foos';", 222 "(17)Stylesheet with literal 'param' select" 223 }, 224 { 225 "s1", 226 "foos", 227 "foos,foos;", 228 "(17a)Stylesheet with literal param select" 229 }, 230 { 231 "s1", 232 "'bars'", 233 "<outs>'bars','bars'; s2val,s2val; s3val,s3val; </outs>", 234 "(18)Stylesheet with replaced/another literal 'param' select" 235 }, 236 { 237 "s1", 238 "bars", 239 "<outs>bars,bars; s2val,s2val; s3val,s3val; </outs>", 240 "(18a)Stylesheet with replaced/another literal param select" 241 }, 242 { 243 "s2", 244 "'<item/>'", 245 "'&lt;item/&gt;','&lt;item/&gt;'; s3val,s3val; </outs>", 246 "(19)Stylesheet with nodes(?) 'param' select" 247 }, 248 { 249 "s2", 250 "<item/>", 251 "&lt;item/&gt;,&lt;item/&gt;; s3val,s3val; </outs>", 252 "(19a)Stylesheet with nodes(?) param select" 253 }, 254 { 255 "s3", 256 "foos3", 257 "s3val,s3val;", 258 "(20)Stylesheet with literal 'param' select in a template, is not passed" 259 }, 260 }; // end of paramTests array 261 262 263 /** 264 * Setting various string-valued params. 265 * Just loops through array of simple test data. 266 * 267 * @return false if we should abort the test; true otherwise 268 */ testCase1()269 public boolean testCase1() 270 { 271 reporter.testCaseInit("Setting various simple string-valued params"); 272 try 273 { 274 // Just loop through test elements and try each one 275 // Loop separately for each worker method 276 for (int i = 0; i < paramTests.length; i++) 277 { 278 // Try on a completely independent 279 // transformer and sources each time 280 testSetParam(paramTests[i][0], paramTests[i][1], 281 new StreamSource(paramTest.xmlName), new StreamSource(paramTest.inputName), 282 paramTests[i][2], paramTests[i][3]); 283 } 284 } 285 catch (Exception e) 286 { 287 reporter.logThrowable(Logger.ERRORMSG, e, "Testcase threw"); 288 reporter.logErrorMsg("Testcase threw: " + e.toString()); 289 } 290 reporter.testCaseClose(); 291 return true; 292 } 293 294 295 /** 296 * Reuse the same transformer multiple times with params set. 297 * This also reproduces Bugzilla1611 298 * 299 * @return false if we should abort the test; true otherwise 300 */ testCase2()301 public boolean testCase2() 302 { 303 reporter.testCaseInit("Reuse the same transformer multiple times with params set"); 304 TransformerFactory factory = null; 305 Templates templates = null; 306 Transformer transformer = null; 307 try 308 { 309 factory = TransformerFactory.newInstance(); 310 templates = factory.newTemplates(new StreamSource(paramTest2.inputName)); 311 312 // Process the file as-is, without any params set 313 transformer = templates.newTransformer(); 314 reporter.logInfoMsg("Transforming " + paramTest.xmlName + " with " + paramTest2.inputName); 315 transformer.transform(new StreamSource(paramTest.xmlName), 316 new StreamResult(outNames.nextName())); 317 // Verify the values are correct for no params set 318 checkFileContains(outNames.currentName(), "<globalVarAttr>ParameterTest.xml:</globalVarAttr>", 319 "(2.0)Processing 1,2 w/no params into: " + outNames.currentName()); 320 321 // Do NOT call clearParameters here; reuse the transformer 322 reporter.logInfoMsg("Reused-Transforming " + paramTest2.xmlName + " with " + paramTest2.inputName); 323 transformer.transform(new StreamSource(paramTest2.xmlName), 324 new StreamResult(outNames.nextName())); 325 // Verify the values are correct for no params set 326 checkFileContains(outNames.currentName(), "<globalVarAttr>ParameterTest2.xml:</globalVarAttr>", 327 "(2.0a) Bugzilla1611 Reused Transformer processing 2,2 w/no params into: " + outNames.currentName()); 328 329 // Do NOT call clearParameters here; reuse the transformer again 330 reporter.logInfoMsg("Reused-Transforming-again " + paramTest.xmlName + " with " + paramTest2.inputName); 331 transformer.transform(new StreamSource(paramTest.xmlName), 332 new StreamResult(outNames.nextName())); 333 // Verify the values are correct for no params set 334 checkFileContains(outNames.currentName(), "<globalVarAttr>ParameterTest.xml:</globalVarAttr>", 335 "(2.0b) Bugzilla1611 Reused-Again Transformer processing 1,2 w/no params into: " + outNames.currentName()); 336 } 337 catch (Exception e) 338 { 339 reporter.logThrowable(Logger.ERRORMSG, e, "Testcase threw"); 340 reporter.logErrorMsg("Testcase threw: " + e.toString()); 341 } 342 reporter.testCaseClose(); 343 return true; 344 } 345 346 /** 347 * Setting various string-valued params and reusing transformers. 348 * Creates one transformer first, then loops through array 349 * of simple test data re-using transformer. 350 * 351 * @return false if we should abort the test; true otherwise 352 */ testCase3()353 public boolean testCase3() 354 { 355 reporter.testCaseInit("Setting various string-valued params and re-using transformer"); 356 TransformerFactory factory = null; 357 Templates templates = null; 358 Transformer transformer = null; 359 try 360 { 361 factory = TransformerFactory.newInstance(); 362 factory.setErrorListener(new DefaultErrorHandler()); 363 templates = factory.newTemplates(new StreamSource(paramTest.inputName)); 364 } 365 catch (Exception e) 366 { 367 reporter.checkFail("Problem creating Templates; cannot continue testcase"); 368 reporter.logThrowable(reporter.ERRORMSG, e, 369 "Problem creating Templates; cannot continue testcase"); 370 return true; 371 } 372 373 try 374 { 375 // Process the file as-is, without any params set 376 transformer = templates.newTransformer(); 377 transformer.setErrorListener(new DefaultErrorHandler()); 378 transformer.transform(new StreamSource(paramTest.xmlName), 379 new StreamResult(outNames.nextName())); 380 transformer.clearParameters(); 381 // Verify each of the three kinds of params are correct 382 checkFileContains(outNames.currentName(), "<outp>ABC,<B>ABC</B>; DEF,<B>DEF</B>; GHI,<B>GHI</B>; </outp>", 383 "(0) Stylesheet with default param value into: " + outNames.currentName()); 384 385 checkFileContains( 386 outNames.currentName(), 387 "<outs>s1val,s1val; s2val,s2val; s3val,s3val; </outs>", 388 "(1) ... also with default param value in select expr into: " + outNames.currentName()); 389 checkFileContains( 390 outNames.currentName(), 391 "<outt>true-notset,false-blank,false-a,false-1,notset</outt>", 392 "(2) ... also with default param value in select expr into: " + outNames.currentName()); 393 394 // Just loop through test elements and try each one 395 for (int i = 0; i < paramTests.length; i++) 396 { 397 // Re-use the transformer from above for each test 398 transformer.clearParameters(); 399 testSetParam(paramTests[i][0], paramTests[i][1], 400 transformer, new StreamSource(paramTest.xmlName), new StreamSource(paramTest.inputName), 401 paramTests[i][2], paramTests[i][3]); 402 } 403 } 404 catch (Exception e) 405 { 406 reporter.logThrowable(Logger.ERRORMSG, e, "Testcase threw"); 407 reporter.logErrorMsg("Testcase threw: " + e.toString()); 408 } 409 reporter.testCaseClose(); 410 return true; 411 } 412 413 414 /** 415 * Test setting a single string-valued parameter. 416 * Uses the supplied Transformer and calls setParameter() 417 * then transform(Source, Source), then uses the worker 418 * method checkFileContains() to validate and output results. 419 * 420 * @param paramName simple name of parameter 421 * @param paramVal String value of parameter 422 * @param transformer object to use 423 * @param xmlSource object to use in transform 424 * @param xslStylesheet object to use in transform 425 * @param checkString to look for in output file (logged) 426 * @param comment to log with check() call 427 * @return true if pass, false otherwise 428 */ testSetParam(String paramName, String paramVal, Transformer transformer, Source xmlSource, Source xslStylesheet, String checkString, String comment)429 protected boolean testSetParam(String paramName, String paramVal, 430 Transformer transformer, 431 Source xmlSource, 432 Source xslStylesheet, 433 String checkString, String comment) 434 { 435 try 436 { 437 reporter.logTraceMsg("setParameter(" + paramName + ", " + paramVal +")"); 438 transformer.setParameter(paramName, paramVal); 439 reporter.logTraceMsg("transform(" + xmlSource.getSystemId() + ", " + xslStylesheet.getSystemId() +", ...)"); 440 transformer.transform(xmlSource, new StreamResult(outNames.nextName())); 441 } 442 catch (Throwable t) 443 { 444 reporter.logThrowable(Logger.ERRORMSG, t, "testSetParam unexpectedly threw"); 445 reporter.logErrorMsg("//@todo HACK: intermittent NPE; please report to curcuru@apache.org if you get this"); 446 reporter.logErrorMsg("//@todo HACK: intermittent NPE; please report to curcuru@apache.org if you get this"); 447 reporter.logErrorMsg("//@todo HACK: intermittent NPE; please report to curcuru@apache.org if you get this"); 448 // Since we the NPE is intermittent, and we want the rest 449 // of this test in the smoketest, I'll go against my 450 // better nature and ignore this fail 451 return true; //HACK: should be removed when fixed 452 } 453 return checkFileContains(outNames.currentName(), checkString, 454 "Reused:" + comment + " into: " + outNames.currentName()); 455 } 456 457 458 /** 459 * Test setting a single string-valued parameter. 460 * Creates a Transformer and calls setParameter() 461 * then transform(Source, Source), then uses the worker 462 * method checkFileContains() to validate and output results. 463 * 464 * @param paramName simple name of parameter 465 * @param paramVal String value of parameter 466 * @param xmlSource object to use in transform 467 * @param xslStylesheet object to use in transform 468 * @param checkString to look for in output file (logged) 469 * @param comment to log with check() call 470 * @return true if pass, false otherwise 471 */ testSetParam(String paramName, String paramVal, Source xmlSource, Source xslStylesheet, String checkString, String comment)472 protected boolean testSetParam(String paramName, String paramVal, 473 Source xmlSource, 474 Source xslStylesheet, 475 String checkString, String comment) 476 { 477 try 478 { 479 TransformerFactory factory = TransformerFactory.newInstance(); 480 factory.setErrorListener(new DefaultErrorHandler()); 481 Transformer transformer = factory.newTransformer(xslStylesheet); 482 transformer.setErrorListener(new DefaultErrorHandler()); 483 484 reporter.logTraceMsg("setParameter(" + paramName + ", " + paramVal +")"); 485 transformer.setParameter(paramName, paramVal); 486 reporter.logTraceMsg("transform(" + xmlSource.getSystemId() + ", " + xslStylesheet.getSystemId() +", ...)"); 487 transformer.transform(xmlSource, new StreamResult(outNames.nextName())); 488 } 489 catch (Throwable t) 490 { 491 reporter.logThrowable(Logger.ERRORMSG, t, "testSetParam unexpectedly threw"); 492 } 493 return checkFileContains(outNames.currentName(), checkString, 494 "New:" + comment + " into: " + outNames.currentName()); 495 } 496 497 498 /** 499 * Checks and reports if a file contains a certain string 500 * (all within one line). 501 * We should really consider validating the entire output 502 * file, but this is the important funtionality, and it makes 503 * maintaining the test and gold data easier (since it's all 504 * in this file). 505 * 506 * @param fName local path/name of file to check 507 * @param checkStr String to look for in the file 508 * @param comment to log with the check() call 509 * @return true if pass, false otherwise 510 */ checkFileContains(String fName, String checkStr, String comment)511 protected boolean checkFileContains(String fName, String checkStr, 512 String comment) 513 { 514 boolean passFail = false; 515 File f = new File(fName); 516 517 if (!f.exists()) 518 { 519 reporter.checkFail("checkFileContains(" + fName 520 + ") does not exist: " + comment); 521 return false; 522 } 523 524 try 525 { 526 InputStreamReader is = new InputStreamReader(new FileInputStream(f), "UTF-8"); 527 BufferedReader br = new BufferedReader(is); 528 529 for (;;) 530 { 531 String inbuf = br.readLine(); 532 if (inbuf == null) 533 break; 534 535 if (inbuf.indexOf(checkStr) >= 0) 536 { 537 passFail = true; 538 reporter.logTraceMsg( 539 "checkFileContains passes with line: " + inbuf); 540 break; 541 } 542 } 543 } 544 catch (IOException ioe) 545 { 546 reporter.checkFail("checkFileContains(" + fName + ") threw: " 547 + ioe.toString() + " for: " + comment); 548 549 return false; 550 } 551 552 if (!passFail) 553 { 554 reporter.logErrorMsg("checkFileContains failed to find: " + checkStr); 555 } 556 reporter.check(passFail, true, comment); 557 return passFail; 558 } 559 560 561 /** 562 * Convenience method to print out usage information - update if needed. 563 * @return String denoting usage of this test class 564 */ usage()565 public String usage() 566 { 567 return ("Common [optional] options supported by ParameterTest:\n" 568 + "(Note: assumes inputDir=.\\tests\\api)\n" 569 + super.usage()); // Grab our parent classes usage as well 570 } 571 572 573 /** 574 * Main method to run test from the command line - can be left alone. 575 * @param args command line argument array 576 */ main(String[] args)577 public static void main(String[] args) 578 { 579 ParameterTest app = new ParameterTest(); 580 app.doMain(args); 581 } 582 583 // Android-added: Run main method as a JUnit test case. 584 @FlakyTest(bugId = 292520220) 585 @Test main()586 public void main() { 587 main(new String[0]); 588 } 589 } 590