package net.bytebuddy.dynamic.scaffold;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.annotation.AnnotationList;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.attribute.AnnotationValueFilter;
import net.bytebuddy.implementation.attribute.FieldAttributeAppender;
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 org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import java.lang.annotation.RetentionPolicy;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;
public class TypeWriterFieldPoolRecordTest {
private static final int MODIFIER = 42;
private static final String FOO = "foo", BAR = "bar", QUX = "qux", BAZ = "baz";
@Rule
public TestRule mockitoRule = new MockitoRule(this);
@Mock
private FieldAttributeAppender fieldAttributeAppender;
@Mock
private AnnotationValueFilter valueFilter;
@Mock
private AnnotationValueFilter.Factory annotationValueFilterFactory;
@Mock
private ClassVisitor classVisitor;
@Mock
private FieldVisitor fieldVisitor;
@Mock
private AnnotationVisitor annotationVisitor;
@Mock
private FieldDescription fieldDescription;
@Mock
private AnnotationDescription annotationDescription;
@Mock
private TypeDescription annotationType;
@Mock
private Object defaultValue;
@Before
@SuppressWarnings("unchecked")
public void setUp() throws Exception {
when(fieldDescription.getActualModifiers()).thenReturn(MODIFIER);
when(fieldDescription.getInternalName()).thenReturn(FOO);
when(fieldDescription.getDescriptor()).thenReturn(BAR);
when(fieldDescription.getGenericSignature()).thenReturn(QUX);
when(fieldDescription.getDeclaredAnnotations()).thenReturn(new AnnotationList.Explicit(annotationDescription));
when(fieldDescription.getType()).thenReturn(TypeDescription.Generic.OBJECT);
when(classVisitor.visitField(MODIFIER, FOO, BAR, QUX, defaultValue)).thenReturn(fieldVisitor);
when(classVisitor.visitField(MODIFIER, FOO, BAR, QUX, FieldDescription.NO_DEFAULT_VALUE)).thenReturn(fieldVisitor);
when(annotationValueFilterFactory.on(fieldDescription)).thenReturn(valueFilter);
when(fieldVisitor.visitAnnotation(any(String.class), anyBoolean())).thenReturn(annotationVisitor);
when(annotationDescription.getAnnotationType()).thenReturn(annotationType);
when(annotationType.getDescriptor()).thenReturn(BAZ);
when(annotationType.getDeclaredMethods()).thenReturn(new MethodList.Empty<MethodDescription.InDefinedShape>());
when(annotationDescription.getRetention()).thenReturn(RetentionPolicy.RUNTIME);
}
@Test
public void testExplicitFieldEntryProperties() throws Exception {
TypeWriter.FieldPool.Record record = new TypeWriter.FieldPool.Record.ForExplicitField(fieldAttributeAppender, defaultValue, fieldDescription);
assertThat(record.getFieldAppender(), is(fieldAttributeAppender));
assertThat(record.resolveDefault(FieldDescription.NO_DEFAULT_VALUE), is(defaultValue));
assertThat(record.isImplicit(), is(false));
}
@Test
public void testExplicitFieldEntryWritesField() throws Exception {
TypeWriter.FieldPool.Record record = new TypeWriter.FieldPool.Record.ForExplicitField(fieldAttributeAppender, defaultValue, fieldDescription);
record.apply(classVisitor, annotationValueFilterFactory);
verify(classVisitor).visitField(MODIFIER, FOO, BAR, QUX, defaultValue);
verifyNoMoreInteractions(classVisitor);
verify(fieldAttributeAppender).apply(fieldVisitor, fieldDescription, valueFilter);
verifyNoMoreInteractions(fieldAttributeAppender);
verify(fieldVisitor).visitEnd();
verifyNoMoreInteractions(fieldVisitor);
}
@Test
public void testExplicitFieldEntryWritesFieldPartialApplication() throws Exception {
TypeWriter.FieldPool.Record record = new TypeWriter.FieldPool.Record.ForExplicitField(fieldAttributeAppender, defaultValue, fieldDescription);
record.apply(fieldVisitor, annotationValueFilterFactory);
verify(fieldAttributeAppender).apply(fieldVisitor, fieldDescription, valueFilter);
verifyNoMoreInteractions(fieldAttributeAppender);
verifyZeroInteractions(fieldVisitor);
}
@Test
public void testImplicitFieldEntryProperties() throws Exception {
TypeWriter.FieldPool.Record record = new TypeWriter.FieldPool.Record.ForImplicitField(fieldDescription);
assertThat(record.isImplicit(), is(true));
}
@Test
public void testImplicitFieldEntryWritesField() throws Exception {
TypeWriter.FieldPool.Record record = new TypeWriter.FieldPool.Record.ForImplicitField(fieldDescription);
record.apply(classVisitor, annotationValueFilterFactory);
verify(classVisitor).visitField(MODIFIER, FOO, BAR, QUX, FieldDescription.NO_DEFAULT_VALUE);
verifyNoMoreInteractions(classVisitor);
verify(fieldVisitor).visitAnnotation(BAZ, true);
verify(fieldVisitor).visitEnd();
verifyNoMoreInteractions(fieldVisitor);
verify(annotationVisitor).visitEnd();
verifyNoMoreInteractions(annotationVisitor);
}
@Test(expected = IllegalStateException.class)
public void testImplicitFieldWritesFieldPartialApplication() throws Exception {
new TypeWriter.FieldPool.Record.ForImplicitField(fieldDescription).apply(fieldVisitor, annotationValueFilterFactory);
}
@Test(expected = IllegalStateException.class)
public void testImplicitFieldEntryAppliedToField() throws Exception {
new TypeWriter.FieldPool.Record.ForImplicitField(fieldDescription).apply(fieldVisitor, annotationValueFilterFactory);
}
@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(TypeWriter.FieldPool.Record.ForImplicitField.class).apply();
ObjectPropertyAssertion.of(TypeWriter.FieldPool.Record.ForExplicitField.class).apply();
}
}