1 26 27 package net.sourceforge.groboutils.codecoverage.v2.compiler; 28 29 import java.io.ByteArrayInputStream ; 30 import java.io.IOException ; 31 import java.io.InputStream ; 32 import java.util.ArrayList ; 33 import java.util.Iterator ; 34 import java.util.List ; 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 54 public class RebuildClassIUTest extends TestCase 55 { 56 59 private static final Class THIS_CLASS = RebuildClassIUTest.class; 60 private static final AutoDoc DOC = new AutoDoc( THIS_CLASS ); 61 62 public RebuildClassIUTest( String name ) 63 { 64 super( name ); 65 } 66 67 68 69 72 public static class MarkData 73 { 74 public String classSig; 75 public short measureIndex; 76 public short methodIndex; 77 public short markIndex; 78 79 public MarkData( String 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 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 marks = new ArrayList (); 98 99 100 public synchronized static void cover( String 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 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 COVER_METHOD_NAME = "cover"; 129 private static final String CLASSFILE_PATH = 130 "net/sourceforge/groboutils/codecoverage/v2/compiler/testcode/"; 131 private static final String CLASSNAME_PACKAGE = 132 "net.sourceforge.groboutils.codecoverage.v2.compiler.testcode."; 133 private static final String MAIN_SIG = "main([Ljava/lang/String;)V"; 134 public void testRebuild1() 135 throws Exception 136 { 137 final String classFileName = CLASSFILE_PATH+"Main1.class"; 138 final String className = CLASSNAME_PACKAGE+"Main1"; 139 byte[] origClassBytes = loadBytecode( classFileName ); 140 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 mi.addMark( (short)0, (short)1 ); 178 179 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 mc = null; 192 mi = null; 193 mil = null; 194 mm = null; 195 mmL = null; 196 197 ArrayClassLoader acl = new ArrayClassLoader(); 199 acl.addClass( className, newClassfile ); 200 Class clazz = acl.loadClass( className ); 202 203 MyLogger.reset(); 205 runMain( clazz ); 206 207 Iterator 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 233 234 protected byte[] loadBytecode( String classFileName ) 235 throws IOException 236 { 237 ClassLoader cl = this.getClass().getClassLoader(); 238 InputStream 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 cz ) 247 throws Exception 248 { 249 String s[] = new String [0]; 250 java.lang.reflect.Method m = cz.getMethod( "main", 251 new Class [] { s.getClass() } ); 252 m.invoke( null, new Object [] { s } ); 253 } 254 255 256 protected static void debugClass( byte[] classBytes, String filename ) 257 throws Exception 258 { 259 ByteArrayInputStream bais = new ByteArrayInputStream ( 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 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 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 314 } 315 DOC.getLog().debug( "<<--" ); 316 } 317 318 319 protected static String printConstant( org.apache.bcel.classfile.Constant c ) 320 { 321 if (c == null) 322 { 323 return null; 324 } 325 StringBuffer sb = new StringBuffer ( "Tag " ); 326 sb.append( c.getTag() ). 327 append( '\'' ).append( c.toString() ).append( '\'' ); 328 return sb.toString(); 329 } 330 331 332 333 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 [] args ) 345 { 346 String [] name = { THIS_CLASS.getName() }; 347 348 351 junit.textui.TestRunner.main( name ); 352 } 353 354 355 359 protected void setUp() throws Exception 360 { 361 super.setUp(); 362 363 } 365 366 367 371 protected void tearDown() throws Exception 372 { 373 375 376 super.tearDown(); 377 } 378 } 379 380 | Popular Tags |