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

org.evosuite.graphs.cfg.ControlFlowGraph 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.graphs.cfg;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

import org.evosuite.graphs.EvoSuiteGraph;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.objectweb.asm.Opcodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Abstract base class for both forms of CFGs inside EvoSuite
 *
 * One implementation of this is cfg.RawControlFlowGraph, which is also known as
 * the complete CFG The other implementation of this is
 * cfg.ActualControlFlowGraph which is also known as the minimal CFG Look at the
 * respective classes for more detailed information
 *
 * The CFGs can be accessed via the GraphPool which holds for each CUT and each
 * of their methods a complete and a minimal CFG
 *
 * CFGs are created by the CFGGenerator during the analysis of the CUTs'
 * byteCode performed by the BytecodeAnalyzer
 *
 * @author Gordon Fraser, Andre Mis
 */
public abstract class ControlFlowGraph extends
		EvoSuiteGraph {

	private static Logger logger = LoggerFactory
			.getLogger(ControlFlowGraph.class);

	protected String className;
	protected String methodName;
	protected int access;

	private int diameter = -1;

	/**
	 * Creates a fresh and empty CFG for the given class and method
	 *
	 * @param className a {@link java.lang.String} object.
	 * @param methodName a {@link java.lang.String} object.
	 * @param access a int.
	 */
	protected ControlFlowGraph(String className, String methodName, int access) {
		super(ControlFlowEdge.class);

		if (className == null || methodName == null)
			throw new IllegalArgumentException("null given");

		this.className = className;
		this.methodName = methodName;
		this.access = access;
	}

	/**
	 * Creates a CFG determined by the given jGraph for the given class and
	 * method
	 *
	 * @param className a {@link java.lang.String} object.
	 * @param methodName a {@link java.lang.String} object.
	 * @param access a int.
	 * @param jGraph a {@link org.jgrapht.graph.DefaultDirectedGraph} object.
	 */
	protected ControlFlowGraph(String className, String methodName, int access,
			DefaultDirectedGraph jGraph) {
		super(jGraph, ControlFlowEdge.class);

		if (className == null || methodName == null)
			throw new IllegalArgumentException("null given");

		this.className = className;
		this.methodName = methodName;
		this.access = access;
	}

	/**
	 * 

leadsToNode

* * @param e a {@link org.evosuite.graphs.cfg.ControlFlowEdge} object. * @param b a V object. * @return a boolean. */ public boolean leadsToNode(ControlFlowEdge e, V b) { Set handled = new HashSet(); Queue queue = new LinkedList(); queue.add(getEdgeTarget(e)); while (!queue.isEmpty()) { V current = queue.poll(); if (handled.contains(current)) continue; handled.add(current); for (V next : getChildren(current)) if (next.equals(b)) return true; else queue.add(next); } return false; } // /** // * Can be used to retrieve a Branch contained in this CFG identified by // it's // * branchId // * // * If no such branch exists in this CFG, null is returned // */ // public abstract BytecodeInstruction getBranch(int branchId); /** * Can be used to retrieve an instruction contained in this CFG identified * by it's instructionId * * If no such instruction exists in this CFG, null is returned * * @param instructionId a int. * @return a {@link org.evosuite.graphs.cfg.BytecodeInstruction} object. */ public abstract BytecodeInstruction getInstruction(int instructionId); /** * Determines, whether a given instruction is contained in this CFG * * @param instruction a {@link org.evosuite.graphs.cfg.BytecodeInstruction} object. * @return a boolean. */ public abstract boolean containsInstruction(BytecodeInstruction instruction); /** * Computes the diameter of this CFG and the mutation distances * * Since both takes some time this is not automatically done on each CFG * * GraphPool will automatically call this immediately after the * instantiation of an ActualControlFlowGraph, but not after the creation of * a RawControlFlowGraph */ public void finalise() { computeDiameter(); // TODO: call this! // and sanity check with a flag whenever a call // to this method is assumed to have been made } /** * Returns the Diameter of this CFG * * If the diameter of this graph was not computed previously it is computed * first * * @return a int. */ public int getDiameter() { if (diameter == -1) { logger.debug("diameter not computed yet. calling computeDiameter() first!"); computeDiameter(); } return diameter; } public int getCyclomaticComplexity() { // E = the number of edges of the graph. // N = the number of nodes of the graph. // M = E − N + 2 int E = this.edgeCount(); int N = this.vertexCount(); return E -N + 2; } /** *

computeDiameter

*/ protected void computeDiameter() { // The diameter is just an upper bound for the approach level // Let's try to use something that's easier to compute than // FLoydWarshall diameter = this.edgeCount(); /* * FloydWarshall f = new FloydWarshall(graph); diameter = (int) f.getDiameter(); */ } /** *

determineEntryPoint

* * @return a V object. */ public V determineEntryPoint() { Set candidates = determineEntryPoints(); if (candidates.size() > 1) throw new IllegalStateException( "expect CFG of a method to contain at most one instruction with no parent in " + methodName); for (V instruction : candidates) return instruction; // there was a back loop to the first instruction within this CFG, so no // candidate // TODO for now return null and handle in super class // RawControlFlowGraph separately by overwriting this method // can also happen in empty methods return null; } /** *

Getter for the field className.

* * @return a {@link java.lang.String} object. */ public String getClassName() { return className; } /** *

Getter for the field methodName.

* * @return a {@link java.lang.String} object. */ public String getMethodName() { return methodName; } /** *

getMethodAccess

* * @return a int. */ public int getMethodAccess() { return access; } /** *

isPublicMethod

* * @return a boolean. */ public boolean isPublicMethod() { return (access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC; } /** *

isStaticMethod

* * @return a boolean. */ public boolean isStaticMethod() { return (access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC; } /** {@inheritDoc} */ @Override public String getName() { return methodName + " " + getCFGType(); } /** {@inheritDoc} */ @Override protected String dotSubFolder() { return toFileString(className) + "/" + getCFGType() + "/"; } /** *

getCFGType

* * @return a {@link java.lang.String} object. */ public abstract String getCFGType(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy