/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.usergrid.chop.runner.drivers; import java.io.File; import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.Preconditions; /** * Executes and tracks chop run statistics. */ public abstract class Tracker { private static final Logger LOG = LoggerFactory.getLogger( Tracker.class ); public static final int INVALID_TIME = -1; protected final Class<?> testClass; private final IResultsLog resultsLog; private long startTime = System.currentTimeMillis(); private long stopTime = INVALID_TIME; // the total number of test methods run (will be >= actualIterations) private final AtomicInteger totalTestsRun = new AtomicInteger( 0 ); // the total number of failures that resulted private final AtomicLong failures = new AtomicLong( 0 ); // the total number of run iterations on the test class private final AtomicLong actualIterations = new AtomicLong( 0 ); // the total number of ignored test methods private final AtomicLong ignores = new AtomicLong( 0 ); // the total run time of the tests minus setup time private final AtomicLong totalRunTime = new AtomicLong( 0 ); // the max run time encountered for a test class run private long maxTime = Long.MIN_VALUE; // the min run time encountered for a test class run private long minTime = Long.MAX_VALUE; // the average run time encountered across all test class runs private long meanTime = 0; // by default we have started but we just want to detect a stop private AtomicBoolean isStarted = new AtomicBoolean( true ); protected Tracker( Class<?> testClass ) { this.testClass = testClass; try { resultsLog = new ResultsLog( this ); resultsLog.open(); } catch ( IOException e ) { LOG.error( "Failed to open the results log.", e ); throw new RuntimeException( "Could not open results log.", e ); } } @JsonProperty public Class<?> getTestClass() { return testClass; } public Result execute() { Preconditions.checkState( isStarted.get(), "Cannot execute a tracker that has not started!" ); Result result = new JUnitCore().run( testClass ); long runTime = result.getRunTime(); // collect some statistics maxTime = Math.max( maxTime, runTime ); minTime = Math.min( minTime, runTime ); long timesRun = actualIterations.incrementAndGet(); long totalTime = totalRunTime.addAndGet( runTime ); totalTestsRun.addAndGet( result.getRunCount() ); meanTime = totalTime / timesRun; if ( ! result.wasSuccessful() ) { failures.addAndGet( result.getFailureCount() ); ignores.addAndGet( result.getIgnoreCount() ); } resultsLog.write( result ); return result; } @JsonProperty public abstract long getDelay(); @JsonProperty public abstract int getThreads(); @JsonProperty public abstract boolean getSaturate(); @JsonProperty public long getDuration() { Preconditions.checkState( stopTime != INVALID_TIME, "The stopTime has not been set: check that the test completed." ); return stopTime - startTime; } @JsonProperty public long getStartTime() { return startTime; } @JsonProperty public long getStopTime() { Preconditions.checkState( stopTime != INVALID_TIME, "The stopTime has not been set: check that the test completed." ); return stopTime; } void stop() { Preconditions.checkState( isStarted.get(), "Cannot stop Tracker which has not started." ); stopTime = System.currentTimeMillis(); try { resultsLog.close(); } catch ( IOException e ) { LOG.error( "Failed to close the results log", e ); } } File getResultsFile() { return new File( resultsLog.getPath() ); } @JsonProperty public long getMaxTime() { return maxTime; } @JsonProperty public long getMinTime() { return minTime; } @JsonProperty public long getMeanTime() { return meanTime; } @JsonProperty public long getActualTime() { return stopTime - startTime; } @JsonProperty public long getActualIterations() { return actualIterations.get(); } @JsonProperty public long getTotalTestsRun() { return totalTestsRun.get(); } @JsonProperty public long getFailures() { return failures.get(); } @JsonProperty public long getIgnores() { return ignores.get(); } @JsonProperty public long getTotalRunTime() { return totalRunTime.get(); } @JsonProperty public abstract int getPercentCompleted(); }