1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2002, 2012, 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.batch; 28 29 import java.io.PrintWriter; 30 import java.text.DateFormat; 31 import java.util.Date; 32 import java.util.Iterator; 33 34 import com.sun.javatest.Harness; 35 import com.sun.javatest.Parameters; 36 import com.sun.javatest.Status; 37 import com.sun.javatest.TestFinder; 38 import com.sun.javatest.TestResult; 39 import com.sun.javatest.tool.Command; 40 import com.sun.javatest.tool.CommandContext; 41 import com.sun.javatest.tool.VerboseCommand; 42 import com.sun.javatest.util.HelpTree; 43 import com.sun.javatest.util.I18NResourceBundle; 44 45 class RunTestsCommand extends Command 46 { 47 static String getName() { 48 return "runTests"; 49 } 50 51 private static final String DATE_OPTION = "date"; 52 private static final String NON_PASS_OPTION = "non-pass"; 53 private static final String START_OPTION = "start"; 54 private static final String FINISH_OPTION = "stop"; 55 private static final String PROGRESS_OPTION = "progress"; 56 57 private Harness harness; 58 59 static void initVerboseOptions() { 60 VerboseCommand.addOption(DATE_OPTION, new HelpTree.Node(i18n, "runTests.verbose.date")); 61 VerboseCommand.addOption(NON_PASS_OPTION, new HelpTree.Node(i18n, "runTests.verbose.nonPass")); 62 VerboseCommand.addOption(START_OPTION, new HelpTree.Node(i18n, "runTests.verbose.start")); 63 VerboseCommand.addOption(FINISH_OPTION, new HelpTree.Node(i18n, "runTests.verbose.stop")); 64 VerboseCommand.addOption(PROGRESS_OPTION, new HelpTree.Node(i18n, "runTests.verbose.progress")); 65 } 66 67 RunTestsCommand() { 68 super(getName()); 69 } 70 71 RunTestsCommand(Iterator argIter) { 72 super(getName()); 73 } 74 75 public boolean isActionCommand() { 76 return true; 77 } 78 79 public void run(CommandContext ctx) throws Fault { 80 this.ctx = ctx; 81 82 try { 83 Parameters p = getConfig(ctx); // throws fault if not set 84 85 // might want to move harness down into CommandContext 86 // to share with GUI 87 Harness h = new Harness(); 88 harness = h; 89 90 Harness.Observer[] observers = ctx.getHarnessObservers(); 91 for (int i = 0; i < observers.length; i++) 92 h.addObserver(observers[i]); 93 94 // should really merge VerboseObserver and BatchObserver 95 VerboseObserver vo = new VerboseObserver(ctx); 96 h.addObserver(vo); 97 98 BatchObserver bo = new BatchObserver(); 99 h.addObserver(bo); 100 p.getTestSuite().getTestFinder().setErrorHandler(bo); 101 102 boolean ok = h.batch(p); 103 104 if (bo.getFinderErrorCount() > 0) { 105 // other problems during run 106 ctx.printErrorMessage(i18n, "runTests.warnError"); 107 } 108 109 if (!ctx.isVerboseQuiet()) { 110 long tt = h.getElapsedTime(); 111 long setupT = h.getTotalSetupTime(); 112 long cleanupT = h.getTotalCleanupTime(); 113 ctx.printMessage(i18n, "runTests.totalTime", tt/1000L); 114 ctx.printMessage(i18n, "runTests.setupTime", setupT/1000L); 115 ctx.printMessage(i18n, "runTests.cleanupTime", cleanupT/1000L); 116 117 showResultStats(bo.getStats()); 118 } 119 120 121 int testsFound = h.getTestsFoundCount(); 122 123 if (testsFound > 0 && !ctx.isVerboseQuiet()) 124 ctx.printMessage(i18n, "runTests.resultsDone", p.getWorkDirectory().getPath()); 125 int[] stats = bo.getStats(); 126 127 if (!ok) { 128 if (testsFound > 0 && 129 testsFound != stats[Status.PASSED]) { 130 // some tests are actually not passed, print 131 // appropriate message 132 ctx.printErrorMessage(i18n, "runTests.testsFailed"); 133 } 134 } 135 136 ctx.addTestStats(stats); 137 } 138 catch (Harness.Fault e) { 139 throw new Fault(i18n, "runTests.harnessError", e.getMessage()); 140 } 141 catch (InterruptedException e) { 142 throw new Fault(i18n, "runTests.interrupted"); 143 } 144 } 145 146 private void showResultStats(int[] stats) { 147 int p = stats[Status.PASSED]; 148 int f = stats[Status.FAILED]; 149 int e = stats[Status.ERROR]; 150 int nr = stats[Status.NOT_RUN] = 151 harness.getTestsFoundCount() - p - f - e; 152 153 154 if (p + f + e + nr == 0) 155 ctx.printMessage(i18n, "runTests.noTests"); 156 else { 157 ctx.printMessage(i18n, "runTests.tests", 158 new Object[] { 159 new Integer(p), 160 new Integer((p > 0) && (f + e + nr > 0) ? 1 : 0), 161 new Integer(f), 162 new Integer((f > 0) && (e + nr > 0) ? 1 : 0), 163 new Integer(e), 164 new Integer((e > 0) && (nr > 0) ? 1 : 0), 165 new Integer(nr) 166 }); 167 } 168 } 169 170 //------------------------------------------------------------------------- 171 172 private CommandContext ctx; 173 174 private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(RunTestsCommand.class); 175 176 //------------------------------------------------------------------------- 177 178 private class BatchObserver 179 implements Harness.Observer, TestFinder.ErrorHandler { 180 181 int[] getStats() { 182 return stats; 183 } 184 185 int getFinderErrorCount() { 186 return finderErrors; 187 } 188 189 public void startingTestRun(Parameters params) { 190 stats = new int[Status.NUM_STATES]; 191 } 192 193 public void startingTest(TestResult tr) { } 194 195 public void finishedTest(TestResult tr) { 196 stats[tr.getStatus().getType()]++; 197 } 198 199 public void stoppingTestRun() { } 200 201 public void finishedTesting() { } 202 public void finishedTestRun(boolean allOK) { } 203 204 public void error(String msg) { 205 ctx.printMessage(i18n, "runTests.error", msg); 206 finderErrors++; 207 } 208 209 private int[] stats; 210 private int finderErrors; 211 } 212 213 private class VerboseObserver implements Harness.Observer 214 { 215 VerboseObserver(CommandContext ctx) { 216 this.ctx = ctx; 217 this.out = ctx.getLogWriter(); 218 219 quiet_flag = ctx.isVerboseQuiet(); 220 df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, 221 DateFormat.MEDIUM); 222 ctx.addHarnessObserver(this); 223 224 boolean defaultFlag = ctx.getVerboseOptionValue("default", false); 225 options = new boolean[OPTION_COUNT]; 226 options[NO_DATE] = !ctx.isVerboseTimestampEnabled(); 227 options[NON_PASS] = ctx.getVerboseOptionValue(NON_PASS_OPTION, false); 228 options[START] = ctx.getVerboseOptionValue(START_OPTION, false); 229 options[FINISH] = ctx.getVerboseOptionValue(FINISH_OPTION, false); 230 options[PROGRESS] = ctx.getVerboseOptionValue(PROGRESS_OPTION, defaultFlag); 231 } 232 233 public boolean isVerbose(int kind) { 234 if (quiet_flag) 235 return false; 236 237 if (max_flag) 238 return true; 239 240 if (kind < OPTION_COUNT) 241 return options[kind]; 242 else 243 return false; 244 } 245 246 private void printTimestamp() { 247 if (quiet_flag || options[NO_DATE]) 248 return; 249 250 out.print(df.format(new Date())); 251 out.print(" "); 252 } 253 254 // ---- Harness.Observer ---- 255 public void startingTestRun(Parameters params) { 256 stats = new int[Status.NUM_STATES]; 257 258 if (!quiet_flag) { 259 if (progressOnline) 260 out.println(); 261 printTimestamp(); 262 ctx.printMessage(i18n, "cmgr.verb.strt", 263 params.getEnv().getName()); 264 out.flush(); 265 progressOnline = false; 266 } 267 } 268 269 public void startingTest(TestResult tr) { 270 if (!isVerbose(START)) 271 return; 272 273 if (progressOnline) 274 out.println(); 275 276 printTimestamp(); 277 ctx.printMessage(i18n, "cmgr.verb.tsts", tr.getTestName()); 278 out.flush(); 279 280 progressOnline = false; 281 } 282 283 public void finishedTest(TestResult tr) { 284 Status s = tr.getStatus(); 285 stats[s.getType()]++; 286 287 switch(s.getType()) { 288 case Status.FAILED: 289 case Status.ERROR: 290 if (isVerbose(NON_PASS) || isVerbose(FINISH)) { 291 printFinish(s, tr); 292 progressOnline = false; 293 } 294 break; 295 default: 296 if (isVerbose(FINISH)) { 297 printFinish(s, tr); 298 progressOnline = false; 299 } 300 } // switch 301 302 printStats(); 303 out.flush(); 304 } 305 306 public void stoppingTestRun() { 307 if (progressOnline) 308 out.println(); 309 310 printTimestamp(); 311 ctx.printMessage(i18n, "cmgr.verb.stpng"); 312 out.flush(); 313 314 progressOnline = false; 315 } 316 317 public void finishedTesting() { 318 if (!quiet_flag) { 319 if (progressOnline) 320 out.println(); 321 322 printTimestamp(); 323 ctx.printMessage(i18n, "cmgr.verb.donerun"); 324 out.flush(); 325 326 progressOnline = false; 327 } 328 } 329 330 public void finishedTestRun(boolean allOK) { 331 if (!quiet_flag) { 332 if (progressOnline) 333 out.println(); 334 335 printTimestamp(); 336 ctx.printMessage(i18n, "cmgr.verb.finish"); 337 out.flush(); 338 339 progressOnline = false; 340 } 341 } 342 343 public void error(String msg) { 344 if (progressOnline) 345 out.println(); 346 347 printTimestamp(); 348 ctx.printErrorMessage(i18n, "cmgr.verb.err", msg); 349 out.flush(); 350 351 progressOnline = false; 352 } 353 354 // utility methods 355 private void printStats() { 356 if (!isVerbose(PROGRESS)) 357 return; 358 359 if (progressOnline) 360 out.print("\r"); 361 362 int p = stats[Status.PASSED]; 363 int f = stats[Status.FAILED]; 364 int e = stats[Status.ERROR]; 365 int nr = stats[Status.NOT_RUN] = 366 harness.getTestsFoundCount() - p - f - e; 367 368 out.print(i18n.getString("cmgr.verb.prog", 369 new Object[] { 370 new Integer(p), 371 new Integer(f), 372 new Integer(e), 373 new Integer(nr) 374 })); 375 out.print(" "); 376 377 progressOnline = true; 378 } 379 380 private void printFinish(Status s, TestResult tr) { 381 if (!quiet_flag) { 382 // need to create newline if we are doing single-line 383 // updates 384 if (progressOnline) 385 out.println(); 386 387 printTimestamp(); 388 String[] args = {tr.getTestName(), 389 s.toString()}; 390 ctx.printMessage(i18n, "cmgr.verb.tstd", args); 391 out.flush(); 392 progressOnline = false; 393 } 394 } 395 396 /** 397 * Is the text being displayed using println during the run? 398 * This affects our ability to update a progress counter. 399 */ 400 private boolean isScolling() { 401 if (!isVerbose(START) && !isVerbose(FINISH)) 402 return false; 403 else 404 return true; 405 } 406 407 private boolean[] options; 408 private boolean quiet_flag = false; 409 private boolean max_flag = false; 410 private DateFormat df; 411 private CommandContext ctx; 412 private PrintWriter out; 413 private int[] stats; 414 private boolean progressOnline = false; 415 416 public static final int NO_DATE = 0; 417 public static final int NON_PASS = 1; 418 public static final int START = 2; 419 public static final int FINISH = 3; 420 public static final int PROGRESS = 4; 421 422 public static final int DEFAULT = PROGRESS; 423 424 private static final int OPTION_COUNT = 5; 425 } 426 }