Skip to content

Commit

Permalink
Added tests and fixed type relation check when implementing interface…
Browse files Browse the repository at this point in the history
… methods.
  • Loading branch information
raphw committed Dec 19, 2016
1 parent dc954f7 commit 5b88c71
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 10 deletions.
37 changes: 34 additions & 3 deletions byte-buddy-dep/src/main/java/net/bytebuddy/ByteBuddy.java
Expand Up @@ -212,6 +212,10 @@ protected ByteBuddy(ClassFileVersion classFileVersion,
* to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
* {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Class, ConstructorStrategy)}.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superClass The super class or interface type to extend.
* @param <T> A loaded type that the generated class is guaranteed to inherit.
Expand All @@ -222,8 +226,14 @@ public <T> DynamicType.Builder<T> subclass(Class<T> superClass) {
}

/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superClass The super class or interface type to extend.
* @param constructorStrategy A constructor strategy that determines the
Expand All @@ -244,6 +254,10 @@ public <T> DynamicType.Builder<T> subclass(Class<T> superClass, ConstructorStrat
* to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
* {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Class, ConstructorStrategy)}.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
* variables that are referenced by the generic type must be declared by the generated subclass before creating
Expand All @@ -256,8 +270,14 @@ public <T> DynamicType.Builder<T> subclass(Type superType) {
}

/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized
* type. All type variables that are referenced by the generic type must be declared by the
Expand All @@ -278,7 +298,12 @@ public <T> DynamicType.Builder<T> subclass(Type superType, ConstructorStrategy c
* <p>
* When extending a class, Byte Buddy imitates all visible constructors of the subclassed type and sets them to be {@code public}.
* Any constructor is implemented to only invoke its super type constructor of equal signature. Another behavior can be specified by
* supplying an explicit {@link ConstructorStrategy} by {@link ByteBuddy#subclass(TypeDefinition, ConstructorStrategy)}.
* supplying a
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
* n explicit {@link ConstructorStrategy} by {@link ByteBuddy#subclass(TypeDefinition, ConstructorStrategy)}.
* </p>
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
Expand All @@ -292,8 +317,14 @@ public <T> DynamicType.Builder<T> subclass(TypeDefinition superType) {
}

/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized
* type. All type variables that are referenced by the generic type must be declared by the
Expand Down Expand Up @@ -579,8 +610,8 @@ public <T> DynamicType.Builder<T> redefine(TypeDescription type, ClassFileLocato
* alternative {@link ClassFileLocator}, use {@link ByteBuddy#redefine(Class, ClassFileLocator)}.
* </p>
*
* @param type The type that is being rebased.
* @param <T> The loaded type of the rebased type.
* @param type The type that is being rebased.
* @param <T> The loaded type of the rebased type.
* @return A type builder for rebasing the provided type.
*/
public <T> DynamicType.Builder<T> rebase(Class<T> type) {
Expand Down
Expand Up @@ -4082,8 +4082,8 @@ public <V> MethodDefinition.ReceiverTypeDefinition<U> defaultValue(V value, Clas
*/
private MethodDefinition.ImplementationDefinition<U> interfaceType() {
ElementMatcher.Junction<MethodDescription> elementMatcher = none();
for (TypeDescription.Generic typeDescription : interfaces) {
elementMatcher = elementMatcher.or(isDeclaredBy(isSubTypeOf(typeDescription.asErasure())));
for (TypeDescription typeDescription : interfaces.asErasures()) {
elementMatcher = elementMatcher.or(isDeclaredBy(isSuperTypeOf(typeDescription)));
}
return materialize().invokable(isDeclaredBy(isInterface()).and(elementMatcher));
}
Expand Down
@@ -1,6 +1,7 @@
package net.bytebuddy.dynamic;

import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.annotation.AbstractAnnotationDescriptionTest;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.annotation.AnnotationValue;
import net.bytebuddy.description.field.FieldDescription;
Expand All @@ -14,10 +15,7 @@
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.dynamic.loading.PackageDefinitionStrategy;
import net.bytebuddy.dynamic.scaffold.InstrumentedType;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.MethodCall;
import net.bytebuddy.implementation.StubMethod;
import net.bytebuddy.implementation.*;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import net.bytebuddy.implementation.bytecode.StackManipulation;
Expand Down Expand Up @@ -1031,6 +1029,58 @@ public void testCanOverloadFieldByType() throws Exception {
}
}

@Test
public void testInterfaceInterception() throws Exception {
assertThat(((SampleInterface) createPlain()
.implement(SampleInterface.class)
.intercept(FixedValue.value(FOO))
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded()
.getDeclaredConstructor()
.newInstance()).foo(), is(FOO));
}

@Test
public void testInterfaceInterceptionPreviousSuperseeded() throws Exception {
assertThat(((SampleInterface) createPlain()
.method(named(FOO))
.intercept(ExceptionMethod.throwing(AssertionError.class))
.implement(SampleInterface.class)
.intercept(FixedValue.value(FOO))
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded()
.getDeclaredConstructor()
.newInstance()).foo(), is(FOO));
}

@Test
public void testInterfaceInterceptionLaterSuperseeding() throws Exception {
assertThat(((SampleInterface) createPlain()
.implement(SampleInterface.class)
.intercept(ExceptionMethod.throwing(AssertionError.class))
.method(named(FOO))
.intercept(FixedValue.value(FOO))
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded()
.getDeclaredConstructor()
.newInstance()).foo(), is(FOO));
}

@Test
public void testInterfaceInterceptionSubClass() throws Exception {
assertThat(((SampleInterface) createPlain()
.implement(SampleInterface.SubInterface.class)
.intercept(FixedValue.value(FOO))
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded()
.getDeclaredConstructor()
.newInstance()).foo(), is(FOO));
}

@Test
public void testInterfaceMakesClassMethodPublic() throws Exception {
Class<?> type = createPlain()
Expand All @@ -1040,7 +1090,7 @@ public void testInterfaceMakesClassMethodPublic() throws Exception {
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded();
Cloneable cloneable = (Cloneable) type.newInstance();
Cloneable cloneable = (Cloneable) type.getDeclaredConstructor().newInstance();
assertThat(cloneable.clone(), sameInstance((Object) cloneable));
}

Expand Down Expand Up @@ -1160,4 +1210,13 @@ public interface Cloneable {

Object clone();
}

public interface SampleInterface {

String foo();

interface SubInterface extends SampleInterface {

}
}
}

0 comments on commit 5b88c71

Please sign in to comment.