/*==========================================================================*\
| $Id: AverageTimeout.java,v 1.2 2011/06/09 15:35:28 stedwar2 Exp $
|*-------------------------------------------------------------------------*|
| Copyright (C) 2011 Virginia Tech
|
| This file is part of the Student-Library.
|
| The Student-Library is free software; you can redistribute it and/or
| modify it under the terms of the GNU Lesser General Public License as
| published by the Free Software Foundation; either version 3 of the
| License, or (at your option) any later version.
|
| The Student-Library is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU Lesser General Public License for more details.
|
| You should have received a copy of the GNU Lesser General Public License
| along with the Student-Library; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/
package student.testingsupport.junit4;
import org.junit.internal.runners.statements.FailOnTimeout;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
//-------------------------------------------------------------------------
/**
* Attempts to give test methods in a class enough time to execute, while at
* the same time watching out for long-running methods, based on the running
* average.
*
* This class is really just a proof-of-concept class for experimental
* purposes.
*
* @author Craig Estep
* @author Last changed by $Author: stedwar2 $
* @version $Revision: 1.2 $, $Date: 2011/06/09 15:35:28 $
*/
public class AverageTimeout
implements MethodRule
{
//~ Instance/static variables .............................................
private static long start;
private static long last;
// private static ArrayList<Integer> times;
private int avg;
private int allowance;
private boolean exceeded;
private int strict;
private int count;
//~ Constructors ..........................................................
// ----------------------------------------------------------
/**
* Sets the default values of 5x average runtime when a test has not timed
* out, and a 2x multiplier if one has.
*/
public AverageTimeout()
{
this(5, 2);
}
// ----------------------------------------------------------
/**
* Sets the multipliers to the values provided.
*
* @param allowanceMultiplier the multiplier on the average that each
* method is allowed before a timeout has
* occurred.
* @param strictMultiplier the multiplier after a timout has occurred.
*/
public AverageTimeout(int allowanceMultiplier, int strictMultiplier)
{
start = System.currentTimeMillis();
last = start;
allowance = allowanceMultiplier;
strict = strictMultiplier;
count = 0;
avg = 0;
exceeded = false;
// times = new ArrayList<Integer>();
}
//~ Methods ...............................................................
// ----------------------------------------------------------
/**
* Applies the appropriate multiplier to the running average and gives
* this method that as the maximum running time before timeout.
*/
public Statement apply(
Statement base, FrameworkMethod method, Object target)
{
long curr = System.currentTimeMillis();
if (last != start)
{
int diff = (int) (curr - last);
boolean exceeded = false;
int t = (avg * ((exceeded) ? strict : allowance));
// System.out.println("d: " + diff + ", t: " + t);
if (t > 0 && diff > t)
{
exceeded = true;
// System.out.println("timeout detected");
}
// times.add(diff);
avg = (int) ((curr - start) / count);
// System.out.println("last method took " + diff + "ms. Average "
// + avg + "ms");
if (exceeded)
{
// System.out.println("last method timed out");
this.exceeded = true;
}
}
last = curr;
count++;
if (avg != 0)
{
// if (exceeded)
// System.out.println("timeout was exceeded previously");
int timeout = (exceeded) ? avg * strict : avg * allowance;
// System.out.println("giving next test " + timeout + "ms to run");
return new FailOnTimeout(base, timeout);
} else
{
return base;
}
}
// ----------------------------------------------------------
/**
* Prints statistics of run tests to the console.
*/
public void printStats()
{
System.out.println();
System.out.println("printing adaptive timeout stats");
System.out.println(count + " test(s) run");
long curr = System.currentTimeMillis();
System.out.println("total running time: " + (curr - start) + "ms");
avg = (int) ((curr - start) / count);
System.out.println("average: " + avg + "ms");
if (exceeded)
{
System.out.println("a test timed out");
}
else
{
System.out.println("no tests timed out");
}
}
}