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

org.evosuite.continuous.project.ProjectAnalyzer 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.continuous.project;

import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.evosuite.Properties;
import org.evosuite.TestGenerationContext;
import org.evosuite.Properties.AvailableSchedule;
import org.evosuite.classpath.ClassPathHandler;
import org.evosuite.classpath.ResourceList;
import org.evosuite.continuous.job.schedule.HistorySchedule;
import org.evosuite.continuous.project.ProjectStaticData.ClassInfo;
import org.evosuite.coverage.branch.BranchPool;
import org.evosuite.instrumentation.InstrumentingClassLoader;
import org.evosuite.junit.CoverageAnalysis;
import org.evosuite.runtime.sandbox.Sandbox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 

* This class is used to analyze and gather all the * static information of the target project. *

* *

* To be useful, this analysis does not need to be 100% precise, * as we use the generated statistics only for heuristics *

* *

* Note: this class assumes the classpath is properly set * * @author arcuri * */ public class ProjectAnalyzer { private static Logger logger = LoggerFactory.getLogger(ProjectAnalyzer.class); /** * the folder/jar where to find the .class files used as CUTs */ private final String target; /** * package prefix to select a subset of classes on classpath/target to define * what to run CTG on */ private final String prefix; private transient Set cutsToAnalyze; /** * When specifying a set of CUTs, still check if they do exist (eg scan folder to search for * them), instead of justing using them directly (and get errors later) * */ private boolean validateCutsToAnalyze; /** * Main constructor * * @param target * @param prefix * @param cuts */ public ProjectAnalyzer(String target, String prefix, String[] cuts) { super(); this.target = target; this.prefix = prefix==null ? "" : prefix; this.validateCutsToAnalyze = true; if(cuts == null){ this.cutsToAnalyze = null; } else { this.cutsToAnalyze = new LinkedHashSet<>(); for(String s : cuts){ if(s!=null && !s.isEmpty()){ cutsToAnalyze.add(s.trim()); } } } } /** * Instead of scanning for classes in the given target, directly specify * the class names the project is composed by * *

* Note: this constructor is mainly meant for unit tests * @param cuts */ public ProjectAnalyzer(String[] cuts) throws NullPointerException { super(); if(cuts==null){ throw new NullPointerException("Input array cannot be null"); } this.target = null; this.prefix = null; this.validateCutsToAnalyze = false; this.cutsToAnalyze = new LinkedHashSet<>(); cutsToAnalyze.addAll(Arrays.asList(cuts)); } private Collection getCutsToAnalyze(){ if(cutsToAnalyze!=null && !validateCutsToAnalyze){ // this is mainly in test cases return cutsToAnalyze; } Set suts = null; if(target!=null){ if(!target.contains(File.pathSeparator)){ suts = ResourceList.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getAllClasses(target, prefix, false); } else { suts = new LinkedHashSet<>(); for(String element : target.split(File.pathSeparator)){ suts.addAll(ResourceList.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getAllClasses(element, prefix, false)); } } } else { /* * if no target specified, just grab everything on SUT classpath */ suts = ResourceList.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getAllClasses(ClassPathHandler.getInstance().getTargetProjectClasspath(), prefix, false); } List cuts = new LinkedList(); for (String className : suts) { if(cutsToAnalyze!=null && !cutsToAnalyze.contains(className)){ /* * Note: if this is happens, it is not necessarily an error. * For example, this will happen when CTG is run on a multi-module * maven project */ continue; } try { Class clazz = Class.forName(className); if (!CoverageAnalysis.isTest(clazz)){ cuts.add(className); } } catch (ClassNotFoundException e) { logger.error(""+e,e); } catch(ExceptionInInitializerError | NoClassDefFoundError | UnsatisfiedLinkError e){ /** * TODO: for now we skip it, but at a certain point * we should able to handle it, especially if it * is due to static state initialization */ logger.warn("Cannot initialize class: "+className); } } return cuts; } /** * Analyze the classes in the given target * @return */ public ProjectStaticData analyze(){ ProjectStaticData data = new ProjectStaticData(); if(Properties.CTG_SCHEDULE.equals(AvailableSchedule.HISTORY)){ data.initializeLocalHistory(); } for (String className : getCutsToAnalyze()) { Class theClass = null; int numberOfBranches = -1; boolean hasCode = false; Properties.TARGET_CLASS = className; InstrumentingClassLoader instrumenting = new InstrumentingClassLoader(); BranchPool.getInstance(instrumenting).reset(); try{ /* * to access number of branches, we need to use * instrumenting class loader. But loading a class would * execute its static code, and so we need to * use a security manager. */ Sandbox.goingToExecuteUnsafeCodeOnSameThread(); instrumenting.loadClass(className); numberOfBranches = BranchPool.getInstance(instrumenting).getBranchCounter(); hasCode = (numberOfBranches > 0) || (BranchPool.getInstance(instrumenting).getBranchlessMethods().size() > 0); /* * just to avoid possible issues with instrumenting classloader */ theClass = ClassLoader.getSystemClassLoader().loadClass(className); //TODO kind //if(theClass.isInterface()){ // kind = ClassKind.INTERFACE; //} else if(theClass.is Modifier.isAbstract( someClass.getModifiers() ); } catch (Exception e) { logger.warn("Cannot handle "+className+" due to: "+e.getClass()+" "+e.getMessage()); continue; } finally { Sandbox.doneWithExecutingUnsafeCodeOnSameThread(); BranchPool.getInstance(instrumenting).reset(); Properties.TARGET_CLASS = ""; } ClassInfo ci = new ClassInfo(theClass, numberOfBranches, hasCode); data.addNewClass(ci); if (Properties.CTG_SCHEDULE == AvailableSchedule.HISTORY) { ci.setChanged(data.hasChanged(theClass.getCanonicalName() + ".java")); ci.isToTest(data.isToTest(theClass.getCanonicalName(), HistorySchedule.COMMIT_IMPROVEMENT)); } } return data; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy