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