package net.bytebuddy.implementation.bytecode.member; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.implementation.bytecode.StackManipulation; import net.bytebuddy.implementation.bytecode.assign.TypeCasting; import net.bytebuddy.test.utility.MockitoRule; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.mockito.Mock; import java.util.Collections; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class MethodInvocationGenericTest { private static final String FOO = "foo"; @Rule public TestRule mockitoRule = new MockitoRule(this); @Mock private MethodDescription.InDefinedShape declaredMethod; @Mock private MethodDescription methodDescription; @Mock private TypeDescription.Generic methodReturnType, declaredReturnType; @Mock private TypeDescription declaredErasure, declaringType, targetType, otherType; @Mock private MethodDescription.SignatureToken token; @Before public void setUp() throws Exception { when(methodDescription.asDefined()).thenReturn(declaredMethod); when(methodDescription.getReturnType()).thenReturn(methodReturnType); when(declaredMethod.getReturnType()).thenReturn(declaredReturnType); when(declaredReturnType.asErasure()).thenReturn(declaredErasure); when(declaredMethod.getDeclaringType()).thenReturn(declaringType); when(declaringType.asErasure()).thenReturn(declaringType); when(declaredMethod.asSignatureToken()).thenReturn(token); when(declaredMethod.isSpecializableFor(targetType)).thenReturn(true); when(declaredMethod.asDefined()).thenReturn(declaredMethod); } @Test public void testGenericMethod() throws Exception { TypeDescription genericErasure = mock(TypeDescription.class); when(methodReturnType.asErasure()).thenReturn(genericErasure); StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription); assertThat(stackManipulation.isValid(), is(true)); assertThat(stackManipulation, is((StackManipulation) new MethodInvocation.OfGenericMethod(genericErasure, MethodInvocation.invoke(declaredMethod)))); } @Test public void testGenericMethodErasureEqual() throws Exception { when(methodReturnType.asErasure()).thenReturn(declaredErasure); StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription); assertThat(stackManipulation.isValid(), is(true)); assertThat(stackManipulation, is((StackManipulation) MethodInvocation.invoke(declaredMethod))); } @Test public void testGenericMethodVirtual() throws Exception { TypeDescription genericErasure = mock(TypeDescription.class); when(methodReturnType.asErasure()).thenReturn(genericErasure); when(genericErasure.asErasure()).thenReturn(genericErasure); StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription).virtual(targetType); assertThat(stackManipulation.isValid(), is(true)); assertThat(stackManipulation, is((StackManipulation) new StackManipulation.Compound(MethodInvocation.invoke(declaredMethod).virtual(targetType), TypeCasting.to(genericErasure)))); } @Test public void testGenericMethodVirtualErasureEqual() throws Exception { when(methodReturnType.asErasure()).thenReturn(declaredErasure); StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription).virtual(targetType); assertThat(stackManipulation.isValid(), is(true)); assertThat(stackManipulation, is(MethodInvocation.invoke(declaredMethod).virtual(targetType))); } @Test public void testGenericMethodSpecial() throws Exception { TypeDescription genericErasure = mock(TypeDescription.class); when(methodReturnType.asErasure()).thenReturn(genericErasure); when(genericErasure.asErasure()).thenReturn(genericErasure); StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription).special(targetType); assertThat(stackManipulation.isValid(), is(true)); assertThat(stackManipulation, is((StackManipulation) new StackManipulation.Compound(MethodInvocation.invoke(declaredMethod).special(targetType), TypeCasting.to(genericErasure)))); } @Test public void testGenericMethodSpecialErasureEqual() throws Exception { when(methodReturnType.asErasure()).thenReturn(declaredErasure); StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription).special(targetType); assertThat(stackManipulation.isValid(), is(true)); assertThat(stackManipulation, is(MethodInvocation.invoke(declaredMethod).special(targetType))); } @Test public void testGenericMethodDynamic() throws Exception { TypeDescription genericErasure = mock(TypeDescription.class); when(methodReturnType.asErasure()).thenReturn(genericErasure); when(declaredMethod.isBootstrap()).thenReturn(true); StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription).dynamic(FOO, otherType, Collections.<TypeDescription>emptyList(), Collections.emptyList()); assertThat(stackManipulation.isValid(), is(true)); assertThat(stackManipulation, is(MethodInvocation.invoke(declaredMethod).dynamic(FOO, otherType, Collections.<TypeDescription>emptyList(), Collections.emptyList()))); } @Test public void testGenericMethodDynamicErasureEqual() throws Exception { when(methodReturnType.asErasure()).thenReturn(declaredErasure); when(declaredMethod.isBootstrap()).thenReturn(true); StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription).dynamic(FOO, otherType, Collections.<TypeDescription>emptyList(), Collections.emptyList()); assertThat(stackManipulation.isValid(), is(true)); assertThat(stackManipulation, is(MethodInvocation.invoke(declaredMethod).dynamic(FOO, otherType, Collections.<TypeDescription>emptyList(), Collections.emptyList()))); } @Test public void testIllegal() throws Exception { TypeDescription genericErasure = mock(TypeDescription.class); when(methodReturnType.asErasure()).thenReturn(genericErasure); when(declaredMethod.isTypeInitializer()).thenReturn(true); StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription); assertThat(stackManipulation.isValid(), is(false)); } }