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

org.evosuite.coverage.dataflow.DefUseCoverageFactory Maven / Gradle / Ivy

/**
 * 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.coverage.dataflow;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.evosuite.Properties;
import org.evosuite.TestGenerationContext;
import org.evosuite.coverage.dataflow.DefUseCoverageTestFitness.DefUsePairType;
import org.evosuite.coverage.dataflow.analysis.AllUsesAnalysis;
import org.evosuite.graphs.GraphPool;
import org.evosuite.graphs.ccfg.ClassControlFlowGraph;
import org.evosuite.graphs.cfg.BytecodeInstruction;
import org.evosuite.rmi.ClientServices;
import org.evosuite.statistics.RuntimeVariable;
import org.evosuite.testcase.execution.ExecutionResult;
import org.evosuite.testsuite.AbstractFitnessFactory;
import org.evosuite.utils.LoggingUtils;
import org.evosuite.utils.JdkPureMethodsList;
import org.objectweb.asm.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 

* DefUseCoverageFactory class. *

* * @author Andre Mis */ public class DefUseCoverageFactory extends AbstractFitnessFactory { private static final Logger logger = LoggerFactory.getLogger(DefUseCoverageFactory.class); // TestSuiteMinimizer seems to call getCoverageGoals() a second time // and since analysis takes a little ... private static boolean called = false; private static List duGoals; // TODO: What's the difference to goals? private static List goals; // map of all NON-parameter-goals private static Map> goalMap = new HashMap>(); private static Map goalCounts = new HashMap(); /** *

* getDUGoals *

* * @return a {@link java.util.List} object. */ public static List getDUGoals() { if (!called) computeGoals(); return duGoals; } /* * (non-Javadoc) * * @see * org.evosuite.coverage.TestFitnessFactory#getCoverageGoals() */ /** {@inheritDoc} */ @Override public List getCoverageGoals() { if (!called) computeGoals(); return goals; } /** * Determines all goals that need to get covered in order to fulfill * DefUseCoverage * * Those are the following: - for each parameterUse this method creates a * goal trying to cover i - for each duPair with a definition clear path * inside the methods of the CUT a goal is created - for each definition in * the CUT with a clear path to an exit of its method and each use with a * clear path from its methods entry a goal is created */ public static void computeGoals() { categorizeFieldMethodCalls(); // XXX testing purposes /*for(String methodInCCFG : GraphPool.getInstance(TestGenerationContext.getClassLoader()).getRawCFGs(Properties.TARGET_CLASS).keySet()) { if(GraphPool.getInstance(TestGenerationContext.getClassLoader()).getCCFG(Properties.TARGET_CLASS).isPure(methodInCCFG)) LoggingUtils.getEvoLogger().debug("PURE method:\t"+methodInCCFG); else LoggingUtils.getEvoLogger().debug("IMPURE method:\t"+methodInCCFG); } */ long start = System.currentTimeMillis(); LoggingUtils.getEvoLogger().info("starting DefUse-Coverage goal generation"); duGoals = new ArrayList(); if(!GraphPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).canMakeCCFGForClass(Properties.TARGET_CLASS)) { goals = new ArrayList(); logger.info("Have no CFGs, is this an interface?"); return; } LoggingUtils.getEvoLogger().info("* Creating DefUse-Pairs from CCFG..."); duGoals.addAll(getCCFGPairs()); LoggingUtils.getEvoLogger().info(" ..created " + getIntraMethodGoalsCount() + " intra-method-, " + getInterMethodGoalsCount() + " inter-method- and " + getIntraClassGoalsCount() + " intra-class-pairs"); LoggingUtils.getEvoLogger().info(" "+duGoals.toString()); LoggingUtils.getEvoLogger().info("* Creating parameter goals..."); duGoals.addAll(getParameterGoals()); LoggingUtils.getEvoLogger().info(" created " + getParamGoalsCount() + " parameter goals"); called = true; goals = new ArrayList(); goals.addAll(duGoals); long end = System.currentTimeMillis(); goalComputationTime = end - start; LoggingUtils.getEvoLogger().info("* Goal computation took: " + goalComputationTime + "ms"); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.IntraMethodPairs, getIntraMethodGoalsCount()); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.InterMethodPairs, getInterMethodGoalsCount()); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.ParameterPairs, getParamGoalsCount()); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.IntraClassPairs, getIntraClassGoalsCount()); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.DefUsePairs, goals.size()); } /** * Determines for all method calls on fields of the CUT whether the call is * to a pure or impure method. For these calls Uses and Definitions are * created respectively. * * Since purity analysis is used here and requires all classes along the * call tree to be completely analyzed this part of the CUT analysis can not * be done in the CFGMethodAdapter like the rest of it. * */ private static void categorizeFieldMethodCalls() { Set fieldMethodCalls = DefUsePool.retrieveFieldMethodCalls(); LoggingUtils.getEvoLogger().info("Categorizing field method calls: " + fieldMethodCalls.size()); for (BytecodeInstruction fieldMethodCall : fieldMethodCalls) { if (GraphPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).canMakeCCFGForClass(fieldMethodCall.getCalledMethodsClass())) { ClassControlFlowGraph ccfg = GraphPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getCCFG(fieldMethodCall.getCalledMethodsClass()); if (ccfg.isPure(fieldMethodCall.getCalledMethod())) { if (!DefUsePool.addAsUse(fieldMethodCall)) throw new IllegalStateException( "unable to register field method call as a use " + fieldMethodCall.toString()); } else { if (!DefUsePool.addAsDefinition(fieldMethodCall)) throw new IllegalStateException( "unable to register field method call as a definition " + fieldMethodCall.toString()); } } else { String toAnalyze = fieldMethodCall.getCalledMethodsClass() + "." + fieldMethodCall.getCalledMethodName(); if (toAnalyze != null && toAnalyze.startsWith("java.")) { Type[] parameters = org.objectweb.asm.Type.getArgumentTypes(fieldMethodCall.getMethodCallDescriptor()); String newParams = ""; if (parameters.length != 0) { for (Type i : parameters) { newParams = newParams + "," + i.getClassName(); } newParams = newParams.substring(1, newParams.length()); } toAnalyze = fieldMethodCall.getCalledMethodsClass() + "." + fieldMethodCall.getCalledMethodName() + "(" + newParams + ")"; //System.out.println(toAnalyze); if (JdkPureMethodsList.instance.checkPurity(toAnalyze)) { if (!DefUsePool.addAsUse(fieldMethodCall)) throw new IllegalStateException( "unable to register field method call as a use " + fieldMethodCall.toString()); } else { if (!DefUsePool.addAsDefinition(fieldMethodCall)) throw new IllegalStateException( "unable to register field method call as a definition " + fieldMethodCall.toString()); } } else { if (!DefUsePool.addAsUse(fieldMethodCall)) throw new IllegalStateException( "unable to register field method call as a use " + fieldMethodCall.toString()); } } } } private static Set getCCFGPairs() { ClassControlFlowGraph ccfg = GraphPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getCCFG(Properties.TARGET_CLASS); AllUsesAnalysis aua = new AllUsesAnalysis(ccfg); Set r = aua.determineDefUsePairs(); return r; } /** * Given a definition and a use, this method creates a DefUseCoverageGoal * for this DefUsePair. * * @param def * The definition of the goal * @param use * The use of the goal * @return The created DefUseCoverageGoal * @param type * a * {@link org.evosuite.coverage.dataflow.DefUseCoverageTestFitness.DefUsePairType} * object. */ public static DefUseCoverageTestFitness createGoal(Definition def, Use use, DefUseCoverageTestFitness.DefUsePairType type) { DefUseCoverageTestFitness goal = new DefUseCoverageTestFitness(def, use, type); if (registerGoal(goal)) return goal; else { // System.out.println("Discarding goal: "+goal.toString()); return null; } } /** * Convenience method that retrieves the Definition and Use object for the * given BytecodeInstructions from the DefUsePool and calls * createGoal(Definition,Use) * * @param def * a {@link org.evosuite.graphs.cfg.BytecodeInstruction} object. * @param use * a {@link org.evosuite.graphs.cfg.BytecodeInstruction} object. * @param type * a * {@link org.evosuite.coverage.dataflow.DefUseCoverageTestFitness.DefUsePairType} * object. * @return a * {@link org.evosuite.coverage.dataflow.DefUseCoverageTestFitness} * object. */ public static DefUseCoverageTestFitness createGoal(BytecodeInstruction def, BytecodeInstruction use, DefUseCoverageTestFitness.DefUsePairType type) { if (def == null) throw new IllegalArgumentException("null given as def"); if (use == null) throw new IllegalArgumentException("null given as use"); Definition definition = DefUsePool.getDefinitionByInstruction(def); Use usee = DefUsePool.getUseByInstruction(use); if (definition == null || usee == null) // can happen in (very, very) // weird cases, ignoring that // for now return null; return createGoal(definition, usee, type); } private static boolean registerGoal(DefUseCoverageTestFitness goal) { if (!goalMap.containsKey(goal.getGoalDefinition())) goalMap.put(goal.getGoalDefinition(), new HashMap()); if (goalMap.get(goal.getGoalDefinition()).containsKey(goal.getGoalUse()) /* && goal.isInterMethodPair() */) // when intra-goal DUs also have free paths to method start and end // it can be declared both an intra-goal and an inter-goal. in this // case we declare the goal to be intra return false; goalMap.get(goal.getGoalDefinition()).put(goal.getGoalUse(), goal); countGoal(goal); return true; } private static void countGoal(DefUseCoverageTestFitness goal) { if (goalCounts.get(goal.getType()) == null) goalCounts.put(goal.getType(), 0); goalCounts.put(goal.getType(), goalCounts.get(goal.getType()) + 1); // LoggingUtils.getEvoLogger().info(goal.toString()); } /** *

* retrieveGoal *

* * @param defId * a int. * @param useId * a int. * @return a * {@link org.evosuite.coverage.dataflow.DefUseCoverageTestFitness} * object. */ public static DefUseCoverageTestFitness retrieveGoal(int defId, int useId) { Definition def = DefUsePool.getDefinitionByDefId(defId); Use use = DefUsePool.getUseByUseId(useId); return retrieveGoal(def, use); } /** *

* retrieveGoal *

* * @param def * a {@link org.evosuite.coverage.dataflow.Definition} object. * @param use * a {@link org.evosuite.coverage.dataflow.Use} object. * @return a * {@link org.evosuite.coverage.dataflow.DefUseCoverageTestFitness} * object. */ public static DefUseCoverageTestFitness retrieveGoal(Definition def, Use use) { if (!goalMap.containsKey(def)) return null; if (!goalMap.get(def).containsKey(use)) return null; return goalMap.get(def).get(use); } /** * For each parameterUse in the CUT this method creates a * DefUseCoverageTestFitness that tries to cover that use * * @return a {@link java.util.Set} object. */ public static Set getParameterGoals() { Set r = new HashSet(); Set parameterUses = DefUsePool.retrieveRegisteredParameterUses(); for (Use use : parameterUses) { DefUseCoverageTestFitness goal = new DefUseCoverageTestFitness(use); r.add(goal); countGoal(goal); } // paramGoalsCount = r.size(); // LoggingUtils.getEvoLogger().debug("# Parameter-Uses: " + r.size()); return r; } /** *

* getRegsiteredDefinitions *

* * @return a {@link java.util.Set} object. */ public static Set getRegisteredDefinitions() { if (!called) computeGoals(); return new HashSet(goalMap.keySet()); } /** *

* getRegisteredGoalsForDefinition *

* * @param def * a {@link org.evosuite.coverage.dataflow.Definition} object. * @return a {@link java.util.Map} object. */ public static Map getRegisteredGoalsForDefinition( Definition def) { if (!called) computeGoals(); return goalMap.get(def); } // Getter /** *

* getParamGoalsCount *

* * @return a int. */ public static int getParamGoalsCount() { Integer r = goalCounts.get(DefUsePairType.PARAMETER); if (r == null) return 0; return r; } /** *

* getIntraMethodGoalsCount *

* * @return a int. */ public static int getIntraMethodGoalsCount() { Integer r = goalCounts.get(DefUsePairType.INTRA_METHOD); if (r == null) return 0; return r; } /** *

* getInterMethodGoalsCount *

* * @return a int. */ public static int getInterMethodGoalsCount() { Integer r = goalCounts.get(DefUsePairType.INTER_METHOD); if (r == null) return 0; return r; } /** *

* getIntraClassGoalsCount *

* * @return a int. */ public static int getIntraClassGoalsCount() { Integer r = goalCounts.get(DefUsePairType.INTRA_CLASS); if (r == null) return 0; return r; } public static void clear() { if (called) { called = false; duGoals.clear(); goals.clear(); goalMap.clear(); goalCounts.clear(); } } public static boolean detectAliasingGoals(List results) { if (!Properties.DEFUSE_ALIASES) return false; Set aliasingGoals = new HashSet(); for (ExecutionResult result : results) { aliasingGoals.addAll(detectAliasingGoals(result)); } // Need to add here to avoid concurrent access if (!aliasingGoals.isEmpty()) { goals.addAll(aliasingGoals); duGoals.addAll(aliasingGoals); } return !aliasingGoals.isEmpty(); } private static Set detectAliasingGoals( ExecutionResult result) { Map>> passedDefsObject = result.getTrace().getDefinitionDataObjects(); Map>> passedUsesObject = result.getTrace().getUseDataObjects(); Map>> passedDefs = result.getTrace().getDefinitionData(); Map>> passedUses = result.getTrace().getUseData(); Set aliasingGoals = new HashSet(); for (String goalVariable : passedUsesObject.keySet()) { for (Integer objectId : passedUsesObject.get(goalVariable).keySet()) { for (Object o1 : passedUsesObject.get(goalVariable).get(objectId).values()) { for (String otherGoalVariable : passedDefsObject.keySet()) { for (Integer otherObjectId : passedDefsObject.get(otherGoalVariable).keySet()) { for (Object o2 : passedDefsObject.get(otherGoalVariable).get(otherObjectId).values()) { if (o1 != null && o1 == o2 && objectId == otherObjectId && !goalVariable.equals(otherGoalVariable)) { Map currentDefMap = passedDefs.get(otherGoalVariable).get(objectId); Map currentUseMap = passedUses.get(goalVariable).get(objectId); List duCounterTrace = new ArrayList( currentDefMap.keySet()); duCounterTrace.addAll(currentUseMap.keySet()); // System.out.println(duCounterTrace.size()); oO for ncs.Bessj these can be up to 50k entries big Collections.sort(duCounterTrace); int traceLength = duCounterTrace.size(); Integer[] sortedDefDUTrace = duCounterTrace.toArray(new Integer[traceLength]); int activeDef = -1; for (int i = 0; i < traceLength; i++) { int currentDUCounter = sortedDefDUTrace[i]; if (currentDefMap.containsKey(currentDUCounter)) { activeDef = currentDefMap.get(currentDUCounter); } else if (activeDef != -1) { int currentUse = currentUseMap.get(currentDUCounter); DefUseCoverageTestFitness currentGoal = DefUseCoverageFactory.retrieveGoal(activeDef, currentUse); if (currentGoal == null) { logger.info("New alias found: Variable defined as " + otherGoalVariable + " appeared in use as " + goalVariable); Definition def = DefUsePool.getDefinitionByDefId(activeDef); Use use = DefUsePool.getUseByUseId(currentUse); for (DefUseCoverageTestFitness defUse : duGoals) { // Find all other defs of the variable in the use if (defUse.getGoalUse().equals(use)) { Map defUseMap = getRegisteredGoalsForDefinition(defUse.getGoalDefinition()); for (Use otherUse : defUseMap.keySet()) { // For each defuse pair, add new defuse pair with alternative def DefUseCoverageTestFitness goal = DefUseCoverageFactory.createGoal(def, otherUse, defUseMap.get(otherUse).getType()); if (goal != null) { logger.info("Created new defuse pair: " + goal + " of type " + goal.getType()); aliasingGoals.add(goal); } } } } } } } } } } } } } } return aliasingGoals; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy