package net.bytebuddy.agent.builder;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ByteArrayClassLoader;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.dynamic.loading.PackageDefinitionStrategy;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.test.utility.AgentAttachmentRule;
import net.bytebuddy.test.utility.ClassFileExtraction;
import net.bytebuddy.test.utility.IntegrationRule;
import net.bytebuddy.utility.JavaModule;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.none;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
public class AgentBuilderDefaultApplicationSuperTypeLoadingTest {
private static final String FOO = "foo", BAR = "bar";
@Rule
public MethodRule agentAttachmentRule = new AgentAttachmentRule();
@Rule
public MethodRule integrationRule = new IntegrationRule();
private ClassLoader classLoader;
private ExecutorService executorService;
@Before
public void setUp() throws Exception {
classLoader = new ByteArrayClassLoader(ClassLoadingStrategy.BOOTSTRAP_LOADER,
ClassFileExtraction.of(Foo.class, Bar.class, AgentBuilderDefaultApplicationSuperTypeLoadingTest.class),
ByteArrayClassLoader.PersistenceHandler.MANIFEST);
executorService = Executors.newCachedThreadPool();
}
@After
public void tearDown() throws Exception {
executorService.shutdownNow();
}
@Test
@AgentAttachmentRule.Enforce
@IntegrationRule.Enforce
public void testSynchronousSuperTypeLoading() throws Exception {
assertThat(ByteBuddyAgent.install(), instanceOf(Instrumentation.class));
ClassFileTransformer classFileTransformer = new AgentBuilder.Default()
.with(AgentBuilder.DescriptionStrategy.Default.POOL_ONLY.withSuperTypeLoading())
.ignore(none())
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
.type(ElementMatchers.isSubTypeOf(Foo.class), ElementMatchers.is(classLoader)).transform(new ConstantTransformer())
.installOnByteBuddyAgent();
try {
Class<?> type = classLoader.loadClass(Bar.class.getName());
assertThat(type.getDeclaredMethod(BAR).invoke(type.getDeclaredConstructor().newInstance()), is((Object) BAR));
assertThat(type.getSuperclass().getDeclaredMethod(FOO).invoke(type.getDeclaredConstructor().newInstance()), nullValue(Object.class));
} finally {
ByteBuddyAgent.getInstrumentation().removeTransformer(classFileTransformer);
}
}
@Test
@AgentAttachmentRule.Enforce
@IntegrationRule.Enforce
public void testAsynchronousSuperTypeLoading() throws Exception {
assertThat(ByteBuddyAgent.install(), instanceOf(Instrumentation.class));
ClassFileTransformer classFileTransformer = new AgentBuilder.Default()
.with(AgentBuilder.DescriptionStrategy.Default.POOL_ONLY.withSuperTypeLoading(executorService))
.ignore(none())
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
.type(ElementMatchers.isSubTypeOf(Foo.class), ElementMatchers.is(classLoader)).transform(new ConstantTransformer())
.installOnByteBuddyAgent();
try {
Class<?> type = classLoader.loadClass(Bar.class.getName());
assertThat(type.getDeclaredMethod(BAR).invoke(type.getDeclaredConstructor().newInstance()), is((Object) BAR));
assertThat(type.getSuperclass().getDeclaredMethod(FOO).invoke(type.getDeclaredConstructor().newInstance()), is((Object) FOO));
} finally {
ByteBuddyAgent.getInstrumentation().removeTransformer(classFileTransformer);
}
}
public static class Foo {
public String foo() {
return null;
}
}
public static class Bar extends Foo {
public String bar() {
return null;
}
}
private static class ConstantTransformer implements AgentBuilder.Transformer {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule module) {
return builder
.method(isDeclaredBy(typeDescription).and(named(FOO))).intercept(FixedValue.value(FOO))
.method(isDeclaredBy(typeDescription).and(named(BAR))).intercept(FixedValue.value(BAR));
}
}
}