Search in sources :

Example 1 with MethodIdentifier

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");
}
Also used : LinkedHashSet(java.util.LinkedHashSet) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) GenericMethod(org.evosuite.utils.generic.GenericMethod) GenericField(org.evosuite.utils.generic.GenericField) Field(java.lang.reflect.Field) GenericClass(org.evosuite.utils.generic.GenericClass) InnerClassNode(org.objectweb.asm.tree.InnerClassNode) ClassNode(org.objectweb.asm.tree.ClassNode) GenericConstructor(org.evosuite.utils.generic.GenericConstructor) GenericMethod(org.evosuite.utils.generic.GenericMethod) Method(java.lang.reflect.Method) MethodIdentifier(org.evosuite.setup.PutStaticMethodCollector.MethodIdentifier) InnerClassNode(org.objectweb.asm.tree.InnerClassNode) LinkedList(java.util.LinkedList) GenericClass(org.evosuite.utils.generic.GenericClass) GenericAccessibleObject(org.evosuite.utils.generic.GenericAccessibleObject) GenericField(org.evosuite.utils.generic.GenericField)

Example 2 with MethodIdentifier

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);
}
Also used : MethodIdentifier(org.evosuite.setup.PutStaticMethodCollector.MethodIdentifier) FooBar2(com.examples.with.different.packagename.staticusage.FooBar2) Test(org.junit.Test)

Aggregations

MethodIdentifier (org.evosuite.setup.PutStaticMethodCollector.MethodIdentifier)2 FooBar2 (com.examples.with.different.packagename.staticusage.FooBar2)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1 LinkedHashSet (java.util.LinkedHashSet)1 LinkedList (java.util.LinkedList)1 Set (java.util.Set)1 GenericAccessibleObject (org.evosuite.utils.generic.GenericAccessibleObject)1 GenericClass (org.evosuite.utils.generic.GenericClass)1 GenericConstructor (org.evosuite.utils.generic.GenericConstructor)1 GenericField (org.evosuite.utils.generic.GenericField)1 GenericMethod (org.evosuite.utils.generic.GenericMethod)1 Test (org.junit.Test)1 ClassNode (org.objectweb.asm.tree.ClassNode)1 InnerClassNode (org.objectweb.asm.tree.InnerClassNode)1