use of org.evosuite.utils.generic.GenericConstructor 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.utils.generic.GenericConstructor in project evosuite by EvoSuite.
the class TestCluster method sortCalls.
/**
* Sort by remaining uncovered goals to bias search towards most rewarding methods
*
* @param testMethods
* @return
*/
private List<GenericAccessibleObject<?>> sortCalls(List<GenericAccessibleObject<?>> testMethods) {
// TODO: This can be done more efficiently, but we're just trying to see if this makes a difference at all
Map<GenericAccessibleObject<?>, String> mapCallToName = new LinkedHashMap<>();
for (GenericAccessibleObject<?> call : testMethods) {
String name = call.getDeclaringClass().getCanonicalName();
if (call.isMethod()) {
GenericMethod method = (GenericMethod) call;
name += method.getNameWithDescriptor();
} else if (call.isConstructor()) {
GenericConstructor constructor = (GenericConstructor) call;
name += constructor.getNameWithDescriptor();
} else {
throw new RuntimeException("Coverage goals must be methods or constructors");
}
mapCallToName.put(call, name);
}
Map<String, Integer> mapMethodToGoals = new LinkedHashMap<>();
for (String methodName : mapCallToName.values()) {
// MethodKey is class+method+desc
mapMethodToGoals.put(methodName, Archive.getArchiveInstance().getNumOfRemainingTargets(methodName));
}
return testMethods.stream().sorted(Comparator.comparingInt(item -> mapMethodToGoals.get(mapCallToName.get(item))).reversed()).collect(Collectors.toList());
}
use of org.evosuite.utils.generic.GenericConstructor in project evosuite by EvoSuite.
the class EnvironmentTestClusterAugmenter method addEnvironmentClassToCluster.
/**
* Add the given klass to the test cluster. Also recursively add (as
* modifiers) all the other EvoSuite classes for which the given class is a
* generator
*
* @param klass
*/
private boolean addEnvironmentClassToCluster(Class<?> klass) {
if (handledClasses.contains(klass.getCanonicalName()) || !TestClusterUtils.isEvoSuiteClass(klass)) {
// already handled, or not valid
return false;
}
handledClasses.add(klass.getCanonicalName());
boolean excludeClass = klass.getAnnotation(EvoSuiteClassExclude.class) != null;
for (Constructor c : klass.getConstructors()) {
// first check if it should be skipped
if (shouldSkip(excludeClass, c)) {
continue;
}
GenericAccessibleObject gc = new GenericConstructor(c, klass);
TestCluster.getInstance().addEnvironmentTestCall(gc);
GenericClass genclass = new GenericClass(klass);
TestCluster.getInstance().invalidateGeneratorCache(genclass);
TestCluster.getInstance().addGenerator(genclass, gc);
testClusterGenerator.addNewDependencies(Arrays.asList(c.getParameterTypes()));
}
for (Method m : klass.getMethods()) {
if (shouldSkip(excludeClass, m)) {
continue;
}
GenericAccessibleObject gm = new GenericMethod(m, klass);
TestCluster.getInstance().addEnvironmentTestCall(gm);
testClusterGenerator.addNewDependencies(Arrays.asList(m.getParameterTypes()));
Class<?> returnType = m.getReturnType();
if (!returnType.equals(Void.TYPE)) {
GenericClass genclass = new GenericClass(returnType);
TestCluster.getInstance().invalidateGeneratorCache(genclass);
TestCluster.getInstance().addGenerator(genclass, gm);
addEnvironmentDependency(returnType);
}
}
return true;
}
use of org.evosuite.utils.generic.GenericConstructor in project evosuite by EvoSuite.
the class TestFactory method insertRandomCallOnEnvironment.
/**
* @param test
* @param lastValidPosition
* @return the position where the insertion happened, or a negative value otherwise
*/
public int insertRandomCallOnEnvironment(TestCase test, int lastValidPosition) {
int previousLength = test.size();
currentRecursion.clear();
List<GenericAccessibleObject<?>> shuffledOptions = TestCluster.getInstance().getRandomizedCallsToEnvironment();
if (shuffledOptions == null || shuffledOptions.isEmpty()) {
return -1;
}
// iterate (in random order) over all possible environment methods till we find one that can be inserted
for (GenericAccessibleObject<?> o : shuffledOptions) {
try {
int position = ConstraintVerifier.getAValidPositionForInsertion(o, test, lastValidPosition);
if (position < 0) {
// the given method/constructor cannot be added
continue;
}
if (o.isConstructor()) {
GenericConstructor c = (GenericConstructor) o;
addConstructor(test, c, position, 0);
return position;
} else if (o.isMethod()) {
GenericMethod m = (GenericMethod) o;
if (!m.isStatic()) {
VariableReference callee = null;
Type target = m.getOwnerType();
if (!test.hasObject(target, position)) {
callee = createObject(test, target, position, 0, null);
position += test.size() - previousLength;
previousLength = test.size();
} else {
callee = test.getRandomNonNullObject(target, position);
}
if (!TestUsageChecker.canUse(m.getMethod(), callee.getVariableClass())) {
logger.error("Cannot call method " + m + " with callee of type " + callee.getClassName());
}
addMethodFor(test, callee, m.copyWithNewOwner(callee.getGenericClass()), position);
return position;
} else {
addMethod(test, m, position, 0);
return position;
}
} else {
throw new RuntimeException("Unrecognized type for environment: " + o);
}
} catch (ConstructionFailedException e) {
// TODO what to do here?
AtMostOnceLogger.warn(logger, "Failed environment insertion: " + e);
}
}
return -1;
}
use of org.evosuite.utils.generic.GenericConstructor in project evosuite by EvoSuite.
the class TestFactory method insertRandomCall.
/**
* Insert a random call for the UUT at the given position
*
* @param test
* @param position
*/
public boolean insertRandomCall(TestCase test, int position) {
int previousLength = test.size();
String name = "";
currentRecursion.clear();
logger.debug("Inserting random call at position {}", position);
try {
if (reflectionFactory == null) {
final Class<?> targetClass = Properties.getTargetClassAndDontInitialise();
reflectionFactory = new ReflectionFactory(targetClass);
}
if (reflectionFactory.hasPrivateFieldsOrMethods() && TimeController.getInstance().getPhasePercentage() >= Properties.REFLECTION_START_PERCENT && (Randomness.nextDouble() < Properties.P_REFLECTION_ON_PRIVATE || TestCluster.getInstance().getNumTestCalls() == 0)) {
logger.debug("Going to insert random reflection call");
return insertRandomReflectionCall(test, position, 0);
}
GenericAccessibleObject<?> o = TestCluster.getInstance().getRandomTestCall(test);
if (o == null) {
logger.warn("Have no target methods to test");
return false;
} else if (o.isConstructor()) {
if (InstanceOnlyOnce.canInstantiateOnlyOnce(o.getDeclaringClass()) && ConstraintHelper.countNumberOfNewInstances(test, o.getDeclaringClass()) != 0) {
return false;
}
GenericConstructor c = (GenericConstructor) o;
logger.debug("Adding constructor call {}", c.getName());
name = c.getName();
addConstructor(test, c, position, 0);
} else if (o.isMethod()) {
GenericMethod m = (GenericMethod) o;
logger.debug("Adding method call {}", m.getName());
name = m.getName();
if (!m.isStatic()) {
logger.debug("Getting callee of type {}", m.getOwnerClass().getTypeName());
VariableReference callee = null;
Type target = m.getOwnerType();
if (!test.hasObject(target, position)) {
// no FM for SUT
callee = createObject(test, target, position, 0, null, false, false, true);
position += test.size() - previousLength;
previousLength = test.size();
} else {
callee = test.getRandomNonNullObject(target, position);
// This may also be an inner class, in this case we can't use a SUT instance
// if (!callee.isAssignableTo(m.getDeclaringClass())) {
// callee = test.getRandomNonNullObject(m.getDeclaringClass(), position);
// }
}
logger.debug("Got callee of type {}", callee.getGenericClass().getTypeName());
if (!TestUsageChecker.canUse(m.getMethod(), callee.getVariableClass())) {
logger.debug("Cannot call method {} with callee of type {}", m, callee.getClassName());
throw new ConstructionFailedException("Cannot apply method to this callee");
}
addMethodFor(test, callee, m.copyWithNewOwner(callee.getGenericClass()), position);
} else {
// We only use this for static methods to avoid using wrong constructors (?)
addMethod(test, m, position, 0);
}
} else if (o.isField()) {
GenericField f = (GenericField) o;
name = f.getName();
logger.debug("Adding field {}", f.getName());
if (Randomness.nextBoolean()) {
addFieldAssignment(test, f, position, 0);
} else {
addField(test, f, position, 0);
}
} else {
logger.error("Got type other than method or constructor!");
return false;
}
return true;
} catch (ConstructionFailedException e) {
// TODO: Check this! - TestCluster replaced
// TestCluster.getInstance().checkDependencies(o);
logger.debug("Inserting statement {} has failed. Removing statements: {}", name, e);
// TODO: Doesn't work if position != test.size()
int lengthDifference = test.size() - previousLength;
for (int i = lengthDifference - 1; i >= 0; i--) {
// we need to remove them in order, so that the testcase is at all time consistent
if (logger.isDebugEnabled()) {
logger.debug(" Removing statement: " + test.getStatement(position + i).getCode());
}
test.remove(position + i);
}
return false;
}
}
Aggregations