/* * 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.Analyzer; import java.util.*; import Sequenic.T2ext.util.*; import Sequenic.T2ext.Instrumenter.*; /** * Provides functionality to analyze the coverage of a set of methods, * given a set of observed execution paths. * * @author Wishnu Prasetya * @author Original algorithm and code by Maaike Gerritsen */ public class CoverageAnalyzer { /** * Representing the set of target methods and their CFGs. They contain * information of the set of paths for each that have to be covered. */ CFGBunchFile CFGs ; /** * The set of observed execution paths. This is typically obtained from * the class Sensor. */ Map observedpaths ; /** * The support map that belongs to the above list of observed paths. */ Map> observationGroups ; public Map result = new HashMap() ; private PathDistanceCalculator calculator = new PathDistanceCalculator() ; public boolean debug = false ; public CoverageAnalyzer(String cfgbunchFile){ CFGs = CFGBunchFile.load(cfgbunchFile) ; observedpaths = Sensor.getObservedPaths() ; observationGroups = Sensor.getObservationGroups() ; } public CoverageAnalyzer(CFGBunchFile cfgs){ CFGs = cfgs ; observedpaths = Sensor.getObservedPaths() ; observationGroups = Sensor.getObservationGroups() ; } /** * Will return the result of coverage analysis on all given target methods. */ public Map calculateCoverage(){ result.clear() ; for (CFG cfg : CFGs.cfgs) { CoverageResult r = calculateMethodCoverage(cfg) ; result.put(cfg,r) ; if (debug) { cfg.simplePrint() ; r.simplePrint(observedpaths) ; } } return result ; } /** * Will return the result of the coverage analysis of a single method. * This method must be in the list of the target methods passed to * this object. */ public CoverageResult calculateMethodCoverage(CFG cfg) { CoverageResult R = new CoverageResult() ; String tmethodUname = cfg.getMethodName() ; // Loop over every target-path to determine its // coverage: for (LinkedList targetP : cfg.getTargetPaths()) { LinkedList targetpath = convertToIntList(targetP) ; int minDirectDistSoFar = Integer.MAX_VALUE ; int minDetourDistSoFar = Integer.MAX_VALUE ; Long bestDirectExecPathSoFar = null ; Long bestDetourExecPathSoFar = null ; // Loop over observations to determine the closest one: List runIds_set = observationGroups.get(tmethodUname) ; if (runIds_set == null) runIds_set = new LinkedList() ; for (Long runId : runIds_set) { LinkedList executionpath = observedpaths.get(runId).getNodes() ; int directDistance = calculator.directCoveragePathDistance(executionpath,targetpath) ; int detourDistance = calculator.detourCoveragePathDistance(executionpath,targetpath) ; if (directDistance < minDirectDistSoFar) { minDirectDistSoFar = directDistance ; bestDirectExecPathSoFar = runId ; } if (detourDistance < minDetourDistSoFar) { minDetourDistSoFar = detourDistance ; bestDetourExecPathSoFar = runId ; } if (directDistance == 0) break ; } if (minDirectDistSoFar==0) R.directlyCoveredPaths.add(targetP) ; if (minDetourDistSoFar==0 && minDirectDistSoFar>0) { // Note: we'll only add if it is not directly covered; // because any directly covered path will be detourly covered // as well; therefore we'll not maintain this duplication R.detourlyCoveredPaths.add(targetP) ; } if (bestDirectExecPathSoFar != null && ! cfg.getDirectlyUnfeasibleTargetPaths().contains(targetP)) { R.directlyClosestPaths.put(targetP,bestDirectExecPathSoFar) ; //assert observedpaths.keySet().contains(bestDirectExecPathSoFar) ; } if (bestDetourExecPathSoFar != null) R.detourlyClosestPaths.put(targetP,bestDirectExecPathSoFar) ; } // DONE return R ; } private LinkedList convertToIntList(LinkedList NodeList){ LinkedList P = new LinkedList() ; for (Node N : NodeList) P.add(N.getId()) ; return P ; } public CFGBunchFile getCFGs() { return CFGs; } }