All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.evosuite.testcase.statements.reflection.ReflectionFactory Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2010-2018 Gordon Fraser, Andrea Arcuri and EvoSuite
 * contributors
 *
 * This file is part of EvoSuite.
 *
 * EvoSuite is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3.0 of the License, or
 * (at your option) any later version.
 *
 * EvoSuite is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with EvoSuite. If not, see .
 */
package org.evosuite.testcase.statements.reflection;

import org.evosuite.Properties;
import org.evosuite.runtime.Reflection;
import org.evosuite.runtime.javaee.injection.Injector;
import org.evosuite.testcase.statements.MethodStatement;
import org.evosuite.utils.Randomness;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * Class used to get private fields/methods to construct statements in the generated tests
 *
 * Created by Andrea Arcuri on 22/02/15.
 */
public class ReflectionFactory {

    private final Class target;
    private final List fields;
    private final List methods;


    public ReflectionFactory(Class target) throws IllegalArgumentException{
        this.target = target;
        if(target==null){
            throw new IllegalArgumentException("Target class cannot be null");
        }

        fields = new ArrayList<>();
        methods = new ArrayList<>();

        for(Method m : Reflection.getDeclaredMethods(target)){
            if(Modifier.isPrivate(m.getModifiers()) && !m.isBridge() && !m.isSynthetic()){
                //only interested in private methods, as the others can be called directly
                methods.add(m);
            }
        }

        //do not use reflection on JEE injection
        List toSkip = null;
        if(Properties.JEE){
            toSkip = Injector.getAllFieldsToInject(target);
        }

        for(Field f : Reflection.getDeclaredFields(target)){
            if(Modifier.isPrivate(f.getModifiers())
                    && !f.isSynthetic()
                    && (toSkip==null || ! toSkip.contains(f))
                    && !f.getName().equals("serialVersionUID")
                    // read/writeObject must not be invoked directly, otherwise it raises a java.io.NotActiveException
                    && !f.getName().equals("writeObject")
                    && !f.getName().equals("readObject")
                    // final primitives cannot be changed
                    && !(Modifier.isFinal(f.getModifiers()) && f.getType().isPrimitive())
                    // changing final strings also doesn't make much sense
                    && !(Modifier.isFinal(f.getModifiers()) && f.getType().equals(String.class))
                    //static fields lead to just too many problems... although this could be set as a parameter
                    && !Modifier.isStatic(f.getModifiers())
                    ) {
                fields.add(f);
            }
        }
    }

    public int getNumberOfUsableFields(){
        return fields.size();
    }

    public boolean hasPrivateFieldsOrMethods(){
        return  !(fields.isEmpty() && methods.isEmpty());
    }

    public boolean nextUseField(){
        if(fields.isEmpty()){
            return false;
        }
        if(methods.isEmpty()){
            assert !fields.isEmpty();
            return true;
        }

        assert !fields.isEmpty() && !methods.isEmpty();

        int tot = fields.size() + methods.size();
        double ratio = (double)fields.size() / (double) tot;

        return Randomness.nextDouble() <= ratio;
    }

    public Field nextField() throws IllegalStateException{
        if(fields.isEmpty()){
            throw new IllegalStateException("No private field");
        }
        return Randomness.choice(fields);
    }

    public Method nextMethod()  throws IllegalStateException{
        if(methods.isEmpty()){
            throw new IllegalStateException("No private method");
        }
        return Randomness.choice(methods);
    }

    public Class getReflectedClass(){
        return target;
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy