package net.bytebuddy.asm;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.StubMethod;
import org.junit.Test;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
public class AdviceImplementationTest {
private static final String FOO = "foo";
@Test(expected = IllegalStateException.class)
public void testAbstractMethod() throws Exception {
new ByteBuddy()
.subclass(Foo.class)
.method(named(FOO))
.intercept(Advice.to(Foo.class))
.make();
}
@Test
public void testActualMethod() throws Exception {
assertThat(new ByteBuddy()
.subclass(Bar.class)
.method(named(FOO))
.intercept(Advice.to(Bar.class))
.make()
.load(Bar.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.getDeclaredConstructor()
.newInstance()
.foo(), is((Object) FOO));
}
@Test
public void testExplicitWrap() throws Exception {
assertThat(new ByteBuddy()
.subclass(Qux.class)
.method(named(FOO))
.intercept(Advice.to(Qux.class).wrap(StubMethod.INSTANCE))
.make()
.load(Qux.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.getDeclaredConstructor()
.newInstance()
.foo(), is(FOO));
}
@Test
public void testExplicitWrapMultiple() throws Exception {
Class<?> type = new ByteBuddy()
.redefine(Baz.class)
.method(named(FOO))
.intercept(Advice.to(Baz.class).wrap(Advice.to(Baz.class).wrap(StubMethod.INSTANCE)))
.make()
.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Object baz = type.getDeclaredConstructor().newInstance();
assertThat(type.getDeclaredMethod(FOO).invoke(baz), nullValue(Object.class));
assertThat(type.getDeclaredField(FOO).getInt(null), is(2));
}
public abstract static class Foo {
public abstract String foo();
@Advice.OnMethodExit
public static void exit(@Advice.Return(readOnly = false) String returned) {
returned = FOO;
}
}
public static class Bar {
public Object foo() {
throw new RuntimeException();
}
@Advice.OnMethodExit(onThrowable = RuntimeException.class)
public static void exit(@Advice.Thrown(readOnly = false) Throwable throwable, @Advice.Return(readOnly = false) Object returned) {
if (!(throwable instanceof RuntimeException)) {
throw new AssertionError();
}
throwable = null;
returned = FOO;
}
}
public static class Qux {
public String foo() {
throw new AssertionError();
}
@Advice.OnMethodExit
public static void exit(@Advice.Return(readOnly = false) String returned) {
if (returned != null) {
throw new AssertionError();
}
returned = FOO;
}
}
public static class Baz {
public static int foo;
public void foo() {
/* empty */
}
@Advice.OnMethodExit
public static void exit() {
foo += 1;
}
}
}