package net.bytebuddy.implementation;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.implementation.bytecode.constant.TextConstant;
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.test.utility.*;
import net.bytebuddy.utility.JavaConstant;
import net.bytebuddy.utility.JavaType;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.junit.rules.TestRule;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Iterator;
import java.util.concurrent.Callable;
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.*;
public class MethodCallTest {
private static final String FOO = "foo", BAR = "bar", INVOKE_FOO = "invokeFoo";
private static final String SINGLE_DEFAULT_METHOD = "net.bytebuddy.test.precompiled.SingleDefaultMethodInterface";
@Rule
public TestRule methodRule = new MockitoRule(this);
@Rule
public MethodRule javaVersionRule = new JavaVersionRule();
@Mock
private Assigner nonAssigner;
private static Object makeMethodType(Class<?> returnType, Class<?>... parameterType) throws Exception {
return JavaType.METHOD_TYPE.load().getDeclaredMethod("methodType", Class.class, Class[].class).invoke(null, returnType, parameterType);
}
private static Object makeMethodHandle() throws Exception {
Object lookup = Class.forName("java.lang.invoke.MethodHandles").getDeclaredMethod("publicLookup").invoke(null);
return JavaType.METHOD_HANDLES_LOOKUP.load().getDeclaredMethod("findStatic", Class.class, String.class, JavaType.METHOD_TYPE.load())
.invoke(lookup, Foo.class, BAR, makeMethodType(String.class, Object.class, Object.class));
}
@Before
public void setUp() throws Exception {
when(nonAssigner.assign(Mockito.any(TypeDescription.Generic.class),
Mockito.any(TypeDescription.Generic.class),
Mockito.any(Assigner.Typing.class))).thenReturn(StackManipulation.Illegal.INSTANCE);
}
@Test
public void testStaticMethodInvocationWithoutArguments() throws Exception {
DynamicType.Loaded<SimpleMethod> loaded = new ByteBuddy()
.subclass(SimpleMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(SimpleMethod.class.getDeclaredMethod(BAR)))
.make()
.load(SimpleMethod.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
SimpleMethod instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.foo(), is(BAR));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(SimpleMethod.class)));
assertThat(instance, instanceOf(SimpleMethod.class));
}
@Test
public void testExternalStaticMethodInvocationWithoutArguments() throws Exception {
DynamicType.Loaded<SimpleMethod> loaded = new ByteBuddy()
.subclass(SimpleMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(StaticExternalMethod.class.getDeclaredMethod(BAR)))
.make()
.load(SimpleMethod.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
SimpleMethod instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.foo(), is(BAR));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(SimpleMethod.class)));
assertThat(instance, instanceOf(SimpleMethod.class));
}
@Test
public void testInstanceMethodInvocationWithoutArguments() throws Exception {
DynamicType.Loaded<InstanceMethod> loaded = new ByteBuddy()
.subclass(InstanceMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(InstanceMethod.class.getDeclaredMethod(BAR)))
.make()
.load(SimpleMethod.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
InstanceMethod instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.foo(), is(BAR));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(InstanceMethod.class)));
assertThat(instance, instanceOf(InstanceMethod.class));
}
@Test
public void testInstanceMethodInvocationWithoutArgumentsByMatcher() throws Exception {
DynamicType.Loaded<InstanceMethod> loaded = new ByteBuddy()
.subclass(InstanceMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(named(BAR)))
.make()
.load(SimpleMethod.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
InstanceMethod instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.foo(), is(BAR));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(InstanceMethod.class)));
assertThat(instance, instanceOf(InstanceMethod.class));
}
@Test(expected = IllegalStateException.class)
public void testMatchedCallAmbiguous() throws Exception {
new ByteBuddy()
.subclass(InstanceMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(ElementMatchers.any()))
.make();
}
@Test(expected = IllegalArgumentException.class)
public void testOnArgumentInvocationNegativeArgument() throws Exception {
MethodCall.invoke(Object.class.getDeclaredMethod("toString")).onArgument(-1);
}
@Test(expected = IllegalArgumentException.class)
public void testOnArgumentInvocationNonExisting() throws Exception {
new ByteBuddy()
.subclass(ArgumentCall.class)
.method(isDeclaredBy(ArgumentCall.class))
.intercept(MethodCall.invoke(Object.class.getDeclaredMethod("toString")).onArgument(10))
.make();
}
@Test
public void testInvokeOnArgument() throws Exception {
DynamicType.Loaded<ArgumentCall> loaded = new ByteBuddy()
.subclass(ArgumentCall.class)
.method(isDeclaredBy(ArgumentCall.class))
.intercept(MethodCall.invoke(ArgumentCall.Target.class.getDeclaredMethod("foo")).onArgument(0))
.make()
.load(ArgumentCall.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
ArgumentCall instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.foo(new ArgumentCall.Target(BAR)), is(BAR));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(InstanceMethod.class)));
assertThat(instance, instanceOf(ArgumentCall.class));
}
@Test(expected = IllegalStateException.class)
public void testInvokeOnArgumentNonAssignable() throws Exception {
new ByteBuddy()
.subclass(ArgumentCallDynamic.class)
.method(isDeclaredBy(ArgumentCallDynamic.class))
.intercept(MethodCall.invoke(ArgumentCallDynamic.Target.class.getDeclaredMethod("foo")).onArgument(0))
.make();
}
@Test(expected = IllegalStateException.class)
public void testInvokeOnArgumentNonVirtual() throws Exception {
new ByteBuddy()
.subclass(ArgumentCallDynamic.class)
.method(isDeclaredBy(ArgumentCallDynamic.class))
.intercept(MethodCall.invoke(NonVirtual.class.getDeclaredMethod("foo")).onArgument(0))
.make();
}
@Test
public void testInvokeOnArgumentDynamic() throws Exception {
DynamicType.Loaded<ArgumentCallDynamic> loaded = new ByteBuddy()
.subclass(ArgumentCallDynamic.class)
.method(isDeclaredBy(ArgumentCallDynamic.class))
.intercept(MethodCall.invoke(ArgumentCallDynamic.Target.class.getDeclaredMethod("foo")).onArgument(0)
.withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC))
.make()
.load(ArgumentCallDynamic.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
ArgumentCallDynamic instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.foo(new ArgumentCallDynamic.Target(BAR)), is(BAR));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(InstanceMethod.class)));
assertThat(instance, instanceOf(ArgumentCallDynamic.class));
}
@Test
public void testSuperConstructorInvocationWithoutArguments() throws Exception {
DynamicType.Loaded<Object> loaded = new ByteBuddy()
.subclass(Object.class)
.constructor(ElementMatchers.any())
.intercept(MethodCall.invoke(Object.class.getDeclaredConstructor()).onSuper())
.make()
.load(Object.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(0));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
Object instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(Object.class)));
assertThat(instance, instanceOf(Object.class));
}
@Test
public void testObjectConstruction() throws Exception {
DynamicType.Loaded<SelfReference> loaded = new ByteBuddy()
.subclass(SelfReference.class)
.method(isDeclaredBy(SelfReference.class))
.intercept(MethodCall.construct(SelfReference.class.getDeclaredConstructor()))
.make()
.load(SelfReference.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
SelfReference instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
SelfReference created = instance.foo();
assertThat(created.getClass(), CoreMatchers.<Class<?>>is(SelfReference.class));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(SelfReference.class)));
assertThat(instance, instanceOf(SelfReference.class));
assertThat(created, not(instance));
}
@Test
public void testSelfInvocation() throws Exception {
SuperMethodInvocation delegate = mock(SuperMethodInvocation.class);
when(delegate.foo()).thenReturn(FOO);
DynamicType.Loaded<SuperMethodInvocation> loaded = new ByteBuddy()
.subclass(SuperMethodInvocation.class)
.method(takesArguments(0).and(named(FOO)))
.intercept(MethodCall.invokeSelf().on(delegate))
.make()
.load(SuperMethodInvocation.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(1));
SuperMethodInvocation instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(SuperMethodInvocation.class)));
assertThat(instance, instanceOf(SuperMethodInvocation.class));
assertThat(instance.foo(), is(FOO));
verify(delegate).foo();
verifyNoMoreInteractions(delegate);
}
@Test
public void testSuperInvocation() throws Exception {
DynamicType.Loaded<SuperMethodInvocation> loaded = new ByteBuddy()
.subclass(SuperMethodInvocation.class)
.method(takesArguments(0).and(named(FOO)))
.intercept(MethodCall.invokeSuper())
.make()
.load(SuperMethodInvocation.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
SuperMethodInvocation instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(SuperMethodInvocation.class)));
assertThat(instance, instanceOf(SuperMethodInvocation.class));
assertThat(instance.foo(), is(FOO));
}
@Test
public void testWithExplicitArgumentConstantPool() throws Exception {
DynamicType.Loaded<MethodCallWithExplicitArgument> loaded = new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.method(isDeclaredBy(MethodCallWithExplicitArgument.class))
.intercept(MethodCall.invokeSuper().with(FOO))
.make()
.load(MethodCallWithExplicitArgument.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, String.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallWithExplicitArgument instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithExplicitArgument.class)));
assertThat(instance, instanceOf(MethodCallWithExplicitArgument.class));
assertThat(instance.foo(BAR), is(FOO));
}
@Test(expected = IllegalStateException.class)
public void testWithExplicitArgumentConstantPoolNonAssignable() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.method(isDeclaredBy(MethodCallWithExplicitArgument.class))
.intercept(MethodCall.invokeSuper().with(FOO).withAssigner(nonAssigner, Assigner.Typing.STATIC))
.make();
}
@Test
public void testWithExplicitArgumentStackManipulation() throws Exception {
DynamicType.Loaded<MethodCallWithExplicitArgument> loaded = new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.method(isDeclaredBy(MethodCallWithExplicitArgument.class))
.intercept(MethodCall.invokeSuper().with(new TextConstant(FOO), String.class))
.make()
.load(MethodCallWithExplicitArgument.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, String.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallWithExplicitArgument instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithExplicitArgument.class)));
assertThat(instance, instanceOf(MethodCallWithExplicitArgument.class));
assertThat(instance.foo(BAR), is(FOO));
}
@Test
public void testWithExplicitArgumentField() throws Exception {
DynamicType.Loaded<MethodCallWithExplicitArgument> loaded = new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.method(isDeclaredBy(MethodCallWithExplicitArgument.class))
.intercept(MethodCall.invokeSuper().withReference(FOO))
.make()
.load(MethodCallWithExplicitArgument.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, String.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(1));
MethodCallWithExplicitArgument instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithExplicitArgument.class)));
assertThat(instance, instanceOf(MethodCallWithExplicitArgument.class));
assertThat(instance.foo(BAR), is(FOO));
}
@Test(expected = IllegalStateException.class)
public void testWithExplicitArgumentFieldNonAssignable() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.method(isDeclaredBy(MethodCallWithExplicitArgument.class))
.intercept(MethodCall.invokeSuper().withReference(FOO).withAssigner(nonAssigner, Assigner.Typing.STATIC))
.make();
}
@Test
public void testWithArgument() throws Exception {
DynamicType.Loaded<MethodCallWithExplicitArgument> loaded = new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.method(isDeclaredBy(MethodCallWithExplicitArgument.class))
.intercept(MethodCall.invokeSuper().withArgument(0))
.make()
.load(MethodCallWithExplicitArgument.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, String.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallWithExplicitArgument instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithExplicitArgument.class)));
assertThat(instance, instanceOf(MethodCallWithExplicitArgument.class));
assertThat(instance.foo(BAR), is(BAR));
}
@Test
public void testWithAllArguments() throws Exception {
DynamicType.Loaded<MethodCallWithExplicitArgument> loaded = new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.method(isDeclaredBy(MethodCallWithExplicitArgument.class))
.intercept(MethodCall.invokeSuper().withAllArguments())
.make()
.load(MethodCallWithExplicitArgument.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, String.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallWithExplicitArgument instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithExplicitArgument.class)));
assertThat(instance, instanceOf(MethodCallWithExplicitArgument.class));
assertThat(instance.foo(BAR), is(BAR));
}
@Test
public void testWithAllArgumentsTwoArguments() throws Exception {
DynamicType.Loaded<MethodCallWithTwoExplicitArguments> loaded = new ByteBuddy()
.subclass(MethodCallWithTwoExplicitArguments.class)
.method(isDeclaredBy(MethodCallWithTwoExplicitArguments.class))
.intercept(MethodCall.invokeSuper().withAllArguments())
.make()
.load(MethodCallWithTwoExplicitArguments.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, String.class, String.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallWithTwoExplicitArguments instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithTwoExplicitArguments.class)));
assertThat(instance, instanceOf(MethodCallWithTwoExplicitArguments.class));
assertThat(instance.foo(FOO, BAR), is(FOO + BAR));
}
@Test
public void testWithArgumentsAsArray() throws Exception {
DynamicType.Loaded<ArrayConsuming> loaded = new ByteBuddy()
.subclass(ArrayConsuming.class)
.method(named(FOO))
.intercept(MethodCall.invoke(ArrayConsuming.class.getDeclaredMethod(BAR, String[].class)).withArgumentArray())
.make()
.load(ArrayConsuming.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, String.class, String.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
ArrayConsuming instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(ArrayConsuming.class)));
assertThat(instance, instanceOf(ArrayConsuming.class));
assertThat(instance.foo(FOO, BAR), is(FOO + BAR));
}
@Test
public void testWithArgumentsFromArray() throws Exception {
DynamicType.Loaded<MethodCallWithExplicitArgument> loaded = new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.implement(MethodCallDelegator.class)
.intercept(MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(0, 1))
.make()
.load(MethodCallDelegator.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(INVOKE_FOO, String[].class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallDelegator instance = (MethodCallDelegator) loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithExplicitArgument.class)));
assertThat(instance, instanceOf(MethodCallDelegator.class));
assertThat(instance.invokeFoo(BAR), is(BAR));
}
@Test
public void testWithArgumentsFromArrayComplete() throws Exception {
DynamicType.Loaded<MethodCallWithExplicitArgument> loaded = new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.implement(MethodCallDelegator.class)
.intercept(MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(0))
.make()
.load(MethodCallDelegator.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(INVOKE_FOO, String[].class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallDelegator instance = (MethodCallDelegator) loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithExplicitArgument.class)));
assertThat(instance, instanceOf(MethodCallDelegator.class));
assertThat(instance.invokeFoo(BAR), is(BAR));
}
@Test
public void testWithArgumentsFromArrayExplicitSize() throws Exception {
DynamicType.Loaded<MethodCallWithExplicitArgument> loaded = new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.implement(MethodCallDelegator.class)
.intercept(MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(0, 1, 1))
.make()
.load(MethodCallDelegator.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(INVOKE_FOO, String[].class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallDelegator instance = (MethodCallDelegator) loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithExplicitArgument.class)));
assertThat(instance, instanceOf(MethodCallDelegator.class));
assertThat(instance.invokeFoo(FOO, BAR, FOO), is(BAR));
}
@Test(expected = IllegalStateException.class)
public void testWithArgumentsFromArrayDoesNotExist() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.implement(MethodCallDelegator.class)
.intercept(MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(1, 1))
.make();
}
@Test(expected = IllegalStateException.class)
public void testWithArgumentsFromArrayDoesNotExistCompleteArray() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.implement(MethodCallDelegator.class)
.intercept(MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(1))
.make();
}
@Test(expected = IllegalStateException.class)
public void testWithArgumentsFromArrayIllegalType() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.implement(IllegalMethodCallDelegator.class)
.intercept(MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(0, 1))
.make();
}
@Test(expected = IllegalStateException.class)
public void testWithArgumentsFromArrayIllegalTypeCompleteArray() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.implement(IllegalMethodCallDelegator.class)
.intercept(MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(0))
.make();
}
@Test(expected = IllegalArgumentException.class)
public void testNegativeIndex() throws Exception {
MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(-1, 1);
}
@Test(expected = IllegalArgumentException.class)
public void testNegativeIndexComplete() throws Exception {
MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(-1);
}
@Test(expected = IllegalArgumentException.class)
public void testNegativeStartIndex() throws Exception {
MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(0, -1, 1);
}
@Test(expected = IllegalArgumentException.class)
public void testNegativeSize() throws Exception {
MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class)).withArgumentArrayElements(0, 1, -1);
}
@Test
public void testSameSize() throws Exception {
MethodCall methodCall = MethodCall.invoke(MethodCallWithExplicitArgument.class.getDeclaredMethod("foo", String.class));
assertThat(methodCall.withArgumentArrayElements(0, 0), sameInstance(methodCall));
}
@Test(expected = IllegalStateException.class)
public void testWithTooBigParameter() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.method(isDeclaredBy(MethodCallWithExplicitArgument.class))
.intercept(MethodCall.invokeSuper().withArgument(1))
.make();
}
@Test(expected = IllegalStateException.class)
public void testWithParameterNonAssignable() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithExplicitArgument.class)
.method(isDeclaredBy(MethodCallWithExplicitArgument.class))
.intercept(MethodCall.invokeSuper().withArgument(0).withAssigner(nonAssigner, Assigner.Typing.STATIC))
.make();
}
@Test
public void testWithField() throws Exception {
DynamicType.Loaded<MethodCallWithField> loaded = new ByteBuddy()
.subclass(MethodCallWithField.class)
.method(isDeclaredBy(MethodCallWithField.class))
.intercept(MethodCall.invokeSuper().withField(FOO))
.make()
.load(MethodCallWithField.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, String.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallWithField instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
instance.foo = FOO;
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithField.class)));
assertThat(instance, instanceOf(MethodCallWithField.class));
assertThat(instance.foo(BAR), is(FOO));
}
@Test(expected = IllegalStateException.class)
public void testWithFieldNotExist() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithField.class)
.method(isDeclaredBy(MethodCallWithField.class))
.intercept(MethodCall.invokeSuper().withField(BAR))
.make();
}
@Test(expected = IllegalStateException.class)
public void testWithFieldNonAssignable() throws Exception {
new ByteBuddy()
.subclass(MethodCallWithField.class)
.method(isDeclaredBy(MethodCallWithField.class))
.intercept(MethodCall.invokeSuper().withField(FOO).withAssigner(nonAssigner, Assigner.Typing.STATIC))
.make();
}
@Test
public void testWithFieldHierarchyVisibility() throws Exception {
DynamicType.Loaded<InvisibleMethodCallWithField> loaded = new ByteBuddy()
.subclass(InvisibleMethodCallWithField.class)
.method(isDeclaredBy(InvisibleMethodCallWithField.class))
.intercept(MethodCall.invokeSuper().withField(FOO))
.make()
.load(InvisibleMethodCallWithField.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, String.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
InvisibleMethodCallWithField instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
((InvisibleBase) instance).foo = FOO;
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(InvisibleMethodCallWithField.class)));
assertThat(instance, instanceOf(InvisibleMethodCallWithField.class));
assertThat(instance.foo(BAR), is(FOO));
}
@Test
public void testWithThis() throws Exception {
DynamicType.Loaded<MethodCallWithThis> loaded = new ByteBuddy()
.subclass(MethodCallWithThis.class)
.method(isDeclaredBy(MethodCallWithThis.class))
.intercept(MethodCall.invokeSuper().withThis())
.make()
.load(MethodCallWithThis.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, MethodCallWithThis.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallWithThis instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithThis.class)));
assertThat(instance, instanceOf(MethodCallWithThis.class));
assertThat(instance.foo(null), is(instance));
}
@Test
public void testWithOwnType() throws Exception {
DynamicType.Loaded<MethodCallWithOwnType> loaded = new ByteBuddy()
.subclass(MethodCallWithOwnType.class)
.method(isDeclaredBy(MethodCallWithOwnType.class))
.intercept(MethodCall.invokeSuper().withOwnType())
.make()
.load(MethodCallWithOwnType.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO, Class.class), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallWithOwnType instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallWithThis.class)));
assertThat(instance, instanceOf(MethodCallWithOwnType.class));
assertThat(instance.foo(null), CoreMatchers.<Class<?>>is(loaded.getLoaded()));
}
@Test
public void testImplementationAppendingMethod() throws Exception {
DynamicType.Loaded<MethodCallAppending> loaded = new ByteBuddy()
.subclass(MethodCallAppending.class)
.method(isDeclaredBy(MethodCallAppending.class))
.intercept(MethodCall.invokeSuper().andThen(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE)))
.make()
.load(MethodCallAppending.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallAppending instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallAppending.class)));
assertThat(instance, instanceOf(MethodCallAppending.class));
assertThat(instance.foo(), is((Object) FOO));
instance.assertOnlyCall(FOO);
}
@Test
public void testImplementationAppendingConstructor() throws Exception {
DynamicType.Loaded<MethodCallAppending> loaded = new ByteBuddy()
.subclass(MethodCallAppending.class)
.method(isDeclaredBy(MethodCallAppending.class))
.intercept(MethodCall.construct(Object.class.getDeclaredConstructor())
.andThen(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE)))
.make()
.load(MethodCallAppending.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
MethodCallAppending instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(MethodCallAppending.class)));
assertThat(instance, instanceOf(MethodCallAppending.class));
assertThat(instance.foo(), is((Object) FOO));
instance.assertZeroCalls();
}
@Test
public void testWithExplicitTarget() throws Exception {
Object target = new Object();
DynamicType.Loaded<ExplicitTarget> loaded = new ByteBuddy()
.subclass(ExplicitTarget.class)
.method(isDeclaredBy(ExplicitTarget.class))
.intercept(MethodCall.invoke(Object.class.getDeclaredMethod("toString")).on(target))
.make()
.load(ExplicitTarget.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(1));
ExplicitTarget instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(ExplicitTarget.class)));
assertThat(instance, instanceOf(ExplicitTarget.class));
assertThat(instance.foo(), is(target.toString()));
}
@Test
public void testWithFieldTarget() throws Exception {
Object target = new Object();
DynamicType.Loaded<ExplicitTarget> loaded = new ByteBuddy()
.subclass(ExplicitTarget.class)
.defineField(FOO, Object.class, Visibility.PUBLIC)
.method(isDeclaredBy(ExplicitTarget.class))
.intercept(MethodCall.invoke(Object.class.getDeclaredMethod("toString")).onField(FOO))
.make()
.load(ExplicitTarget.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredMethod(FOO), not(nullValue(Method.class)));
assertThat(loaded.getLoaded().getDeclaredConstructors().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(1));
ExplicitTarget instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
loaded.getLoaded().getDeclaredField(FOO).set(instance, target);
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(ExplicitTarget.class)));
assertThat(instance, instanceOf(ExplicitTarget.class));
assertThat(instance.foo(), is(target.toString()));
}
@Test
public void testUnloadedType() throws Exception {
DynamicType.Loaded<SimpleMethod> loaded = new ByteBuddy()
.subclass(SimpleMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(Foo.class.getDeclaredMethod(BAR, Object.class, Object.class)).with(TypeDescription.OBJECT, TypeDescription.STRING))
.make()
.load(SimpleMethod.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
SimpleMethod instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.foo(), is("" + Object.class + String.class));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(SimpleMethod.class)));
assertThat(instance, instanceOf(SimpleMethod.class));
}
@Test
@JavaVersionRule.Enforce(value = 7, hotSpot = 7)
public void testJava7Types() throws Exception {
DynamicType.Loaded<SimpleMethod> loaded = new ByteBuddy()
.subclass(SimpleMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(Foo.class.getDeclaredMethod(BAR, Object.class, Object.class)).with(makeMethodHandle(), makeMethodType(void.class)))
.make()
.load(SimpleMethod.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
SimpleMethod instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.foo(), is("" + makeMethodHandle() + makeMethodType(void.class)));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(SimpleMethod.class)));
assertThat(instance, instanceOf(SimpleMethod.class));
}
@Test
@JavaVersionRule.Enforce(value = 7, hotSpot = 7)
public void testJava7TypesExplicit() throws Exception {
DynamicType.Loaded<SimpleMethod> loaded = new ByteBuddy()
.subclass(SimpleMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(Foo.class.getDeclaredMethod(BAR, Object.class, Object.class))
.with(JavaConstant.MethodHandle.ofLoaded(makeMethodHandle()), JavaConstant.MethodType.ofLoaded(makeMethodType(void.class))))
.make()
.load(SimpleMethod.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoadedAuxiliaryTypes().size(), is(0));
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
assertThat(loaded.getLoaded().getDeclaredFields().length, is(0));
SimpleMethod instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(instance.foo(), is("" + makeMethodHandle() + makeMethodType(void.class)));
assertThat(instance.getClass(), not(CoreMatchers.<Class<?>>is(SimpleMethod.class)));
assertThat(instance, instanceOf(SimpleMethod.class));
}
@Test
@JavaVersionRule.Enforce(8)
public void testDefaultMethod() throws Exception {
DynamicType.Loaded<Object> loaded = new ByteBuddy()
.subclass(Object.class)
.implement(Class.forName(SINGLE_DEFAULT_METHOD))
.method(ElementMatchers.not(isDeclaredBy(Object.class)))
.intercept(MethodCall.invoke(Class.forName(SINGLE_DEFAULT_METHOD).getDeclaredMethod(FOO)).onDefault())
.make()
.load(Class.forName(SINGLE_DEFAULT_METHOD).getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoaded().getDeclaredMethods().length, is(1));
Method method = loaded.getLoaded().getDeclaredMethod(FOO);
Object instance = loaded.getLoaded().getDeclaredConstructor().newInstance();
assertThat(method.invoke(instance), is((Object) FOO));
}
@Test
public void testCallable() throws Exception {
Traceable traceable = new Traceable();
DynamicType.Loaded<SimpleStringMethod> loaded = new ByteBuddy()
.subclass(SimpleStringMethod.class)
.method(isDeclaredBy(SimpleStringMethod.class))
.intercept(MethodCall.call(traceable))
.make()
.load(SimpleStringMethod.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoaded().getDeclaredConstructor().newInstance().foo(), is(FOO));
traceable.assertOnlyCall(FOO);
}
@Test
public void testRunnable() throws Exception {
Traceable traceable = new Traceable();
DynamicType.Loaded<SimpleStringMethod> loaded = new ByteBuddy()
.subclass(SimpleStringMethod.class)
.method(isDeclaredBy(SimpleStringMethod.class))
.intercept(MethodCall.run(traceable))
.make()
.load(SimpleStringMethod.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
assertThat(loaded.getLoaded().getDeclaredConstructor().newInstance().foo(), nullValue(String.class));
traceable.assertOnlyCall(FOO);
}
@Test(expected = IllegalStateException.class)
public void testDefaultMethodNotCompatible() throws Exception {
new ByteBuddy()
.subclass(Object.class)
.method(isDeclaredBy(Object.class))
.intercept(MethodCall.invoke(String.class.getDeclaredMethod("toString")).onDefault())
.make();
}
@Test(expected = IllegalStateException.class)
public void testMethodTypeIncompatible() throws Exception {
new ByteBuddy()
.subclass(InstanceMethod.class)
.method(isDeclaredBy(InstanceMethod.class))
.intercept(MethodCall.invoke(String.class.getDeclaredMethod("toLowerCase")))
.make();
}
@Test(expected = IllegalStateException.class)
public void testArgumentIncompatibleTooFew() throws Exception {
new ByteBuddy()
.subclass(InstanceMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(StaticIncompatibleExternalMethod.class.getDeclaredMethod("bar", String.class)))
.make();
}
@Test(expected = IllegalStateException.class)
public void testArgumentIncompatibleTooMany() throws Exception {
new ByteBuddy()
.subclass(InstanceMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(StaticIncompatibleExternalMethod.class.getDeclaredMethod("bar", String.class)).with(FOO, BAR))
.make();
}
@Test(expected = IllegalStateException.class)
public void testArgumentIncompatibleNotAssignable() throws Exception {
new ByteBuddy()
.subclass(InstanceMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(StaticIncompatibleExternalMethod.class.getDeclaredMethod("bar", String.class)).with(new Object()))
.make();
}
@Test(expected = IllegalArgumentException.class)
public void testConstructNonConstructorThrowsException() throws Exception {
MethodCall.construct(mock(MethodDescription.class));
}
@Test(expected = IllegalArgumentException.class)
public void testIllegalIndex() throws Exception {
MethodCall.invokeSuper().withArgument(-1);
}
@Test(expected = IllegalStateException.class)
public void testMethodCallNonVirtual() throws Exception {
new ByteBuddy()
.subclass(InstanceMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(StaticIncompatibleExternalMethod.class.getDeclaredMethod("bar", String.class)).on(new StaticIncompatibleExternalMethod()).with(FOO))
.make();
}
@Test(expected = IllegalStateException.class)
public void testMethodCallIncompatibleInstance() throws Exception {
new ByteBuddy()
.subclass(InstanceMethod.class)
.method(named(FOO))
.intercept(MethodCall.invoke(StaticIncompatibleExternalMethod.class.getDeclaredMethod("bar", String.class)).on(new Object()).with(FOO))
.make();
}
@Test(expected = IllegalStateException.class)
public void testMethodCallNonVisibleType() throws Exception {
new ByteBuddy()
.subclass(Object.class)
.method(isDeclaredBy(Object.class))
.intercept(MethodCall.invoke(PackagePrivateType.class.getDeclaredMethod("foo")).on(new PackagePrivateType()))
.make();
}
@Test(expected = IllegalStateException.class)
public void testMethodCallStaticTargetNonVisibleType() throws Exception {
new ByteBuddy()
.subclass(Object.class)
.method(isDeclaredBy(Object.class))
.intercept(MethodCall.invoke(PackagePrivateType.class.getDeclaredMethod("bar")))
.make();
}
@Test(expected = IllegalStateException.class)
public void testMethodCallSuperCallNonInvokable() throws Exception {
new ByteBuddy()
.subclass(Object.class)
.method(isDeclaredBy(Object.class))
.intercept(MethodCall.invoke(Bar.class.getDeclaredMethod("bar")).onSuper())
.make();
}
@Test(expected = IllegalStateException.class)
public void testMethodCallDefaultCallNonInvokable() throws Exception {
new ByteBuddy()
.subclass(Object.class)
.method(isDeclaredBy(Object.class))
.intercept(MethodCall.invoke(Bar.class.getDeclaredMethod("bar")).onDefault())
.make();
}
@Test(expected = IllegalStateException.class)
public void testMethodCallFieldDoesNotExist() throws Exception {
new ByteBuddy()
.subclass(ExplicitTarget.class)
.method(isDeclaredBy(ExplicitTarget.class))
.intercept(MethodCall.invoke(Object.class.getDeclaredMethod("toString")).onField(FOO))
.make();
}
@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(MethodCall.class).apply();
ObjectPropertyAssertion.of(MethodCall.WithoutSpecifiedTarget.class).apply();
ObjectPropertyAssertion.of(MethodCall.Appender.class).apply();
ObjectPropertyAssertion.of(MethodCall.MethodLocator.ForExplicitMethod.class).apply();
ObjectPropertyAssertion.of(MethodCall.MethodLocator.ForInstrumentedMethod.class).apply();
ObjectPropertyAssertion.of(MethodCall.MethodLocator.ForElementMatcher.class).apply();
ObjectPropertyAssertion.of(MethodCall.MethodInvoker.ForContextualInvocation.class).apply();
final Iterator<Class<?>> iterator = Arrays.<Class<?>>asList(String.class, Object.class).iterator();
ObjectPropertyAssertion.of(MethodCall.MethodInvoker.ForVirtualInvocation.class).create(new ObjectPropertyAssertion.Creator<Class<?>>() {
@Override
public Class<?> create() {
return iterator.next();
}
}).apply();
ObjectPropertyAssertion.of(MethodCall.MethodInvoker.ForVirtualInvocation.WithImplicitType.class).apply();
ObjectPropertyAssertion.of(MethodCall.MethodInvoker.ForSuperMethodInvocation.class).apply();
ObjectPropertyAssertion.of(MethodCall.MethodInvoker.ForDefaultMethodInvocation.class).apply();
ObjectPropertyAssertion.of(MethodCall.TerminationHandler.class).apply();
ObjectPropertyAssertion.of(MethodCall.TargetHandler.ForValue.class).apply();
ObjectPropertyAssertion.of(MethodCall.TargetHandler.ForField.class).apply();
ObjectPropertyAssertion.of(MethodCall.TargetHandler.ForSelfOrStaticInvocation.class).apply();
ObjectPropertyAssertion.of(MethodCall.TargetHandler.ForConstructingInvocation.class).apply();
ObjectPropertyAssertion.of(MethodCall.TargetHandler.ForMethodParameter.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForNullConstant.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForThisReference.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForThisReference.Factory.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForInstrumentedType.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForInstrumentedType.Factory.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForInstance.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForInstance.Factory.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForField.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForField.Factory.class).apply();
// ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForStackManipulation.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForMethodParameter.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForMethodParameter.Factory.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForMethodParameter.OfInstrumentedMethod.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForMethodParameterArray.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForMethodParameterArray.Factory.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForMethodParameterArrayElement.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForMethodParameterArrayElement.OfParameter.class).apply();
ObjectPropertyAssertion.of(MethodCall.ArgumentLoader.ForMethodParameterArrayElement.OfInvokedMethod.class).apply();
}
public static class SimpleMethod {
public String foo() {
return null;
}
public String bar() {
return BAR;
}
}
public static class StaticExternalMethod {
public static String bar() {
return BAR;
}
}
public static class InstanceMethod {
public String foo() {
return null;
}
public String bar() {
return BAR;
}
}
public abstract static class ArgumentCall {
public abstract String foo(Target target);
public static class Target {
private final String value;
public Target(String value) {
this.value = value;
}
public String foo() {
return value;
}
}
}
public abstract static class ArgumentCallDynamic {
public abstract String foo(Object target);
public static class Target {
private final String value;
public Target(String value) {
this.value = value;
}
public String foo() {
return value;
}
}
}
public static class SelfReference {
public SelfReference foo() {
return null;
}
}
public static class SuperMethodInvocation {
public String foo() {
return FOO;
}
}
public static class MethodCallWithExplicitArgument {
public String foo(String value) {
return value;
}
}
public static class MethodCallWithTwoExplicitArguments {
public String foo(String first, String second) {
return first + second;
}
}
public interface MethodCallDelegator {
String invokeFoo(String... argument);
}
public interface IllegalMethodCallDelegator {
String invokeFoo(String argument);
}
@SuppressWarnings("unused")
public static class MethodCallWithField {
public String foo;
public String foo(String value) {
return value;
}
}
@SuppressWarnings("unused")
public static class InvisibleMethodCallWithField extends InvisibleBase {
private String foo;
public String foo(String value) {
return value;
}
}
public static class InvisibleBase {
public String foo;
}
public static class MethodCallWithThis {
public MethodCallWithThis foo(MethodCallWithThis value) {
return value;
}
}
public static class MethodCallWithOwnType {
public Class<?> foo(Class<?> value) {
return value;
}
}
public static class MethodCallAppending extends CallTraceable {
public Object foo() {
register(FOO);
return null;
}
}
public static class ExplicitTarget {
public String foo() {
return null;
}
}
@SuppressWarnings("unused")
public static class StaticIncompatibleExternalMethod {
public static String bar(String value) {
return null;
}
}
public static class Foo {
public static String bar(Object arg0, Object arg1) {
return "" + arg0 + arg1;
}
}
static class PackagePrivateType {
public String foo() {
return FOO;
}
public static String bar() {
return BAR;
}
}
public static class Bar {
public void bar() {
/* empty */
}
}
public static class SimpleStringMethod {
public String foo() {
return null;
}
}
public static class Traceable extends CallTraceable implements Runnable, Callable<String> {
@Override
public String call() throws Exception {
register(FOO);
return FOO;
}
@Override
public void run() {
register(FOO);
}
}
public static class NonVirtual {
public static void foo() {
/* empty */
}
}
public abstract static class ArrayConsuming {
public abstract String foo(String arg1, String arg2);
public String bar(String[] arg) {
return arg[0] + arg[1];
}
}
}