/* * Copyright 2009 Wishnu Prasetya. * * This file is part of T2. * T2 is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License (GPL) as published by the * Free Software Foundation; either version 3 of the License, or any * later version. * * T2 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 General Public License * for more details. * * A copy of the GNU General Public License can be found in T2 distribution. * If it is missing, see http://www.gnu.org/licenses. */ package Sequenic.T2ext.Instrumenter; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Method; import java.util.*; import Sequenic.Graph.Graph; import Sequenic.Graph.PathUtil; import Sequenic.Graph.Vertex; /** * This represent a control flow graph (CFG) associated to a method. * * @author Wishnu Prasetya * */ public class CFG extends Graph implements Serializable { private static final long serialVersionUID = 1L; /** * The unique name of the method to which this CFG belongs to. */ // java.lang.reflect.Method method ; String methodName ; private String originalMethodName; public String getOriginalMethodName() { return originalMethodName; } public void setOriginalMethodName(String originalMethodName) { this.originalMethodName = originalMethodName; } /** * The class to which the method belong to. Note that this is not necessarily * the class that declares the method. */ // Class C ; String C ; /** * Pointer to the starting node, which represents the starting block * of a program. */ Node startNode ; /** * This a derived field to hold the list of edges of the graph; for convenience. */ List> edges = new LinkedList>() ; /** * List of the target paths. These are the paths in the CFG that we have set up * as the goal to be covered. E.g. these can be the prime paths, but I'll not * fix the choice here. */ LinkedList> targetPaths = new LinkedList>() ; /** * This contains a subset of the target paths that have been marked as * unfeasible to be directly covered (but they can still be detourly * covered!). */ LinkedList> directlyUnfeasibleTargetPaths = new LinkedList>() ; /* public java.lang.reflect.Method getMethod() { return method; } */ public String getMethodName() { return methodName; } /* public Class getC() { return C; } */ public String getC() { return C; } public Node getStartNode() { return startNode; } public LinkedList> getTargetPaths() { return targetPaths; } public LinkedList> getDirectlyUnfeasibleTargetPaths() { return directlyUnfeasibleTargetPaths; } public List getNodes() { // This won't work, the known generic casting problem: // return (List) nodes; // So, using this ugly cheat: return (List) ((Object) nodes) ; } @Override public String toString() { StringBuffer res = new StringBuffer() ; if (edges.isEmpty() || nodes.isEmpty()) buildDerivedLists() ; // res.append("\nCFG of (" + C + ") " + method) ; res.append("\nCFG of " + methodName + "\n") ; // Nodes ids and edges: res.append(super.toString()) ; // Printing the nodes and their line numbers: res.append("\nLine numbers:") ; for (Node N : getNodes()) { res.append("\n Node " + N.id + " --> lines ") ; res.append(N.lineNr_start + " - " + N.lineNr_end) ; } // Constant lists: Integer[] intConsts = getIntConstants() ; String[] strConsts = getStringConstants() ; res.append("\nConstants:\n ") ; int N1 = intConsts.length ; int N2 = strConsts.length ; for (int i=0; i 0) res.append(intConsts[N1-1]) ; res.append('\n') ; for (int i=0; i 0) res.append(strConsts[N2-1]) ; res.append('\n') ; /* res.append("Parents:") ; for (Node N : nodes) { res.append("\n Node " + N.id + " has parents: ") ; for (Node P : N.parents) res.append(P.id + ", ") ; res.append('\n') ; } */ // Printing some statistics: int N = nodes.size() ; int E = numberOfEdges() ; int P = getCycles().size() ; int mcCabe = targetPaths.size() ; res.append("\n#Nodes: " + N) ; res.append("\n#Edges: " + E) ; res.append("\n#Branching nodes: " + numberOfBranchingVertices()) ; res.append("\n#Cycles: " + P) ; res.append("\n#Prime paths : " + mcCabe) ; // Printing the target paths: res.append("\nTarget paths:") ; for (LinkedList path : targetPaths) { res.append("\n ").append(PathUtil.pathSimpleShow(path)) ; if (directlyUnfeasibleTargetPaths.contains(path)) res.append(" (directly unfeasible)") ; } res.append('\n') ; return res.toString() ; } /** * Just a method to print a small CFG to system.out */ public void simplePrint(){ System.out.println(toString()) ; } /** * To build the nodes and edges lists. */ public void buildDerivedLists() { edges.clear() ; for (Node N1 : getNodes()) { for (Vertex N2 : N1.children) { edges.add(new Edge(N1, (Node) N2)) ; } } // nodes.clear() ; //buildDerivedListWorker(startNode) ; } /* private void buildDerivedListWorker(Node N){ if (nodes.contains(N)) return ; nodes.add(N) ; for (Node O : N.children) edges.add(new Edge(N,O)) ; for (Node O : N.children) buildDerivedListWorker(O) ; } */ /** * Return the int constants. */ Integer[] getIntConstants(){ Set res = new HashSet() ; for (Node x : getNodes()) { Integer[] cs = x.getIntConstants() ; for (int i=0; i res = new HashSet() ; for (Node x : getNodes()) { String[] cs = x.getStringConstants() ; for (int i=0; i