I have the following Test class:
@Features(value = {"baa.boo", "foo.boo"})
public class JavaTest {
@Test
public void shouldExecuteJavaTest() {
System.out.println("Simple Java Test.");
}
}
And an ASM class visitor that process class annotations and inject a method on visitEnd:
public class TestInjectorVisitor extends ClassVisitor {
private List<String> features = new ArrayList<>();
private ClassVisitor cw;
public TestInjectorVisitor(final ClassVisitor cv) {
super(ASM4, cv);
cw = cv;
}
@Override
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean
runtimeVisible) {
if (descriptor.equals("Lcom/github/bmsantos/asm/Features;")) {
return new AnnotationVisitor(ASM4, super.visitAnnotation(descriptor, runtimeVisible))
{
@Override
public AnnotationVisitor visitArray(final String name) {
if ("value".equals(name)) {
return new AnnotationVisitor(ASM4, super.visitArray(name)) {
@Override
public void visit(final String name, final Object value) {
features.add(value.toString());
super.visit(name, value);
}
};
}
return super.visitArray(name);
}
};
}
return super.visitAnnotation(descriptor, runtimeVisible);
}
@Override
public void visitEnd() {
for (final String feature : features) {
System.err.println("Found feature: " + feature);
}
injectJavaTestMethod();
super.visitEnd();
}
private void injectJavaTestMethod() {
final MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "shouldDisplayJavaMonkey", "
()V", null, null);
final AnnotationVisitor av = mv.visitAnnotation("Lorg/junit/Test;", true);
av.visitEnd();
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Hello Java Monkeys!");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "
(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
}
The method is successfully injected when the Features annotation is not present on the
JUnit test.
Is this an issue or am I just overlooking something?
Thanks,
Bruno