use of org.evosuite.ga.ConstructionFailedException in project evosuite by EvoSuite.
the class TestCluster method removeDirectCycle.
/**
* if a class X has a generator non-static method for Y, but, among its own generators for X it has one
* that uses Y as input, then do not use any non-static method of X as generator for Y.
* This is to avoid nasty cycles.
* For example, consider the case of:
*
* <p>
* X(Y y){...} <br>
* Y getY(){...}
*
* <p>
* If we need Y, we could end up using x.getY(), which for instantiating x would need a Y, which might
* end up in an infinite recursion...
*/
private void removeDirectCycle() {
// check each generator Y
for (Map.Entry<GenericClass, Set<GenericAccessibleObject<?>>> entry : generators.entrySet()) {
if (entry.getValue().isEmpty()) {
continue;
}
// for a given type Y, check all its generators X, like "Y x.getY()"
Iterator<GenericAccessibleObject<?>> iter = entry.getValue().iterator();
while (iter.hasNext()) {
GenericAccessibleObject<?> gao = iter.next();
// or at least make sure that we don't delete constructors.
if (gao.isConstructor() || gao.isStatic()) {
continue;
}
// eg X
GenericClass owner = gao.getOwnerClass();
try {
cacheGenerators(owner);
} catch (ConstructionFailedException e) {
continue;
}
for (GenericAccessibleObject<?> genOwner : generatorCache.get(owner)) {
if (genOwner.isStatic()) {
// as there is no need to instantiate X, it is not an issue
continue;
}
// is any generator for X using as input an instance of Y?
if (Arrays.asList(genOwner.getGenericParameterTypes()).stream().anyMatch(t -> t.equals(entry.getKey().getType()))) {
iter.remove();
break;
}
}
}
if (entry.getValue().isEmpty()) {
recursiveRemoveGenerators(entry.getKey());
}
}
}
use of org.evosuite.ga.ConstructionFailedException in project evosuite by EvoSuite.
the class TestCluster method removeUnusableGenerators.
/**
* A generator for X might be a non-static method M of Y, but what if Y itself has no generator?
* In that case, M should not be a generator for X, as it is impossible to instantiate Y
*/
public void removeUnusableGenerators() {
generatorCache.clear();
Set<GenericClass> removed = new LinkedHashSet<>();
for (Map.Entry<GenericClass, Set<GenericAccessibleObject<?>>> entry : generators.entrySet()) {
if (entry.getValue().isEmpty()) {
recursiveRemoveGenerators(entry.getKey());
}
Set<GenericClass> toRemove = new LinkedHashSet<>();
for (GenericAccessibleObject<?> gao : entry.getValue()) {
GenericClass owner = gao.getOwnerClass();
if (removed.contains(owner)) {
continue;
}
try {
cacheGenerators(owner);
} catch (ConstructionFailedException e) {
continue;
}
if (generatorCache.get(owner).isEmpty()) {
toRemove.add(owner);
}
}
for (GenericClass tr : toRemove) {
recursiveRemoveGenerators(tr);
removed.add(tr);
}
}
removeOnlySelfGenerator();
removeDirectCycle();
generatorCache.clear();
}
use of org.evosuite.ga.ConstructionFailedException in project evosuite by EvoSuite.
the class TestCluster method getRandomGenerator.
/**
* Randomly select one generator
*
* @param clazz
* @param excluded
* @param test
* @return {@code null} if there is no valid generator
* @throws ConstructionFailedException
*/
public GenericAccessibleObject<?> getRandomGenerator(GenericClass clazz, Set<GenericAccessibleObject<?>> excluded, TestCase test, int position, VariableReference generatorRefToExclude, int recursionDepth) throws ConstructionFailedException {
logger.debug("Getting random generator for " + clazz);
// Instantiate generics
if (clazz.hasWildcardOrTypeVariables()) {
logger.debug("Target class is generic: " + clazz);
GenericClass concreteClass = clazz.getGenericInstantiation();
if (!concreteClass.equals(clazz)) {
logger.debug("Target class is generic: " + clazz + ", getting instantiation " + concreteClass);
return getRandomGenerator(concreteClass, excluded, test, position, generatorRefToExclude, recursionDepth);
}
}
GenericAccessibleObject<?> generator = null;
// Collection, Map, Number
if (isSpecialCase(clazz)) {
generator = Randomness.choice(getGeneratorsForSpecialCase(clazz));
if (generator == null) {
logger.warn("No generator for special case class: " + clazz);
throw new ConstructionFailedException("Have no generators for special case: " + clazz);
}
} else {
cacheGenerators(clazz);
Set<GenericAccessibleObject<?>> candidates = new LinkedHashSet<>(generatorCache.get(clazz));
candidates.removeAll(excluded);
if (Properties.JEE) {
Iterator<GenericAccessibleObject<?>> iter = candidates.iterator();
while (iter.hasNext()) {
GenericAccessibleObject<?> gao = iter.next();
if (gao instanceof GenericConstructor) {
Class<?> klass = gao.getDeclaringClass();
if (InstanceOnlyOnce.canInstantiateOnlyOnce(klass) && ConstraintHelper.countNumberOfNewInstances(test, klass) != 0) {
iter.remove();
}
}
if (!ConstraintVerifier.isValidPositionForInsertion(gao, test, position)) {
iter.remove();
}
}
}
if (generatorRefToExclude != null) {
Iterator<GenericAccessibleObject<?>> iter = candidates.iterator();
while (iter.hasNext()) {
GenericAccessibleObject<?> gao = iter.next();
// if current generator could be called from excluded ref, then we cannot use it
if (generatorRefToExclude.isAssignableTo(gao.getOwnerType())) {
iter.remove();
}
}
}
logger.debug("Candidate generators for " + clazz + ": " + candidates.size());
if (candidates.isEmpty()) {
return null;
}
if (recursionDepth >= Properties.MAX_RECURSION / 2) {
/*
if going long into the recursion, then do prefer direct constructors or static methods,
as non-static methods would require to get a caller which, if it is missing, would need
to be created, and that could lead to further calls if its generators need input parameters
*/
Set<GenericAccessibleObject<?>> set = candidates.stream().filter(p -> p.isStatic() || p.isConstructor()).collect(Collectors.toCollection(() -> new LinkedHashSet<GenericAccessibleObject<?>>()));
if (!set.isEmpty()) {
candidates = set;
}
}
generator = Randomness.choice(candidates);
logger.debug("Chosen generator: " + generator);
}
if (generator.getOwnerClass().hasWildcardOrTypeVariables()) {
logger.debug("Owner class has a wildcard: " + clazz.getTypeName());
generator = generator.copyWithNewOwner(generator.getOwnerClass().getGenericInstantiation());
}
if (generator.hasTypeParameters()) {
logger.debug("Generator has a type parameter: " + generator);
generator = generator.getGenericInstantiationFromReturnValue(clazz);
if (!generator.getGeneratedClass().isAssignableTo(clazz)) {
throw new ConstructionFailedException("Generics error");
}
}
return generator;
}
use of org.evosuite.ga.ConstructionFailedException in project evosuite by EvoSuite.
the class TestCluster method getObjectGenerators.
/**
* Determine the set of generators for an Object.class instance
*
* @return a collection of all cast classes stored in {@link CastClassManager}; cannot be <code>null</code>>.
*/
public Set<GenericAccessibleObject<?>> getObjectGenerators() {
// TODO: Use probabilities based on distance to SUT
Set<GenericAccessibleObject<?>> result = new LinkedHashSet<>();
List<GenericClass> classes = new ArrayList<>(CastClassManager.getInstance().getCastClasses());
for (GenericClass clazz : classes) {
try {
result.addAll(getGenerators(clazz, true));
} catch (ConstructionFailedException e) {
// ignore
}
}
try {
result.addAll(getGenerators(new GenericClass(Object.class), true));
} catch (ConstructionFailedException e) {
// ignore
}
return result;
}
use of org.evosuite.ga.ConstructionFailedException in project evosuite by EvoSuite.
the class TestFactory method addFieldFor.
/**
* Add reference to a field of variable "callee"
*
* @param test
* @param callee
* @param field
* @param position
* @return
* @throws ConstructionFailedException
*/
public VariableReference addFieldFor(TestCase test, VariableReference callee, GenericField field, int position) throws ConstructionFailedException {
logger.debug("Adding field " + field + " for variable " + callee);
if (position <= callee.getStPosition())
throw new ConstructionFailedException("Cannot insert call on object before the object is defined");
currentRecursion.clear();
FieldReference fieldVar = new FieldReference(test, field, callee);
int length = test.size();
VariableReference value = createOrReuseVariable(test, fieldVar.getType(), position, 0, callee, true, false, true);
int newLength = test.size();
position += (newLength - length);
Statement st = new AssignmentStatement(test, fieldVar, value);
VariableReference ret = test.addStatement(st, position);
ret.setDistance(callee.getDistance() + 1);
assert (test.isValid());
return ret;
}
Aggregations