Added BCEL and some basic instrumenation code to the test library.
git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@602 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
parent
bfd6dfe36c
commit
98f4920739
18
build.xml
18
build.xml
|
|
@ -211,10 +211,11 @@
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- TEST -->
|
<!-- TEST -->
|
||||||
<target name="test" depends="test.compile" description="Run unit tests">
|
<target name="test" depends="test.compile,agent" description="Run unit tests">
|
||||||
<mkdir dir="${report}"/>
|
<mkdir dir="${report}"/>
|
||||||
<echo message="Sting: Running test cases!"/>
|
<echo message="Sting: Running test cases!"/>
|
||||||
<junit printsummary="yes" showoutput="yes" clonevm="yes" haltonfailure="yes" failureProperty="test.failure">
|
<junit printsummary="yes" showoutput="yes" clonevm="yes" haltonfailure="yes" failureProperty="test.failure">
|
||||||
|
<jvmarg value="-javaagent:build/TestAgent.jar"/>
|
||||||
<formatter type="brief" usefile="false" />
|
<formatter type="brief" usefile="false" />
|
||||||
<classpath>
|
<classpath>
|
||||||
<path refid="external.dependencies"/>
|
<path refid="external.dependencies"/>
|
||||||
|
|
@ -228,6 +229,8 @@
|
||||||
<fileset dir="${test.classes}">
|
<fileset dir="${test.classes}">
|
||||||
<include name="**/${single}.class"/>
|
<include name="**/${single}.class"/>
|
||||||
<exclude name="**/BaseTest.class"/>
|
<exclude name="**/BaseTest.class"/>
|
||||||
|
<!-- omit our instrumenation class -->
|
||||||
|
<exclude name="**/TrivialInstrumenter.class"/>
|
||||||
<!-- Omit inner classes -->
|
<!-- Omit inner classes -->
|
||||||
<exclude name="**/*$*.class" />
|
<exclude name="**/*$*.class" />
|
||||||
</fileset>
|
</fileset>
|
||||||
|
|
@ -237,7 +240,20 @@
|
||||||
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<!-- this builds the instrumentation library we're going to use for test cases -->
|
||||||
|
<target name="agent" description="build the agent">
|
||||||
|
<echo message="Sting: Creating test agent!"/>
|
||||||
|
<jar jarfile="build/TestAgent.jar">
|
||||||
|
<fileset dir="build">
|
||||||
|
<include name="**/TrivialInstrumenter.class" />
|
||||||
|
</fileset>
|
||||||
|
|
||||||
|
<manifest>
|
||||||
|
<attribute name="Class-Path" value="${jar.classpath}"/>
|
||||||
|
<attribute name="Premain-Class" value="org.broadinstitute.sting.TrivialInstrumenter"/>
|
||||||
|
</manifest>
|
||||||
|
</jar>
|
||||||
|
</target>
|
||||||
|
|
||||||
<target name="javadoc" depends="init,resolve" description="generates javadoc">
|
<target name="javadoc" depends="init,resolve" description="generates javadoc">
|
||||||
<mkdir dir="javadoc"/>
|
<mkdir dir="javadoc"/>
|
||||||
|
|
|
||||||
1
ivy.xml
1
ivy.xml
|
|
@ -8,6 +8,7 @@
|
||||||
<dependency org="log4j" name="log4j" rev="1.2.15" />
|
<dependency org="log4j" name="log4j" rev="1.2.15" />
|
||||||
<dependency org="colt" name="colt" rev="1.2.0" />
|
<dependency org="colt" name="colt" rev="1.2.0" />
|
||||||
<dependency org="commons-cli" name="commons-cli" rev="1.2" />
|
<dependency org="commons-cli" name="commons-cli" rev="1.2" />
|
||||||
|
<dependency org="bcel" name="bcel" rev="5.1" />
|
||||||
|
|
||||||
<!-- The following are all castor dependencies. Remove when transitive dependencies are working -->
|
<!-- The following are all castor dependencies. Remove when transitive dependencies are working -->
|
||||||
<dependency org="commons-logging" name="commons-logging" rev="latest.integration" />
|
<dependency org="commons-logging" name="commons-logging" rev="latest.integration" />
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ public abstract class BaseTest {
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void baseStartup() {
|
public static void baseStartup() {
|
||||||
if (!alreadySetup) {
|
if (!alreadySetup) {
|
||||||
|
|
||||||
alreadySetup = true;
|
alreadySetup = true;
|
||||||
// setup a basic log configuration
|
// setup a basic log configuration
|
||||||
BasicConfigurator.configure();
|
BasicConfigurator.configure();
|
||||||
|
|
@ -148,15 +149,11 @@ public abstract class BaseTest {
|
||||||
|
|
||||||
// pass through to the junit 3 calls, which are not annotated
|
// pass through to the junit 3 calls, which are not annotated
|
||||||
@Before
|
@Before
|
||||||
final public void baseSetup() throws Exception {
|
public void baseSetup() throws Exception {
|
||||||
startTime = System.currentTimeMillis();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void baseTearDown() throws Exception {
|
public void baseTearDown() throws Exception {
|
||||||
long endTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
logger.warn(String.format("runtime: %dms", (endTime - startTime)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,150 @@
|
||||||
|
package org.broadinstitute.sting;
|
||||||
|
|
||||||
|
import org.apache.bcel.Constants;
|
||||||
|
import org.apache.bcel.Repository;
|
||||||
|
import org.apache.bcel.classfile.JavaClass;
|
||||||
|
import org.apache.bcel.generic.*;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
|
import java.lang.instrument.IllegalClassFormatException;
|
||||||
|
import java.lang.instrument.Instrumentation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* User: aaron
|
||||||
|
* Date: May 5, 2009
|
||||||
|
* Time: 4:27:04 PM
|
||||||
|
*
|
||||||
|
* The Broad Institute
|
||||||
|
* SOFTWARE COPYRIGHT NOTICE AGREEMENT
|
||||||
|
* This software and its documentation are copyright 2009 by the
|
||||||
|
* Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
|
||||||
|
*
|
||||||
|
* This software is supplied without any warranty or guaranteed support whatsoever. Neither
|
||||||
|
* the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author aaron
|
||||||
|
* @version 1.0
|
||||||
|
* @date May 5, 2009
|
||||||
|
* <p/>
|
||||||
|
* Class TrivalInstrumenter
|
||||||
|
* <p/>
|
||||||
|
* A descriptions should go here. Blame aaron if it's missing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** A trivial example program that basically just says hello! */
|
||||||
|
@Ignore
|
||||||
|
public class TrivialInstrumenter implements ClassFileTransformer {
|
||||||
|
|
||||||
|
public static void premain(String options, Instrumentation ins) {
|
||||||
|
if (options != null) {
|
||||||
|
System.out.printf(" I've been called with options: \"%s\"\n", options);
|
||||||
|
} else
|
||||||
|
ins.addTransformer(new TrivialInstrumenter());
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] transform(ClassLoader loader,
|
||||||
|
String className,
|
||||||
|
Class cBR, java.security.ProtectionDomain pD,
|
||||||
|
byte[] classfileBuffer)
|
||||||
|
throws IllegalClassFormatException {
|
||||||
|
if (className.contains("broadinstitute") && !(className.endsWith("BaseTest"))) {
|
||||||
|
JavaClass jclas = null;
|
||||||
|
try {
|
||||||
|
jclas = Repository.lookupClass(className);
|
||||||
|
if (jclas == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!(jclas.getSuperClass().getClassName().contains("BaseTest"))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ClassGen cgen = new ClassGen(jclas);
|
||||||
|
ConstantPoolGen pgen = cgen.getConstantPool();
|
||||||
|
InstructionFactory fact = new InstructionFactory(cgen, pgen);
|
||||||
|
createFields(cgen, pgen);
|
||||||
|
createBeforeMethod(cgen, pgen, fact);
|
||||||
|
createAfterMethod(cgen, pgen, fact);
|
||||||
|
|
||||||
|
|
||||||
|
return cgen.getJavaClass().getBytes();
|
||||||
|
}
|
||||||
|
return null; // No transformation required
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create any fields we need here
|
||||||
|
*
|
||||||
|
* @param cgen our classgen for the class to add to
|
||||||
|
* @param pgen our constant pool generator, check out the JVM spec about this
|
||||||
|
*/
|
||||||
|
private void createFields(ClassGen cgen, ConstantPoolGen pgen) {
|
||||||
|
FieldGen field;
|
||||||
|
|
||||||
|
field = new FieldGen(Constants.ACC_PRIVATE | Constants.ACC_STATIC, Type.LONG, "startTime", pgen);
|
||||||
|
cgen.addField(field.getField());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the before method
|
||||||
|
*
|
||||||
|
* @param cgen our classgen for the class to add to
|
||||||
|
* @param pgen our constant pool generator
|
||||||
|
* @param fact the instruction factory we're using
|
||||||
|
*/
|
||||||
|
private void createBeforeMethod(ClassGen cgen, ConstantPoolGen pgen, InstructionFactory fact) {
|
||||||
|
InstructionList il = new InstructionList();
|
||||||
|
MethodGen method = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_FINAL, Type.VOID, Type.NO_ARGS, new String[]{}, "baseSetup", cgen.getClassName(), il, pgen);
|
||||||
|
|
||||||
|
InstructionHandle ih_0 = il.append(fact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC));
|
||||||
|
il.append(fact.createFieldAccess(cgen.getClassName(), "startTime", Type.LONG, Constants.PUTSTATIC));
|
||||||
|
InstructionHandle ih_6 = il.append(fact.createReturn(Type.VOID));
|
||||||
|
|
||||||
|
method.setMaxStack();
|
||||||
|
method.setMaxLocals();
|
||||||
|
cgen.addMethod(method.getMethod());
|
||||||
|
il.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the after method
|
||||||
|
*
|
||||||
|
* @param cgen our classgen for the class to add to
|
||||||
|
* @param pgen our constant pool generator
|
||||||
|
* @param fact the instruction factory we're using
|
||||||
|
*/
|
||||||
|
private void createAfterMethod(ClassGen cgen, ConstantPoolGen pgen, InstructionFactory fact) {
|
||||||
|
InstructionList il = new InstructionList();
|
||||||
|
MethodGen method = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, Type.NO_ARGS, new String[]{}, "baseTearDown", cgen.getClassName(), il, pgen);
|
||||||
|
|
||||||
|
InstructionHandle ih_0 = il.append(fact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC));
|
||||||
|
il.append(fact.createStore(Type.LONG, 1));
|
||||||
|
InstructionHandle ih_4 = il.append(fact.createFieldAccess(cgen.getClassName(), "logger", new ObjectType("org.apache.log4j.Logger"), Constants.GETSTATIC));
|
||||||
|
il.append(new PUSH(pgen, cgen.getClassName() + " runtime: %dms"));
|
||||||
|
il.append(new PUSH(pgen, 1));
|
||||||
|
il.append(fact.createNewArray(Type.OBJECT, (short) 1));
|
||||||
|
il.append(InstructionConstants.DUP);
|
||||||
|
il.append(new PUSH(pgen, 0));
|
||||||
|
il.append(fact.createLoad(Type.LONG, 1));
|
||||||
|
il.append(fact.createFieldAccess(cgen.getClassName(), "startTime", Type.LONG, Constants.GETSTATIC));
|
||||||
|
il.append(InstructionConstants.LSUB);
|
||||||
|
il.append(fact.createInvoke("java.lang.Long", "valueOf", new ObjectType("java.lang.Long"), new Type[]{Type.LONG}, Constants.INVOKESTATIC));
|
||||||
|
il.append(InstructionConstants.AASTORE);
|
||||||
|
il.append(fact.createInvoke("java.lang.String", "format", Type.STRING, new Type[]{Type.STRING, new ArrayType(Type.OBJECT, 1)}, Constants.INVOKESTATIC));
|
||||||
|
il.append(fact.createInvoke("org.apache.log4j.Logger", "warn", Type.VOID, new Type[]{Type.OBJECT}, Constants.INVOKEVIRTUAL));
|
||||||
|
InstructionHandle ih_30 = il.append(fact.createReturn(Type.VOID));
|
||||||
|
method.setMaxStack();
|
||||||
|
method.setMaxLocals();
|
||||||
|
cgen.addMethod(method.getMethod());
|
||||||
|
il.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue