package net.bytebuddy.asm; import net.bytebuddy.ByteBuddy; import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; import net.bytebuddy.implementation.bytecode.assign.Assigner; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.Arrays; import java.util.Collection; import static net.bytebuddy.matcher.ElementMatchers.named; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @RunWith(Parameterized.class) public class AdviceBoxedReturnAssignmentTest { private static final String FOO = "foo"; private static final byte NUMERIC_VALUE = 42; @Parameterized.Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][]{ {VoidAssignment.class, null}, {BooleanAssignment.class, true}, {ByteAssignment.class, NUMERIC_VALUE}, {ShortAssignment.class, (short) NUMERIC_VALUE}, {CharacterAssignment.class, (char) NUMERIC_VALUE}, {IntegerAssignment.class, (int) NUMERIC_VALUE}, {LongAssignment.class, (long) NUMERIC_VALUE}, {FloatAssignment.class, (float) NUMERIC_VALUE}, {DoubleAssignment.class, (double) NUMERIC_VALUE}, {ReferenceAssignment.class, FOO}, }); } private final Class<?> type; private final Object expected; public AdviceBoxedReturnAssignmentTest(Class<?> type, Object expected) { this.type = type; this.expected = expected; } @Test public void testAssignment() throws Exception { Class<?> dynamicType = new ByteBuddy() .redefine(type) .visit(Advice.to(type).on(named(FOO))) .make() .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(dynamicType.getDeclaredMethod(FOO).invoke(dynamicType.getDeclaredConstructor().newInstance()), is(expected)); } @SuppressWarnings("all") public static class VoidAssignment { public void foo() { /* empty */ } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = FOO; } } @SuppressWarnings("all") public static class BooleanAssignment { public boolean foo() { return false; } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = true; } } @SuppressWarnings("all") public static class ByteAssignment { public byte foo() { return 0; } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = NUMERIC_VALUE; } } @SuppressWarnings("all") public static class ShortAssignment { public short foo() { return 0; } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = (short) NUMERIC_VALUE; } } @SuppressWarnings("all") public static class CharacterAssignment { public char foo() { return 0; } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = (char) NUMERIC_VALUE; } } @SuppressWarnings("all") public static class IntegerAssignment { public int foo() { return 0; } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = (int) NUMERIC_VALUE; } } @SuppressWarnings("all") public static class LongAssignment { public long foo() { return 0L; } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = (long) NUMERIC_VALUE; } } @SuppressWarnings("all") public static class FloatAssignment { public float foo() { return 0f; } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = (float) NUMERIC_VALUE; } } @SuppressWarnings("all") public static class DoubleAssignment { public double foo() { return 0d; } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = (double) NUMERIC_VALUE; } } @SuppressWarnings("all") public static class ReferenceAssignment { public String foo() { return null; } @Advice.OnMethodExit private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object value) { value = FOO; } } }