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