package net.bytebuddy.implementation.bind.annotation;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.ParameterDescription;
import net.bytebuddy.description.method.ParameterList;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bind.MethodDelegationBinder;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.test.utility.JavaVersionRule;
import net.bytebuddy.test.utility.ObjectPropertyAssertion;
import net.bytebuddy.utility.JavaType;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.mockito.Mock;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;
public class OriginBinderTest extends AbstractAnnotationBinderTest<Origin> {
private static final String FOO = "foo";
@Rule
public MethodRule javaVersionRule = new JavaVersionRule();
@Mock
private TypeDescription targetType;
@Mock
private TypeDescription.Generic genericTargetType;
@Mock
private MethodDescription.InDefinedShape methodDescription;
public OriginBinderTest() {
super(Origin.class);
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
when(target.getType()).thenReturn(genericTargetType);
when(targetType.asErasure()).thenReturn(targetType);
when(genericTargetType.asErasure()).thenReturn(targetType);
when(source.asDefined()).thenReturn(methodDescription);
}
@Override
protected TargetMethodAnnotationDrivenBinder.ParameterBinder<Origin> getSimpleBinder() {
return Origin.Binder.INSTANCE;
}
@Test
public void testClassBinding() throws Exception {
when(targetType.getInternalName()).thenReturn(FOO);
when(targetType.represents(Class.class)).thenReturn(true);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(true));
verify(implementationTarget).getOriginType();
}
@Test
public void testMethodBinding() throws Exception {
when(targetType.getInternalName()).thenReturn(FOO);
when(targetType.represents(Method.class)).thenReturn(true);
when(source.isMethod()).thenReturn(true);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(true));
}
@Test
public void testMethodBindingForNonMethod() throws Exception {
when(targetType.getInternalName()).thenReturn(FOO);
when(targetType.represents(Method.class)).thenReturn(true);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(false));
}
@Test
public void testConstructorBinding() throws Exception {
when(targetType.getInternalName()).thenReturn(FOO);
when(targetType.represents(Constructor.class)).thenReturn(true);
when(source.isConstructor()).thenReturn(true);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(true));
}
@Test
public void testConstructorBindingForNonConstructor() throws Exception {
when(targetType.getInternalName()).thenReturn(FOO);
when(targetType.represents(Constructor.class)).thenReturn(true);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(false));
}
@Test
public void testStringBinding() throws Exception {
when(targetType.getInternalName()).thenReturn(FOO);
when(targetType.represents(String.class)).thenReturn(true);
when(targetType.getSort()).thenReturn(TypeDefinition.Sort.NON_GENERIC);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(true));
}
@Test
public void testModifierBinding() throws Exception {
when(targetType.getInternalName()).thenReturn(FOO);
when(targetType.represents(int.class)).thenReturn(true);
when(targetType.getSort()).thenReturn(TypeDefinition.Sort.NON_GENERIC);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(true));
}
@Test
@JavaVersionRule.Enforce(7)
public void testMethodHandleBinding() throws Exception {
when(genericTargetType.asErasure()).thenReturn(new TypeDescription.ForLoadedType(JavaType.METHOD_HANDLE.load()));
when(methodDescription.getReturnType()).thenReturn(TypeDescription.Generic.VOID);
when(methodDescription.getParameters()).thenReturn(new ParameterList.Empty<ParameterDescription.InDefinedShape>());
TypeDescription typeDescription = mock(TypeDescription.class);
when(typeDescription.asErasure()).thenReturn(typeDescription);
when(methodDescription.getDeclaringType()).thenReturn(typeDescription);
MethodDelegationBinder.ParameterBinding<?> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(true));
}
@Test
@JavaVersionRule.Enforce(7)
public void testMethodTypeBinding() throws Exception {
when(genericTargetType.asErasure()).thenReturn(new TypeDescription.ForLoadedType(JavaType.METHOD_TYPE.load()));
when(methodDescription.getReturnType()).thenReturn(TypeDescription.Generic.VOID);
when(methodDescription.getParameters()).thenReturn(new ParameterList.Empty<ParameterDescription.InDefinedShape>());
MethodDelegationBinder.ParameterBinding<?> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
assertThat(parameterBinding.isValid(), is(true));
}
@Test(expected = IllegalStateException.class)
public void testIllegalBinding() throws Exception {
when(targetType.getInternalName()).thenReturn(FOO);
when(targetType.getSort()).thenReturn(TypeDefinition.Sort.NON_GENERIC);
Origin.Binder.INSTANCE.bind(annotationDescription, source, target, implementationTarget, assigner, Assigner.Typing.STATIC);
}
@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(Origin.Binder.class).apply();
}
}