KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > groboutils > codecoverage > v2 > module > BranchCountMeasure


1 /*
2  * @(#)BranchCountMeasure.java
3  *
4  * Copyright (C) 2003-2004 Matt Albrecht
5  * groboclown@users.sourceforge.net
6  * http://groboutils.sourceforge.net
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  */

26
27 package net.sourceforge.groboutils.codecoverage.v2.module;
28
29
30 import net.sourceforge.groboutils.codecoverage.v2.IAnalysisMetaData;
31 import net.sourceforge.groboutils.codecoverage.v2.IMethodCode;
32
33 import org.apache.bcel.classfile.CodeException;
34 import org.apache.bcel.generic.IfInstruction;
35 import org.apache.bcel.generic.Instruction;
36 import org.apache.bcel.generic.InstructionHandle;
37 import org.apache.bcel.generic.JsrInstruction;
38 import org.apache.bcel.generic.Select;
39
40
41 /**
42  * Processes methods for branch coverage analysis, where each branch
43  * instruction and its corresponding not-taken instruction are marked.
44  * Currently, this does not support localization.
45  * <P>
46  * This is more accurately called "Object Code Branch Coverage", since
47  * true branch coverage requires the originating source code to correctly
48  * discover the branches.
49  * <P>
50  * This measure can be superior to line coverage due to the Java construct
51  * of the <tt>?:</tt> operation. This hides a branch inside a single
52  * statement. Also, some developers may put an <tt>if</tt> statement and
53  * its one-line branch all on the same line, which will hide the branch
54  * that was taken.
55  *
56  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
57  * @author Juergen Kindler <a HREF="mailto:jkindler@freenet.de">jkindler@freenet.de</a>
58  * @version $Date: 2004/04/15 05:48:26 $
59  * @since January 26, 2003
60  * @see IAnalysisMetaData
61  */

62 public class BranchCountMeasure extends AbstractMeasure
63 {
64     //private static final org.apache.log4j.Logger LOG =
65
// org.apache.log4j.Logger.getLogger( BranchCountMeasure.class );
66

67     /**
68      * Returns the human-readable name of the measure.
69      */

70     public String JavaDoc getMeasureName()
71     {
72         return "Branch";
73     }
74     
75     /**
76      * Returns the unit name for this particular coverage measure.
77      */

78     public String JavaDoc getMeasureUnit()
79     {
80         return "branches";
81     }
82     
83     
84     /**
85      * Returns the text format used in meta-data formatted text. This should
86      * be the mime encoding type, such as "text/plain" or "text/html".
87      */

88     public String JavaDoc getMimeEncoding()
89     {
90         return "text/plain";
91     }
92     
93     
94     /**
95      * Perform the analysis on the method.
96      */

97     public void analyze( IMethodCode method )
98     {
99         BytecodeLineUtil blu = new BytecodeLineUtil( method );
100         InstructionHandle handles[] = blu.getHandles();
101         
102         // always mark the first instruction, even if there are no
103
// instructions.
104
markInstruction( method, 0, createAMD( "Start of Method",
105             blu.getLineNumberForInstructionPos( 0 ) ), false );
106
107         
108         // find the positions of the instructions in the bytecode
109
for (int i = 0; i < handles.length; ++i)
110         {
111             InstructionHandle h = handles[i];
112             Instruction instr = h.getInstruction();
113             
114             // Mark the if, select, and jsr instructions
115
if (instr instanceof IfInstruction)
116             {
117                 markIf( method, (IfInstruction)instr, i, blu );
118             }
119             else
120             if (instr instanceof Select)
121             {
122                 markSelect( method, (Select)instr, i, blu );
123             }
124             else
125             if (instr instanceof JsrInstruction)
126             {
127                 markJsr( method, (JsrInstruction)instr, i, blu );
128             }
129         }
130         
131         // Also need to mark all exception handlers.
132
CodeException exceptions[] = method.getOriginalMethod().getCode().
133             getExceptionTable();
134         for (int i = 0; i < exceptions.length; ++i)
135         {
136             markExceptionHandler( method, exceptions[i], blu );
137         }
138     }
139     
140     
141     /**
142      * The target will be the "else" or "default" instruction.
143      */

144     private void markIf( IMethodCode method, IfInstruction instr,
145             int i, BytecodeLineUtil blu )
146     {
147         int lineNo = blu.getLineNumberForInstructionPos( i+1 );
148         
149         // the mark on this part goes AFTER the branch instruction,
150
// not before it.
151
// Bug 906198
152
// Bug 906207
153
markInstruction( method, i+1,
154             createAMD( "'True' branch", lineNo ), false );
155         
156         InstructionHandle target = instr.getTarget();
157         markTarget( method, target, blu, "'False' branch" );
158     }
159     
160     
161     /**
162      *
163      */

164     private void markSelect( IMethodCode method, Select instr,
165             int i, BytecodeLineUtil blu )
166     {
167         int lineNo = blu.getLineNumberForInstructionPos( i+1 );
168         markInstruction( method, i+1,
169             createAMD( "After switch", lineNo ), false );
170         
171         InstructionHandle targets[] = instr.getTargets();
172         for (int tIndex = 0; tIndex < targets.length; ++tIndex)
173         {
174             markTarget( method,
175                 targets[ tIndex ],
176                 blu,
177                 "Case index "+Integer.toString( tIndex + 1 ) );
178         }
179     }
180     
181     
182     /**
183      *
184      */

185     private void markJsr( IMethodCode method, JsrInstruction instr,
186             int i, BytecodeLineUtil blu )
187     {
188         // For a JSR, the target indicates the location of a finally block.
189
InstructionHandle target = instr.getTarget();
190         markTarget( method, target, blu, "Finally block" );
191     }
192     
193     
194     /**
195      *
196      */

197     private void markExceptionHandler( IMethodCode method, CodeException ce,
198             BytecodeLineUtil blu )
199     {
200         int pc = ce.getHandlerPC();
201             
202         // Bug 906207
203
markInstruction( method,
204             blu.getInstructionPosForBytecodePos( pc ),
205             createAMD( "Exception handler",
206                 blu.getLineNumberForBytecodePos( pc ) ),
207             false );
208     }
209     
210     
211     private void markTarget( IMethodCode method, InstructionHandle target,
212             BytecodeLineUtil blu, String JavaDoc branchDesc )
213     {
214         if (target != null)
215         {
216             // This does not relate to bug 906207 due to bug 906211
217
markInstruction( method,
218                 blu.getInstructionPosForBytecodePos( target.getPosition() ),
219                 createAMD(
220                     branchDesc,
221                     blu.getLineNumber( target ) ),
222                 false );
223         }
224     }
225     
226     
227     /**
228      *
229      */

230     private IAnalysisMetaData createAMD( String JavaDoc type, int lineNo )
231     {
232         return new DefaultAnalysisMetaData(
233             type+" at line "+lineNo,
234             "Didn't cover "+type+" at line "+lineNo,
235             (byte)0 );
236     }
237 }
238
Popular Tags