KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > groboutils > codecoverage > v2 > compiler > RebuildClassIUTest


1 /*
2  * @(#)RebuildClassIUTest.java
3  *
4  * Copyright (C) 2002-2003 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.compiler;
28
29 import java.io.ByteArrayInputStream JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.io.InputStream JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35
36 import junit.framework.Test;
37 import junit.framework.TestCase;
38 import junit.framework.TestSuite;
39 import net.sourceforge.groboutils.autodoc.v1.AutoDoc;
40 import net.sourceforge.groboutils.codecoverage.v2.ArrayClassLoader;
41 import net.sourceforge.groboutils.codecoverage.v2.BytecodeLoaderUtil;
42 import net.sourceforge.groboutils.util.io.v1.ReadByteStream;
43
44
45 /**
46  * Attempts to load a classfile, disassemble it, modify the class file with
47  * the logging, rebuild it to a new file, then load the new class file and
48  * run it to ensure that everything's kosher with it.
49  *
50  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
51  * @version $Date: 2004/04/15 05:48:27 $
52  * @since December 19, 2002
53  */

54 public class RebuildClassIUTest extends TestCase
55 {
56     //-------------------------------------------------------------------------
57
// Standard JUnit Class-specific declarations
58

59     private static final Class JavaDoc THIS_CLASS = RebuildClassIUTest.class;
60     private static final AutoDoc DOC = new AutoDoc( THIS_CLASS );
61     
62     public RebuildClassIUTest( String JavaDoc name )
63     {
64         super( name );
65     }
66
67
68
69     //-------------------------------------------------------------------------
70
// Tests
71

72     public static class MarkData
73     {
74         public String JavaDoc classSig;
75         public short measureIndex;
76         public short methodIndex;
77         public short markIndex;
78         
79         public MarkData( String JavaDoc sig, short meaI, short metI, short marI )
80         {
81             this.classSig = sig;
82             this.measureIndex = meaI;
83             this.methodIndex = metI;
84             this.markIndex = marI;
85         }
86         
87         public String JavaDoc toString()
88         {
89             return "[Class Sig="+this.classSig+";measure="+
90                 this.measureIndex+";method="+this.methodIndex+
91                 ";mark="+this.markIndex+"]";
92         }
93     }
94    
95     public static class MyLogger
96     {
97         public static List JavaDoc marks = new ArrayList JavaDoc();
98         
99         
100         public synchronized static void cover( String JavaDoc classSig,
101                 short methodIndex, short channel, short markIndex )
102         {
103             DOC.getLog().info( "Inside cover" );
104             MarkData md = new MarkData( classSig, channel, methodIndex,
105                 markIndex );
106             DOC.getLog().info( "adding mark: "+md );
107             marks.add( md );
108         }
109         
110         
111         public synchronized static void reset()
112         {
113             marks.clear();
114         }
115     }
116    
117     public static class MyLogger2
118     {
119         public static void cover( String JavaDoc classSig,
120                 short methodIndex, short channel, short markIndex )
121         {
122             System.out.println( "MyLogger2.cover" );
123             DOC.getLog().info( "!!cover!!" );
124         }
125     }
126     
127     
128     private static final String JavaDoc COVER_METHOD_NAME = "cover";
129     private static final String JavaDoc CLASSFILE_PATH =
130         "net/sourceforge/groboutils/codecoverage/v2/compiler/testcode/";
131     private static final String JavaDoc CLASSNAME_PACKAGE =
132         "net.sourceforge.groboutils.codecoverage.v2.compiler.testcode.";
133     private static final String JavaDoc MAIN_SIG = "main([Ljava/lang/String;)V";
134     public void testRebuild1()
135             throws Exception JavaDoc
136     {
137         final String JavaDoc classFileName = CLASSFILE_PATH+"Main1.class";
138         final String JavaDoc className = CLASSNAME_PACKAGE+"Main1";
139         byte[] origClassBytes = loadBytecode( classFileName );
140 // ModifiedClass mc = new ModifiedClass( new ParseCoverageLogger(
141
// Main1.class, COVER_METHOD_NAME ), classFileName, origClassBytes );
142
ModifiedClass mc = new ModifiedClass( new ParseCoverageLogger(
143             MyLogger.class, COVER_METHOD_NAME ), classFileName, origClassBytes );
144         ModifiedMethod[] mmL = mc.getMethods();
145         assertNotNull(
146             "Returned null method list.",
147             mmL );
148         ModifiedMethod mm = null;
149         for (int i = 0; i < mmL.length; ++i)
150         {
151             assertNotNull(
152                 "Method "+i+" is null.",
153                 mmL[i] );
154             DOC.getLog().info("Method "+i+": "+mmL[i].getMethodName());
155             if (mmL[i].getMethodName().equals( MAIN_SIG ))
156             {
157                 mm = mmL[i];
158             }
159         }
160         assertNotNull(
161             "Did not find a main method.",
162             mm );
163         DOC.getLog().info( "Modifying method "+mm.getMethodName()+"." );
164         ModifiedInstructionList mil = mm.getInstructionList();
165         assertNotNull(
166             "Null instruction list returned.",
167             mil );
168         DOC.getLog().info( "Instruction count: "+mil.getInstructionCount() );
169         assertTrue(
170             "Do not have any instructions to mark.",
171             mil.getInstructionCount() > 0 );
172         MarkedInstruction mi = mil.getInstructionAt( 0 );
173         assertNotNull(
174             "Null instruction returned.",
175             mi );
176         // set measure, mark, and modify method
177
mi.addMark( (short)0, (short)1 );
178         
179         // recompile!!!!
180
final byte[] newClassfile = mc.getModifiedClass();
181         assertNotNull(
182             "Returned null classfile array.",
183             newClassfile );
184         
185         DOC.getLog().info( "Original Classfile:" );
186         debugClass( origClassBytes, classFileName );
187         DOC.getLog().info( "Recompiled Classfile:" );
188         debugClass( newClassfile, classFileName );
189         
190         // clean-up
191
mc = null;
192         mi = null;
193         mil = null;
194         mm = null;
195         mmL = null;
196         
197         // load new, modified class.
198
ArrayClassLoader acl = new ArrayClassLoader();
199         acl.addClass( className, newClassfile );
200 // acl.addClass( className, origClassBytes );
201
Class JavaDoc clazz = acl.loadClass( className );
202         
203         // run the class
204
MyLogger.reset();
205         runMain( clazz );
206         
207         // check results
208
Iterator JavaDoc iter = MyLogger.marks.iterator();
209         assertTrue(
210             "Did not record any marks in MyLogger.",
211             iter.hasNext() );
212         MarkData md = (MarkData)iter.next();
213         assertNotNull(
214             "Returned null mark data entry.",
215             md );
216         DOC.getLog().info( "First mark is: "+md );
217         assertEquals(
218             "Did not set correct measure.",
219             (short)0,
220             md.measureIndex );
221         assertEquals(
222             "Did not set correct mark.",
223             (short)1,
224             md.markIndex );
225     }
226     
227     
228     
229     
230     //-------------------------------------------------------------------------
231
// helpers
232

233     
234     protected byte[] loadBytecode( String JavaDoc classFileName )
235             throws IOException JavaDoc
236     {
237         ClassLoader JavaDoc cl = this.getClass().getClassLoader();
238         InputStream JavaDoc is = cl.getSystemResourceAsStream( classFileName );
239         assertNotNull(
240             "resource '"+classFileName+"' could not be found.",
241             is );
242         return ReadByteStream.readByteStream( is );
243     }
244     
245     
246     protected void runMain( Class JavaDoc cz )
247             throws Exception JavaDoc
248     {
249         String JavaDoc s[] = new String JavaDoc[0];
250         java.lang.reflect.Method JavaDoc m = cz.getMethod( "main",
251             new Class JavaDoc[] { s.getClass() } );
252         m.invoke( null, new Object JavaDoc[] { s } );
253     }
254     
255     
256     protected static void debugClass( byte[] classBytes, String JavaDoc filename )
257             throws Exception JavaDoc
258     {
259         ByteArrayInputStream JavaDoc bais = new ByteArrayInputStream JavaDoc( classBytes );
260         org.apache.bcel.classfile.ClassParser cp =
261             new org.apache.bcel.classfile.ClassParser( bais, filename );
262         org.apache.bcel.classfile.JavaClass origClass = cp.parse();
263         String JavaDoc className = origClass.getClassName();
264         org.apache.bcel.generic.ClassGen modClass =
265             new org.apache.bcel.generic.ClassGen( origClass );
266         org.apache.bcel.generic.ConstantPoolGen constantPool =
267             modClass.getConstantPool();
268         org.apache.bcel.classfile.Method mL[] = modClass.getMethods();
269         
270         DOC.getLog().debug( "-->> Class "+className+":" );
271         /*
272         DOC.getLog().debug( " ClassGen ["+modClass+"]" );
273         DOC.getLog().debug( " Class Version ["+modClass.getMajor()+"."+
274             modClass.getMinor()+"]" );
275         DOC.getLog().debug( " ConstantPoolGen:" );
276         for (int i = 0; i < constantPool.getSize(); ++i)
277         {
278             DOC.getLog().debug( " "+i+": ["+
279                 printConstant( constantPool.getConstant( i ) )+"]" );
280         }
281         */

282         for (int i = 0; i < mL.length; ++i)
283         {
284             BytecodeLoaderUtil.verifyMethod( mL[i], constantPool );
285             if (mL[i].getName().equals( "main" ))
286             {
287                 int nameIndex = mL[i].getNameIndex();
288                 int sigIndex = mL[i].getSignatureIndex();
289                 DOC.getLog().debug( " main name["+nameIndex+"] = ["+
290                     printConstant(constantPool.getConstant( nameIndex ))+"]" );
291                 DOC.getLog().debug( " main signature["+sigIndex+"] = ["+
292                     printConstant(constantPool.getConstant( sigIndex ))+"]" );
293                 org.apache.bcel.classfile.Attribute attr[] =
294                     mL[i].getCode().getAttributes();
295                 DOC.getLog().debug( " code attributes:" );
296                 for (int j = 0; j < attr.length; ++j)
297                 {
298                     nameIndex = attr[j].getNameIndex();
299                     DOC.getLog().debug( " "+
300                         printConstant(constantPool.getConstant( nameIndex ))+
301                         " ("+j+") ["+attr[j].getTag()+"] = ["+
302                         attr[j]+"] ("+attr[j].getClass().getName()+")" );
303                 }
304             }
305             org.apache.bcel.generic.MethodGen mg =
306                 new org.apache.bcel.generic.MethodGen( mL[i], className,
307                 constantPool );
308             DOC.getLog().debug( " Method "+i+" ["+mg+"]" );
309             /*
310             org.apache.bcel.generic.InstructionList il =
311                 mg.getInstructionList();
312             DOC.getLog().debug( " Code [\n"+il+"]" );
313             */

314         }
315         DOC.getLog().debug( "<<--" );
316     }
317     
318     
319     protected static String JavaDoc printConstant( org.apache.bcel.classfile.Constant c )
320     {
321         if (c == null)
322         {
323             return null;
324         }
325         StringBuffer JavaDoc sb = new StringBuffer JavaDoc( "Tag " );
326         sb.append( c.getTag() ).
327             append( '\'' ).append( c.toString() ).append( '\'' );
328         return sb.toString();
329     }
330     
331     
332     
333     //-------------------------------------------------------------------------
334
// Standard JUnit declarations
335

336     
337     public static Test suite()
338     {
339         TestSuite suite = new TestSuite( THIS_CLASS );
340         
341         return suite;
342     }
343     
344     public static void main( String JavaDoc[] args )
345     {
346         String JavaDoc[] name = { THIS_CLASS.getName() };
347         
348         // junit.textui.TestRunner.main( name );
349
// junit.swingui.TestRunner.main( name );
350

351         junit.textui.TestRunner.main( name );
352     }
353     
354     
355     /**
356      *
357      * @exception Exception thrown under any exceptional condition.
358      */

359     protected void setUp() throws Exception JavaDoc
360     {
361         super.setUp();
362         
363         // set ourself up
364
}
365     
366     
367     /**
368      *
369      * @exception Exception thrown under any exceptional condition.
370      */

371     protected void tearDown() throws Exception JavaDoc
372     {
373         // tear ourself down
374

375         
376         super.tearDown();
377     }
378 }
379
380
Popular Tags