package net.bytebuddy.description.field; import net.bytebuddy.description.annotation.AnnotationList; import net.bytebuddy.description.type.TypeDefinition; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.test.packaging.VisibilityFieldTestHelper; import org.junit.Before; import org.junit.Test; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.List; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public abstract class AbstractFieldDescriptionTest { private Field first, second, genericField; protected abstract FieldDescription.InDefinedShape describe(Field field); @Before public void setUp() throws Exception { first = FirstSample.class.getDeclaredField("first"); second = SecondSample.class.getDeclaredField("second"); genericField = GenericField.class.getDeclaredField("foo"); } @Test public void testPrecondition() throws Exception { assertThat(describe(first), not(describe(second))); assertThat(describe(first), is(describe(first))); assertThat(describe(second), is(describe(second))); assertThat(describe(first), is((FieldDescription) new FieldDescription.ForLoadedField(first))); assertThat(describe(second), is((FieldDescription) new FieldDescription.ForLoadedField(second))); } @Test public void testFieldType() throws Exception { assertThat(describe(first).getType(), is((TypeDefinition) new TypeDescription.ForLoadedType(first.getType()))); assertThat(describe(second).getType(), is((TypeDefinition) new TypeDescription.ForLoadedType(second.getType()))); } @Test public void testFieldName() throws Exception { assertThat(describe(first).getName(), is(first.getName())); assertThat(describe(second).getName(), is(second.getName())); assertThat(describe(first).getInternalName(), is(first.getName())); assertThat(describe(second).getInternalName(), is(second.getName())); } @Test public void testDescriptor() throws Exception { assertThat(describe(first).getDescriptor(), is(Type.getDescriptor(first.getType()))); assertThat(describe(second).getDescriptor(), is(Type.getDescriptor(second.getType()))); } @Test public void testFieldModifier() throws Exception { assertThat(describe(first).getModifiers(), is(first.getModifiers())); assertThat(describe(second).getModifiers(), is(second.getModifiers())); } @Test public void testFieldDeclaringType() throws Exception { assertThat(describe(first).getDeclaringType(), is((TypeDescription) new TypeDescription.ForLoadedType(first.getDeclaringClass()))); assertThat(describe(second).getDeclaringType(), is((TypeDescription) new TypeDescription.ForLoadedType(second.getDeclaringClass()))); } @Test public void testHashCode() throws Exception { assertThat(describe(first).hashCode(), is(new TypeDescription.ForLoadedType(FirstSample.class).hashCode() + 31 * first.getName().hashCode())); assertThat(describe(second).hashCode(), is(new TypeDescription.ForLoadedType(SecondSample.class).hashCode() + 31 * second.getName().hashCode())); assertThat(describe(first).hashCode(), is(describe(first).hashCode())); assertThat(describe(second).hashCode(), is(describe(second).hashCode())); assertThat(describe(first).hashCode(), not(describe(second).hashCode())); } @Test public void testEquals() throws Exception { FieldDescription identical = describe(first); assertThat(identical, is(identical)); FieldDescription equalFirst = mock(FieldDescription.class); when(equalFirst.getName()).thenReturn(first.getName()); when(equalFirst.getDeclaringType()).thenReturn(new TypeDescription.ForLoadedType(FirstSample.class)); assertThat(describe(first), is(equalFirst)); FieldDescription equalSecond = mock(FieldDescription.class); when(equalSecond.getName()).thenReturn(second.getName()); when(equalSecond.getDeclaringType()).thenReturn(new TypeDescription.ForLoadedType(SecondSample.class)); assertThat(describe(second), is(equalSecond)); FieldDescription equalFirstTypeOnly = mock(FieldDescription.class); when(equalFirstTypeOnly.getName()).thenReturn(second.getName()); when(equalFirstTypeOnly.getDeclaringType()).thenReturn(new TypeDescription.ForLoadedType(FirstSample.class)); assertThat(describe(first), not(equalFirstTypeOnly)); FieldDescription equalFirstNameOnly = mock(FieldDescription.class); when(equalFirstNameOnly.getName()).thenReturn(first.getName()); when(equalFirstNameOnly.getDeclaringType()).thenReturn(new TypeDescription.ForLoadedType(SecondSample.class)); assertThat(describe(first), not(equalFirstNameOnly)); assertThat(describe(first), not(equalSecond)); assertThat(describe(first), not(new Object())); assertThat(describe(first), not(equalTo(null))); } @Test public void testToString() throws Exception { assertThat(describe(first).toString(), is(first.toString())); assertThat(describe(second).toString(), is(second.toString())); } @Test public void testSynthetic() throws Exception { assertThat(describe(first).isSynthetic(), is(first.isSynthetic())); assertThat(describe(second).isSynthetic(), is(second.isSynthetic())); } @Test public void testTransient() throws Exception { assertThat(describe(first).isTransient(), is(Modifier.isTransient(first.getModifiers()))); assertThat(describe(TransientSample.class.getDeclaredField("foo")).isTransient(), is(Modifier.isTransient(TransientSample.class.getDeclaredField("foo").getModifiers()))); } @Test public void testIsVisibleTo() throws Exception { assertThat(describe(PublicType.class.getDeclaredField("publicField")) .isVisibleTo(new TypeDescription.ForLoadedType(PublicType.class)), is(true)); assertThat(describe(PublicType.class.getDeclaredField("protectedField")) .isVisibleTo(new TypeDescription.ForLoadedType(PublicType.class)), is(true)); assertThat(describe(PublicType.class.getDeclaredField("packagePrivateField")) .isVisibleTo(new TypeDescription.ForLoadedType(PublicType.class)), is(true)); assertThat(describe(PublicType.class.getDeclaredField("privateField")) .isVisibleTo(new TypeDescription.ForLoadedType(PublicType.class)), is(true)); assertThat(describe(PublicType.class.getDeclaredField("publicField")) .isVisibleTo(new TypeDescription.ForLoadedType(FirstSample.class)), is(true)); assertThat(describe(PublicType.class.getDeclaredField("protectedField")) .isVisibleTo(new TypeDescription.ForLoadedType(FirstSample.class)), is(true)); assertThat(describe(PublicType.class.getDeclaredField("packagePrivateField")) .isVisibleTo(new TypeDescription.ForLoadedType(FirstSample.class)), is(true)); assertThat(describe(PublicType.class.getDeclaredField("privateField")) .isVisibleTo(new TypeDescription.ForLoadedType(FirstSample.class)), is(false)); assertThat(describe(PublicType.class.getDeclaredField("publicField")) .isVisibleTo(TypeDescription.OBJECT), is(true)); assertThat(describe(PublicType.class.getDeclaredField("protectedField")) .isVisibleTo(TypeDescription.OBJECT), is(false)); assertThat(describe(PublicType.class.getDeclaredField("packagePrivateField")) .isVisibleTo(TypeDescription.OBJECT), is(false)); assertThat(describe(PublicType.class.getDeclaredField("privateField")) .isVisibleTo(TypeDescription.OBJECT), is(false)); assertThat(describe(PublicType.class.getDeclaredField("publicField")) .isVisibleTo(new TypeDescription.ForLoadedType(VisibilityFieldTestHelper.class)), is(true)); assertThat(describe(PublicType.class.getDeclaredField("protectedField")) .isVisibleTo(new TypeDescription.ForLoadedType(VisibilityFieldTestHelper.class)), is(true)); assertThat(describe(PublicType.class.getDeclaredField("packagePrivateField")) .isVisibleTo(new TypeDescription.ForLoadedType(VisibilityFieldTestHelper.class)), is(false)); assertThat(describe(PublicType.class.getDeclaredField("privateField")) .isVisibleTo(new TypeDescription.ForLoadedType(VisibilityFieldTestHelper.class)), is(false)); assertThat(describe(PackagePrivateType.class.getDeclaredField("publicField")) .isVisibleTo(TypeDescription.OBJECT), is(false)); assertThat(describe(PackagePrivateType.class.getDeclaredField("protectedField")) .isVisibleTo(TypeDescription.OBJECT), is(false)); assertThat(describe(PackagePrivateType.class.getDeclaredField("packagePrivateField")) .isVisibleTo(TypeDescription.OBJECT), is(false)); assertThat(describe(PackagePrivateType.class.getDeclaredField("privateField")) .isVisibleTo(TypeDescription.OBJECT), is(false)); assertThat(describe(PackagePrivateFieldType.class.getDeclaredField("packagePrivateType")) .isVisibleTo(new TypeDescription.ForLoadedType(PackagePrivateFieldType.class)), is(true)); assertThat(describe(PackagePrivateFieldType.class.getDeclaredField("packagePrivateType")) .isVisibleTo(TypeDescription.OBJECT), is(true)); } @Test public void testAnnotations() throws Exception { assertThat(describe(first).getDeclaredAnnotations(), is((AnnotationList) new AnnotationList.Empty())); assertThat(describe(second).getDeclaredAnnotations(), is((AnnotationList) new AnnotationList.ForLoadedAnnotations(second.getDeclaredAnnotations()))); } @Test public void testGenericTypes() throws Exception { assertThat(describe(genericField).getType(), is(TypeDefinition.Sort.describe(genericField.getGenericType()))); assertThat(describe(genericField).getType().asErasure(), is((TypeDescription) new TypeDescription.ForLoadedType(genericField.getType()))); } @Test public void testToGenericString() throws Exception { assertThat(describe(genericField).toGenericString(), is(genericField.toGenericString())); } @Test public void testGetActualModifiers() throws Exception { assertThat(describe(first).getActualModifiers(), is(first.getModifiers())); assertThat(describe(DeprecationSample.class.getDeclaredField("foo")).getActualModifiers(), is(Opcodes.ACC_DEPRECATED | Opcodes.ACC_PRIVATE)); } @Test public void testSyntheticField() throws Exception { assertThat(describe(SyntheticField.class.getDeclaredFields()[0]).getModifiers(), is(SyntheticField.class.getDeclaredFields()[0].getModifiers())); assertThat(describe(SyntheticField.class.getDeclaredFields()[0]).isSynthetic(), is(SyntheticField.class.getDeclaredFields()[0].isSynthetic())); } @Retention(RetentionPolicy.RUNTIME) private @interface SampleAnnotation { } @SuppressWarnings("unused") protected static class FirstSample { private Void first; } @SuppressWarnings("unused") protected static class SecondSample { @SampleAnnotation int second; } @SuppressWarnings("unused") public static class PublicType { public Void publicField; protected Void protectedField; Void packagePrivateField; private Void privateField; } @SuppressWarnings("unused") static class PackagePrivateType { public Void publicField; protected Void protectedField; Void packagePrivateField; private Void privateField; } @SuppressWarnings("unused") static class GenericField { List<String> foo; } public static class PackagePrivateFieldType { public PackagePrivateType packagePrivateType; } private static class DeprecationSample { @Deprecated private Void foo; } private class SyntheticField { /* empty */ } private static class TransientSample { public transient Void foo; } }