package net.bytebuddy.implementation.bind.annotation;
import net.bytebuddy.description.annotation.AnnotationList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bind.MethodDelegationBinder;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.test.utility.ObjectPropertyAssertion;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;
public class ThisBinderTest extends AbstractAnnotationBinderTest<This> {
@Mock
private TypeDescription.Generic parameterType, genericInstrumentedType;
public ThisBinderTest() {
super(This.class);
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
when(stackManipulation.isValid()).thenReturn(true);
when(instrumentedType.asGenericType()).thenReturn(genericInstrumentedType);
}
@Override
protected TargetMethodAnnotationDrivenBinder.ParameterBinder<This> getSimpleBinder() {
return This.Binder.INSTANCE;
}
@Test
public void testLegalBinding() throws Exception {
when(stackManipulation.isValid()).thenReturn(true);
when(target.getType()).thenReturn(parameterType);
when(target.getDeclaredAnnotations()).thenReturn(new AnnotationList.Empty());
MethodDelegationBinder.ParameterBinding<?> parameterBinding = This.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(true));
verify(assigner).assign(genericInstrumentedType, parameterType, Assigner.Typing.STATIC);
verifyNoMoreInteractions(assigner);
verify(target, atLeast(1)).getType();
verify(target, never()).getDeclaredAnnotations();
}
@Test
public void testLegalBindingRuntimeType() throws Exception {
when(stackManipulation.isValid()).thenReturn(true);
when(target.getType()).thenReturn(parameterType);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = This.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.DYNAMIC);
assertThat(parameterBinding.isValid(), is(true));
verify(assigner).assign(genericInstrumentedType, parameterType, Assigner.Typing.DYNAMIC);
verifyNoMoreInteractions(assigner);
verify(target, atLeast(1)).getType();
verify(target, never()).getDeclaredAnnotations();
}
@Test
public void testIllegalBinding() throws Exception {
when(stackManipulation.isValid()).thenReturn(false);
when(target.getType()).thenReturn(parameterType);
when(target.getDeclaredAnnotations()).thenReturn(new AnnotationList.Empty());
when(assigner.assign(any(TypeDescription.Generic.class), any(TypeDescription.Generic.class), any(Assigner.Typing.class)))
.thenReturn(StackManipulation.Illegal.INSTANCE);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = This.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(false));
verify(assigner).assign(genericInstrumentedType, parameterType, Assigner.Typing.STATIC);
verifyNoMoreInteractions(assigner);
verify(target, atLeast(1)).getType();
verify(target, never()).getDeclaredAnnotations();
}
@Test
public void testOptionalBinding() throws Exception {
when(stackManipulation.isValid()).thenReturn(true);
when(annotation.optional()).thenReturn(true);
when(source.isStatic()).thenReturn(true);
when(target.getType()).thenReturn(parameterType);
when(target.getDeclaredAnnotations()).thenReturn(new AnnotationList.Empty());
MethodDelegationBinder.ParameterBinding<?> parameterBinding = This.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(true));
verify(annotation).optional();
verify(source, atLeast(1)).isStatic();
verifyZeroInteractions(assigner);
}
@Test
public void testStaticMethodIllegal() throws Exception {
when(target.getType()).thenReturn(parameterType);
when(source.isStatic()).thenReturn(true);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = This.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(false));
}
@Test(expected = IllegalStateException.class)
public void testPrimitiveType() throws Exception {
when(parameterType.isPrimitive()).thenReturn(true);
when(target.getType()).thenReturn(parameterType);
This.Binder.INSTANCE.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
}
@Test(expected = IllegalStateException.class)
public void testArrayType() throws Exception {
when(parameterType.isArray()).thenReturn(true);
when(target.getType()).thenReturn(parameterType);
This.Binder.INSTANCE.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
}
@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(This.Binder.class).apply();
}
}