/* * 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.T2.*; import Sequenic.T2.Seq.*; import Sequenic.T2ext.Instrumenter.*; /** * * @author Wishnu Prasetya */ public class T2TraceFileCoverageResult { /** * Pointer to the original trace-file to which this coverage result * belongs to. */ public TrFile trfile ; /** * The set of collected observations. */ public Map observedpaths = new HashMap() ; /** * The total coverage delivered by all the traces together. */ public Map totCoverage = new HashMap() ; /** * This maintains information of which trace generates which runids. * Given a valid runid, then there will be two CONSECUTIVE pairs * (id1,tr1) and (id2,tr2) such that: * * id1> runIdTableLevel1 = new LinkedList> () ; /** * This maintains information of which step in a trace generates * which runids. Given a valid runid, let tr be the trace that * generates it (which you can obtain through the level1 table). * Then there will be two CONSECUTIVE pairs (id1,k1) and (id2,k2) * in the Level2 table such that: * * id1< runid <= id2 * * Then step k1 in the trace tr is responsible for generating runid. * To be more precise, if k1=0 then it is tr's creation step that * does it. * * Else it is step tr.trace.get(k1-1) that does it. */ public LinkedList> runIdTableLevel2 = new LinkedList> () ; static private void println(String s){ System.out.println(s) ; } static private void print(String s){ System.out.print(s) ; } /** * Calculate the n/d in percentage, rounded to 2 decimals after * the comma. */ public static float calcPercentage(int n, int d) { if (d<=0) return 100 ; int p = 10000 * n / d ; // preparing to round to 2 decimals float percentage = ((float) p ) / 100f ; // rounding to 2 decimals return Math.min(100,percentage) ; } public void simplePrint(){ println("** Target class: " + trfile.CUTname) ; println("** Pool: " + trfile.poolClassName) ; println("** #traces: " + trfile.traces.size()) ; for (CFG cfg : totCoverage.keySet()) { cfg.simplePrint() ; totCoverage.get(cfg).simplePrint(observedpaths) ; } println("** Summary:") ; for (CFG cfg : totCoverage.keySet()) { println(" " + cfg.getMethodName()) ; int numOfTargetPaths = cfg.getTargetPaths().size() ; int numOfDirectlyFeasibleTargetPaths = numOfTargetPaths - cfg.getDirectlyUnfeasibleTargetPaths().size() ; CoverageResult res = totCoverage.get(cfg) ; int numOfDirectlyCov = res.directlyCoveredPaths.size() ; int numOfDetourlyCov = numOfDirectlyCov + res.detourlyCoveredPaths.size() ; println(" Direct path coverage = " + numOfDirectlyCov + "/" + numOfDirectlyFeasibleTargetPaths + " (" + calcPercentage(numOfDirectlyCov, numOfDirectlyFeasibleTargetPaths) + "%), ") ; println(" Detour path coverage = " + numOfDetourlyCov + "/" + numOfTargetPaths + " (" + calcPercentage(numOfDetourlyCov, numOfTargetPaths) + "%)") ; LinkedList> coveredPaths = new LinkedList>() ; coveredPaths.addAll(res.directlyCoveredPaths) ; coveredPaths.addAll(res.detourlyCoveredPaths) ; println(" Node coverage = " + CoverageResult.calcNodeCoverage(cfg.getTargetPaths(), coveredPaths) ) ; println(" Branch coverage = " + CoverageResult.calcBranchCoverage(cfg.getNodes(), cfg.getTargetPaths(), coveredPaths) ) ; } int totTP = totNumberOfTargetPaths() ; int totDFTP = totNumberOfDirectlyFeasibleTargetPaths() ; int totDi = totNumberOfDirectlyCoveredPaths() ; int totDe = totNumberOfDetourlyCoveredPaths() ; println("** TOT direct path coverage = " + totDi + "/"+ totDFTP + " (" + calcPercentage(totDi,totDFTP) + "%)") ; println("** TOT detour path covergae = " + totDe + "/"+ totTP + " (" + calcPercentage(totDe,totTP) + "%)") ; println("** TOT node coverage = " + totNodeCoverage() + "%") ; println("** TOT branch coverage = " + totBranchCoverage() + "%") ; } public int totNumberOfTargetPaths() { int totTP = 0 ; for (CFG cfg : totCoverage.keySet()) totTP += cfg.getTargetPaths().size() ; return totTP ; } public int totNumberOfDirectlyFeasibleTargetPaths() { int totTP = 0 ; for (CFG cfg : totCoverage.keySet()) { totTP += cfg.getTargetPaths().size() - cfg.getDirectlyUnfeasibleTargetPaths().size() ; } return totTP ; } public int totNumberOfDirectlyCoveredPaths() { int totDi = 0 ; for (CFG cfg : totCoverage.keySet()) totDi += totCoverage.get(cfg).directlyCoveredPaths.size() ; return totDi ; } public int totNumberOfDetourlyCoveredPaths() { int totDe = 0 ; for (CFG cfg : totCoverage.keySet()) totDe += totCoverage.get(cfg).detourlyCoveredPaths.size() ; return totNumberOfDirectlyCoveredPaths() + totDe ; } public float totNodeCoverage(){ int numOfNodes = 0 ; int coveredNodes = 0 ; for (CFG cfg : totCoverage.keySet()) { CoverageResult res = totCoverage.get(cfg) ; LinkedList> coveredPaths = new LinkedList>() ; coveredPaths.addAll(res.directlyCoveredPaths) ; coveredPaths.addAll(res.detourlyCoveredPaths) ; numOfNodes += CoverageResult.getPassedNodes(cfg.getTargetPaths()).size() ; coveredNodes += CoverageResult.getPassedNodes(coveredPaths).size() ; } return calcPercentage(coveredNodes,numOfNodes) ; } public float totBranchCoverage() { int numOfBranches = 0 ; int coveredBranches = 0 ; for (CFG cfg : totCoverage.keySet()) { CoverageResult res = totCoverage.get(cfg) ; LinkedList> coveredPaths = new LinkedList>() ; coveredPaths.addAll(res.directlyCoveredPaths) ; coveredPaths.addAll(res.detourlyCoveredPaths) ; numOfBranches += CoverageResult.getPassedBranches(cfg.getNodes(),cfg.getTargetPaths()).size() ; coveredBranches += CoverageResult.getPassedBranches(cfg.getNodes(),coveredPaths).size() ; } return calcPercentage(coveredBranches,numOfBranches) ; } /** * Given a runid, this will return the corresponding observed-path. */ public ObservedPath getObservedPath(Long runid) { return observedpaths.get(runid) ; } /** * Same as the other getObservedPath, but will return the observed-path * as a list of Nodes from the CFG. * * You must pass the CFG to which the runid should belong to. */ public List getObservedPath(CFG cfg, Long runid) { ObservedPath path = observedpaths.get(runid) ; List P = new LinkedList() ; for (Integer N : path.getNodes()) { Node nd = null ; for (Node ndx : cfg.getNodes()) { if (ndx.getId() == N) { nd = ndx; break ; } } assert nd != null ; P.add(nd) ; } return P ; } /** * Given a runid, this will return the T2-test-trace that produces a run with * this runid. */ public Trace getTrace(Long runid){ if (runIdTableLevel1.isEmpty()) return null ; Trace previous = null ; for (Pair entry : runIdTableLevel1) { if (entry.fst >= runid) break ; previous = entry.snd ; } return previous ; } /** * Given a runid, this will return the step (in a T2-test-trace) that produces * a run with this runid. Note that this step can be either the creation step, * or just a normal step. Both have different classes, but both are subclasses * of METARUN; which explains the return type below. */ public METARUN getStep(Long runid){ // Obtain the trace to which this runid belongs to: Trace tr = getTrace(runid) ; Integer index = getStepIndex(runid) ; if (index == null) return null ; if (index==0) return tr.creation ; else return tr.trace.get(index-1) ; } /** * Given a runid, this will return the index of the step in a T2-test-trace * that produces a run with this runid. Index 0 refers to the trace's creation * step. Index i+1 refers to the i-th step in the trace's trace field. * *

If a null is returned, it means that the runId can't be found in the * given observation set. */ public Integer getStepIndex(Long runid){ if (runIdTableLevel1.isEmpty() || runIdTableLevel2.isEmpty()) return null ; int previous = -1 ; for (Pair entry : runIdTableLevel2) { if (entry.fst >= runid) break ; previous = entry.snd ; } assert previous>0 ; return previous ; } }