package net.bytebuddy.implementation.bind; import net.bytebuddy.description.method.ParameterDescription; import net.bytebuddy.description.method.ParameterList; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.test.utility.ObjectPropertyAssertion; import org.junit.Before; import org.junit.Test; import org.mockito.AdditionalMatchers; import org.mockito.Mock; import org.mockito.Mockito; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.AdditionalMatchers.not; import static org.mockito.Mockito.*; public class ArgumentTypeResolverReferenceTest extends AbstractArgumentTypeResolverTest { @Mock private TypeDescription weakTargetType, dominantTargetType; @Mock private TypeDescription.Generic genericWeakTargetType, genericDominantTargetType; @Mock private ParameterDescription weakTargetParameter, dominantTargetParameter; @Override @Before public void setUp() throws Exception { super.setUp(); when(weakTargetType.isAssignableFrom(dominantTargetType)).thenReturn(true); when(weakTargetType.isAssignableFrom(weakTargetType)).thenReturn(true); when(weakTargetType.isAssignableTo(weakTargetType)).thenReturn(true); when(dominantTargetType.isAssignableTo(weakTargetType)).thenReturn(true); when(weakTargetParameter.getType()).thenReturn(genericWeakTargetType); when(dominantTargetParameter.getType()).thenReturn(genericDominantTargetType); when(genericWeakTargetType.asErasure()).thenReturn(weakTargetType); when(genericDominantTargetType.asErasure()).thenReturn(dominantTargetType); } @Test @SuppressWarnings("unchecked") public void testMethodWithoutArguments() throws Exception { when(source.getParameters()).thenReturn((ParameterList) sourceParameterList); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution.isUnresolved(), is(true)); verify(source, atLeast(1)).getParameters(); verifyZeroInteractions(left); verifyZeroInteractions(right); } @Test public void testMethodWithoutMappedArguments() throws Exception { when(sourceParameterList.size()).thenReturn(1); when(left.getTargetParameterIndex(argThat(describesArgument(0)))).thenReturn(null); when(right.getTargetParameterIndex(argThat(describesArgument(0)))).thenReturn(null); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution, is(MethodDelegationBinder.AmbiguityResolver.Resolution.AMBIGUOUS)); verify(source, atLeast(1)).getParameters(); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(left, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(right, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); } @Test public void testMethodWithoutSeveralUnmappedArguments() throws Exception { when(sourceParameterList.size()).thenReturn(3); when(left.getTargetParameterIndex(any())).thenReturn(null); when(right.getTargetParameterIndex(any())).thenReturn(null); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution, is(MethodDelegationBinder.AmbiguityResolver.Resolution.AMBIGUOUS)); verify(source, atLeast(1)).getParameters(); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(1))); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(2))); verify(left, never()).getTargetParameterIndex(not(argThat(describesArgument(0, 1, 2)))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(1))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(2))); verify(right, never()).getTargetParameterIndex(not(argThat(describesArgument(0, 1, 2)))); } @Test public void testLeftMethodDominantByType() throws Exception { when(sourceParameterList.size()).thenReturn(1); when(leftParameterList.get(0)).thenReturn(dominantTargetParameter); when(left.getTargetParameterIndex(any())).thenAnswer(new TokenAnswer(new int[][]{{0, 0}})); when(rightParameterList.get(1)).thenReturn(weakTargetParameter); when(right.getTargetParameterIndex(any())).thenAnswer(new TokenAnswer(new int[][]{{0, 1}})); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution, is(MethodDelegationBinder.AmbiguityResolver.Resolution.LEFT)); verify(source, atLeast(1)).getParameters(); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(left, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(right, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); } @Test public void testRightMethodDominantByType() throws Exception { when(sourceParameterList.size()).thenReturn(1); when(leftParameterList.get(0)).thenReturn(weakTargetParameter); when(left.getTargetParameterIndex(any())).thenAnswer(new TokenAnswer(new int[][]{{0, 0}})); when(rightParameterList.get(1)).thenReturn(dominantTargetParameter); when(right.getTargetParameterIndex(any())).thenAnswer(new TokenAnswer(new int[][]{{0, 1}})); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution, is(MethodDelegationBinder.AmbiguityResolver.Resolution.RIGHT)); verify(source, atLeast(1)).getParameters(); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(left, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(right, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); } @Test public void testAmbiguousByCrossAssignableType() throws Exception { when(sourceParameterList.size()).thenReturn(1); when(leftParameterList.get(0)).thenReturn(weakTargetParameter); when(left.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}})); when(rightParameterList.get(0)).thenReturn(weakTargetParameter); when(right.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}})); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution, is(MethodDelegationBinder.AmbiguityResolver.Resolution.AMBIGUOUS)); verify(source, atLeast(1)).getParameters(); verify(leftMethod, atLeast(1)).getParameters(); verify(rightMethod, atLeast(1)).getParameters(); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(left, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(right, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); } @Test public void testAmbiguousByNonCrossAssignableType() throws Exception { when(sourceParameterList.size()).thenReturn(1); when(leftParameterList.get(0)).thenReturn(dominantTargetParameter); when(left.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}})); when(rightParameterList.get(0)).thenReturn(dominantTargetParameter); when(right.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}})); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution, is(MethodDelegationBinder.AmbiguityResolver.Resolution.AMBIGUOUS)); verify(source, atLeast(1)).getParameters(); verify(leftMethod, atLeast(1)).getParameters(); verify(rightMethod, atLeast(1)).getParameters(); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(left, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(right, never()).getTargetParameterIndex(not(argThat(describesArgument(0)))); } @Test public void testAmbiguousByDifferentIndexedAssignableType() throws Exception { when(sourceParameterList.size()).thenReturn(2); when(leftParameterList.get(0)).thenReturn(dominantTargetParameter); when(leftParameterList.get(1)).thenReturn(weakTargetParameter); when(left.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}, {1, 1}})); when(rightParameterList.get(0)).thenReturn(weakTargetParameter); when(rightParameterList.get(1)).thenReturn(dominantTargetParameter); when(right.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}, {1, 1}})); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution, is(MethodDelegationBinder.AmbiguityResolver.Resolution.AMBIGUOUS)); verify(source, atLeast(1)).getParameters(); verify(leftMethod, atLeast(1)).getParameters(); verify(rightMethod, atLeast(1)).getParameters(); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(1))); verify(left, never()).getTargetParameterIndex(not(argThat(describesArgument(0, 1)))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(1))); verify(right, never()).getTargetParameterIndex(not(argThat(describesArgument(0, 1)))); } @Test public void testLeftMethodDominantByScore() throws Exception { when(sourceParameterList.size()).thenReturn(2); when(leftParameterList.get(0)).thenReturn(dominantTargetParameter); when(leftParameterList.get(1)).thenReturn(weakTargetParameter); when(left.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}, {1, 1}})); when(rightParameterList.get(0)).thenReturn(dominantTargetParameter); when(right.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}})); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution, is(MethodDelegationBinder.AmbiguityResolver.Resolution.LEFT)); verify(source, atLeast(1)).getParameters(); verify(leftMethod, atLeast(1)).getParameters(); verify(rightMethod, atLeast(1)).getParameters(); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(1))); verify(left, never()).getTargetParameterIndex(not(argThat(describesArgument(0, 1)))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(1))); verify(right, never()).getTargetParameterIndex(not(argThat(describesArgument(0, 1)))); } @Test public void testRightMethodDominantByScore() throws Exception { when(sourceParameterList.size()).thenReturn(2); when(leftParameterList.get(0)).thenReturn(dominantTargetParameter); when(left.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}})); when(rightParameterList.get(0)).thenReturn(dominantTargetParameter); when(rightParameterList.get(1)).thenReturn(dominantTargetParameter); when(right.getTargetParameterIndex(any(ArgumentTypeResolver.ParameterIndexToken.class))) .thenAnswer(new TokenAnswer(new int[][]{{0, 0}, {1, 1}})); MethodDelegationBinder.AmbiguityResolver.Resolution resolution = ArgumentTypeResolver.INSTANCE.resolve(source, left, right); assertThat(resolution, is(MethodDelegationBinder.AmbiguityResolver.Resolution.RIGHT)); verify(source, atLeast(1)).getParameters(); verify(leftMethod, atLeast(1)).getParameters(); verify(rightMethod, atLeast(1)).getParameters(); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(left, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(1))); verify(left, never()).getTargetParameterIndex(not(argThat((describesArgument(0, 1))))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(0))); verify(right, atLeast(1)).getTargetParameterIndex(argThat(describesArgument(1))); verify(right, never()).getTargetParameterIndex(not(argThat(describesArgument(0, 1)))); } @Test public void testObjectProperties() throws Exception { ObjectPropertyAssertion.of(ArgumentTypeResolver.class).apply(); ObjectPropertyAssertion.of(ArgumentTypeResolver.PrimitiveTypePrecedence.class).apply(); ObjectPropertyAssertion.of(ArgumentTypeResolver.ParameterIndexToken.class).apply(); } }