package net.bytebuddy.dynamic.scaffold.subclass;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.PackageDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.AbstractDynamicTypeBuilderTest;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.TargetType;
import net.bytebuddy.dynamic.loading.ByteArrayClassLoader;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.dynamic.loading.PackageDefinitionStrategy;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.StubMethod;
import net.bytebuddy.implementation.bytecode.constant.TextConstant;
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
import net.bytebuddy.test.scope.GenericType;
import net.bytebuddy.test.utility.ClassFileExtraction;
import net.bytebuddy.test.utility.JavaVersionRule;
import net.bytebuddy.test.utility.ObjectPropertyAssertion;
import org.hamcrest.CoreMatchers;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.objectweb.asm.Opcodes;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static junit.framework.TestCase.assertEquals;
import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
public class SubclassDynamicTypeBuilderTest extends AbstractDynamicTypeBuilderTest {
private static final String TYPE_VARIABLE_NAME = "net.bytebuddy.test.precompiled.TypeAnnotation", VALUE = "value";
private static final String FOO = "foo", BAR = "bar", QUX = "qux";
private static final int BAZ = 42;
private static final String DEFAULT_METHOD_INTERFACE = "net.bytebuddy.test.precompiled.SingleDefaultMethodInterface";
private static final String PARAMETER_NAME_CLASS = "net.bytebuddy.test.precompiled.ParameterNames";
private static final Object STATIC_FIELD = null;
private static final String INTERFACE_STATIC_FIELD_NAME = "FOO";
@Rule
public MethodRule javaVersionRule = new JavaVersionRule();
@Override
protected DynamicType.Builder<?> createPlain() {
return new ByteBuddy().subclass(Object.class);
}
@Override
protected DynamicType.Builder<?> createPlainWithoutValidation() {
return new ByteBuddy().with(TypeValidation.DISABLED).subclass(Object.class);
}
@Test
public void testSimpleSubclass() throws Exception {
Class<?> type = new ByteBuddy()
.subclass(Object.class)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethods().length, is(0));
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredConstructor(), notNullValue(Constructor.class));
assertThat(Object.class.isAssignableFrom(type), is(true));
assertThat(type, not(CoreMatchers.<Class<?>>is(Object.class)));
assertThat(type.getDeclaredConstructor().newInstance(), notNullValue(Object.class));
assertThat(type.isInterface(), is(false));
assertThat(type.isAnnotation(), is(false));
}
@Test
public void testSimpleSubclassWithoutConstructor() throws Exception {
Class<?> type = new ByteBuddy()
.subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethods().length, is(0));
assertThat(type.getDeclaredConstructors().length, is(0));
assertThat(Object.class.isAssignableFrom(type), is(true));
assertThat(type, not(CoreMatchers.<Class<?>>is(Object.class)));
assertThat(type.isInterface(), is(false));
assertThat(type.isAnnotation(), is(false));
}
@Test
public void testSimpleSubclassWithDefaultConstructor() throws Exception {
Class<? extends DefaultConstructor> type = new ByteBuddy()
.subclass(DefaultConstructor.class, ConstructorStrategy.Default.DEFAULT_CONSTRUCTOR)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethods().length, is(0));
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredConstructor(), notNullValue(Constructor.class));
assertThat(DefaultConstructor.class.isAssignableFrom(type), is(true));
assertThat(type, not(CoreMatchers.<Class<?>>is(DefaultConstructor.class)));
assertThat(type.getDeclaredConstructor().newInstance(), notNullValue(DefaultConstructor.class));
assertThat(type.isInterface(), is(false));
assertThat(type.isAnnotation(), is(false));
}
@Test(expected = IllegalArgumentException.class)
public void testNonExtendableIsIllegal() throws Exception {
new ByteBuddy().subclass(String.class);
}
@Test
public void testInterfaceDefinition() throws Exception {
Class<? extends SimpleInterface> type = new ByteBuddy()
.makeInterface(SimpleInterface.class)
.defineMethod(FOO, void.class, Visibility.PUBLIC).withParameters(Void.class)
.withoutCode()
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethods().length, is(1));
assertThat(type.getDeclaredMethod(FOO, Void.class), notNullValue(Method.class));
assertThat(type.getDeclaredConstructors().length, is(0));
assertThat(SimpleInterface.class.isAssignableFrom(type), is(true));
assertThat(type, not(CoreMatchers.<Class<?>>is(SimpleInterface.class)));
assertThat(type.isInterface(), is(true));
assertThat(type.isAnnotation(), is(false));
}
@Test
public void testAnnotationDefinition() throws Exception {
Class<? extends Annotation> type = new ByteBuddy()
.makeAnnotation()
.defineMethod(FOO, int.class, Visibility.PUBLIC)
.withoutCode()
.defineMethod(BAR, String.class, Visibility.PUBLIC)
.defaultValue(FOO, String.class)
.defineMethod(QUX, SimpleEnum.class, Visibility.PUBLIC)
.defaultValue(SimpleEnum.FIRST, SimpleEnum.class)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethods().length, is(3));
assertThat(type.getDeclaredMethod(FOO), notNullValue(Method.class));
assertThat(type.getDeclaredMethod(BAR).getDefaultValue(), is((Object) FOO));
assertThat(type.getDeclaredMethod(QUX).getDefaultValue(), is((Object) SimpleEnum.FIRST));
assertThat(type.getDeclaredConstructors().length, is(0));
assertThat(Annotation.class.isAssignableFrom(type), is(true));
assertThat(type, not(CoreMatchers.<Class<?>>is(Annotation.class)));
assertThat(type.isInterface(), is(true));
assertThat(type.isAnnotation(), is(true));
}
@Test
@SuppressWarnings("unchecked")
public void testEnumerationDefinition() throws Exception {
Class<? extends Enum<?>> type = new ByteBuddy()
.makeEnumeration(FOO, BAR)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethods().length, is(2));
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredFields().length, is(3));
assertThat(Enum.class.isAssignableFrom(type), is(true));
assertThat(type, not(CoreMatchers.<Class<?>>is(Enum.class)));
assertThat(type.isInterface(), is(false));
assertThat(type.isAnnotation(), is(false));
assertThat(type.isEnum(), is(true));
Enum foo = Enum.valueOf((Class) type, FOO);
assertThat(foo.name(), is(FOO));
assertThat(foo.ordinal(), is(0));
Enum bar = Enum.valueOf((Class) type, BAR);
assertThat(bar.name(), is(BAR));
assertThat(bar.ordinal(), is(1));
}
@Test
public void testPackageDefinition() throws Exception {
Class<?> packageType = new ByteBuddy()
.makePackage(FOO)
.annotateType(AnnotationDescription.Builder.ofType(Foo.class).build())
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
assertThat(packageType.getSimpleName(), is(PackageDescription.PACKAGE_CLASS_NAME));
assertThat(packageType.getName(), is(FOO + "." + PackageDescription.PACKAGE_CLASS_NAME));
assertThat(packageType.getModifiers(), is(PackageDescription.PACKAGE_MODIFIERS));
assertThat(packageType.getDeclaredFields().length, is(0));
assertThat(packageType.getDeclaredMethods().length, is(0));
assertThat(packageType.getDeclaredAnnotations().length, is(1));
assertThat(packageType.getAnnotation(Foo.class), notNullValue(Foo.class));
}
@Test
@JavaVersionRule.Enforce(8)
public void testDefaultMethodNonOverridden() throws Exception {
Class<?> interfaceType = Class.forName(DEFAULT_METHOD_INTERFACE);
Object interfaceMarker = interfaceType.getDeclaredField(INTERFACE_STATIC_FIELD_NAME).get(STATIC_FIELD);
Method interfaceMethod = interfaceType.getDeclaredMethod(FOO);
Class<?> dynamicType = new ByteBuddy()
.subclass(interfaceType)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(dynamicType.getDeclaredFields().length, is(0));
assertThat(dynamicType.getDeclaredMethods().length, is(0));
assertThat(interfaceMethod.invoke(dynamicType.getDeclaredConstructor().newInstance()), is(interfaceMarker));
}
@Test
@JavaVersionRule.Enforce(8)
public void testDefaultMethodOverridden() throws Exception {
Class<?> interfaceType = Class.forName(DEFAULT_METHOD_INTERFACE);
Method interfaceMethod = interfaceType.getDeclaredMethod(FOO);
Class<?> dynamicType = new ByteBuddy()
.subclass(interfaceType)
.method(isDeclaredBy(interfaceType)).intercept(FixedValue.value(BAR))
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(dynamicType.getDeclaredFields().length, is(0));
assertThat(dynamicType.getDeclaredMethods().length, is(1));
assertThat(interfaceMethod.invoke(dynamicType.getDeclaredConstructor().newInstance()), is((Object) BAR));
}
@Test
@JavaVersionRule.Enforce(8)
public void testParameterMetaDataSubclassForLoaded() throws Exception {
Class<?> dynamicType = new ByteBuddy()
.subclass(Class.forName(PARAMETER_NAME_CLASS))
.method(named(FOO)).intercept(StubMethod.INSTANCE)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(dynamicType.getDeclaredMethods().length, is(1));
Class<?> executable = Class.forName("java.lang.reflect.Executable");
Method getParameters = executable.getDeclaredMethod("getParameters");
Class<?> parameter = Class.forName("java.lang.reflect.Parameter");
Method getName = parameter.getDeclaredMethod("getName");
Method getModifiers = parameter.getDeclaredMethod("getModifiers");
Method first = dynamicType.getDeclaredMethod("foo", String.class, long.class, int.class);
Object[] methodParameter = (Object[]) getParameters.invoke(first);
assertThat(getName.invoke(methodParameter[0]), is((Object) "first"));
assertThat(getName.invoke(methodParameter[1]), is((Object) "second"));
assertThat(getName.invoke(methodParameter[2]), is((Object) "third"));
assertThat(getModifiers.invoke(methodParameter[0]), is((Object) Opcodes.ACC_FINAL));
assertThat(getModifiers.invoke(methodParameter[1]), is((Object) 0));
assertThat(getModifiers.invoke(methodParameter[2]), is((Object) 0));
}
@Test
@JavaVersionRule.Enforce(8)
public void testDefaultInterfaceSubInterface() throws Exception {
Class<?> interfaceType = Class.forName(DEFAULT_METHOD_INTERFACE);
Class<?> dynamicInterfaceType = new ByteBuddy()
.subclass(interfaceType)
.modifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT)
.method(named(FOO)).intercept(MethodDelegation.to(InterfaceOverrideInterceptor.class))
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Class<?> dynamicClassType = new ByteBuddy()
.subclass(dynamicInterfaceType)
.make()
.load(dynamicInterfaceType.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(dynamicClassType.getMethod(FOO).invoke(dynamicClassType.getDeclaredConstructor().newInstance()), is((Object) (FOO + BAR)));
assertThat(dynamicInterfaceType.getDeclaredMethods().length, is(2));
assertThat(dynamicClassType.getDeclaredMethods().length, is(0));
}
@Test
public void testDoesNotOverrideMethodWithPackagePrivateReturnType() throws Exception {
Class<?> type = new ByteBuddy()
.subclass(PackagePrivateReturnType.class)
.name("net.bytebuddy.test.generated." + FOO)
.method(isDeclaredBy(PackagePrivateReturnType.class))
.intercept(StubMethod.INSTANCE)
.make()
.load(new ByteArrayClassLoader(ClassLoadingStrategy.BOOTSTRAP_LOADER,
ClassFileExtraction.of(PackagePrivateReturnType.class, PackagePrivateReturnType.Argument.class)), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethods().length, is(0));
}
@Test
public void testDoesNotOverrideMethodWithPackagePrivateArgumentType() throws Exception {
Class<?> type = new ByteBuddy()
.subclass(PackagePrivateArgumentType.class)
.name("net.bytebuddy.test.generated." + FOO)
.method(isDeclaredBy(PackagePrivateArgumentType.class))
.intercept(StubMethod.INSTANCE)
.make()
.load(new ByteArrayClassLoader(ClassLoadingStrategy.BOOTSTRAP_LOADER,
ClassFileExtraction.of(PackagePrivateArgumentType.class, PackagePrivateArgumentType.Argument.class)), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethods().length, is(0));
}
@Test
public void testDoesNotOverridePrivateMethod() throws Exception {
Class<?> type = new ByteBuddy()
.subclass(PrivateMethod.class)
.method(isDeclaredBy(PrivateMethod.class))
.intercept(StubMethod.INSTANCE)
.make()
.load(new ByteArrayClassLoader(ClassLoadingStrategy.BOOTSTRAP_LOADER,
ClassFileExtraction.of(PrivateMethod.class)), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethods().length, is(0));
}
@Test
public void testGenericTypeRawExtension() throws Exception {
Class<?> dynamicType = new ByteBuddy()
.subclass(GenericType.Inner.class)
.method(named(FOO).or(named("call"))).intercept(StubMethod.INSTANCE)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
assertThat(dynamicType.getTypeParameters().length, is(0));
assertThat(dynamicType.getGenericSuperclass(), instanceOf(Class.class));
assertThat(dynamicType.getGenericSuperclass(), is((Type) GenericType.Inner.class));
assertThat(dynamicType.getGenericInterfaces().length, is(0));
Method foo = dynamicType.getDeclaredMethod(FOO, String.class);
assertThat(foo.getTypeParameters().length, is(0));
assertThat(foo.getGenericReturnType(), is((Object) List.class));
Method call = dynamicType.getDeclaredMethod("call");
assertThat(call.getGenericReturnType(), is((Object) Map.class));
}
@Test
@SuppressWarnings("unchecked")
public void testBridgeMethodCreation() throws Exception {
Class<?> dynamicType = new ByteBuddy()
.subclass(BridgeRetention.Inner.class)
.method(named(FOO)).intercept(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE))
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded();
assertEquals(String.class, dynamicType.getDeclaredMethod(FOO).getReturnType());
assertThat(dynamicType.getDeclaredMethod(FOO).getGenericReturnType(), is((Type) String.class));
BridgeRetention<String> bridgeRetention = (BridgeRetention<String>) dynamicType.getDeclaredConstructor().newInstance();
assertThat(bridgeRetention.foo(), is(FOO));
bridgeRetention.assertZeroCalls();
}
@Test
@SuppressWarnings("unchecked")
public void testBridgeMethodCreationForExistingBridgeMethod() throws Exception {
Class<?> dynamicType = new ByteBuddy()
.subclass(CallSuperMethod.Inner.class)
.method(named(FOO)).intercept(net.bytebuddy.implementation.SuperMethodCall.INSTANCE)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded();
assertThat(dynamicType.getDeclaredMethods().length, is(2));
assertEquals(String.class, dynamicType.getDeclaredMethod(FOO, String.class).getReturnType());
assertThat(dynamicType.getDeclaredMethod(FOO, String.class).getGenericReturnType(), is((Type) String.class));
assertThat(dynamicType.getDeclaredMethod(FOO, String.class).isBridge(), is(false));
assertEquals(Object.class, dynamicType.getDeclaredMethod(FOO, Object.class).getReturnType());
assertThat(dynamicType.getDeclaredMethod(FOO, Object.class).getGenericReturnType(), is((Type) Object.class));
assertThat(dynamicType.getDeclaredMethod(FOO, Object.class).isBridge(), is(true));
CallSuperMethod<String> callSuperMethod = (CallSuperMethod<String>) dynamicType.getDeclaredConstructor().newInstance();
assertThat(callSuperMethod.foo(FOO), is(FOO));
callSuperMethod.assertOnlyCall(FOO);
}
@Test
public void testBridgeMethodForAbstractMethod() throws Exception {
Class<?> dynamicType = new ByteBuddy()
.subclass(AbstractGenericType.Inner.class)
.modifiers(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC)
.method(named(FOO)).withoutCode()
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded();
assertThat(dynamicType.getDeclaredMethods().length, is(2));
assertEquals(Void.class, dynamicType.getDeclaredMethod(FOO, Void.class).getReturnType());
assertThat(dynamicType.getDeclaredMethod(FOO, Void.class).getGenericReturnType(), is((Type) Void.class));
assertThat(dynamicType.getDeclaredMethod(FOO, Void.class).isBridge(), is(false));
assertThat(Modifier.isAbstract(dynamicType.getDeclaredMethod(FOO, Void.class).getModifiers()), is(true));
assertEquals(Object.class, dynamicType.getDeclaredMethod(FOO, Object.class).getReturnType());
assertThat(dynamicType.getDeclaredMethod(FOO, Object.class).getGenericReturnType(), is((Type) Object.class));
assertThat(dynamicType.getDeclaredMethod(FOO, Object.class).isBridge(), is(true));
assertThat(Modifier.isAbstract(dynamicType.getDeclaredMethod(FOO, Object.class).getModifiers()), is(false));
}
@Test
public void testVisibilityBridge() throws Exception {
Class<?> type = new ByteBuddy()
.subclass(VisibilityBridge.class)
.modifiers(Visibility.PUBLIC)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(2));
Method foo = type.getDeclaredMethod(FOO, String.class);
assertThat(foo.isBridge(), is(true));
assertThat(foo.getDeclaredAnnotations().length, is(1));
assertThat(foo.getAnnotation(Foo.class), notNullValue(Foo.class));
assertThat(foo.invoke(type.getDeclaredConstructor().newInstance(), BAR), is((Object) (FOO + BAR)));
Method bar = type.getDeclaredMethod(BAR, List.class);
assertThat(bar.isBridge(), is(true));
assertThat(bar.getDeclaredAnnotations().length, is(0));
List<?> list = new ArrayList<Object>();
assertThat(bar.invoke(type.getDeclaredConstructor().newInstance(), list), sameInstance((Object) list));
assertThat(bar.getGenericReturnType(), instanceOf(Class.class));
assertThat(bar.getGenericParameterTypes()[0], instanceOf(Class.class));
assertThat(bar.getGenericExceptionTypes()[0], instanceOf(Class.class));
}
@Test
@JavaVersionRule.Enforce(8)
public void testVisibilityBridgeForDefaultMethod() throws Exception {
Class<?> defaultInterface = new ByteBuddy()
.makeInterface()
.merge(Visibility.PACKAGE_PRIVATE)
.defineMethod(FOO, String.class, Visibility.PUBLIC)
.intercept(FixedValue.value(BAR))
.make()
.load(ClassLoadingStrategy.BOOTSTRAP_LOADER)
.getLoaded();
Class<?> type = new ByteBuddy()
.subclass(defaultInterface)
.modifiers(Visibility.PUBLIC)
.make()
.load(defaultInterface.getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(1));
Method foo = type.getDeclaredMethod(FOO);
assertThat(foo.isBridge(), is(true));
assertThat(foo.invoke(type.getDeclaredConstructor().newInstance()), is((Object) (BAR)));
}
@Test
public void testNoVisibilityBridgeForNonPublicType() throws Exception {
Class<?> type = new ByteBuddy()
.subclass(VisibilityBridge.class)
.modifiers(0)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(0));
}
@Test
public void testNoVisibilityBridgeForInheritedType() throws Exception {
Class<?> type = new ByteBuddy()
.subclass(VisibilityBridgeExtension.class)
.modifiers(Opcodes.ACC_PUBLIC)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(0));
}
@Test
public void testNoVisibilityBridgeForAbstractMethod() throws Exception {
Class<?> type = new ByteBuddy()
.subclass(VisibilityBridgeAbstractMethod.class)
.modifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(0));
}
@Test
@JavaVersionRule.Enforce(8)
@SuppressWarnings("unchecked")
public void testAnnotationTypeOnSuperClass() throws Exception {
Class<? extends Annotation> typeAnnotationType = (Class<? extends Annotation>) Class.forName(TYPE_VARIABLE_NAME);
MethodDescription.InDefinedShape value = new TypeDescription.ForLoadedType(typeAnnotationType).getDeclaredMethods().filter(named(VALUE)).getOnly();
Class<?> type = new ByteBuddy()
.subclass(TypeDescription.Generic.Builder.rawType(Object.class)
.build(AnnotationDescription.Builder.ofType(typeAnnotationType).define(VALUE, BAZ).build()))
.make()
.load(typeAnnotationType.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded();
assertThat(type.getSuperclass(), is((Object) Object.class));
assertThat(TypeDescription.Generic.AnnotationReader.DISPATCHER.resolveSuperClassType(type).asList().size(), is(1));
assertThat(TypeDescription.Generic.AnnotationReader.DISPATCHER.resolveSuperClassType(type).asList().ofType(typeAnnotationType)
.getValue(value).resolve(Integer.class), is(BAZ));
}
@Test
@JavaVersionRule.Enforce(8)
@SuppressWarnings("unchecked")
public void testReceiverTypeDefinition() throws Exception {
Class<? extends Annotation> typeAnnotationType = (Class<? extends Annotation>) Class.forName(TYPE_VARIABLE_NAME);
MethodDescription.InDefinedShape value = new TypeDescription.ForLoadedType(typeAnnotationType).getDeclaredMethods().filter(named(VALUE)).getOnly();
Method method = createPlain()
.defineMethod(FOO, void.class)
.intercept(StubMethod.INSTANCE)
.receiverType(TypeDescription.Generic.Builder.rawType(TargetType.class)
.annotate(AnnotationDescription.Builder.ofType(typeAnnotationType).define(VALUE, BAZ).build())
.build())
.make()
.load(typeAnnotationType.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.getDeclaredMethod(FOO);
assertThat(TypeDescription.Generic.AnnotationReader.DISPATCHER.resolveReceiverType(method).getDeclaredAnnotations().size(), is(1));
assertThat(TypeDescription.Generic.AnnotationReader.DISPATCHER.resolveReceiverType(method).getDeclaredAnnotations()
.ofType(typeAnnotationType).getValue(value).resolve(Integer.class), is(BAZ));
}
@Test
@JavaVersionRule.Enforce(8)
@SuppressWarnings("unchecked")
public void testReceiverTypeInterception() throws Exception {
Class<? extends Annotation> typeAnnotationType = (Class<? extends Annotation>) Class.forName(TYPE_VARIABLE_NAME);
MethodDescription.InDefinedShape value = new TypeDescription.ForLoadedType(typeAnnotationType).getDeclaredMethods().filter(named(VALUE)).getOnly();
Method method = createPlain()
.method(named("toString"))
.intercept(StubMethod.INSTANCE)
.receiverType(TypeDescription.Generic.Builder.rawType(TargetType.class)
.annotate(AnnotationDescription.Builder.ofType(typeAnnotationType).define(VALUE, BAZ).build())
.build())
.make()
.load(typeAnnotationType.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.getDeclaredMethod("toString");
assertThat(TypeDescription.Generic.AnnotationReader.DISPATCHER.resolveReceiverType(method).getDeclaredAnnotations().size(), is(1));
assertThat(TypeDescription.Generic.AnnotationReader.DISPATCHER.resolveReceiverType(method).getDeclaredAnnotations()
.ofType(typeAnnotationType).getValue(value).resolve(Integer.class), is(BAZ));
}
@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(SubclassDynamicTypeBuilder.class).create(new ObjectPropertyAssertion.Creator<List<?>>() {
@Override
public List<?> create() {
return Collections.singletonList(new Object());
}
}).apply();
}
@SuppressWarnings("unused")
public enum SimpleEnum {
FIRST,
SECOND
}
public interface SimpleInterface {
void bar(Void arg);
}
@Retention(RetentionPolicy.RUNTIME)
public @interface Foo {
/* empty */
}
@SuppressWarnings("unused")
public static class DefaultConstructor {
public DefaultConstructor() {
/* empty */
}
public DefaultConstructor(Void arg) {
/* empty */
}
}
public static class PackagePrivateReturnType {
public Argument foo() {
return null;
}
static class Argument {
/* empty */
}
}
@SuppressWarnings("unused")
public static class PackagePrivateArgumentType {
public void foo(Argument argument) {
/* empty */
}
static class Argument {
/* empty */
}
}
@SuppressWarnings("unused")
public static class PrivateMethod {
private void foo() {
/* empty */
}
}
@SuppressWarnings("unused")
static class VisibilityBridge {
@Foo
public String foo(@Foo String value) {
return FOO + value;
}
public <T extends Exception> List<String> bar(List<String> value) throws T {
return value;
}
void qux() {
/* empty */
}
protected void baz() {
/* empty */
}
public final void foobar() {
/* empty */
}
}
abstract static class VisibilityBridgeAbstractMethod {
public abstract void foo();
}
public static class VisibilityBridgeExtension extends VisibilityBridge {
/* empty */
}
public abstract static class AbstractGenericType<T> {
public abstract T foo(T t);
public abstract static class Inner extends AbstractGenericType<Void> {
/* empty */
}
}
}