Added some code to change the instrumentation for tests.
git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@756 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
parent
c34eaa6962
commit
b840dd1320
|
|
@ -43,15 +43,14 @@ public abstract class BaseTest {
|
|||
protected static String seqLocation = "/seq";
|
||||
protected static String oneKGLocation = "/broad/1KG";
|
||||
protected static String testDir = "testdata/";
|
||||
|
||||
protected static boolean alreadySetup = false;
|
||||
private static long startTime;
|
||||
|
||||
|
||||
/** before the class starts up */
|
||||
@BeforeClass
|
||||
public static void baseStartup() {
|
||||
if (!alreadySetup) {
|
||||
|
||||
|
||||
alreadySetup = true;
|
||||
// setup a basic log configuration
|
||||
BasicConfigurator.configure();
|
||||
|
|
@ -78,7 +77,7 @@ public abstract class BaseTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void findFileLocations() throws IOException {
|
||||
// if either doesn't exist
|
||||
if (!fileExist(seqLocation) || !fileExist(oneKGLocation)) {
|
||||
|
|
@ -132,29 +131,4 @@ public abstract class BaseTest {
|
|||
return temp.exists();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this test is here so that we can always pass when this test is run
|
||||
*/
|
||||
@Test
|
||||
public void basicTest() {
|
||||
|
||||
}
|
||||
|
||||
/** after the class runs */
|
||||
@AfterClass
|
||||
public static void baseShutdown() {
|
||||
|
||||
}
|
||||
|
||||
// pass through to the junit 3 calls, which are not annotated
|
||||
@Before
|
||||
public void baseSetup() throws Exception {
|
||||
}
|
||||
|
||||
@After
|
||||
public void baseTearDown() throws Exception {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
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 javassist.*;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
import java.lang.instrument.IllegalClassFormatException;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
|
|
@ -40,7 +38,6 @@ import java.lang.instrument.Instrumentation;
|
|||
/** 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);
|
||||
|
|
@ -53,223 +50,104 @@ public class TrivialInstrumenter implements ClassFileTransformer {
|
|||
Class cBR, java.security.ProtectionDomain pD,
|
||||
byte[] classfileBuffer)
|
||||
throws IllegalClassFormatException {
|
||||
if (className.contains("broadinstitute") && !(className.endsWith("BaseTest"))) {
|
||||
int size = classfileBuffer.length;
|
||||
|
||||
if (className.contains("broadinstitute") &&
|
||||
className.endsWith("Test") &&
|
||||
!(className.endsWith("BaseTest"))) {
|
||||
ClassPool pool = ClassPool.getDefault();
|
||||
CtClass cl = null;
|
||||
|
||||
JavaClass jclas = null;
|
||||
try {
|
||||
jclas = Repository.lookupClass(className);
|
||||
if (jclas == null) {
|
||||
return null;
|
||||
cl = pool.makeClass(new java.io.ByteArrayInputStream(classfileBuffer));
|
||||
if (cl.isInterface() == false) {
|
||||
for (CtBehavior meth : cl.getDeclaredMethods()) {
|
||||
|
||||
if (meth.isEmpty() == false) {
|
||||
Object anns[] = meth.getAvailableAnnotations();
|
||||
boolean weAreAJunitTest = false;
|
||||
for (Object obj : anns) {
|
||||
if (obj instanceof org.junit.Test) {
|
||||
weAreAJunitTest = true;
|
||||
}
|
||||
}
|
||||
if (weAreAJunitTest) {
|
||||
addAnnouncement(meth, cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
classfileBuffer = cl.toBytecode();
|
||||
return classfileBuffer;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
if (!(jclas.getSuperClass().getClassName().contains("BaseTest"))) {
|
||||
return null;
|
||||
}
|
||||
System.err.println("looking at " + className);
|
||||
ClassGen cgen = new ClassGen(jclas);
|
||||
ConstantPoolGen pgen = cgen.getConstantPool();
|
||||
InstructionFactory fact = new InstructionFactory(cgen, pgen);
|
||||
createFields(cgen, pgen);
|
||||
/*for (Method m : cgen.getMethods()) {
|
||||
System.err.println("looking at " + m.getName());
|
||||
addStringOutputToMethod(jclas, cgen, pgen, m, fact);
|
||||
}*/
|
||||
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());
|
||||
field = new FieldGen(Constants.ACC_PRIVATE, Type.STRING, "currentTestName", pgen);
|
||||
cgen.addField(field.getField());
|
||||
}
|
||||
|
||||
/*
|
||||
private void addStringOutputToMethod(JavaClass classname, ClassGen cgen, ConstantPoolGen pgen, Method meth, InstructionFactory fact) {
|
||||
|
||||
if(true) {return;}
|
||||
if (meth.getName().contains("<")) {
|
||||
System.err.println("Nope -> " + meth.getName());
|
||||
return;
|
||||
}
|
||||
//if (meth.isPublic()) {
|
||||
boolean outputInstead = true;
|
||||
MethodGen g = new MethodGen(meth, cgen.getClassName(), pgen);
|
||||
InstructionList il = g.getInstructionList();
|
||||
//if (outputInstead) {
|
||||
BufferedWriter outputStream = null;
|
||||
BufferedWriter outputStream2 = null;
|
||||
//}
|
||||
Instruction returnInstruction = null;
|
||||
InstructionHandle[] iHandles = il.getInstructionHandles();
|
||||
for (int f = 0; f < iHandles.length; f++) {
|
||||
if (iHandles[f].getInstruction() instanceof ReturnInstruction) {
|
||||
returnInstruction = iHandles[f].getInstruction();
|
||||
//System.out.println("found the invoke virtual");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (outputInstead) {
|
||||
try {
|
||||
outputStream =
|
||||
new BufferedWriter(new FileWriter("one.txt"));
|
||||
outputStream2 =
|
||||
new BufferedWriter(new FileWriter("two.txt"));
|
||||
|
||||
outputStream.write(meth.getName() + " of " + meth.getClass());
|
||||
|
||||
for (Instruction i : il.getInstructions()) {
|
||||
|
||||
outputStream.write(i.getName() + " <code> " + i.getOpcode() + " <toString> " + i.toString() + "\n");
|
||||
|
||||
}
|
||||
outputStream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// baseTearDown
|
||||
} catch (NotFoundException e) {
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
//InstructionHandle handle = il.getEnd();
|
||||
//il.s
|
||||
//il.insert(getFieldInstruction, fact.createLoad(Type.OBJECT, 0));
|
||||
//il.insert(getFieldInstruction, fact.createNew("java.lang.String"));
|
||||
//il.insert(getFieldInstruction, InstructionConstants.DUP);
|
||||
//il.insert(getFieldInstruction, new PUSH(pgen, meth.getName()));
|
||||
//il.insert(getFieldInstruction, fact.createInvoke("java.lang.String", "<init>", Type.VOID, new Type[]{Type.STRING}, Constants.INVOKESPECIAL));
|
||||
//il.insert(getFieldInstruction, fact.createFieldAccess(cgen.getClassName(), "currentTestName", Type.STRING, Constants.PUTFIELD));
|
||||
//il.insert(getFieldInstruction,fact.createPrintln("Hello World"));
|
||||
/*il.insert(returnInstruction, new ALOAD(0));
|
||||
il.insert(returnInstruction, fact.createNew("java.lang.String"));
|
||||
il.insert(returnInstruction, InstructionConstants.DUP);
|
||||
il.insert(returnInstruction, new PUSH(pgen, meth.getName()));
|
||||
il.insert(returnInstruction, fact.createInvoke("java.lang.String", "<init>", Type.VOID, new Type[]{Type.STRING}, Constants.INVOKESPECIAL));
|
||||
il.insert(returnInstruction, fact.createFieldAccess(classname.replace("/","."), "currentTestName", Type.STRING, Constants.PUTFIELD));*/
|
||||
/*il.setPositions();
|
||||
g.setMaxStack();
|
||||
g.setMaxLocals();
|
||||
g.removeLineNumbers();
|
||||
//org.apache.bcel.classfile.LocalVariableTypeTable table;
|
||||
InstructionList inst = g.getInstructionList();
|
||||
if (outputInstead) {
|
||||
try {
|
||||
outputStream2.write(meth.getName() + " of " + meth.getClass() + " classname: " + classname.getClassName() + "\n");
|
||||
|
||||
for (Instruction i : inst.getInstructions()) {
|
||||
|
||||
outputStream2.write(i.getName() + " <code> " + i.getOpcode() + " <toString> " + i.toString() + "\n");
|
||||
|
||||
}
|
||||
outputStream2.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
} catch (CannotCompileException e) {
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
} finally {
|
||||
if (cl != null) {
|
||||
cl.detach();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//.
|
||||
cgen.replaceMethod(meth, g.getMethod());
|
||||
il.dispose();*/
|
||||
//}
|
||||
/*if (meth.isPublic()) {
|
||||
InstructionList il = new InstructionList();
|
||||
MethodGen method = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, Type.NO_ARGS, new String[]{}, meth.getName(), cgen.getClassName(), il, pgen);
|
||||
|
||||
InstructionHandle ih_0 = il.append(fact.createLoad(Type.OBJECT, 0));
|
||||
il.append(fact.createNew("java.lang.String"));
|
||||
il.append(InstructionConstants.DUP);
|
||||
il.append(new PUSH(pgen, "grrr"));
|
||||
il.append(fact.createInvoke("java.lang.String", "<init>", Type.VOID, new Type[]{Type.STRING}, Constants.INVOKESPECIAL));
|
||||
il.append(fact.createFieldAccess(cgen.getClassName(), "currentTestName", Type.STRING, Constants.PUTFIELD));
|
||||
InstructionHandle ih_13 = il.append(fact.createReturn(Type.VOID));
|
||||
method.setMaxStack();
|
||||
method.setMaxLocals();
|
||||
cgen.removeMethod(meth);
|
||||
cgen.addMethod(method.getMethod());
|
||||
il.dispose();
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
private static void addTiming(CtClass clas, String mname)
|
||||
throws NotFoundException, CannotCompileException {
|
||||
|
||||
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(fact.createNew("java.lang.StringBuilder"));
|
||||
il.append(InstructionConstants.DUP);
|
||||
il.append(fact.createInvoke("java.lang.StringBuilder", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
|
||||
il.append(new PUSH(pgen, "Test Name: "));
|
||||
il.append(fact.createInvoke("java.lang.StringBuilder", "append", new ObjectType("java.lang.StringBuilder"), new Type[]{Type.STRING}, Constants.INVOKEVIRTUAL));
|
||||
il.append(fact.createLoad(Type.OBJECT, 0));
|
||||
il.append(fact.createFieldAccess(cgen.getClassName(), "currentTestName", Type.STRING, Constants.GETFIELD));
|
||||
il.append(fact.createInvoke("java.lang.StringBuilder", "append", new ObjectType("java.lang.StringBuilder"), new Type[]{Type.STRING}, Constants.INVOKEVIRTUAL));
|
||||
il.append(new PUSH(pgen, " runtime: %dms"));
|
||||
il.append(fact.createInvoke("java.lang.StringBuilder", "append", new ObjectType("java.lang.StringBuilder"), new Type[]{Type.STRING}, Constants.INVOKEVIRTUAL));
|
||||
il.append(fact.createInvoke("java.lang.StringBuilder", "toString", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
|
||||
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_55 = il.append(fact.createReturn(Type.VOID));
|
||||
method.setMaxStack();
|
||||
method.setMaxLocals();
|
||||
cgen.addMethod(method.getMethod());
|
||||
il.dispose();
|
||||
// get the method information (throws exception if method with
|
||||
// given name is not declared directly by this class, returns
|
||||
// arbitrary choice if more than one with the given name)
|
||||
CtMethod mold = clas.getDeclaredMethod(mname);
|
||||
|
||||
// rename old method to synthetic name, then duplicate the
|
||||
// method with original name for use as interceptor
|
||||
String nname = mname + "$impl";
|
||||
mold.setName(nname);
|
||||
CtMethod mnew = CtNewMethod.copy(mold, mname, clas, null);
|
||||
|
||||
// start the body text generation by saving the start time
|
||||
// to a local variable, then call the timed method; the
|
||||
// actual code generated needs to depend on whether the
|
||||
// timed method returns a value
|
||||
String type = mold.getReturnType().getName();
|
||||
StringBuffer body = new StringBuffer();
|
||||
body.append("{\nlong start = System.currentTimeMillis();\n");
|
||||
if (!"void".equals(type)) {
|
||||
body.append(type + " result = ");
|
||||
}
|
||||
body.append(nname + "($$);\n");
|
||||
|
||||
// finish body text generation with call to print the timing
|
||||
// information, and return saved value (if not void)
|
||||
body.append("System.out.println(\"Call to method " + mname +
|
||||
" took \" +\n (System.currentTimeMillis()-start) + " +
|
||||
"\" ms.\");\n");
|
||||
if (!"void".equals(type)) {
|
||||
body.append("return result;\n");
|
||||
}
|
||||
body.append("}");
|
||||
|
||||
// replace the body of the interceptor method with generated
|
||||
// code block and add it to class
|
||||
mnew.setBody(body.toString());
|
||||
clas.addMethod(mnew);
|
||||
|
||||
// print the generated code block just to show what was done
|
||||
//System.out.println("Interceptor method body:");
|
||||
//System.out.println(body.toString());
|
||||
}
|
||||
|
||||
|
||||
private void addAnnouncement(CtBehavior method, CtClass cl)
|
||||
throws NotFoundException, CannotCompileException {
|
||||
String name = method.getName();
|
||||
method.insertAfter("logger.warn(\"\");");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue