package net.bytebuddy.description.type;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.FixedValue;
import org.junit.Test;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
public class GenericSignatureResolutionTest {
private static final String FOO = "foo", BAR = "bar";
@Test
public void testGenericType() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(GenericType.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(GenericType.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), is(originalType.getSuperClass()));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
@Test
public void testGenericField() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(GenericField.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
FieldDescription createdField = new FieldDescription.ForLoadedField(type.getDeclaredField(FOO));
FieldDescription originalField = new FieldDescription.ForLoadedField(GenericField.class.getDeclaredField(FOO));
assertThat(createdField.getType(), is(originalField.getType()));
}
@Test
public void testGenericMethod() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(GenericMethod.class)
.method(named(FOO))
.intercept(FixedValue.nullValue())
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
MethodDescription createdMethod = new MethodDescription.ForLoadedMethod(type.getDeclaredMethod(FOO, Exception.class));
MethodDescription originalMethod = new MethodDescription.ForLoadedMethod(GenericMethod.class.getDeclaredMethod(FOO, Exception.class));
assertThat(createdMethod.getTypeVariables(), is(originalMethod.getTypeVariables()));
assertThat(createdMethod.getReturnType(), is(originalMethod.getReturnType()));
assertThat(createdMethod.getParameters().getOnly().getType(), is(originalMethod.getParameters().getOnly().getType()));
assertThat(createdMethod.getExceptionTypes().getOnly(), is(originalMethod.getExceptionTypes().getOnly()));
}
@Test
public void testGenericMethodWithoutGenericExceptionTypes() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(GenericMethod.class)
.method(named(BAR))
.intercept(FixedValue.nullValue())
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
MethodDescription createdMethod = new MethodDescription.ForLoadedMethod(type.getDeclaredMethod(BAR, Object.class));
MethodDescription originalMethod = new MethodDescription.ForLoadedMethod(GenericMethod.class.getDeclaredMethod(BAR, Object.class));
assertThat(createdMethod.getTypeVariables(), is(originalMethod.getTypeVariables()));
assertThat(createdMethod.getReturnType(), is(originalMethod.getReturnType()));
assertThat(createdMethod.getParameters().getOnly().getType(), is(originalMethod.getParameters().getOnly().getType()));
assertThat(createdMethod.getExceptionTypes().getOnly(), is(originalMethod.getExceptionTypes().getOnly()));
}
@Test
public void testNoSuperClass() throws Exception {
assertThat(new ByteBuddy().redefine(Object.class).make(), notNullValue(DynamicType.class));
}
@Test
public void testTypeVariableClassBound() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(TypeVariableClassBound.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(TypeVariableClassBound.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), is(originalType.getSuperClass()));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
@Test
public void testTypeVariableInterfaceBound() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(TypeVariableInterfaceBound.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(TypeVariableInterfaceBound.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), is(originalType.getSuperClass()));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
@Test
public void testTypeVariableClassAndInterfaceBound() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(TypeVariableClassAndInterfaceBound.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(TypeVariableClassAndInterfaceBound.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), is(originalType.getSuperClass()));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
@Test
public void testTypeVariableWildcardNoBound() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(TypeVariableWildcardNoBound.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(TypeVariableWildcardNoBound.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), is(originalType.getSuperClass()));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
@Test
public void testTypeVariableWildcardUpperClassBound() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(TypeVariableWildcardUpperClassBound.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(TypeVariableWildcardUpperClassBound.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), is(originalType.getSuperClass()));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
@Test
public void testTypeVariableWildcardUpperInterfaceBound() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(TypeVariableWildcardUpperInterfaceBound.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(TypeVariableWildcardUpperInterfaceBound.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), is(originalType.getSuperClass()));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
@Test
public void testTypeVariableWildcardLowerClassBound() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(TypeVariableWildcardLowerClassBound.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(TypeVariableWildcardLowerClassBound.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), is(originalType.getSuperClass()));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
@Test
public void testTypeVariableWildcardLowerInterfaceBound() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(TypeVariableWildcardLowerInterfaceBound.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(TypeVariableWildcardLowerInterfaceBound.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), is(originalType.getSuperClass()));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
@Test
public void testInterfaceType() throws Exception {
DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(InterfaceType.class)
.make();
Class<?> type = unloaded.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
TypeDescription createdType = new TypeDescription.ForLoadedType(type);
TypeDescription originalType = new TypeDescription.ForLoadedType(InterfaceType.class);
assertThat(createdType.getTypeVariables(), is(originalType.getTypeVariables()));
assertThat(createdType.getSuperClass(), nullValue(TypeDescription.Generic.class));
assertThat(createdType.getInterfaces(), is(originalType.getInterfaces()));
}
public abstract static class GenericType<T extends ArrayList<T> & Callable<T>,
S extends Callable<?>,
U extends Callable<? extends Callable<U>>,
V extends ArrayList<? super ArrayList<V>>,
W extends Callable<W[]>> extends ArrayList<T> implements Callable<T> {
}
@SuppressWarnings("unused")
public static class GenericMethod {
<T extends Exception & Callable<T>> T foo(T arg) throws T {
return null;
}
<T> T bar(T arg) throws Exception {
return null;
}
}
public static class GenericField<T> {
T foo;
}
public static class TypeVariableClassBound<T extends ArrayList<T>> {
/* empty */
}
public abstract static class TypeVariableInterfaceBound<T extends Callable<T>> {
/* empty */
}
public abstract static class TypeVariableClassAndInterfaceBound<T extends ArrayList<T> & Callable<T>> {
/* empty */
}
public static class TypeVariableWildcardNoBound<T extends ArrayList<?>> {
/* empty */
}
public static class TypeVariableWildcardUpperClassBound<T extends ArrayList<? extends ArrayList<T>>> {
/* empty */
}
public static class TypeVariableWildcardUpperInterfaceBound<T extends ArrayList<? extends Callable<T>>> {
/* empty */
}
public static class TypeVariableWildcardLowerClassBound<T extends ArrayList<? super ArrayList<T>>> {
/* empty */
}
public static class TypeVariableWildcardLowerInterfaceBound<T extends ArrayList<? super Callable<T>>> {
/* empty */
}
public interface InterfaceType<T> extends Callable<T> {
/* empty */
}
}