1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 package com.sun.javatest; 28 29 import java.io.*; 30 import java.nio.charset.StandardCharsets; 31 import java.util.Iterator; 32 33 import com.sun.javatest.util.I18NResourceBundle; 34 import com.sun.javatest.util.Properties; 35 import com.sun.javatest.util.StringArray; 36 37 /** 38 * An implementation of Parameters, using data read from a .jtp file. 39 */ 40 public class FileParameters 41 extends 42 BasicParameters 43 implements 44 Parameters.LegacyEnvParameters 45 { 46 /** 47 * Determine if the specified file is a parameter file, 48 * as determined by whether its extension is .jtp or not. 49 * @param file the file to be checked 50 * @return true if the specified file is a parameter file, 51 * and false otherwise 52 */ 53 public static boolean isParameterFile(File file) { 54 return file.getPath().endsWith(PARAMFILE_EXTN); 55 } 56 57 /** 58 * Create an empty FileParameters object. 59 */ 60 public FileParameters() { 61 } 62 63 /** 64 * Create a FileParameters object, based on data read from a parameter file. 65 * @param file the file to be read to initialize this object 66 * @throws FileNotFoundException if the file does not exist 67 * @throws IOException if there is a problem reading the file 68 */ 69 public FileParameters(File file) 70 throws FileNotFoundException, IOException 71 { 72 Properties p = new Properties(); 73 Reader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)); 74 p.load(in); 75 in.close(); 76 77 setTestSuite(adjustPath(p.getProperty("javasoft.sqe.javatest.selection.testSuite"))); 78 setWorkDirectory(p.getProperty("javasoft.sqe.javatest.results.workDir")); 79 setTests(p.getProperty("javasoft.sqe.javatest.selection.tests")); 80 setExcludeFiles(p.getProperty("javasoft.sqe.javatest.selection.excludeList")); 81 String keywordOp = p.getProperty("javasoft.sqe.javatest.selection.keywordOp"); 82 String keywords = p.getProperty("javasoft.sqe.javatest.selection.keywords"); 83 setKeywords(keywordOp, keywords); 84 String statusOp = p.getProperty("javasoft.sqe.javatest.selection.status"); 85 String[] statusTests = new String[Status.NUM_STATES]; 86 statusTests[Status.PASSED] = p.getProperty("javasoft.sqe.javatest.selection.prev.passed"); 87 statusTests[Status.FAILED] = p.getProperty("javasoft.sqe.javatest.selection.prev.failed"); 88 statusTests[Status.ERROR] = p.getProperty("javasoft.sqe.javatest.selection.prev.error"); 89 statusTests[Status.NOT_RUN] = p.getProperty("javasoft.sqe.javatest.selection.prev.notRun"); 90 setPriorStatusValues(statusOp, statusTests); 91 setEnvFiles(p.getProperty("javasoft.sqe.javatest.execution.envFiles")); 92 setEnvName(p.getProperty("javasoft.sqe.javatest.execution.environment")); 93 setConcurrency(p.getProperty("javasoft.sqe.javatest.execution.concurrency")); 94 setTimeoutFactor(p.getProperty("javasoft.sqe.javatest.execution.timeFactor")); 95 setReportDir(p.getProperty("javasoft.sqe.javatest.results.reportDir")); 96 } 97 98 /** 99 * Create a FileParameters object, based on command-line-like args. 100 * The args that are accepted are: 101 * <dl> 102 * <dt><code>-t</code> <i>testsuite</i><br><code>-testsuite</code> <i>testsuite</i> 103 * <dd>Specify the test suite 104 * <dt><code>-keywords</code> <i>expr</i> 105 * <dd>Specify a keyword expression, used to filter the tests to be run. 106 * <dt><code>-status</code> <i>status-list</i> 107 * <dd>Specify the status values used to select tests at runtime. 108 * <i>status-list</i> should be a comma-separated list of words from 109 * the following list: 110 * <code>passed</code>, 111 * <code>failed</code>, 112 * <code>error</code>, 113 * <code>notRun</code> 114 * <dt><code>-exclude</code> <i>exclude-list-file</i> 115 * <dd>Specify an exclude-list file containing a list of tests to 116 * be excluded from the test run. 117 * The option can be specified more than once, with different files. 118 * <dt><code>-envFile</code> <i>environment-file</i> 119 * <dd>Specify an environment file, containing environment entries 120 * providing details on how to run tests. 121 * The option can be specified more than once, with different files. 122 * <dt><code>-env</code> <i>environment-name</i> 123 * <dd>Specify the name of the environment to be used from the 124 * set of environment files. 125 * <dt><code>-concurrency</code> <i>number</i> 126 * <dd>Specify how many tests JT Harness may run at once. The default 127 * is 1. 128 * <dt><code>-timeoutFactor</code> <i>number</i> 129 * <dd>Specify a scale factor to be used to multiply the timeout 130 * value for each test, to allow for running on slow CPUs. 131 * <dt><code>-report</code> <i>report-dir</i><br><code>-r</code> <i>report-dir</i> 132 * <dd>Specify a directory in which to write reports at the end of the test run. 133 * <dt><code>-workDir</code> <i>work-dir</i><br><code>-w</code> <i>work-dir</i> 134 * <dd>Specify a directory in which to write the results of the individual tests. 135 * <dt><i>initial-files</i> 136 * <dd>Trailing file arguments are treated as initial files, used to select 137 * which parts of the test suite should be run. 138 * </dl> 139 * The test suite, work directory and report directory are evaluated 140 * relative to the user's current directory, unless the location specified 141 * is an absolute path. The exclude list and environment files are located 142 * relative to the test suite location, unless they are absolute paths. 143 * @param args The args used to initialize the FileParameters object. 144 * @throws IllegalArgumentException If an unrecognized argument is found. 145 */ 146 public FileParameters(String[] args) { 147 String testSuiteArg = null; 148 String workDirArg = null; 149 String testsArgs = null; 150 String exclFilesArgs = null; 151 String keywordsExprArg = null; 152 String priorStatusValuesArg = null; 153 String envFilesArgs = null; 154 String envNameArg = null; 155 String concurrencyArg = null; 156 String timeoutFactorArg = null; 157 String reportDirArg = null; 158 159 for (int i = 0; i < args.length; i++) { 160 if ("-testSuite".equalsIgnoreCase(args[i]) || "-t".equalsIgnoreCase(args[i])) 161 testSuiteArg = args[++i]; 162 else if ("-keywords".equalsIgnoreCase(args[i])) 163 keywordsExprArg = args[++i]; 164 else if ("-status".equalsIgnoreCase(args[i])) 165 priorStatusValuesArg = args[++i].toLowerCase(); 166 else if ("-exclude".equalsIgnoreCase(args[i])) { 167 if (exclFilesArgs == null) 168 exclFilesArgs = args[++i]; 169 else 170 exclFilesArgs += " " + args[++i]; 171 } 172 else if ("-envFile".equalsIgnoreCase(args[i])) { 173 if (envFilesArgs == null) 174 envFilesArgs = args[++i]; 175 else 176 envFilesArgs += " " + args[++i]; 177 } 178 else if ("-env".equalsIgnoreCase(args[i])) 179 envNameArg = args[++i]; 180 else if ("-concurrency".equalsIgnoreCase(args[i])) 181 concurrencyArg = args[++i]; 182 else if ("-timeoutFactor".equalsIgnoreCase(args[i])) 183 timeoutFactorArg = args[++i]; 184 else if ("-report".equalsIgnoreCase(args[i]) || "-r".equalsIgnoreCase(args[i])) 185 reportDirArg = args[++i]; 186 else if ("-workDir".equalsIgnoreCase(args[i]) || "-w".equalsIgnoreCase(args[i])) 187 workDirArg = args[++i]; 188 else if (args[i].startsWith("-")) 189 throw new IllegalArgumentException(args[i]); 190 else { 191 String[] tests = new String[args.length - i]; 192 System.arraycopy(args, i, tests, 0, tests.length); 193 testsArgs = StringArray.join(tests); 194 i = args.length; 195 } 196 } 197 198 setTestSuite(adjustPath(testSuiteArg)); 199 setWorkDirectory(adjustPath(workDirArg)); 200 setTests(testsArgs); 201 setExcludeFiles(exclFilesArgs); 202 setKeywords("expr", keywordsExprArg); 203 setPriorStatusValues(priorStatusValuesArg); 204 setEnvFiles(envFilesArgs); 205 setEnvName(envNameArg); 206 setConcurrency(concurrencyArg); 207 setTimeoutFactor(timeoutFactorArg); 208 setReportDir(adjustPath(reportDirArg)); 209 } 210 211 //--------------------------------------------------------------------- 212 213 public Parameters.EnvParameters getEnvParameters() { 214 return this; 215 } 216 217 public File[] getEnvFiles() { 218 return envFiles; 219 } 220 221 public File[] getAbsoluteEnvFiles() { 222 updateAbsoluteEnvFiles(); 223 return cachedAbsEnvFiles; 224 } 225 226 public void setEnvFiles(File[] files) { 227 envFiles = files; 228 } 229 230 private void setEnvFiles(String files) { 231 String[] f = StringArray.split(files); 232 File[] ff = new File[f.length]; 233 234 // legacy behavior requires that paths be relative to the testSuite 235 // location specified in the JTE or on the cmd line 236 for (int i = 0; i < ff.length; i++) { 237 ff[i] = new File(makeLegacyTsRelative(f[i])); 238 } 239 setEnvFiles(ff); 240 } 241 242 public String getEnvName() { 243 return envName; 244 } 245 246 public void setEnvName(String name) { 247 envName = name; 248 } 249 250 /** 251 * Get an object containing the environments read from the environment files. 252 * @return an object containing all the environments read from the environment files. 253 * @see #setEnvFiles 254 * @see #setEnvName 255 */ 256 public TestEnvContext getEnvTable() { 257 updateEnvTable(); 258 return cachedEnvTable; 259 } 260 261 public TestEnvironment getEnv() { 262 updateEnv(); 263 return cachedEnv; 264 } 265 266 private void updateAbsoluteEnvFiles() { 267 TestSuite ts = getTestSuite(); 268 File base = (ts == null ? null : ts.getRootDir()); 269 if (cachedAbsEnvFiles == null || 270 cachedAbsEnvFiles_base != base || 271 cachedAbsEnvFiles_envFiles != envFiles) { 272 cachedAbsEnvFiles = getAbsoluteFiles(base, envFiles); 273 } 274 } 275 276 private void updateEnvTable() { 277 updateAbsoluteEnvFiles(); 278 File[] absEnvFiles = cachedAbsEnvFiles; 279 if (cachedEnvTable == null 280 || !equal(absEnvFiles, cachedEnvTable_absEnvFiles)) { 281 try { 282 cachedEnvTable = new TestEnvContext(absEnvFiles); 283 cachedEnvTable_absEnvFiles = absEnvFiles; 284 envTableError = null; 285 } 286 catch (TestEnvContext.Fault e) { 287 cachedEnvTable = null; 288 envTableError = e.getMessage(); 289 } 290 } 291 } 292 293 private void updateEnv() { 294 TestEnvContext envTable = getEnvTable(); 295 if (envTable == null) { 296 cachedEnv = null; 297 envError = i18n.getString("fp.noEnvs", envName); 298 return; 299 } 300 301 TestEnvironment env; 302 try { 303 if (envName == null) 304 envName = ""; 305 env = envTable.getEnv(envName); 306 if (env == null) { 307 // note envName==null is always a valid environment 308 cachedEnv = null; 309 envError = i18n.getString("fp.envNotFound", envName); 310 return; 311 } 312 for (Iterator i = env.elements().iterator(); i.hasNext(); ) { 313 TestEnvironment.Element entry = (TestEnvironment.Element) (i.next()); 314 if (entry.value.indexOf("VALUE_NOT_DEFINED") >= 0) { 315 String eText = 316 ( (entry.definedInEnv == null ? "" : "env." + entry.definedInEnv + ".") + 317 entry.key + "=" + entry.value); 318 cachedEnv = null; 319 envError = i18n.getString("fp.undefinedEntry", 320 new Object[] {eText, entry.definedInFile}); 321 return; 322 } 323 } 324 } 325 catch (TestEnvironment.Fault e) { 326 cachedEnv = null; 327 envError = i18n.getString("fp.badEnv", new Object[] {envName, e.getMessage()}); 328 return; 329 } 330 cachedEnv = env; 331 envError = null; 332 } 333 334 private boolean isEnvOK() { 335 updateEnv(); 336 return (envTableError == null && envError == null); 337 } 338 339 private File[] envFiles; 340 private File[] cachedAbsEnvFiles; 341 private File cachedAbsEnvFiles_base; 342 private File[] cachedAbsEnvFiles_envFiles; 343 private String envName; 344 345 private TestEnvContext cachedEnvTable; 346 private File[] cachedEnvTable_absEnvFiles; 347 private String envTableError; 348 349 private TestEnvironment cachedEnv; 350 private TestEnvContext cachedEnv_envTable; 351 private String cachedEnv_envName; 352 private String envError; 353 354 //--------------------------------------------------------------------- 355 356 public boolean isValid() { 357 return ( super.isValid() && isEnvOK() ); 358 } 359 360 public String getErrorMessage() { 361 String basicError = super.getErrorMessage(); 362 return (basicError != null ? basicError 363 : envTableError != null ? envTableError 364 : null); 365 } 366 367 //--------------------------------------------------------------------- 368 369 private void setTestSuite(String path) { 370 legacyTsPath = path; 371 File p = (path == null ? null : new File(path)); 372 373 // we assume that the path has already be made non-relative 374 // i.e. absolute 375 if (p != null && p.isFile()) 376 legacyTsPath = p.getParent(); 377 378 // this strange arrangement of checks is here because we 379 // are trying to ensure that users playing around with legacy 380 // configurations get reasonable results 381 if (p == null || TestSuite.isTestSuite(p)) { 382 setTestSuite(p); 383 } 384 else { 385 File parent = p.getParentFile(); 386 // fallback check, check parent of specified location 387 if (parent != null && TestSuite.isTestSuite(parent)) { 388 setTestSuite(parent); 389 } 390 else { 391 // must do this to ensure proper errors occur 392 setTestSuite(p); 393 } 394 } 395 } 396 397 //--------------------------------------------------------------------- 398 399 private void setWorkDirectory(String path) { 400 setWorkDirectory(path == null ? null : new File(path)); 401 } 402 403 //--------------------------------------------------------------------- 404 405 private void setTests(String tests) { 406 setTests(StringArray.split(tests)); 407 } 408 409 //--------------------------------------------------------------------- 410 411 private void setExcludeFiles(String files) { 412 String[] f = StringArray.split(files); 413 File[] ff = new File[f.length]; 414 415 // legacy behavior requires that paths be relative to the testSuite 416 // location specified in the JTE or on the cmd line 417 for (int i = 0; i < ff.length; i++) { 418 ff[i] = new File(makeLegacyTsRelative(f[i])); 419 } 420 setExcludeFiles(ff); 421 } 422 423 //--------------------------------------------------------------------- 424 425 private void setKeywords(String op, String value) { 426 if (op == null || op.equals("ignore") ) 427 setKeywordsMode(NO_KEYWORDS); 428 else if (op.equals("expr")) 429 setKeywords(EXPR, value); 430 else if (op.equals("allOf")) 431 setKeywords(ALL_OF, value); 432 else if (op.equals("anyOf")) 433 setKeywords(ANY_OF, value); 434 else 435 setKeywordsMode(NO_KEYWORDS); 436 } 437 438 //--------------------------------------------------------------------- 439 440 private void setPriorStatusValues(String op, String[] values) { 441 if (op == null || !op.equals("allOf")) 442 setPriorStatusValues((boolean[]) null); 443 else { 444 boolean[] b = new boolean[Status.NUM_STATES]; 445 for (int i = 0; i < values.length; i++) 446 b[i] = "true".equals(values[i]); 447 setPriorStatusValues(b); 448 } 449 } 450 451 private void setPriorStatusValues(String values) { 452 if (values == null || values.length() == 0) 453 setPriorStatusValues((boolean[]) null); 454 else { 455 boolean[] b = new boolean[Status.NUM_STATES]; 456 b[Status.PASSED] = (values.indexOf("pass") != -1); 457 b[Status.FAILED] = (values.indexOf("fail") != -1); 458 b[Status.ERROR] = (values.indexOf("erro") != -1); 459 b[Status.NOT_RUN] = (values.indexOf("notr") != -1); 460 setPriorStatusValues(b); 461 } 462 } 463 464 //--------------------------------------------------------------------- 465 466 private void setConcurrency(String conc) { 467 if (conc == null) 468 setConcurrency(1); 469 else { 470 try { 471 setConcurrency(Integer.parseInt(conc)); 472 } 473 catch (NumberFormatException e) { 474 concurrencyError = i18n.getString("fp.badConcurrency", conc); 475 } 476 } 477 } 478 479 //--------------------------------------------------------------------- 480 481 private void setTimeoutFactor(String tf) { 482 if (tf == null) 483 setTimeoutFactor(1); 484 else { 485 try { 486 setTimeoutFactor(Float.parseFloat(tf)); 487 } 488 catch (NumberFormatException e) { 489 timeoutFactorError = i18n.getString("fp.badTimeoutFactor", tf); 490 } 491 } 492 } 493 494 //--------------------------------------------------------------------- 495 496 /** 497 * Get the report directory given in the parameters. 498 * @return the report directory 499 * @see #setReportDir 500 */ 501 public File getReportDir() { 502 return reportDir; 503 } 504 505 /** 506 * Set the report directory. 507 * @param dir the report directory 508 * @see #getReportDir 509 */ 510 public void setReportDir(File dir) { 511 // check report dir exists? 512 reportDir = dir; 513 } 514 515 private void setReportDir(String dir) { 516 if (dir == null) 517 setReportDir((File) (null)); 518 else 519 setReportDir(new File(dir)); 520 } 521 522 private File reportDir; 523 524 //--------------------------------------------------------------------- 525 526 /** 527 * Makes the given path relative to the user's CWD if it is a 528 * relative value. So "tests" may be turned into 529 * <code>/home/me/mytck/tests</code>. 530 */ 531 private String adjustPath(String path) { 532 if (path == null) 533 return path; 534 535 File p = new File(path); 536 if (p.isAbsolute()) 537 return path; 538 else { 539 String userDir = System.getProperty("user.dir"); 540 if (userDir == null) 541 return path; 542 else 543 return userDir + File.separator + path; 544 } 545 } 546 547 private String makeLegacyTsRelative(String path) { 548 if (path == null) 549 return path; 550 551 File p = new File(path); 552 if (p.isAbsolute()) 553 return path; 554 else { 555 if (legacyTsPath == null) 556 return path; 557 else 558 return legacyTsPath + File.separator + path; 559 } 560 } 561 562 private String legacyTsPath; // always a directory 563 private static final String PARAMFILE_EXTN = ".jtp"; 564 565 private static final I18NResourceBundle i18n = 566 I18NResourceBundle.getBundleForClass(FileParameters.class); 567 }