1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2001, 2011, 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.exec; 28 29 import java.awt.EventQueue; 30 import java.util.ArrayList; 31 32 import com.sun.javatest.Harness; 33 import com.sun.javatest.Parameters; 34 import com.sun.javatest.Status; 35 import com.sun.javatest.TestResult; 36 import com.sun.javatest.WorkDirectory; 37 import com.sun.javatest.util.DynamicArray; 38 39 /** 40 * This class captures the state of the Harness for the purpose of 41 * presenting the user with useful status/progress info. 42 */ 43 44 class MonitorState { 45 MonitorState(Harness h) { 46 h.addObserver(dispatcher); 47 harness = h; 48 startTime = -1l; 49 finishTime = -1l; 50 stats = new int[Status.NUM_STATES]; 51 } 52 53 /** 54 * Monitor the harness state. 55 * By definition, all observations will be broadcast on the event thread. 56 * Be short and timely in processing these events. 57 */ 58 interface Observer { 59 /** 60 * A new test run is starting. 61 */ 62 public void starting(); 63 64 /** 65 * The tests have stopped running, and the harness is now doing 66 * cleanup. 67 */ 68 public void postProcessing(); 69 70 /** 71 * A test run is being stopped by something. This is not the same 72 * as finishing. 73 */ 74 public void stopping(); 75 76 /** 77 * A test run is finishing. 78 * 79 * @param allOk Did all the tests pass? 80 */ 81 public void finished(boolean allOk); 82 } 83 84 void addObserver(Observer o) { 85 obs = (Observer[])DynamicArray.append(obs, o); 86 } 87 88 void removeObserver(Observer o) { 89 obs = (Observer[])DynamicArray.remove(obs, o); 90 } 91 92 /** 93 * Is the harness currently doing a test run. 94 */ 95 boolean isRunning() { 96 return running; 97 } 98 99 /** 100 * Time since the start of the run. 101 * 102 * @return Zero at the instant we start a run or when no run has been 103 * performed yet. 104 */ 105 long getElapsedTime() { 106 /* 107 // we don't have a valid time available 108 if (startTime == -1) 109 return 0L; 110 111 // provide the current or last time 112 long now = System.currentTimeMillis(); 113 114 // answer depends whether we are running now or not 115 if (finishTime < 0) { 116 // we are still running 117 return now - startTime; 118 } 119 else { 120 return finishTime - startTime; 121 } 122 */ 123 124 return harness.getElapsedTime(); 125 } 126 127 /** 128 * Find out the estimated time required to complete the remaining tests. 129 * 130 * @return A time estimate in milliseconds. Zero if no run is in progress or 131 * no estimate is available. 132 */ 133 synchronized long getEstimatedTime() { 134 return harness.getEstimatedTime(); 135 } 136 137 /** 138 * Discover the number of tests found so far in this testsuite. 139 * 140 * @return estimated number of tests in the entire testsuite, -1 if unknown 141 */ 142 synchronized int getEstimatedTotalTests() { 143 WorkDirectory wd = harness.getResultTable().getWorkDir(); 144 if (wd == null) 145 return -1; 146 147 int count = wd.getTestSuiteTestCount(); 148 149 if (count == -1) 150 count = wd.getTestSuite().getEstimatedTestCount(); 151 152 // make sure we return -1 153 return (count < 0 ? -1 : count); 154 } 155 156 /** 157 * Discover the number of tests found so far by the system to be executed 158 * during this run. 159 * 160 * @return Number of tests found so far to be executed based on the current 161 * parameters. 162 */ 163 synchronized int getTestsFoundCount() { 164 return harness.getTestsFoundCount(); 165 } 166 167 /** 168 * Convenience method to determine how many tests have finished for the 169 * current or last run. 170 */ 171 synchronized int getTestsDoneCount() { 172 int done = 0; 173 for (int i = 0; i < stats.length; i++) 174 done += stats[i]; 175 176 return done; 177 } 178 179 /** 180 * Convenience method to determine how many tests have still need 181 * to be run for the current or last run. 182 */ 183 synchronized int getTestsRemainingCount() { 184 return getTestsFoundCount() - getTestsDoneCount(); 185 } 186 187 /** 188 * Get the test run statistics. 189 * 190 * @return array of counts, based on the indexes of Status types. 191 */ 192 synchronized int[] getStats() { 193 // we could consider trusting the client and not doing the copy 194 int[] copy = new int[stats.length]; 195 System.arraycopy(stats, 0, copy, 0, stats.length); 196 return copy; 197 } 198 199 /** 200 * @return Array representing the currently executing tests. Zero-length 201 * array if there are no tests running. 202 */ 203 TestResult[] getRunningTests() { 204 TestResult[] trs = new TestResult[0]; 205 synchronized (vLock) { 206 if (runningTests != null && runningTests.size() > 0) 207 trs = runningTests.toArray(trs); 208 } 209 210 return trs; 211 } 212 213 /** 214 * Provide synchronized access to the statistics array. 215 */ 216 private synchronized void incrementStat(int state) { 217 // this mainly called by the harness observer implementation 218 stats[state]++; 219 } 220 221 private synchronized void resetStats() { 222 stats = new int[Status.NUM_STATES]; 223 } 224 225 class Dispatcher implements Harness.Observer { 226 227 public void startingTestRun(Parameters p) { 228 running = true; 229 230 startTime = System.currentTimeMillis(); 231 finishTime = -1l; 232 resetStats(); 233 234 synchronized (vLock) { 235 runningTests.clear(); 236 } 237 238 notifySimple(0); 239 } 240 241 public void startingTest(TestResult tr) { 242 synchronized (vLock) { 243 if (!runningTests.contains(tr)) 244 runningTests.add(tr); 245 } 246 } 247 248 public void finishedTest(TestResult tr) { 249 synchronized (vLock) { 250 runningTests.remove(tr); 251 } 252 253 incrementStat(tr.getStatus().getType()); 254 } 255 256 public void stoppingTestRun() { 257 notifySimple(1); 258 } 259 260 public void finishedTesting() { 261 finishTime = System.currentTimeMillis(); 262 263 synchronized (vLock) { 264 runningTests.clear(); 265 } 266 267 notifySimple(2); 268 } 269 270 public void finishedTestRun(boolean allOk) { 271 running = false; 272 notifyComplete(allOk); 273 } 274 275 public void error(String msg) { 276 } 277 278 // --------- private ---------- 279 private void notifySimple(final int which) { 280 if (!EventQueue.isDispatchThread()) { 281 Runnable cmd = new Runnable() { 282 public void run() { 283 MonitorState.Dispatcher.this.notifySimple(which); 284 } // run() 285 }; // end anon. class 286 287 EventQueue.invokeLater(cmd); 288 } 289 else { // now on event thread 290 for (int i = 0; i < obs.length; i++) 291 switch (which) { 292 case 0: 293 obs[i].starting(); break; 294 case 1: 295 obs[i].stopping(); break; 296 case 2: 297 obs[i].postProcessing(); break; 298 default: 299 throw new IllegalStateException(); 300 } // switch 301 // end for 302 } // else 303 } 304 305 private void notifyComplete(final boolean allOk) { 306 if (!EventQueue.isDispatchThread()) { 307 Runnable cmd = new Runnable() { 308 public void run() { 309 MonitorState.Dispatcher.this.notifyComplete(allOk); 310 } // run() 311 }; // end anon. class 312 313 EventQueue.invokeLater(cmd); 314 } 315 else { // now on event thread 316 for (int i = 0; i < obs.length; i++) 317 obs[i].finished(allOk); 318 } 319 } 320 } 321 322 // instance vars for MonitorState 323 private Harness harness; 324 private boolean running; 325 private Observer[] obs = new Observer[0]; 326 private volatile int[] stats; 327 328 private ArrayList<TestResult> runningTests = new ArrayList(5); 329 private final Object vLock = new Object(); 330 331 /** 332 * Basis for the elapsed time. 333 */ 334 private long startTime; 335 private long finishTime; // only used if startTime != -1 and finishTime >= 0 336 private Dispatcher dispatcher = new Dispatcher(); 337 } 338