use of org.evosuite.setup.PutStaticMethodCollector.MethodIdentifier in project evosuite by EvoSuite.
the class TestClusterGenerator method initializeTargetMethods.
/**
* All public methods defined directly in the SUT should be covered
*
* TODO: What if we use instrument_parent?
*/
@SuppressWarnings("unchecked")
private void initializeTargetMethods() throws RuntimeException, ClassNotFoundException {
logger.info("Analyzing target class");
Class<?> targetClass = Properties.getTargetClassAndDontInitialise();
TestCluster cluster = TestCluster.getInstance();
Set<Class<?>> targetClasses = new LinkedHashSet<Class<?>>();
if (targetClass == null) {
throw new RuntimeException("Failed to load " + Properties.TARGET_CLASS);
}
targetClasses.add(targetClass);
addDeclaredClasses(targetClasses, targetClass);
if (Modifier.isAbstract(targetClass.getModifiers())) {
logger.info("SUT is an abstract class");
Set<Class<?>> subclasses = ConcreteClassAnalyzer.getInstance().getConcreteClasses(targetClass, inheritanceTree);
logger.info("Found " + subclasses.size() + " concrete subclasses");
targetClasses.addAll(subclasses);
}
// load all the interesting classes from the callgraph,
// need more testing, seems to slow down the search
// if(Properties.INSTRUMENT_CONTEXT){
// Set<String> toLoad;
// if(Properties.INSTRUMENT_LIBRARIES){
// toLoad = callGraph.getClassesUnderTest();
// }else{
// toLoad = new HashSet<>();
// for (String className : callGraph.getClassesUnderTest()) {
// if (!Properties.INSTRUMENT_LIBRARIES
// && !DependencyAnalysis.isTargetProject(className))
// continue;
// toLoad.add(className);
// }
//
// }
// targetClasses.addAll(loadClasses(toLoad));
//
// }
// To make sure we also have anonymous inner classes double check inner
// classes using ASM
// because the loop changes 'targetClasses' set we cannot iterate over
// it, not even
// using an iterator. a simple workaround is to create a temporary set
// with the content
// of 'targetClasses' and iterate that one
Set<Class<?>> tmp_targetClasses = new LinkedHashSet<Class<?>>(targetClasses);
for (Class<?> _targetClass : tmp_targetClasses) {
ClassNode targetClassNode = DependencyAnalysis.getClassNode(_targetClass.getName());
Queue<InnerClassNode> innerClasses = new LinkedList<InnerClassNode>();
innerClasses.addAll(targetClassNode.innerClasses);
while (!innerClasses.isEmpty()) {
InnerClassNode icn = innerClasses.poll();
try {
logger.debug("Loading inner class: " + icn.innerName + ", " + icn.name + "," + icn.outerName);
String innerClassName = ResourceList.getClassNameFromResourcePath(icn.name);
if (!innerClassName.startsWith(Properties.TARGET_CLASS)) {
// TODO: Why does ASM report inner classes that are not actually inner classes?
// Let's ignore classes that don't start with the SUT name for now.
logger.debug("Ignoring inner class that is outside SUT {}", innerClassName);
continue;
}
Class<?> innerClass = TestGenerationContext.getInstance().getClassLoaderForSUT().loadClass(innerClassName);
// Sometimes strange things appear such as Map$Entry
if (!targetClasses.contains(innerClass) && /*
* FIXME: why all the checks were removed? without
* the following, for example
* com.google.javascript.jscomp.IdMappingUtil in
* 124_closure-compiler is not testable
*/
!innerClassName.contains("Map$Entry")) {
// && !innerClassName.matches(".*\\$\\d+(\\$.*)?$")) {
logger.info("Adding inner class {}", innerClassName);
targetClasses.add(innerClass);
ClassNode innerClassNode = DependencyAnalysis.getClassNode(innerClassName);
innerClasses.addAll(innerClassNode.innerClasses);
}
} catch (Throwable t) {
logger.error("Problem for " + Properties.TARGET_CLASS + ". Error loading inner class: " + icn.innerName + ", " + icn.name + "," + icn.outerName + ": " + t);
}
}
}
for (Class<?> clazz : targetClasses) {
logger.info("Current SUT class: " + clazz);
if (!TestUsageChecker.canUse(clazz)) {
logger.info("Cannot access SUT class: " + clazz);
continue;
}
// Add all constructors
for (Constructor<?> constructor : TestClusterUtils.getConstructors(clazz)) {
logger.info("Checking target constructor " + constructor);
String name = "<init>" + org.objectweb.asm.Type.getConstructorDescriptor(constructor);
if (Properties.TT) {
String orig = name;
name = BooleanTestabilityTransformation.getOriginalNameDesc(clazz.getName(), "<init>", org.objectweb.asm.Type.getConstructorDescriptor(constructor));
if (!orig.equals(name))
logger.info("TT name: " + orig + " -> " + name);
}
if (TestUsageChecker.canUse(constructor)) {
GenericConstructor genericConstructor = new GenericConstructor(constructor, clazz);
if (constructor.getDeclaringClass().equals(clazz))
cluster.addTestCall(genericConstructor);
// TODO: Add types!
// .getWithWildcardTypes(),
cluster.addGenerator(// .getWithWildcardTypes(),
new GenericClass(clazz), genericConstructor);
addDependencies(genericConstructor, 1);
logger.debug("Keeping track of " + constructor.getDeclaringClass().getName() + "." + constructor.getName() + org.objectweb.asm.Type.getConstructorDescriptor(constructor));
} else {
logger.debug("Constructor cannot be used: " + constructor);
}
}
// Add all methods
for (Method method : TestClusterUtils.getMethods(clazz)) {
logger.info("Checking target method " + method);
String name = method.getName() + org.objectweb.asm.Type.getMethodDescriptor(method);
if (Properties.TT) {
String orig = name;
name = BooleanTestabilityTransformation.getOriginalNameDesc(clazz.getName(), method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method));
if (!orig.equals(name))
logger.info("TT name: " + orig + " -> " + name);
}
if (TestUsageChecker.canUse(method, clazz)) {
logger.debug("Adding method " + clazz.getName() + "." + method.getName() + org.objectweb.asm.Type.getMethodDescriptor(method));
GenericMethod genericMethod = new GenericMethod(method, clazz);
if (method.getDeclaringClass().equals(clazz))
cluster.addTestCall(genericMethod);
// removed?
if (!CheapPurityAnalyzer.getInstance().isPure(method)) {
cluster.addModifier(new GenericClass(clazz), genericMethod);
}
addDependencies(genericMethod, 1);
GenericClass retClass = new GenericClass(method.getReturnType());
// if (!retClass.isPrimitive() && !retClass.isVoid() && !retClass.isObject())
if (!retClass.isVoid())
// .getWithWildcardTypes(),
cluster.addGenerator(// .getWithWildcardTypes(),
retClass, genericMethod);
} else {
logger.debug("Method cannot be used: " + method);
// If we do reflection on private methods, we still need to consider dependencies
if (Properties.P_REFLECTION_ON_PRIVATE > 0 && method.getDeclaringClass().equals(clazz)) {
GenericMethod genericMethod = new GenericMethod(method, clazz);
addDependencies(genericMethod, 1);
}
}
}
for (Field field : TestClusterUtils.getFields(clazz)) {
logger.info("Checking target field " + field);
if (TestUsageChecker.canUse(field, clazz)) {
GenericField genericField = new GenericField(field, clazz);
addDependencies(genericField, 1);
// .getWithWildcardTypes(),
cluster.addGenerator(// .getWithWildcardTypes(),
new GenericClass(field.getGenericType()), genericField);
logger.debug("Adding field " + field);
final boolean isFinalField = isFinalField(field);
if (!isFinalField) {
logger.debug("Is not final");
// Setting fields does not contribute to coverage, so we will only count it as a modifier
// if (field.getDeclaringClass().equals(clazz))
// cluster.addTestCall(new GenericField(field, clazz));
cluster.addModifier(new GenericClass(clazz), genericField);
} else {
logger.debug("Is final");
if (Modifier.isStatic(field.getModifiers()) && !field.getType().isPrimitive()) {
logger.debug("Is static non-primitive");
/*
* With this we are trying to cover such cases:
*
* public static final DurationField INSTANCE = new
* MillisDurationField();
*
* private MillisDurationField() { super(); }
*/
try {
Object o = field.get(null);
if (o == null) {
logger.info("Field is not yet initialized: " + field);
} else {
Class<?> actualClass = o.getClass();
logger.debug("Actual class is " + actualClass);
if (!actualClass.isAssignableFrom(genericField.getRawGeneratedType()) && genericField.getRawGeneratedType().isAssignableFrom(actualClass)) {
GenericField superClassField = new GenericField(field, clazz);
cluster.addGenerator(new GenericClass(actualClass), superClassField);
}
}
} catch (IllegalAccessException e) {
logger.error(e.getMessage());
}
}
}
} else {
logger.debug("Can't use field " + field);
// TODO: Duplicate code here
if (Properties.P_REFLECTION_ON_PRIVATE > 0) {
if (Modifier.isPrivate(field.getModifiers()) && !field.isSynthetic() && !field.getName().equals("serialVersionUID") && // primitives cannot be changed
!(field.getType().isPrimitive()) && // changing final strings also doesn't make much sense
!(Modifier.isFinal(field.getModifiers()) && field.getType().equals(String.class)) && // static fields lead to just too many problems... although this could be set as a parameter
!Modifier.isStatic(field.getModifiers())) {
GenericField genericField = new GenericField(field, clazz);
addDependencies(genericField, 1);
}
}
}
}
analyzedClasses.add(clazz);
// TODO: Set to generic type rather than class?
cluster.getAnalyzedClasses().add(clazz);
}
if (Properties.INSTRUMENT_PARENT) {
for (String superClass : inheritanceTree.getSuperclasses(Properties.TARGET_CLASS)) {
try {
Class<?> superClazz = TestGenerationContext.getInstance().getClassLoaderForSUT().loadClass(superClass);
dependencies.add(new DependencyPair(0, superClazz));
} catch (ClassNotFoundException e) {
logger.error("Problem for " + Properties.TARGET_CLASS + ". Class not found: " + superClass, e);
}
}
}
if (Properties.HANDLE_STATIC_FIELDS) {
GetStaticGraph getStaticGraph = GetStaticGraphGenerator.generate(Properties.TARGET_CLASS);
Map<String, Set<String>> staticFields = getStaticGraph.getStaticFields();
for (String className : staticFields.keySet()) {
logger.info("Adding static fields to cluster for class " + className);
Class<?> clazz;
try {
Sandbox.goingToExecuteUnsafeCodeOnSameThread();
clazz = TestClusterUtils.getClass(className);
} catch (ExceptionInInitializerError ex) {
logger.debug("Class class init caused exception " + className);
continue;
} finally {
Sandbox.doneWithExecutingUnsafeCodeOnSameThread();
}
if (clazz == null) {
logger.debug("Class not found " + className);
continue;
}
if (!TestUsageChecker.canUse(clazz))
continue;
Set<String> fields = staticFields.get(className);
for (Field field : TestClusterUtils.getFields(clazz)) {
if (!TestUsageChecker.canUse(field, clazz))
continue;
if (fields.contains(field.getName())) {
if (!isFinalField(field)) {
logger.debug("Is not final");
// cluster.addTestCall(new GenericField(field, clazz));
// Count static field as modifier of SUT, not as test call:
GenericField genericField = new GenericField(field, clazz);
cluster.addModifier(new GenericClass(Properties.getTargetClassAndDontInitialise()), genericField);
}
}
}
}
PutStaticMethodCollector collector = new PutStaticMethodCollector(Properties.TARGET_CLASS, staticFields);
Set<MethodIdentifier> methodIdentifiers = collector.collectMethods();
for (MethodIdentifier methodId : methodIdentifiers) {
Class<?> clazz = TestClusterUtils.getClass(methodId.getClassName());
if (clazz == null)
continue;
if (!TestUsageChecker.canUse(clazz))
continue;
Method method = TestClusterUtils.getMethod(clazz, methodId.getMethodName(), methodId.getDesc());
if (method == null)
continue;
GenericMethod genericMethod = new GenericMethod(method, clazz);
// Setting static fields is a modifier of a SUT
// cluster.addTestCall(genericMethod);
cluster.addModifier(new GenericClass(Properties.getTargetClassAndDontInitialise()), genericMethod);
}
}
logger.info("Finished analyzing target class");
}
use of org.evosuite.setup.PutStaticMethodCollector.MethodIdentifier in project evosuite by EvoSuite.
the class TestPutStaticCollector method testFooBar1.
@Test
public void testFooBar1() {
String className = FooBar1.class.getName();
PutStaticMethodCollector collector = new PutStaticMethodCollector(className);
MethodIdentifier expected_method_id = new MethodIdentifier(FooBar2.class.getName(), "init_used_int_field", Type.getMethodDescriptor(Type.VOID_TYPE));
Set<MethodIdentifier> expected_methods = Collections.singleton(expected_method_id);
Set<MethodIdentifier> methods = collector.collectMethods();
assertEquals(expected_methods, methods);
}
Aggregations