package net.bytebuddy.dynamic.scaffold; import net.bytebuddy.description.annotation.AnnotationDescription; import net.bytebuddy.description.field.FieldDescription; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeVariableToken; import net.bytebuddy.implementation.LoadedTypeInitializer; import net.bytebuddy.matcher.ElementMatchers; import net.bytebuddy.test.utility.JavaVersionRule; import net.bytebuddy.test.utility.ObjectPropertyAssertion; import org.junit.Rule; import org.junit.Test; import org.junit.rules.MethodRule; import org.objectweb.asm.Opcodes; import java.util.Collections; import static net.bytebuddy.matcher.ElementMatchers.*; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; public class MethodGraphCompilerDefaultTest { private static final String TYPE_VARIABLE_INTERFACE_BRIDGE = "net.bytebuddy.test.precompiled.TypeVariableInterfaceBridge"; private static final String RETURN_TYPE_INTERFACE_BRIDGE = "net.bytebuddy.test.precompiled.ReturnTypeInterfaceBridge"; @Rule public MethodRule javaVersionRule = new JavaVersionRule(); @Test public void testTrivialJavaHierarchy() throws Exception { MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(TypeDescription.OBJECT); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size())); assertThat(methodGraph.getSuperClassGraph().listNodes().size(), is(0)); assertThat(methodGraph.getInterfaceGraph(mock(TypeDescription.class)).listNodes().size(), is(0)); for (MethodDescription methodDescription : TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual())) { MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); assertThat(methodGraph.listNodes().contains(node), is(true)); } } @Test public void testTrivialJVMHierarchy() throws Exception { MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJVMHierarchy().compile(TypeDescription.OBJECT); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size())); assertThat(methodGraph.getSuperClassGraph().listNodes().size(), is(0)); assertThat(methodGraph.getInterfaceGraph(mock(TypeDescription.class)).listNodes().size(), is(0)); for (MethodDescription methodDescription : TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual())) { MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); assertThat(methodGraph.listNodes().contains(node), is(true)); } } @Test public void testSimpleClass() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(SimpleClass.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size())); assertThat(methodGraph.getSuperClassGraph().listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size())); assertThat(methodGraph.getInterfaceGraph(mock(TypeDescription.class)).listNodes().size(), is(0)); for (MethodDescription methodDescription : TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual())) { MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); assertThat(methodGraph.listNodes().contains(node), is(true)); } } @Test public void testSimpleInterface() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(SimpleInterface.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(0)); } @Test public void testClassInheritance() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(ClassBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription method = typeDescription.getDeclaredMethods().filter(isMethod()).getOnly(); MethodGraph.Node node = methodGraph.locate(method.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(method.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(method)); assertThat(node.getVisibility(), is(method.getVisibility())); assertThat(methodGraph.listNodes().contains(node), is(true)); MethodGraph.Node baseNode = methodGraph.getSuperClassGraph().locate(method.asSignatureToken()); assertThat(node, not(baseNode)); assertThat(typeDescription.getSuperClass().getDeclaredMethods().filter(ElementMatchers.is(baseNode.getRepresentative())).getOnly(), is(baseNode.getRepresentative())); } @Test public void testInterfaceImplementation() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(InterfaceBase.InnerClass.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription method = typeDescription.getInterfaces().getOnly().getDeclaredMethods().getOnly(); MethodGraph.Node node = methodGraph.locate(method.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(method.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(method)); assertThat(node.getVisibility(), is(method.getVisibility())); assertThat(methodGraph.listNodes().contains(node), is(true)); } @Test public void testInterfaceExtension() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(InterfaceBase.InnerInterface.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription method = typeDescription.getInterfaces().getOnly().getDeclaredMethods().getOnly(); MethodGraph.Node node = methodGraph.locate(method.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(method.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(method)); assertThat(node.getVisibility(), is(method.getVisibility())); assertThat(methodGraph.listNodes().contains(node), is(true)); } @Test public void testInterfaceDuplicateInHierarchyImplementation() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(InterfaceBase.InterfaceDuplicate.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription method = typeDescription.getInterfaces().filter(ElementMatchers.is(InterfaceBase.class)).getOnly().getDeclaredMethods().getOnly(); MethodGraph.Node node = methodGraph.locate(method.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(method.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(method)); assertThat(node.getVisibility(), is(method.getVisibility())); assertThat(methodGraph.listNodes().contains(node), is(true)); } @Test public void testClassAndInterfaceDominantInheritance() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(ClassAndInterfaceInheritance.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription method = typeDescription.getSuperClass().getDeclaredMethods().filter(isMethod()).getOnly(); MethodGraph.Node node = methodGraph.locate(method.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(method.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(method)); assertThat(node.getVisibility(), is(method.getVisibility())); MethodGraph.Node baseNode = methodGraph.getInterfaceGraph(new TypeDescription.ForLoadedType(InterfaceBase.class)).locate(method.asSignatureToken()); assertThat(node, not(baseNode)); assertThat(baseNode.getRepresentative(), is((MethodDescription) typeDescription.getInterfaces().getOnly().getDeclaredMethods().getOnly())); } @Test public void testMultipleAmbiguousClassInheritance() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.ClassTarget.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription first = typeDescription.getInterfaces().filter(erasure(InterfaceBase.class)).getOnly() .getDeclaredMethods().filter(isMethod()).getOnly(); MethodDescription second = typeDescription.getInterfaces().filter(erasure(AmbiguousInterfaceBase.class)).getOnly() .getDeclaredMethods().filter(isMethod()).getOnly(); MethodGraph.Node node = methodGraph.locate(first.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.AMBIGUOUS)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(first.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(second.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(first)); assertThat(node.getRepresentative(), not(second)); assertThat(node.getVisibility(), is(first.getVisibility())); assertThat(node, is(methodGraph.locate(second.asSignatureToken()))); MethodGraph.Node firstBaseNode = methodGraph.getInterfaceGraph(new TypeDescription.ForLoadedType(InterfaceBase.class)).locate(first.asSignatureToken()); assertThat(node, not(firstBaseNode)); assertThat(firstBaseNode.getRepresentative(), is(first)); MethodGraph.Node secondBaseNode = methodGraph.getInterfaceGraph(new TypeDescription.ForLoadedType(InterfaceBase.class)).locate(second.asSignatureToken()); assertThat(node, not(secondBaseNode)); assertThat(secondBaseNode.getRepresentative(), is(first)); } @Test public void testMultipleAmbiguousInterfaceInheritance() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.InterfaceTarget.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription first = typeDescription.getInterfaces().filter(erasure(InterfaceBase.class)).getOnly() .getDeclaredMethods().filter(isMethod()).getOnly(); MethodDescription second = typeDescription.getInterfaces().filter(erasure(AmbiguousInterfaceBase.class)).getOnly() .getDeclaredMethods().filter(isMethod()).getOnly(); MethodGraph.Node node = methodGraph.locate(first.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.AMBIGUOUS)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(first.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(second.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(first)); assertThat(node.getRepresentative(), not(second)); assertThat(node.getVisibility(), is(first.getVisibility())); assertThat(node, is(methodGraph.locate(second.asSignatureToken()))); MethodGraph.Node firstBaseNode = methodGraph.getInterfaceGraph(new TypeDescription.ForLoadedType(InterfaceBase.class)).locate(first.asSignatureToken()); assertThat(node, not(firstBaseNode)); assertThat(firstBaseNode.getRepresentative(), is(first)); MethodGraph.Node secondBaseNode = methodGraph.getInterfaceGraph(new TypeDescription.ForLoadedType(InterfaceBase.class)).locate(second.asSignatureToken()); assertThat(node, not(secondBaseNode)); assertThat(secondBaseNode.getRepresentative(), is(first)); } @Test public void testDominantClassInheritance() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.DominantClassTarget.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription methodDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.DominantIntermediate.class) .getDeclaredMethods().getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); } @Test public void testDominantInterfaceInheritanceLeft() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.DominantInterfaceTargetLeft.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription methodDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.DominantIntermediate.class) .getDeclaredMethods().getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); } @Test public void testDominantInterfaceInheritanceRight() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.DominantInterfaceTargetRight.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription methodDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.DominantIntermediate.class) .getDeclaredMethods().getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); } @Test public void testNonDominantInterfaceInheritanceLeft() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.NonDominantTargetLeft.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription methodDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.DominantIntermediate.class) .getDeclaredMethods().getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.AMBIGUOUS)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); } @Test public void testNonDominantInterfaceInheritanceRight() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.NonDominantTargetRight.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription methodDescription = new TypeDescription.ForLoadedType(AmbiguousInterfaceBase.DominantIntermediate.class) .getDeclaredMethods().getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.AMBIGUOUS)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); } @Test public void testGenericClassSingleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericClassBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken bridgeToken = typeDescription.getSuperClass().getDeclaredMethods().filter(isMethod()).getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(bridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(bridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericClassMultipleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericClassBase.Intermediate.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken firstBridgeToken = typeDescription.getSuperClass().getDeclaredMethods() .filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asDefined().asSignatureToken(); MethodDescription.SignatureToken secondBridgeToken = typeDescription.getSuperClass().getSuperClass().getDeclaredMethods() .filter(isMethod()).getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(firstBridgeToken))); assertThat(node, is(methodGraph.locate(secondBridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(3)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(firstBridgeToken.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(secondBridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testReturnTypeClassSingleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(ReturnTypeClassBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken bridgeToken = typeDescription.getSuperClass().getDeclaredMethods().filter(isMethod()).getOnly().asSignatureToken(); assertThat(node, is(methodGraph.locate(bridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(bridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testReturnTypeClassMultipleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(ReturnTypeClassBase.Intermediate.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken firstBridgeToken = typeDescription.getSuperClass().getDeclaredMethods() .filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asDefined().asSignatureToken(); MethodDescription.SignatureToken secondBridgeToken = typeDescription.getSuperClass().getSuperClass().getDeclaredMethods() .filter(isMethod()).getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(firstBridgeToken))); assertThat(node, is(methodGraph.locate(secondBridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(3)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(firstBridgeToken.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(secondBridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericReturnTypeClassSingleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericReturnClassBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken bridgeToken = typeDescription.getSuperClass().getDeclaredMethods().filter(isMethod()).getOnly().asSignatureToken(); assertThat(node, is(methodGraph.locate(bridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(bridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericReturnTypeClassMultipleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericReturnClassBase.Intermediate.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken firstBridgeToken = typeDescription.getSuperClass().getDeclaredMethods() .filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asDefined().asSignatureToken(); MethodDescription.SignatureToken secondBridgeToken = typeDescription.getSuperClass().getSuperClass().getDeclaredMethods() .filter(isMethod()).getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(firstBridgeToken))); assertThat(node, is(methodGraph.locate(secondBridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(3)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(firstBridgeToken.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(secondBridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericInterfaceSingleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericInterfaceBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken bridgeToken = typeDescription.getInterfaces().getOnly() .getDeclaredMethods().filter(isMethod()).getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(bridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(bridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericInterfaceMultipleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericInterfaceBase.Intermediate.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(ElementMatchers.not(isBridge())).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken firstBridgeToken = typeDescription.getInterfaces().getOnly() .getDeclaredMethods().filter(ElementMatchers.not(isBridge())).getOnly().asDefined().asSignatureToken(); MethodDescription.SignatureToken secondBridgeToken = typeDescription.getInterfaces().getOnly().getInterfaces().getOnly() .getDeclaredMethods().getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(firstBridgeToken))); assertThat(node, is(methodGraph.locate(secondBridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(3)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(firstBridgeToken.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(secondBridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testReturnTypeInterfaceSingleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(ReturnTypeInterfaceBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(ElementMatchers.not(isBridge())).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken bridgeToken = typeDescription.getInterfaces().getOnly().getDeclaredMethods().getOnly().asSignatureToken(); assertThat(node, is(methodGraph.locate(bridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(bridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testReturnTypeInterfaceMultipleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(ReturnTypeInterfaceBase.Intermediate.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(ElementMatchers.not(isBridge())).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken firstBridgeToken = typeDescription.getInterfaces().getOnly() .getDeclaredMethods().filter(ElementMatchers.not(isBridge())).getOnly().asSignatureToken(); MethodDescription.SignatureToken secondBridgeToken = typeDescription.getInterfaces().getOnly().getInterfaces().getOnly() .getDeclaredMethods().getOnly().asSignatureToken(); assertThat(node, is(methodGraph.locate(firstBridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(3)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(firstBridgeToken.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(secondBridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericWithReturnTypeClassSingleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericWithReturnTypeClassBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken bridgeToken = typeDescription.getSuperClass().getDeclaredMethods().filter(isMethod()).getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(bridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(bridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericWithReturnTypeClassMultipleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericWithReturnTypeClassBase.Intermediate.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken firstBridgeToken = typeDescription.getSuperClass().getDeclaredMethods() .filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asDefined().asSignatureToken(); MethodDescription.SignatureToken secondBridgeToken = typeDescription.getSuperClass().getSuperClass().getDeclaredMethods() .filter(isMethod()).getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(firstBridgeToken))); assertThat(node, is(methodGraph.locate(secondBridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(3)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(firstBridgeToken.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(secondBridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericWithReturnTypeInterfaceSingleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericWithReturnTypeInterfaceBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken bridgeToken = typeDescription.getInterfaces().getOnly() .getDeclaredMethods().filter(isMethod()).getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(bridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(bridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericWithReturnTypeInterfaceMultipleEvolution() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericWithReturnTypeInterfaceBase.Intermediate.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription.SignatureToken token = typeDescription.getDeclaredMethods().filter(ElementMatchers.not(isBridge())).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(token); MethodDescription.SignatureToken firstBridgeToken = typeDescription.getInterfaces().getOnly() .getDeclaredMethods().filter(ElementMatchers.not(isBridge())).getOnly().asDefined().asSignatureToken(); MethodDescription.SignatureToken secondBridgeToken = typeDescription.getInterfaces().getOnly().getInterfaces().getOnly() .getDeclaredMethods().getOnly().asDefined().asSignatureToken(); assertThat(node, is(methodGraph.locate(firstBridgeToken))); assertThat(node, is(methodGraph.locate(secondBridgeToken))); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getMethodTypes().size(), is(3)); assertThat(node.getMethodTypes().contains(token.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(firstBridgeToken.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(secondBridgeToken.asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericNonOverriddenClassExtension() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericNonOverriddenClassBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription methodDescription = typeDescription.getSuperClass().getDeclaredMethods().filter(isMethod()).getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(methodDescription.asDefined().asTypeToken()), is(true)); assertThat(node, is(methodGraph.getSuperClassGraph().locate(methodDescription.asSignatureToken()))); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericNonOverriddenInterfaceExtension() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericNonOverriddenInterfaceBase.InnerClass.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription methodDescription = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(isMethod()).getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(methodDescription.asDefined().asTypeToken()), is(true)); assertThat(node, is(methodGraph.getInterfaceGraph(new TypeDescription.ForLoadedType(GenericNonOverriddenInterfaceBase.class)) .locate(methodDescription.asSignatureToken()))); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testGenericNonOverriddenInterfaceImplementation() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericNonOverriddenInterfaceBase.InnerInterface.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription methodDescription = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(isMethod()).getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(methodDescription.asDefined().asTypeToken()), is(true)); assertThat(node, is(methodGraph.getInterfaceGraph(new TypeDescription.ForLoadedType(GenericNonOverriddenInterfaceBase.class)) .locate(methodDescription.asSignatureToken()))); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test @JavaVersionRule.Enforce(8) public void testTypeVariableInterfaceBridge() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(Class.forName(TYPE_VARIABLE_INTERFACE_BRIDGE)); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription methodDescription = typeDescription.getDeclaredMethods().filter(takesArguments(String.class)).getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(typeDescription.getDeclaredMethods().filter(takesArguments(Object.class)).getOnly().asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test @JavaVersionRule.Enforce(8) public void testReturnTypeInterfaceBridge() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(Class.forName(RETURN_TYPE_INTERFACE_BRIDGE)); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription methodDescription = typeDescription.getDeclaredMethods().filter(returns(String.class)).getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(typeDescription.getDeclaredMethods().filter(returns(Object.class)).getOnly().asTypeToken()), is(true)); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testDuplicateNameClass() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameClass.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 2)); MethodDescription objectMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Object.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(1)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectNode.getVisibility(), is(objectMethod.getVisibility())); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testDuplicateNameClassExtension() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameClass.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 3)); MethodDescription objectMethod = typeDescription.getSuperClass().getDeclaredMethods().filter(takesArguments(Object.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(1)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectNode.getVisibility(), is(objectMethod.getVisibility())); MethodDescription integerMethod = typeDescription.getSuperClass().getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node integerNode = methodGraph.locate(integerMethod.asSignatureToken()); assertThat(integerNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(integerNode.getRepresentative(), is(integerMethod)); assertThat(integerNode.getMethodTypes().size(), is(1)); assertThat(integerNode.getMethodTypes().contains(integerMethod.asTypeToken()), is(true)); assertThat(integerNode.getVisibility(), is(integerMethod.getVisibility())); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Void.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testDuplicateNameInterface() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameInterface.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(2)); MethodDescription objectMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Object.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(1)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectNode.getVisibility(), is(objectMethod.getVisibility())); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testDuplicateNameInterfaceImplementation() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameInterface.InnerClass.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 3)); MethodDescription objectMethod = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(takesArguments(Object.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(1)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectMethod.getVisibility(), is(objectMethod.getVisibility())); MethodDescription integerMethod = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node integerNode = methodGraph.locate(integerMethod.asSignatureToken()); assertThat(integerNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(integerNode.getRepresentative(), is(integerMethod)); assertThat(integerNode.getMethodTypes().size(), is(1)); assertThat(integerNode.getMethodTypes().contains(integerMethod.asTypeToken()), is(true)); assertThat(integerNode.getVisibility(), is(integerMethod.getVisibility())); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Void.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testDuplicateNameInterfaceExtension() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameInterface.InnerInterface.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(3)); MethodDescription objectMethod = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(takesArguments(Object.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(1)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectNode.getVisibility(), is(objectMethod.getVisibility())); MethodDescription integerMethod = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node integerNode = methodGraph.locate(integerMethod.asSignatureToken()); assertThat(integerNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(integerNode.getRepresentative(), is(integerMethod)); assertThat(integerNode.getMethodTypes().size(), is(1)); assertThat(integerNode.getMethodTypes().contains(integerMethod.asTypeToken()), is(true)); assertThat(integerMethod.getVisibility(), is(integerNode.getVisibility())); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Void.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testDuplicateNameGenericClass() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameGenericClass.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 2)); MethodDescription objectMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Object.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(1)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectNode.getVisibility(), is(objectMethod.getVisibility())); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testDuplicateNameGenericClassExtension() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameGenericClass.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 3)); MethodDescription objectMethod = typeDescription.getSuperClass().getDeclaredMethods().filter(takesArguments(String.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(2)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asDefined().asTypeToken()), is(true)); assertThat(objectNode.getVisibility(), is(objectMethod.getVisibility())); MethodDescription integerMethod = typeDescription.getSuperClass().getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node integerNode = methodGraph.locate(integerMethod.asSignatureToken()); assertThat(integerNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(integerNode.getRepresentative(), is(integerMethod)); assertThat(integerNode.getMethodTypes().size(), is(1)); assertThat(integerNode.getMethodTypes().contains(integerMethod.asTypeToken()), is(true)); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Void.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testDuplicateNameGenericInterface() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameGenericInterface.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(2)); MethodDescription objectMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Object.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(1)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectNode.getVisibility(), is(objectMethod.getVisibility())); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testDuplicateNameGenericInterfaceImplementation() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameGenericInterface.InnerClass.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 3)); MethodDescription objectMethod = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(takesArguments(String.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(2)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asDefined().asTypeToken()), is(true)); assertThat(objectNode.getVisibility(), is(objectMethod.getVisibility())); MethodDescription integerMethod = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node integerNode = methodGraph.locate(integerMethod.asSignatureToken()); assertThat(integerNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(integerNode.getRepresentative(), is(integerMethod)); assertThat(integerNode.getMethodTypes().size(), is(1)); assertThat(integerNode.getMethodTypes().contains(integerMethod.asTypeToken()), is(true)); assertThat(integerNode.getMethodTypes().contains(integerMethod.asDefined().asTypeToken()), is(true)); assertThat(integerNode.getVisibility(), is(integerMethod.getVisibility())); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Void.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testDuplicateNameGenericInterfaceExtension() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(DuplicateNameGenericInterface.InnerInterface.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(3)); MethodDescription objectMethod = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(takesArguments(String.class)).getOnly(); MethodGraph.Node objectNode = methodGraph.locate(objectMethod.asSignatureToken()); assertThat(objectNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(objectNode.getRepresentative(), is(objectMethod)); assertThat(objectNode.getMethodTypes().size(), is(2)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asTypeToken()), is(true)); assertThat(objectNode.getMethodTypes().contains(objectMethod.asDefined().asTypeToken()), is(true)); assertThat(objectNode.getVisibility(), is(objectMethod.getVisibility())); MethodDescription integerMethod = typeDescription.getInterfaces().getOnly().getDeclaredMethods().filter(takesArguments(Integer.class)).getOnly(); MethodGraph.Node integerNode = methodGraph.locate(integerMethod.asSignatureToken()); assertThat(integerNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(integerNode.getRepresentative(), is(integerMethod)); assertThat(integerNode.getMethodTypes().size(), is(1)); assertThat(integerNode.getMethodTypes().contains(integerMethod.asTypeToken()), is(true)); assertThat(integerNode.getMethodTypes().contains(integerMethod.asDefined().asTypeToken()), is(true)); assertThat(integerNode.getVisibility(), is(integerMethod.getVisibility())); MethodDescription voidMethod = typeDescription.getDeclaredMethods().filter(takesArguments(Void.class)).getOnly(); MethodGraph.Node voidNode = methodGraph.locate(voidMethod.asSignatureToken()); assertThat(voidNode.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(voidNode.getRepresentative(), is(voidMethod)); assertThat(voidNode.getMethodTypes().size(), is(1)); assertThat(voidNode.getMethodTypes().contains(voidMethod.asTypeToken()), is(true)); assertThat(voidNode.getVisibility(), is(voidMethod.getVisibility())); } @Test public void testVisibilityBridge() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(VisibilityBridgeTarget.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription methodDescription = typeDescription.getSuperClass().getDeclaredMethods().filter(isMethod()).getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.VISIBLE)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); } @Test public void testGenericVisibilityBridge() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericVisibilityBridgeTarget.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription methodDescription = typeDescription.getSuperClass() .getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly(); MethodDescription.SignatureToken bridgeToken = typeDescription.getSuperClass().getSuperClass() .getDeclaredMethods().filter(isMethod()).getOnly().asSignatureToken(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.VISIBLE)); assertThat(node, is(methodGraph.locate(bridgeToken))); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(methodDescription.asDefined().asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); } @Test public void testMethodClassConvergence() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(MethodClassConvergence.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription methodDescription = typeDescription.getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly(); MethodDescription genericMethod = typeDescription.getSuperClass().getDeclaredMethods() .filter(isMethod().and(definedMethod(takesArguments(Object.class)))).getOnly(); MethodDescription nonGenericMethod = typeDescription.getSuperClass().getDeclaredMethods() .filter(isMethod().and(definedMethod(takesArguments(Void.class)))).getOnly(); MethodGraph.Node node = methodGraph.locate(methodDescription.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node, is(methodGraph.locate(genericMethod.asDefined().asSignatureToken()))); assertThat(node, is(methodGraph.locate(nonGenericMethod.asDefined().asSignatureToken()))); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(methodDescription.asDefined().asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(methodDescription)); assertThat(node.getVisibility(), is(methodDescription.getVisibility())); MethodGraph superGraph = methodGraph.getSuperClassGraph(); MethodGraph.Node superNode = superGraph.locate(methodDescription.asSignatureToken()); assertThat(superNode.getSort(), is(MethodGraph.Node.Sort.AMBIGUOUS)); assertThat(superNode.getMethodTypes().size(), is(2)); assertThat(superNode.getMethodTypes().contains(methodDescription.asTypeToken()), is(true)); assertThat(superNode.getMethodTypes().contains(methodDescription.asDefined().asTypeToken()), is(true)); assertThat(superNode.getRepresentative(), is(nonGenericMethod)); assertThat(superNode.getRepresentative(), is(genericMethod)); assertThat(superNode.getVisibility(), is(methodDescription.getVisibility())); } @Test public void testMethodInterfaceConvergence() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(MethodInterfaceConvergenceTarget.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription genericMethod = typeDescription.getInterfaces().filter(erasure(MethodInterfaceConvergenceFirstBase.class)).getOnly() .getDeclaredMethods().filter(isMethod()).getOnly(); MethodDescription nonGenericMethod = typeDescription.getInterfaces().filter(erasure(MethodInterfaceConvergenceSecondBase.class)).getOnly() .getDeclaredMethods().filter(isMethod()).getOnly(); assertThat(methodGraph.getSuperClassGraph().locate(genericMethod.asSignatureToken()).getSort(), is(MethodGraph.Node.Sort.UNRESOLVED)); assertThat(methodGraph.getSuperClassGraph().locate(nonGenericMethod.asSignatureToken()).getSort(), is(MethodGraph.Node.Sort.UNRESOLVED)); MethodGraph.Node node = methodGraph.locate(genericMethod.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.AMBIGUOUS)); assertThat(node, is(methodGraph.locate(genericMethod.asDefined().asSignatureToken()))); assertThat(node, is(methodGraph.locate(nonGenericMethod.asDefined().asSignatureToken()))); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(genericMethod.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(genericMethod.asDefined().asTypeToken()), is(true)); assertThat(node.getRepresentative(), is(genericMethod)); assertThat(node.getRepresentative(), not(nonGenericMethod)); assertThat(node.getVisibility(), is(genericMethod.getVisibility())); } @Test public void testMethodConvergenceVisibilityTarget() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(MethodConvergenceVisibilityBridgeTarget.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription genericMethod = typeDescription.getSuperClass().getSuperClass() .getDeclaredMethods().filter(isMethod().and(definedMethod(takesArguments(Object.class)))).getOnly(); MethodDescription nonGenericMethod = typeDescription.getSuperClass().getSuperClass() .getDeclaredMethods().filter(isMethod().and(definedMethod(takesArguments(Void.class)))).getOnly(); MethodGraph.Node node = methodGraph.locate(genericMethod.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.VISIBLE)); assertThat(node, is(methodGraph.locate(nonGenericMethod.asSignatureToken()))); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(genericMethod.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(genericMethod.asDefined().asTypeToken()), is(true)); assertThat(node.getRepresentative(), is((MethodDescription) typeDescription.getSuperClass().getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly())); assertThat(node.getVisibility(), is(genericMethod.getVisibility())); } @Test public void testDiamondInheritanceClass() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericDiamondClassBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription diamondOverride = typeDescription.getInterfaces().getOnly().getDeclaredMethods().getOnly(); MethodDescription explicitOverride = typeDescription.getSuperClass().getDeclaredMethods().filter(isVirtual()).getOnly(); MethodGraph.Node node = methodGraph.locate(diamondOverride.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(methodGraph.locate(explicitOverride.asDefined().asSignatureToken()), is(node)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(diamondOverride.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(explicitOverride.asDefined().asTypeToken()), is(true)); assertThat(node.getVisibility(), is(explicitOverride.getVisibility())); } @Test public void testDiamondInheritanceInterface() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(GenericDiamondInterfaceBase.Inner.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1)); MethodDescription diamondOverride = typeDescription.getInterfaces().get(0).getDeclaredMethods().getOnly(); MethodDescription explicitOverride = typeDescription.getInterfaces().get(1).getDeclaredMethods().getOnly(); MethodGraph.Node node = methodGraph.locate(diamondOverride.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.AMBIGUOUS)); assertThat(methodGraph.locate(explicitOverride.asDefined().asSignatureToken()), is(node)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(diamondOverride.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(explicitOverride.asDefined().asTypeToken()), is(true)); assertThat(node.getVisibility(), is(explicitOverride.getVisibility())); } @Test public void testVisibilityExtension() throws Exception { TypeDescription typeDescription = new InstrumentedType.Default("foo", Opcodes.ACC_PUBLIC, new TypeDescription.Generic.OfNonGenericType.ForLoadedType(VisibilityExtension.Base.class), Collections.<TypeVariableToken>emptyList(), Collections.<TypeDescription.Generic>singletonList(new TypeDescription.Generic.OfNonGenericType.ForLoadedType(VisibilityExtension.class)), Collections.<FieldDescription.Token>emptyList(), Collections.<MethodDescription.Token>emptyList(), Collections.<AnnotationDescription>emptyList(), TypeInitializer.None.INSTANCE, LoadedTypeInitializer.NoOp.INSTANCE, TypeDescription.UNDEFINED, MethodDescription.UNDEFINED, TypeDescription.UNDEFINED, Collections.<TypeDescription>emptyList(), false, false, false); MethodDescription.SignatureToken signatureToken = new MethodDescription.SignatureToken("foo", new TypeDescription.ForLoadedType(void.class), Collections.<TypeDescription>emptyList()); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1 + TypeDescription.OBJECT.getDeclaredMethods().filter(ElementMatchers.isVirtual()).size())); MethodGraph.Node node = methodGraph.locate(signatureToken); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getRepresentative().asSignatureToken(), is(signatureToken)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes(), hasItem(signatureToken.asTypeToken())); assertThat(node.getVisibility(), is(Visibility.PUBLIC)); } @Test public void testOrphanedBridge() throws Exception { MethodDescription.SignatureToken bridgeMethod = new MethodDescription.SignatureToken("foo", TypeDescription.VOID, Collections.<TypeDescription>emptyList()); TypeDescription typeDescription = new InstrumentedType.Default("foo", Opcodes.ACC_PUBLIC, TypeDescription.Generic.OBJECT, Collections.<TypeVariableToken>emptyList(), Collections.<TypeDescription.Generic>emptyList(), Collections.<FieldDescription.Token>emptyList(), Collections.singletonList(new MethodDescription.Token("foo", Opcodes.ACC_BRIDGE, TypeDescription.Generic.VOID, Collections.<TypeDescription.Generic>emptyList())), Collections.<AnnotationDescription>emptyList(), TypeInitializer.None.INSTANCE, LoadedTypeInitializer.NoOp.INSTANCE, TypeDescription.UNDEFINED, MethodDescription.UNDEFINED, TypeDescription.UNDEFINED, Collections.<TypeDescription>emptyList(), false, false, false); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1 + TypeDescription.OBJECT.getDeclaredMethods().filter(ElementMatchers.isVirtual()).size())); MethodGraph.Node node = methodGraph.locate(bridgeMethod); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(node.getRepresentative().asSignatureToken(), is(bridgeMethod)); assertThat(node.getMethodTypes().size(), is(1)); assertThat(node.getMethodTypes(), hasItem(bridgeMethod.asTypeToken())); assertThat(node.getVisibility(), is(Visibility.PACKAGE_PRIVATE)); } @Test public void testRawType() throws Exception { TypeDescription typeDescription = new TypeDescription.ForLoadedType(RawType.Raw.class); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.getSuperClassGraph().listNodes().size(), is(TypeDescription.OBJECT.getDeclaredMethods().filter(isVirtual()).size() + 1)); MethodDescription method = typeDescription.getSuperClass().getDeclaredMethods().filter(isMethod().and(ElementMatchers.not(isBridge()))).getOnly(); MethodGraph.Node node = methodGraph.locate(method.asSignatureToken()); assertThat(node.getSort(), is(MethodGraph.Node.Sort.RESOLVED)); assertThat(methodGraph.locate(method.asDefined().asSignatureToken()), is(node)); assertThat(node.getMethodTypes().size(), is(2)); assertThat(node.getMethodTypes().contains(method.asTypeToken()), is(true)); assertThat(node.getMethodTypes().contains(method.asDefined().asTypeToken()), is(true)); assertThat(node.getVisibility(), is(method.getVisibility())); } @Test public void testObjectProperties() throws Exception { ObjectPropertyAssertion.of(MethodGraph.Compiler.Default.class).apply(); } public interface SimpleInterface { /* empty */ } public interface InterfaceBase { void foo(); interface InnerInterface extends InterfaceBase { /* empty */ } abstract class InnerClass implements InterfaceBase { /* empty */ } interface InterfaceDuplicate extends InnerInterface, InterfaceBase { /* empty */ } } public interface AmbiguousInterfaceBase { void foo(); interface InterfaceTarget extends InterfaceBase, AmbiguousInterfaceBase { /* empty */ } interface DominantIntermediate extends InterfaceBase, AmbiguousInterfaceBase { @Override void foo(); } interface DominantInterfaceTargetLeft extends InterfaceBase, DominantIntermediate { /* empty */ } interface DominantInterfaceTargetRight extends DominantIntermediate, InterfaceBase { /* empty */ } interface NonDominantAmbiguous { void foo(); } interface NonDominantIntermediateLeft extends InterfaceBase, NonDominantAmbiguous { /* empty */ } interface NonDominantIntermediateRight extends NonDominantAmbiguous, InterfaceBase { /* empty */ } interface NonDominantTargetLeft extends DominantIntermediate, NonDominantIntermediateLeft { /* empty */ } interface NonDominantTargetRight extends DominantIntermediate, NonDominantIntermediateRight { /* empty */ } abstract class ClassTarget implements InterfaceBase, AmbiguousInterfaceBase { /* empty */ } abstract class DominantClassBase implements DominantIntermediate { /* empty */ } abstract class DominantClassTarget extends DominantClassBase implements InterfaceBase { /* empty */ } } public interface GenericInterfaceBase<T> { void foo(T t); interface Inner extends GenericInterfaceBase<Void> { @Override void foo(Void t); } interface Intermediate<T extends Number> extends GenericInterfaceBase<T> { @Override void foo(T t); interface Inner extends Intermediate<Integer> { @Override void foo(Integer t); } } } public interface ReturnTypeInterfaceBase { Object foo(); interface Inner extends ReturnTypeInterfaceBase { @Override Void foo(); } interface Intermediate extends ReturnTypeInterfaceBase { @Override Number foo(); interface Inner extends Intermediate { @Override Integer foo(); } } } public interface GenericWithReturnTypeInterfaceBase<T> { Object foo(T t); interface Inner extends GenericWithReturnTypeInterfaceBase<Void> { @Override Void foo(Void t); } interface Intermediate<T extends Number> extends GenericWithReturnTypeInterfaceBase<T> { @Override Number foo(T t); interface Inner extends Intermediate<Integer> { @Override Integer foo(Integer t); } } } public interface GenericNonOverriddenInterfaceBase<T> { T foo(T t); interface InnerInterface extends GenericNonOverriddenInterfaceBase<Void> { /* empty */ } abstract class InnerClass implements GenericNonOverriddenInterfaceBase<Void> { /* empty */ } } public interface DuplicateNameInterface { void foo(Object o); void foo(Integer o); interface InnerInterface extends DuplicateNameInterface { void foo(Void o); } abstract class InnerClass implements DuplicateNameInterface { public abstract void foo(Void o); } } public interface DuplicateNameGenericInterface<T> { void foo(T o); void foo(Integer o); interface InnerInterface extends DuplicateNameGenericInterface<String> { void foo(Void o); } @SuppressWarnings("unused") abstract class InnerClass implements DuplicateNameGenericInterface<String> { public abstract void foo(Void o); } } public interface MethodInterfaceConvergenceFirstBase<T> { T foo(); } public interface MethodInterfaceConvergenceSecondBase { Void foo(); } public interface MethodInterfaceConvergenceTarget extends MethodInterfaceConvergenceFirstBase<Void>, MethodInterfaceConvergenceSecondBase { /* empty */ } public static class SimpleClass { /* empty */ } public static class ClassBase { public void foo() { /* empty */ } static class Inner extends ClassBase { @Override public void foo() { /* empty */ } } } public static class ClassAndInterfaceInheritance extends ClassBase implements InterfaceBase { /* empty */ } public static class GenericClassBase<T> { public void foo(T t) { /* empty */ } public static class Inner extends GenericClassBase<Void> { @Override public void foo(Void t) { /* empty */ } } public static class Intermediate<T extends Number> extends GenericClassBase<T> { @Override public void foo(T t) { /* empty */ } public static class Inner extends Intermediate<Integer> { @Override public void foo(Integer t) { /* empty */ } } } } public static class GenericReturnClassBase<T> { public T foo() { return null; } public static class Inner extends GenericReturnClassBase<Void> { @Override public Void foo() { return null; } } public static class Intermediate<T extends Number> extends GenericReturnClassBase<T> { @Override public T foo() { return null; } public static class Inner extends Intermediate<Integer> { @Override public Integer foo() { return null; } } } } public static class ReturnTypeClassBase { public Object foo() { return null; } public static class Inner extends ReturnTypeClassBase { @Override public Void foo() { return null; } } public static class Intermediate extends ReturnTypeClassBase { @Override public Number foo() { return null; } public static class Inner extends Intermediate { @Override public Integer foo() { return null; } } } } public static class GenericWithReturnTypeClassBase<T> { public Object foo(T t) { return null; } public static class Inner extends GenericWithReturnTypeClassBase<Void> { @Override public Void foo(Void t) { return null; } } public static class Intermediate<T extends Number> extends GenericWithReturnTypeClassBase<T> { @Override public Number foo(T t) { return null; } public static class Inner extends Intermediate<Integer> { @Override public Integer foo(Integer t) { return null; } } } } public static class GenericNonOverriddenClassBase<T> { public T foo(T t) { return null; } public class Inner extends GenericNonOverriddenClassBase<Void> { /* empty */ } } public static class GenericDiamondClassBase<T> { public T foo(T t) { return null; } public interface DiamondInterface { Void foo(Void t); } public class Inner extends GenericNonOverriddenClassBase<Void> implements DiamondInterface { /* empty */ } } public interface GenericDiamondInterfaceBase<T> { T foo(T t); interface DiamondInterface { Void foo(Void s); } interface Inner extends GenericDiamondInterfaceBase<Void>, DiamondInterface { /* empty */ } } public interface VisibilityExtension { void foo(); class Base { protected void foo() { /* do nothing */ } } } public static class DuplicateNameClass { public void foo(Object o) { /* empty */ } public void foo(Integer o) { /* empty */ } public static class Inner extends DuplicateNameClass { public void foo(Void o) { /* empty */ } } } public static class DuplicateNameGenericClass<T> { public void foo(T o) { /* empty */ } public void foo(Integer o) { /* empty */ } public static class Inner extends DuplicateNameGenericClass<String> { public void foo(Void o) { /* empty */ } } } static class VisibilityBridgeBase { public void foo() { /* empty */ } } public static class VisibilityBridgeTarget extends VisibilityBridgeBase { /* empty */ } public static class GenericVisibilityBridgeBase<T> { public void foo(T t) { /* empty */ } } static class GenericVisibilityBridge extends GenericVisibilityBridgeBase<Void> { @Override public void foo(Void aVoid) { /* empty */ } } public static class GenericVisibilityBridgeTarget extends GenericVisibilityBridge { /* empty */ } public static class MethodClassConvergence<T> { public T foo(T arg) { return null; } public Void foo(Void arg) { return null; } public static class Inner extends MethodClassConvergence<Void> { @Override public Void foo(Void arg) { return null; } } } static class MethodConvergenceVisibilityBridgeBase<T> { public T foo(T arg) { return null; } public Void foo(Void arg) { return null; } } static class MethodConvergenceVisibilityBridgeIntermediate extends MethodConvergenceVisibilityBridgeBase<Void> { @Override public Void foo(Void arg) { return null; } } public static class MethodConvergenceVisibilityBridgeTarget extends MethodConvergenceVisibilityBridgeIntermediate { /* empty */ } public static class RawType<T> { public void foo(T t) { /* empty */ } public static class Intermediate<T extends Number> extends RawType<T> { @Override public void foo(T t) { /* empty */ } } public static class Raw extends Intermediate { @Override public void foo(Number t) { /* empty */ } } } }