package net.bytebuddy.implementation.bytecode.member; import net.bytebuddy.description.field.FieldDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.implementation.Implementation; import net.bytebuddy.implementation.bytecode.StackManipulation; import net.bytebuddy.implementation.bytecode.StackSize; import net.bytebuddy.test.utility.MockitoRule; import org.junit.After; import org.junit.Before; 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.MethodVisitor; import org.objectweb.asm.Opcodes; import java.util.Arrays; import java.util.Collection; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.*; @RunWith(Parameterized.class) public class FieldAccessTest { private static final String FOO = "foo", BAR = "bar", QUX = "qux"; private final boolean isStatic; private final StackSize fieldSize; private final int getterChange, getterMaximum, getterOpcode; private final int putterChange, putterMaximum, putterOpcode; @Rule public TestRule mockitoRule = new MockitoRule(this); @Mock private FieldDescription.InDefinedShape fieldDescription; @Mock private TypeDescription declaringType, fieldType; @Mock private TypeDescription.Generic genericFieldType; @Mock private MethodVisitor methodVisitor; @Mock private Implementation.Context implementationContext; public FieldAccessTest(boolean isStatic, StackSize fieldSize, int getterChange, int getterMaximum, int getterOpcode, int putterChange, int putterMaximum, int putterOpcode) { this.isStatic = isStatic; this.fieldSize = fieldSize; this.getterChange = getterChange; this.getterMaximum = getterMaximum; this.getterOpcode = getterOpcode; this.putterChange = putterChange; this.putterMaximum = putterMaximum; this.putterOpcode = putterOpcode; } @Parameterized.Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][]{ {true, StackSize.SINGLE, 1, 1, Opcodes.GETSTATIC, -1, 0, Opcodes.PUTSTATIC}, {true, StackSize.DOUBLE, 2, 2, Opcodes.GETSTATIC, -2, 0, Opcodes.PUTSTATIC}, {false, StackSize.SINGLE, 0, 0, Opcodes.GETFIELD, -2, 0, Opcodes.PUTFIELD}, {false, StackSize.DOUBLE, 1, 1, Opcodes.GETFIELD, -3, 0, Opcodes.PUTFIELD} }); } @Before public void setUp() throws Exception { when(declaringType.asErasure()).thenReturn(declaringType); when(fieldDescription.getDeclaringType()).thenReturn(declaringType); when(fieldDescription.getType()).thenReturn(genericFieldType); when(genericFieldType.asErasure()).thenReturn(fieldType); when(genericFieldType.getStackSize()).thenReturn(fieldSize); when(declaringType.getInternalName()).thenReturn(FOO); when(fieldDescription.getInternalName()).thenReturn(BAR); when(fieldDescription.getDescriptor()).thenReturn(QUX); when(fieldDescription.isStatic()).thenReturn(isStatic); } @After public void tearDown() throws Exception { verifyZeroInteractions(implementationContext); } @Test public void testGetter() throws Exception { FieldAccess.Defined getter = FieldAccess.forField(fieldDescription); assertThat(getter.read().isValid(), is(true)); StackManipulation.Size size = getter.read().apply(methodVisitor, implementationContext); assertThat(size.getSizeImpact(), is(getterChange)); assertThat(size.getMaximalSize(), is(getterMaximum)); verify(methodVisitor).visitFieldInsn(getterOpcode, FOO, BAR, QUX); verifyNoMoreInteractions(methodVisitor); } @Test public void testPutter() throws Exception { FieldAccess.Defined setter = FieldAccess.forField(fieldDescription); assertThat(setter.write().isValid(), is(true)); StackManipulation.Size size = setter.write().apply(methodVisitor, implementationContext); assertThat(size.getSizeImpact(), is(putterChange)); assertThat(size.getMaximalSize(), is(putterMaximum)); verify(methodVisitor).visitFieldInsn(putterOpcode, FOO, BAR, QUX); verifyNoMoreInteractions(methodVisitor); } }