package net.bytebuddy.implementation;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.modifier.FieldManifestation;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.test.utility.CallTraceable;
import net.bytebuddy.test.utility.ObjectPropertyAssertion;
import org.junit.Test;
import java.lang.reflect.Field;
import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
public class FieldAccessorOtherTest {
private static final String FOO = "foo", BAR = "bar", QUX = "qux", BAZ = "baz";
@Test
public void testArgumentSetter() throws Exception {
Class<? extends SampleArgumentSetter> loaded = new ByteBuddy()
.subclass(SampleArgumentSetter.class)
.method(named(FOO))
.intercept(FieldAccessor.ofField(FOO).setsArgumentAt(0))
.make()
.load(SampleArgumentSetter.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
SampleArgumentSetter sampleArgumentSetter = loaded.getDeclaredConstructor().newInstance();
sampleArgumentSetter.foo(FOO);
assertThat(sampleArgumentSetter.foo, is((Object) FOO));
}
@Test
public void testArgumentSetterChained() throws Exception {
Class<? extends SampleArgumentSetter> loaded = new ByteBuddy()
.subclass(SampleArgumentSetter.class)
.method(named(BAR))
.intercept(FieldAccessor.ofField(FOO).setsArgumentAt(0).andThen(FixedValue.value(BAR)))
.make()
.load(SampleArgumentSetter.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
SampleArgumentSetter sampleArgumentSetter = loaded.getDeclaredConstructor().newInstance();
assertThat(sampleArgumentSetter.bar(FOO), is((Object) BAR));
assertThat(sampleArgumentSetter.foo, is((Object) FOO));
}
@Test(expected = IllegalStateException.class)
public void testArgumentSetterNonVoid() throws Exception {
new ByteBuddy()
.subclass(SampleArgumentSetter.class)
.method(named(BAR))
.intercept(FieldAccessor.ofField(FOO).setsArgumentAt(0))
.make();
}
@Test
public void testArgumentSetterConstructor() throws Exception {
Class<?> loaded = new ByteBuddy()
.subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS)
.defineField(FOO, String.class, Visibility.PUBLIC, FieldManifestation.FINAL)
.defineConstructor(Visibility.PUBLIC)
.withParameters(String.class)
.intercept(MethodCall.invoke(Object.class.getDeclaredConstructor()).andThen(FieldAccessor.ofField(FOO).setsArgumentAt(0)))
.make()
.load(null, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(loaded.getDeclaredField(FOO).get(loaded.getDeclaredConstructor(String.class).newInstance(FOO)), is((Object) FOO));
}
@Test(expected = IllegalArgumentException.class)
public void testArgumentCannotBeNegative() throws Exception {
FieldAccessor.ofField(FOO).setsArgumentAt(-1);
}
@Test(expected = IllegalStateException.class)
public void testArgumentSetterNoParameterAtIndex() throws Exception {
new ByteBuddy()
.subclass(SampleArgumentSetter.class)
.method(named(FOO))
.intercept(FieldAccessor.ofField(FOO).setsArgumentAt(1).andThen(FixedValue.value(BAR)))
.make();
}
@Test
public void testExplicitNameSetter() throws Exception {
DynamicType.Loaded<SampleSetter> loaded = new ByteBuddy()
.subclass(SampleSetter.class)
.method(isDeclaredBy(SampleSetter.class))
.intercept(FieldAccessor.ofField(FOO))
.make()
.load(SampleSetter.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
SampleSetter sampleSetter = loaded.getLoaded().getDeclaredConstructor().newInstance();
Field field = SampleSetter.class.getDeclaredField(FOO);
field.setAccessible(true);
assertThat(field.get(sampleSetter), is((Object) QUX));
sampleSetter.bar(BAZ);
assertThat(field.get(sampleSetter), is((Object) BAZ));
sampleSetter.assertZeroCalls();
}
@Test
public void testExplicitNameGetter() throws Exception {
DynamicType.Loaded<SampleGetter> loaded = new ByteBuddy()
.subclass(SampleGetter.class)
.method(isDeclaredBy(SampleGetter.class))
.intercept(FieldAccessor.ofField(FOO))
.make()
.load(SampleSetter.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
SampleGetter sampleGetter = loaded.getLoaded().getDeclaredConstructor().newInstance();
Field field = SampleGetter.class.getDeclaredField(FOO);
field.setAccessible(true);
assertThat(field.get(sampleGetter), is((Object) BAZ));
assertThat(sampleGetter.bar(), is((Object) BAZ));
assertThat(field.get(sampleGetter), is((Object) BAZ));
sampleGetter.assertZeroCalls();
}
@Test(expected = IllegalStateException.class)
public void testNotAssignable() throws Exception {
new ByteBuddy()
.subclass(Baz.class)
.method(isDeclaredBy(Baz.class))
.intercept(FieldAccessor.ofField(FOO))
.make();
}
@Test(expected = IllegalArgumentException.class)
public void testFinalFieldSetter() throws Exception {
new ByteBuddy()
.subclass(Foo.class)
.method(isDeclaredBy(Foo.class))
.intercept(FieldAccessor.ofBeanProperty())
.make();
}
@Test(expected = IllegalStateException.class)
public void testFieldNoVisibleField() throws Exception {
new ByteBuddy()
.subclass(Bar.class)
.method(isDeclaredBy(Bar.class))
.intercept(FieldAccessor.ofBeanProperty())
.make();
}
@Test(expected = IllegalArgumentException.class)
public void testFieldNoBeanMethodName() throws Exception {
new ByteBuddy()
.subclass(Qux.class)
.method(isDeclaredBy(Qux.class))
.intercept(FieldAccessor.ofBeanProperty())
.make();
}
@Test(expected = IllegalStateException.class)
public void testIncompatibleExplicitField() throws Exception {
new ByteBuddy()
.subclass(Qux.class)
.method(isDeclaredBy(Qux.class))
.intercept(FieldAccessor.of(Bar.class.getDeclaredField(BAR)))
.make();
}
@Test(expected = IllegalStateException.class)
public void testInaccessibleExplicitField() throws Exception {
new ByteBuddy()
.subclass(Bar.class)
.method(isDeclaredBy(Bar.class))
.intercept(FieldAccessor.of(Bar.class.getDeclaredField(BAR)))
.make();
}
@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(FieldAccessor.ForImplicitProperty.class).apply();
ObjectPropertyAssertion.of(FieldAccessor.ForImplicitProperty.Appender.class).apply();
ObjectPropertyAssertion.of(FieldAccessor.ForParameterSetter.class).apply();
ObjectPropertyAssertion.of(FieldAccessor.ForParameterSetter.TerminationHandler.class).apply();
ObjectPropertyAssertion.of(FieldAccessor.ForParameterSetter.Appender.class).apply();
ObjectPropertyAssertion.of(FieldAccessor.FieldLocation.Absolute.class).apply();
ObjectPropertyAssertion.of(FieldAccessor.FieldLocation.Relative.class).apply();
ObjectPropertyAssertion.of(FieldAccessor.FieldLocation.Relative.Prepared.class).apply();
}
@SuppressWarnings("unused")
public static class Foo {
protected final Object foo = null;
public void setFoo(Object o) {
/* empty */
}
}
@SuppressWarnings("unused")
public static class Bar {
private Object bar;
public void setBar(Object o) {
/* empty */
}
}
public static class BarSub extends Bar {
/* empty */
}
@SuppressWarnings("unused")
public static class Qux {
private Object qux;
public void qux(Object o) {
/* empty */
}
}
@SuppressWarnings("unused")
public static class Baz {
public String foo;
public void qux(Object o) {
/* empty */
}
}
public static class SampleArgumentSetter {
public Object foo;
public void foo(String value) {
throw new AssertionError();
}
public Object bar(String value) {
throw new AssertionError();
}
}
public static class SampleGetter extends CallTraceable {
protected Object foo = BAZ;
public Object bar() {
register(FOO);
return QUX;
}
}
public static class SampleSetter extends CallTraceable {
protected Object foo = QUX;
public void bar(Object foo) {
register(FOO, foo);
}
}
}