package de.ugoe.cs.quest.testgeneration;
import java.security.InvalidParameterException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.ugoe.cs.quest.eventcore.Event;
import de.ugoe.cs.quest.usageprofiles.IStochasticProcess;
/**
*
* Generates a test suite by randomly walking an {@link IStochasticProcess}.
*
*
* @author Steffen Herbold
* @version 1.0
*/
public class RandomWalkGenerator {
/**
*
* Number of sequences in the test suite.
*
*/
private final int numSequences;
/**
*
* Minimal length of a test sequence.
*
*/
private final int minLength;
/**
*
* Maximal length of a test sequence.
*
*/
private final int maxLength;
/**
*
* In case this member is true, only test cases that end in the global end event
* {@link Event#ENDEVENT} are generated. If it is false, the end event can be any event.
*
*/
private final boolean validEnd;
/**
*
* Maximal number of random walks performed before aborting the test case generation and
* returning a test suite with less than {@link #numSequences} test cases. This can happen if
* too many generated random walks have to be discarded because their length is not between
* {@link #minLength} and {@link #maxLength}.
*
*/
private final long maxIter;
/**
*
* Actual number of random walks performed to generate the test suite.
*
*/
private long actualIter = -1;
/**
*
* Constructor. Creates a new RandomWalkGenerator and ensures the validity of the parameters:
*
* - numSequences must at least be 1
*
- maxLength must at least be 1
*
- minLength must be less than or equal to maxLength
*
- maxIter must be greater than or equal to numSequences
*
* If one of these conditions is violated an {@link InvalidParameterException} is thrown.
*
*
* @param numSequences
* number of sequences desired for the test suite
* @param minLength
* minimal length of a test sequence
* @param maxLength
* maximal length of a test sequence
* @param validEnd
* defines if test cases have to end with the global end event {@link Event#ENDEVENT}
* (see {@link #validEnd})
* @param maxIter
* maximal number of random walks before aborting the test case generation (see
* {@link #maxIter})
*/
public RandomWalkGenerator(int numSequences,
int minLength,
int maxLength,
boolean validEnd,
long maxIter)
{
// check validity of the parameters
if (numSequences < 1) {
throw new InvalidParameterException("number of sequences must be at least 1 but is " +
numSequences);
}
if (maxLength < 1) {
throw new InvalidParameterException(
"maximal allowed length of test cases must be at least 1 but is " +
maxLength);
}
if (minLength > maxLength) {
throw new InvalidParameterException(
"minimal allowed length of test cases must be less than or equal to the maximal allowed length (min length: " +
minLength + " ; max length: " + maxLength + ")");
}
if (maxIter < numSequences) {
throw new InvalidParameterException(
"maximal number of iterations must greater than or equal to the number of sequences (number of sequences: " +
numSequences +
" ; max iterations: " +
maxIter +
")");
}
this.numSequences = numSequences;
this.minLength = minLength;
this.maxLength = maxLength;
this.validEnd = validEnd;
this.maxIter = maxIter;
}
/**
*
* Generates a test suite by repeatedly randomly walking a stochastic process.
*
*
* @param model
* stochastic process which performs the random walks
* @return the test suite
*/
public Collection> generateTestSuite(IStochasticProcess model) {
if (model == null) {
throw new InvalidParameterException("model must not be null!");
}
Set> sequences = new HashSet>(numSequences);
actualIter = 0;
while (sequences.size() < numSequences && actualIter < maxIter) {
List generatedSequence = model.randomSequence(maxLength, validEnd);
if (generatedSequence.size() >= minLength && generatedSequence.size() <= maxLength) {
((List) generatedSequence).add(0, Event.STARTEVENT);
if (validEnd) {
((List) generatedSequence).add(Event.ENDEVENT);
}
sequences.add(generatedSequence);
}
actualIter++;
}
return sequences;
}
/**
*
* Returns the actual number of random walks performed during the last call of
* {@link #generateTestSuite(IStochasticProcess)} or -1 if
* {@link #generateTestSuite(IStochasticProcess)} has not been called yet.
*
*
* @return actual number of random walks or -1 if {@link #generateTestSuite(IStochasticProcess)}
* has not been called
*/
public long getActualIter() {
return actualIter;
}
}