blob: e99fcce7524e36a6525112575d576e3fc3e92ec3 [file] [log] [blame]
/*
*
* 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.qpid.junit.extensions;
import junit.framework.Test;
import junit.framework.TestResult;
import org.apache.log4j.Logger;
import java.util.Timer;
import java.util.TimerTask;
/**
* A test decorator that runs a test repeatedly until a specified length of time has passed.
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Repeatedly run a test for a fixed length of time.
* </table>
*
* @todo The count of the number of tests run is an important number to keep. Also num passed/error/failed is also
* important to record. What to do with these numbers? They are already logged to the test listeners.
*
* @todo The duration test runner wraps on top of size, repeat or thread wrappers, need a way for it to tell
* TKTestResult when the duration is up, so that it can terminate any repeats in progress. It should end
* as soon as possible once the test method exits.
*
* @author Rupert Smith
*/
public class DurationTestDecorator extends WrappedSuiteTestDecorator implements ShutdownHookable
{
/** Used for logging. */
private static final Logger log = Logger.getLogger(DurationTestDecorator.class);
/** The test to run. */
private Test test;
/** The length of time to run the test for. */
private long duration;
/** Flag set by the shutdown hook. This decorator will not start any new tests when this is set. */
private boolean shutdown = false;
/**
* Creates an active test with default multiplier (1).
*
* @param test The target test.
*/
public DurationTestDecorator(WrappedSuiteTestDecorator test)
{
super(test);
this.test = test;
}
/**
* Creates active test with default multiplier (1).
*
* @param test The target test.
* @param duration The duration in milliseconds.
*/
public DurationTestDecorator(WrappedSuiteTestDecorator test, long duration)
{
super(test);
// log.debug("public DurationTestDecorator(Test \"" + test + "\", long " + duration + "): called");
this.test = test;
this.duration = duration;
}
/**
* Runs the test repeatedly for the fixed duration.
*
* @param testResult The the results object to monitor the test results with.
*/
public void run(TestResult testResult)
{
log.debug("public void run(TestResult testResult): called");
// Removing the durationTimer as this addition prevents this TestDecorator being wrapped with a Scaled Test Decorator.
// This change will cause the tests to run for at least the specified duration
// If we need the test to stop much closer to the specified duration then we need to
// ensure that the solution doesn't prevent this Decorator being wrapped with other Decorators.
// // Cast the test result to expose it as a TKTestResult if the test is running under the TKTestRunner.
// TKTestResult tkTestResult = null;
//
// if (testResult instanceof TKTestResult)
// {
// tkTestResult = (TKTestResult) testResult;
// }
//
// // If running under the TKTestRunner, set up a timer to notify the test framework when the test reaches its
// // completion time.
// Timer durationTimer = null;
//
// if (tkTestResult != null)
// {
// log.debug("Creating duration timer.");
//
// durationTimer = new Timer();
// durationTimer.schedule(new DurationTimerTask((TKTestResult) testResult), duration);
// }
// Work out when the test should end.
long now = System.nanoTime();
long end = (duration * 1000000) + now;
// Run the test until the duration times out or the shutdown flag is set. The test method may not exit until
// interrupted in some cases, in which case the timer will do the interrupting.
while ((now < end) && !shutdown)
{
test.run(testResult);
now = System.nanoTime();
}
// // Clean up any timer that was used.
// if (durationTimer != null)
// {
// log.debug("Cancelling duration timer.");
//
// durationTimer.cancel();
// }
}
/**
* Supplies the shutdown hook. This shutdown hook does not call {@link TKTestResult#shutdownNow()} because the
* {@link ScaledTestDecorator} already takes care of that.
*
* @return The shut down hook.
*/
public Thread getShutdownHook()
{
return new Thread(new Runnable()
{
public void run()
{
// log.debug("DurationTestDecorator::ShutdownHook: called");
// Set the shutdown flag so that no new tests are started.
shutdown = true;
}
});
}
// /**
// * DurationTimerTask is a timer task that is configured, upon expiry of its timer, to invoke
// * {@link TKTestResult#shutdownNow()}, for the test result object on which it is set. It also sets
// * the {@link DurationTestDecorator#shutdown} flag to indicate that no new tests should be run.
// *
// * <p/>The test loop implemented by DurationTestDecorator checks that the duration has not expired, on each
// * test case that it runs. However, it is possible to write test cases that never return until explicitly
// * interrupted by the test framework. This timer task exists to notify the test framework
// */
// private class DurationTimerTask extends TimerTask
// {
// /** Used for debugging purposes. */
// private final Logger log = Logger.getLogger(DurationTimerTask.class);
//
// /** Holds the test result for the test to which a duration limit is being applied. */
// TKTestResult testResult;
//
// /**
// * Creates a duration limit timer which will notify the specified test result when the duration has
// * expired.
// *
// * @param testResult The test result to notify upon expiry of the test duration.
// */
// public DurationTimerTask(TKTestResult testResult)
// {
// this.testResult = testResult;
// }
//
// /**
// * The action to be performed by this timer task.
// */
// public void run()
// {
// log.debug("public void run(): called");
//
// shutdown = true;
// testResult.shutdownNow();
// }
// }
}