package net.bytebuddy.utility.visitor; import net.bytebuddy.test.utility.MockitoRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mockito.Mock; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import static org.mockito.Mockito.*; @RunWith(Parameterized.class) public class ExceptionTableSensitiveMethodVisitorTest { @Parameterized.Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][]{ {Opcodes.ASM5, "visitLabel", new Class<?>[]{Label.class}, new Object[]{new Label()}}, {Opcodes.ASM5, "visitIntInsn", new Class<?>[]{int.class, int.class}, new Object[]{0, 0}}, {Opcodes.ASM5, "visitVarInsn", new Class<?>[]{int.class, int.class}, new Object[]{0, 0}}, {Opcodes.ASM5, "visitTypeInsn", new Class<?>[]{int.class, String.class}, new Object[]{0, ""}}, {Opcodes.ASM5, "visitFieldInsn", new Class<?>[]{int.class, String.class, String.class, String.class}, new Object[]{0, "", "", ""}}, {Opcodes.ASM4, "visitMethodInsn", new Class<?>[]{int.class, String.class, String.class, String.class}, new Object[]{0, "", "", ""}}, {Opcodes.ASM5, "visitMethodInsn", new Class<?>[]{int.class, String.class, String.class, String.class, boolean.class}, new Object[]{0, "", "", "", false}}, {Opcodes.ASM5, "visitInvokeDynamicInsn", new Class<?>[]{String.class, String.class, Handle.class, Object[].class}, new Object[]{"", "", new Handle(0, "", "", "", false), new Object[0]}}, {Opcodes.ASM5, "visitJumpInsn", new Class<?>[]{int.class, Label.class}, new Object[]{0, new Label()}}, {Opcodes.ASM5, "visitLdcInsn", new Class<?>[]{Object.class}, new Object[]{new Object()}}, {Opcodes.ASM5, "visitIincInsn", new Class<?>[]{int.class, int.class}, new Object[]{0, 0}}, {Opcodes.ASM5, "visitTableSwitchInsn", new Class<?>[]{int.class, int.class, Label.class, Label[].class}, new Object[]{0, 0, new Label(), new Label[0]}}, {Opcodes.ASM5, "visitLookupSwitchInsn", new Class<?>[]{Label.class, int[].class, Label[].class}, new Object[]{new Label(), new int[0], new Label[0]}}, {Opcodes.ASM5, "visitMultiANewArrayInsn", new Class<?>[]{String.class, int.class}, new Object[]{"", 0}}, {Opcodes.ASM5, "visitInsn", new Class<?>[]{int.class}, new Object[]{0}}, }); } @Rule public TestRule mockitoRule = new MockitoRule(this); @Mock private MethodVisitor methodVisitor; private final int api; private final String name; private final Class<?>[] type; private final Object[] argument; public ExceptionTableSensitiveMethodVisitorTest(int api, String name, Class<?>[] type, Object[] argument) { this.api = api; this.name = name; this.type = type; this.argument = argument; } @Test public void testCallback() throws Exception { Method method = MethodVisitor.class.getDeclaredMethod(name, type); PseudoVisitor pseudoVisitor = new PseudoVisitor(api, methodVisitor); method.invoke(pseudoVisitor, argument); method.invoke(pseudoVisitor, argument); method.invoke(verify(methodVisitor, times(2)), argument); verifyNoMoreInteractions(methodVisitor); pseudoVisitor.check(); } private static class PseudoVisitor extends ExceptionTableSensitiveMethodVisitor { private boolean called; public PseudoVisitor(int api, MethodVisitor methodVisitor) { super(api, methodVisitor); } @Override protected void onAfterExceptionTable() { if (called) { throw new AssertionError(); } called = true; verifyZeroInteractions(mv); } protected void check() { if (!called) { throw new AssertionError(); } } } }