001 /* 002 * Cobertura - http://cobertura.sourceforge.net/ 003 * 004 * Copyright (C) 2003 jcoverage ltd. 005 * Copyright (C) 2005 Mark Doliner 006 * Copyright (C) 2005 Mark Sinke 007 * Copyright (C) 2006 Jiri Mares 008 * 009 * Cobertura is free software; you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published 011 * by the Free Software Foundation; either version 2 of the License, 012 * or (at your option) any later version. 013 * 014 * Cobertura is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 017 * General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with Cobertura; if not, write to the Free Software 021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 022 * USA 023 */ 024 025 package net.sourceforge.cobertura.coveragedata; 026 027 import java.io.Serializable; 028 import java.util.ArrayList; 029 import java.util.List; 030 031 import net.sourceforge.cobertura.util.StringUtil; 032 033 /** 034 * <p> 035 * This class implements HasBeenInstrumented so that when cobertura 036 * instruments itself, it will omit this class. It does this to 037 * avoid an infinite recursion problem because instrumented classes 038 * make use of this class. 039 * </p> 040 */ 041 public class LineData 042 implements Comparable, CoverageData, HasBeenInstrumented, Serializable 043 { 044 private static final long serialVersionUID = 4; 045 046 private long hits; 047 private List jumps; 048 private List switches; 049 private final int lineNumber; 050 private String methodDescriptor; 051 private String methodName; 052 053 LineData(int lineNumber) 054 { 055 this(lineNumber, null, null); 056 } 057 058 LineData(int lineNumber, String methodName, String methodDescriptor) 059 { 060 this.hits = 0; 061 this.jumps = null; 062 this.lineNumber = lineNumber; 063 this.methodName = methodName; 064 this.methodDescriptor = methodDescriptor; 065 } 066 067 /** 068 * This is required because we implement Comparable. 069 */ 070 public int compareTo(Object o) 071 { 072 if (!o.getClass().equals(LineData.class)) 073 return Integer.MAX_VALUE; 074 return this.lineNumber - ((LineData)o).lineNumber; 075 } 076 077 public boolean equals(Object obj) 078 { 079 if (this == obj) 080 return true; 081 if ((obj == null) || !(obj.getClass().equals(this.getClass()))) 082 return false; 083 084 LineData lineData = (LineData)obj; 085 return (this.hits == lineData.hits) 086 && ((this.jumps == lineData.jumps) || ((this.jumps != null) && (this.jumps.equals(lineData.jumps)))) 087 && ((this.switches == lineData.switches) || ((this.switches != null) && (this.switches.equals(lineData.switches)))) 088 && (this.lineNumber == lineData.lineNumber) 089 && (this.methodDescriptor.equals(lineData.methodDescriptor)) 090 && (this.methodName.equals(lineData.methodName)); 091 } 092 093 public double getBranchCoverageRate() 094 { 095 if (getNumberOfValidBranches() == 0) 096 return 1d; 097 return ((double) getNumberOfCoveredBranches()) / getNumberOfValidBranches(); 098 } 099 100 public String getConditionCoverage() 101 { 102 StringBuffer ret = new StringBuffer(); 103 if (getNumberOfValidBranches() == 0) 104 { 105 ret.append(StringUtil.getPercentValue(1.0)); 106 } 107 else 108 { 109 ret.append(StringUtil.getPercentValue(getBranchCoverageRate())); 110 ret.append(" (").append(getNumberOfCoveredBranches()).append("/").append(getNumberOfValidBranches()).append(")"); 111 } 112 return ret.toString(); 113 } 114 115 public long getHits() 116 { 117 return hits; 118 } 119 120 public boolean isCovered() 121 { 122 return (getHits() > 0) && ((getNumberOfValidBranches() == 0) || ((1.0 - getBranchCoverageRate()) < 0.0001)); 123 } 124 125 public double getLineCoverageRate() 126 { 127 return (getHits() > 0) ? 1 : 0; 128 } 129 130 public int getLineNumber() 131 { 132 return lineNumber; 133 } 134 135 public String getMethodDescriptor() 136 { 137 return methodDescriptor; 138 } 139 140 public String getMethodName() 141 { 142 return methodName; 143 } 144 145 /** 146 * @see net.sourceforge.cobertura.coveragedata.CoverageData#getNumberOfCoveredBranches() 147 */ 148 /*public int getNumberOfCoveredBranches() 149 { 150 if (this.branches == null) 151 return 0; 152 int covered = 0; 153 for (Iterator i = this.branches.iterator(); i.hasNext(); covered += ((BranchData) i.next()).getNumberOfCoveredBranches()); 154 return covered; 155 }*/ 156 157 public int getNumberOfCoveredLines() 158 { 159 return (getHits() > 0) ? 1 : 0; 160 } 161 162 public int getNumberOfValidBranches() 163 { 164 int ret = 0; 165 if (jumps != null) 166 for (int i = jumps.size() - 1; i >= 0; i--) 167 ret += ((JumpData) jumps.get(i)).getNumberOfValidBranches(); 168 if (switches != null) 169 for (int i = switches.size() - 1; i >= 0; i--) 170 ret += ((SwitchData) switches.get(i)).getNumberOfValidBranches(); 171 return ret; 172 } 173 174 public int getNumberOfCoveredBranches() 175 { 176 int ret = 0; 177 if (jumps != null) 178 for (int i = jumps.size() - 1; i >= 0; i--) 179 ret += ((JumpData) jumps.get(i)).getNumberOfCoveredBranches(); 180 if (switches != null) 181 for (int i = switches.size() - 1; i >= 0; i--) 182 ret += ((SwitchData) switches.get(i)).getNumberOfCoveredBranches(); 183 return ret; 184 } 185 186 public int getNumberOfValidLines() 187 { 188 return 1; 189 } 190 191 public int hashCode() 192 { 193 return this.lineNumber; 194 } 195 196 public boolean hasBranch() 197 { 198 return (jumps != null) || (switches != null); 199 } 200 201 public void merge(CoverageData coverageData) 202 { 203 LineData lineData = (LineData)coverageData; 204 this.hits += lineData.hits; 205 if (lineData.jumps != null) 206 if (this.jumps == null) 207 this.jumps = lineData.jumps; 208 else 209 { 210 for (int i = Math.min(this.jumps.size(), lineData.jumps.size()) - 1; i >= 0; i--) 211 ((JumpData) this.jumps.get(i)).merge((JumpData) lineData.jumps.get(i)); 212 for (int i = Math.min(this.jumps.size(), lineData.jumps.size()); i < lineData.jumps.size(); i++) 213 this.jumps.add(lineData.jumps.get(i)); 214 } 215 if (lineData.switches != null) 216 if (this.switches == null) 217 this.switches = lineData.switches; 218 else 219 { 220 for (int i = Math.min(this.switches.size(), lineData.switches.size()) - 1; i >= 0; i--) 221 ((SwitchData) this.switches.get(i)).merge((SwitchData) lineData.switches.get(i)); 222 for (int i = Math.min(this.switches.size(), lineData.switches.size()); i < lineData.switches.size(); i++) 223 this.switches.add(lineData.switches.get(i)); 224 } 225 if (lineData.methodName != null) 226 this.methodName = lineData.methodName; 227 if (lineData.methodDescriptor != null) 228 this.methodDescriptor = lineData.methodDescriptor; 229 } 230 231 void addJump(int jumpNumber) 232 { 233 getJumpData(jumpNumber); 234 } 235 236 void addSwitch(int switchNumber, int[] keys) 237 { 238 getSwitchData(switchNumber, new SwitchData(switchNumber, keys)); 239 } 240 241 void addSwitch(int switchNumber, int min, int max) 242 { 243 getSwitchData(switchNumber, new SwitchData(switchNumber, min, max)); 244 } 245 246 void setMethodNameAndDescriptor(String name, String descriptor) 247 { 248 this.methodName = name; 249 this.methodDescriptor = descriptor; 250 } 251 252 void touch() 253 { 254 this.hits++; 255 } 256 257 void touchJump(int jumpNumber, boolean branch) 258 { 259 getJumpData(jumpNumber).touchBranch(branch); 260 } 261 262 void touchSwitch(int switchNumber, int branch) 263 { 264 getSwitchData(switchNumber, null).touchBranch(branch); 265 } 266 267 public int getConditionSize() { 268 return ((jumps == null) ? 0 : jumps.size()) + ((switches == null) ? 0 :switches.size()); 269 } 270 271 public Object getConditionData(int index) 272 { 273 Object branchData = null; 274 int jumpsSize = (jumps == null) ? 0 : jumps.size(); 275 int switchesSize = (switches == null) ? 0 :switches.size(); 276 if (index < jumpsSize) 277 { 278 branchData = jumps.get(index); 279 } 280 else if (index < jumpsSize + switchesSize) 281 { 282 branchData = switches.get(index - jumpsSize); 283 } 284 return branchData; 285 } 286 287 public String getConditionCoverage(int index) { 288 Object branchData = getConditionData(index); 289 if (branchData == null) 290 { 291 return StringUtil.getPercentValue(1.0); 292 } 293 else if (branchData instanceof JumpData) 294 { 295 JumpData jumpData = (JumpData) branchData; 296 return StringUtil.getPercentValue(jumpData.getBranchCoverageRate()); 297 } 298 else 299 { 300 SwitchData switchData = (SwitchData) branchData; 301 return StringUtil.getPercentValue(switchData.getBranchCoverageRate()); 302 303 } 304 } 305 306 JumpData getJumpData(int jumpNumber) 307 { 308 if (jumps == null) 309 { 310 jumps = new ArrayList(); 311 } 312 if (jumps.size() <= jumpNumber) 313 { 314 for (int i = jumps.size(); i <= jumpNumber; jumps.add(new JumpData(i++))); 315 } 316 return (JumpData) jumps.get(jumpNumber); 317 } 318 319 SwitchData getSwitchData(int switchNumber, SwitchData data) 320 { 321 if (switches == null) 322 { 323 switches = new ArrayList(); 324 } 325 if (switches.size() < switchNumber) 326 { 327 for (int i = switches.size(); i < switchNumber; switches.add(new SwitchData(i++))); 328 } 329 if (switches.size() == switchNumber) 330 if (data != null) 331 switches.add(data); 332 else 333 switches.add(new SwitchData(switchNumber)); 334 return (SwitchData) switches.get(switchNumber); 335 } 336 337 }