package net.bytebuddy.dynamic; import net.bytebuddy.description.annotation.AnnotationDescription; import net.bytebuddy.description.annotation.AnnotationList; import net.bytebuddy.description.field.FieldDescription; import net.bytebuddy.description.modifier.ModifierContributor; import net.bytebuddy.description.type.TypeDefinition; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.test.utility.MockitoRule; import net.bytebuddy.test.utility.ObjectPropertyAssertion; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.mockito.Mock; import java.util.Collections; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.none; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.*; public class TransformerForFieldTest { private static final String FOO = "foo", BAR = "bar"; private static final int MODIFIERS = 42, RANGE = 3, MASK = 1; @Rule public TestRule mocktioRule = new MockitoRule(this); @Mock private TypeDescription instrumentedType, rawDeclaringType, rawReturnType, rawParameterType; @Mock private Transformer<FieldDescription.Token> tokenTransformer; @Mock private FieldDescription fieldDescription; @Mock private FieldDescription.InDefinedShape definedField; @Mock private FieldDescription.Token fieldToken; @Mock private TypeDescription.Generic fieldType, declaringType; @Mock private AnnotationDescription fieldAnnotation; @Mock private ModifierContributor.ForField modifierContributor; @Before @SuppressWarnings("unchecked") public void setUp() throws Exception { when(fieldType.accept(any(TypeDescription.Generic.Visitor.class))).thenReturn(fieldType); when(fieldDescription.asToken(none())).thenReturn(fieldToken); when(fieldDescription.getDeclaringType()).thenReturn(declaringType); when(fieldDescription.asDefined()).thenReturn(definedField); when(fieldToken.getName()).thenReturn(FOO); when(fieldToken.getModifiers()).thenReturn(MODIFIERS); when(fieldToken.getType()).thenReturn(fieldType); when(fieldToken.getAnnotations()).thenReturn(new AnnotationList.Explicit(fieldAnnotation)); when(modifierContributor.getMask()).thenReturn(MASK); when(modifierContributor.getRange()).thenReturn(RANGE); } @Test public void testSimpleTransformation() throws Exception { when(tokenTransformer.transform(instrumentedType, fieldToken)).thenReturn(fieldToken); FieldDescription transformed = new Transformer.ForField(tokenTransformer).transform(instrumentedType, fieldDescription); assertThat(transformed.getDeclaringType(), is((TypeDefinition) declaringType)); assertThat(transformed.getInternalName(), is(FOO)); assertThat(transformed.getModifiers(), is(MODIFIERS)); assertThat(transformed.getDeclaredAnnotations(), is(Collections.singletonList(fieldAnnotation))); assertThat(transformed.getType(), is(fieldType)); assertThat(transformed.asDefined(), is(definedField)); } @Test public void testModifierTransformation() throws Exception { FieldDescription.Token transformed = new Transformer.ForField.FieldModifierTransformer(ModifierContributor.Resolver.of(modifierContributor)) .transform(instrumentedType, fieldToken); assertThat(transformed.getName(), is(FOO)); assertThat(transformed.getModifiers(), is((MODIFIERS & ~RANGE) | MASK)); assertThat(transformed.getType(), is(fieldType)); } @Test public void testNoChangesUnlessSpecified() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(Bar.class); FieldDescription fieldDescription = typeDescription.getSuperClass().getDeclaredFields().filter(named(FOO)).getOnly(); FieldDescription transformed = Transformer.ForField.withModifiers().transform(typeDescription, fieldDescription); assertThat(transformed, is(fieldDescription)); assertThat(transformed.getModifiers(), is(fieldDescription.getModifiers())); } @Test public void testRetainsInstrumentedType() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(Bar.class); FieldDescription fieldDescription = typeDescription.getSuperClass().getDeclaredFields().filter(named(BAR)).getOnly(); FieldDescription transformed = Transformer.ForField.withModifiers().transform(typeDescription, fieldDescription); assertThat(transformed, is(fieldDescription)); assertThat(transformed.getModifiers(), is(fieldDescription.getModifiers())); assertThat(transformed.getType().asErasure(), is(typeDescription)); assertThat(transformed.getType().getSort(), is(TypeDefinition.Sort.PARAMETERIZED)); assertThat(transformed.getType().getTypeArguments().size(), is(1)); assertThat(transformed.getType().getTypeArguments().getOnly(), is(typeDescription.getSuperClass().getDeclaredFields().filter(named(FOO)).getOnly().getType())); } @Test public void testObjectProperties() throws Exception { ObjectPropertyAssertion.of(Transformer.ForField.class).apply(); ObjectPropertyAssertion.of(Transformer.ForField.FieldModifierTransformer.class).apply(); } private static class Foo<T> { T foo; Bar<T> bar; } private static class Bar<S> extends Foo<S> { /* empty */ } }