// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed 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 de.ugoe.cs.autoquest.testgeneration; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import de.ugoe.cs.autoquest.eventcore.Event; import de.ugoe.cs.autoquest.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; /** *

* Maximal number of attempts for creating a valid sequence. If this value is reached, the * sequence generation will be aborted. *

*/ private final long maxIterValidSequence; /** *

* 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: *

* If one of these conditions is violated an {@link IllegalArgumentException} 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}) * @param maxIterValidSequence * maximal number of attempts to create a valid sequence within the given restrictions */ public RandomWalkGenerator(int numSequences, int minLength, int maxLength, boolean validEnd, long maxIter, long maxIterValidSequence) { // check validity of the parameters if (numSequences < 1) { throw new IllegalArgumentException("number of sequences must be at least 1 but is " + numSequences); } if (maxLength < 1) { throw new IllegalArgumentException( "maximal allowed length of test cases must be at least 1 but is " + maxLength); } if (minLength > maxLength) { throw new IllegalArgumentException( "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 IllegalArgumentException( "maximal number of iterations must greater than or equal to the number of sequences (number of sequences: " + numSequences + " ; max iterations: " + maxIter + ")"); } if( maxIterValidSequence < 1) { throw new IllegalArgumentException("maximal number of attempts to get a valid sequence must be positive, but is: " + maxIterValidSequence); } this.numSequences = numSequences; this.minLength = minLength; this.maxLength = maxLength; this.validEnd = validEnd; this.maxIter = maxIter; this.maxIterValidSequence = maxIterValidSequence; } /** *

* 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 IllegalArgumentException("model must not be null!"); } Set> sequences = new HashSet>(numSequences); actualIter = 0; while (sequences.size() < numSequences && actualIter < maxIter) { List generatedSequence = model.randomSequence(maxLength, validEnd, maxIterValidSequence); 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; } }