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 025package net.sourceforge.cobertura.coveragedata; 026 027import java.io.Serializable; 028import java.util.ArrayList; 029import java.util.List; 030 031import net.sourceforge.cobertura.CoverageIgnore; 032import net.sourceforge.cobertura.util.StringUtil; 033 034@CoverageIgnore 035public class LineData 036 implements Comparable<Object>, CoverageData, Serializable 037{ 038 private static final long serialVersionUID = 4; 039 040 private long hits; 041 private List<JumpData> jumps; 042 private List<SwitchData> switches; 043 private final int lineNumber; 044 private String methodDescriptor; 045 private String methodName; 046 047 LineData(int lineNumber) { 048 this(lineNumber, null, null); 049 } 050 051 LineData(int lineNumber, String methodName, String methodDescriptor) { 052 this.hits = 0; 053 this.jumps = null; 054 this.lineNumber = lineNumber; 055 this.methodName = methodName; 056 this.methodDescriptor = methodDescriptor; 057 } 058 059 /** 060 * This is required because we implement Comparable. 061 */ 062 public int compareTo(Object o) { 063 if (!o.getClass().equals(LineData.class)) 064 return Integer.MAX_VALUE; 065 return this.lineNumber - ((LineData)o).lineNumber; 066 } 067 068 public boolean equals(Object obj) { 069 if (this == obj) 070 return true; 071 if ((obj == null) || !(obj.getClass().equals(this.getClass()))) 072 return false; 073 074 LineData lineData = (LineData)obj; 075 return (this.hits == lineData.hits) 076 && ((this.jumps == lineData.jumps) || ((this.jumps != null) && (this.jumps.equals(lineData.jumps)))) 077 && ((this.switches == lineData.switches) || ((this.switches != null) && (this.switches.equals(lineData.switches)))) 078 && (this.lineNumber == lineData.lineNumber) 079 && (this.methodDescriptor.equals(lineData.methodDescriptor)) 080 && (this.methodName.equals(lineData.methodName)); 081 } 082 083 public double getBranchCoverageRate() { 084 if (getNumberOfValidBranches() == 0) 085 return 1d; 086 return ((double) getNumberOfCoveredBranches()) / getNumberOfValidBranches(); 087 } 088 089 public String getConditionCoverage() { 090 StringBuffer ret = new StringBuffer(); 091 if (getNumberOfValidBranches() == 0) { 092 ret.append(StringUtil.getPercentValue(1.0)); 093 } else { 094 ret.append(StringUtil.getPercentValue(getBranchCoverageRate())); 095 ret.append(" (").append(getNumberOfCoveredBranches()).append("/").append(getNumberOfValidBranches()).append(")"); 096 } 097 return ret.toString(); 098 } 099 100 public long getHits() { 101 return hits; 102 } 103 104 synchronized public boolean isCovered() { 105 return (getHits() > 0) && ((getNumberOfValidBranches() == 0) || ((1.0 - getBranchCoverageRate()) < 0.0001)); 106 } 107 108 public double getLineCoverageRate() { 109 return (getHits() > 0) ? 1 : 0; 110 } 111 112 public int getLineNumber() { 113 return lineNumber; 114 } 115 116 public String getMethodDescriptor() { 117 return methodDescriptor; 118 } 119 120 public String getMethodName() { 121 return methodName; 122 } 123 124 public int getNumberOfCoveredLines() 125 { 126 return (getHits() > 0) ? 1 : 0; 127 } 128 129 public int getNumberOfValidBranches() { 130 int ret = 0; 131 if (jumps != null) 132 for (int i = jumps.size() - 1; i >= 0; i--) 133 ret += ((JumpData) jumps.get(i)).getNumberOfValidBranches(); 134 if (switches != null) 135 for (int i = switches.size() - 1; i >= 0; i--) 136 ret += ((SwitchData) switches.get(i)).getNumberOfValidBranches(); 137 return ret; 138 } 139 140 public int getNumberOfCoveredBranches() { 141 int ret = 0; 142 if (jumps != null) 143 for (int i = jumps.size() - 1; i >= 0; i--) 144 ret += ((JumpData) jumps.get(i)).getNumberOfCoveredBranches(); 145 if (switches != null) 146 for (int i = switches.size() - 1; i >= 0; i--) 147 ret += ((SwitchData) switches.get(i)).getNumberOfCoveredBranches(); 148 return ret; 149 } 150 151 public int getNumberOfValidLines() { 152 return 1; 153 } 154 155 public int hashCode() { 156 return this.lineNumber; 157 } 158 159 public boolean hasBranch() { 160 return (jumps != null) || (switches != null); 161 } 162 163 synchronized public void merge(CoverageData coverageData) { 164 LineData lineData = (LineData)coverageData; 165 this.hits += lineData.hits; 166 if (lineData.jumps != null) 167 if (this.jumps == null) 168 this.jumps = lineData.jumps; 169 else 170 { 171 for (int i = Math.min(this.jumps.size(), lineData.jumps.size()) - 1; i >= 0; i--) 172 ((JumpData) this.jumps.get(i)).merge((JumpData) lineData.jumps.get(i)); 173 for (int i = Math.min(this.jumps.size(), lineData.jumps.size()); i < lineData.jumps.size(); i++) 174 this.jumps.add(lineData.jumps.get(i)); 175 } 176 if (lineData.switches != null) 177 if (this.switches == null) 178 this.switches = lineData.switches; 179 else 180 { 181 for (int i = Math.min(this.switches.size(), lineData.switches.size()) - 1; i >= 0; i--) 182 ((SwitchData) this.switches.get(i)).merge((SwitchData) lineData.switches.get(i)); 183 for (int i = Math.min(this.switches.size(), lineData.switches.size()); i < lineData.switches.size(); i++) 184 this.switches.add(lineData.switches.get(i)); 185 } 186 if (lineData.methodName != null) 187 this.methodName = lineData.methodName; 188 if (lineData.methodDescriptor != null) 189 this.methodDescriptor = lineData.methodDescriptor; 190 } 191 192 void addJump(int jumpNumber) { 193 getJumpData(jumpNumber); 194 } 195 196 void addSwitch(int switchNumber, int min, int max, int maxBranches) { 197 SwitchData sd = getSwitchData(switchNumber, new SwitchData(switchNumber, min, max, maxBranches)); 198 if (sd.getMaxBranches() > maxBranches) { 199 sd.setMaxBranches(maxBranches); 200 } 201 } 202 203 void setMethodNameAndDescriptor(String name, String descriptor) { 204 this.methodName = name; 205 this.methodDescriptor = descriptor; 206 } 207 208 void touch(int new_hits) { 209 this.hits += new_hits; 210 } 211 212 void touchJump(int jumpNumber, boolean branch, int hits) { 213 getJumpData(jumpNumber).touchBranch(branch,hits); 214 } 215 216 void touchSwitch(int switchNumber, int branch,int hits) { 217 getSwitchData(switchNumber, null).touchBranch(branch,hits); 218 } 219 220 public int getConditionSize() { 221 return ((jumps == null) ? 0 : jumps.size()) + ((switches == null) ? 0 :switches.size()); 222 } 223 224 public Object getConditionData(int index) { 225 Object branchData = null; 226 int jumpsSize = (jumps == null) ? 0 : jumps.size(); 227 int switchesSize = (switches == null) ? 0 :switches.size(); 228 if (index < jumpsSize) 229 { 230 branchData = jumps.get(index); 231 } 232 else if (index < jumpsSize + switchesSize) 233 { 234 branchData = switches.get(index - jumpsSize); 235 } 236 return branchData; 237 } 238 239 public String getConditionCoverage(int index) { 240 Object branchData = getConditionData(index); 241 if (branchData == null) 242 { 243 return StringUtil.getPercentValue(1.0); 244 } else if (branchData instanceof JumpData) { 245 JumpData jumpData = (JumpData) branchData; 246 return StringUtil.getPercentValue(jumpData.getBranchCoverageRate()); 247 } else { 248 SwitchData switchData = (SwitchData) branchData; 249 return StringUtil.getPercentValue(switchData.getBranchCoverageRate()); 250 251 } 252 } 253 254 synchronized JumpData getJumpData(int jumpNumber) { 255 if (jumps == null) { 256 jumps = new ArrayList<JumpData>(); 257 } 258 if (jumps.size() <= jumpNumber) { 259 for (int i = jumps.size(); i <= jumpNumber; jumps.add(new JumpData(i++))); 260 } 261 return jumps.get(jumpNumber); 262 } 263 264 synchronized SwitchData getSwitchData(int switchNumber, SwitchData data) { 265 if (switches == null) { 266 switches = new ArrayList<SwitchData>(); 267 } 268 if (switches.size() < switchNumber) 269 { 270 for (int i = switches.size(); i < switchNumber; switches.add(new SwitchData(i++, Integer.MAX_VALUE ))); 271 } 272 if (switches.size() == switchNumber) { 273 if (data != null) { 274 switches.add(data); 275 } else { 276 switches.add(new SwitchData(switchNumber, Integer.MAX_VALUE)); 277 } 278 } 279 return (SwitchData) switches.get(switchNumber); 280 } 281 282}