/*
* Copyright 2016 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.instrument;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleAroundInterceptor;
import com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorDefinition;
import com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorDefinitionFactory;
import com.navercorp.pinpoint.profiler.instrument.mock.ApiIdAwareInterceptor;
import com.navercorp.pinpoint.profiler.instrument.mock.ArgsArrayInterceptor;
import com.navercorp.pinpoint.profiler.instrument.mock.BaseEnum;
import com.navercorp.pinpoint.profiler.instrument.mock.BasicInterceptor;
import com.navercorp.pinpoint.profiler.instrument.mock.ExceptionInterceptor;
import com.navercorp.pinpoint.profiler.instrument.mock.StaticInterceptor;
import com.navercorp.pinpoint.profiler.interceptor.registry.InterceptorRegistryBinder;
import com.navercorp.pinpoint.profiler.util.TestInterceptorRegistryBinder;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
public class ASMMethodNodeAdapterAddInterceptorTest {
private final static InterceptorRegistryBinder interceptorRegistryBinder = new TestInterceptorRegistryBinder();
private ASMClassNodeLoader.TestClassLoader classLoader;
@BeforeClass
public static void beforeClass() {
interceptorRegistryBinder.bind();
}
@AfterClass
public static void afterClass() {
interceptorRegistryBinder.unbind();
}
@Before
public void before() {
this.classLoader = ASMClassNodeLoader.getClassLoader();
}
@Test
public void addArgsArrayInterceptor() throws Exception {
int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new ArgsArrayInterceptor());
addInterceptor(interceptorId, ArgsArrayInterceptor.class);
}
@Test
public void addStaticInterceptor() throws Exception {
int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new StaticInterceptor());
addInterceptor(interceptorId, StaticInterceptor.class);
}
@Test
public void addApiIdAwareInterceptor() throws Exception {
int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new ApiIdAwareInterceptor());
addInterceptor(interceptorId, ApiIdAwareInterceptor.class);
}
@Test
public void addBasicInterceptor() throws Exception {
int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new BasicInterceptor());
addInterceptor(interceptorId, BasicInterceptor.class);
}
@Ignore
@Test
public void addExceptionInterceptor() throws Exception {
ExceptionHandleAroundInterceptor interceptor = new ExceptionHandleAroundInterceptor(new ExceptionInterceptor());
int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(interceptor);
addInterceptor(interceptorId, ExceptionHandleAroundInterceptor.class);
}
private void addInterceptor(int interceptorId, Class interceptorClass) throws Exception {
// method
checkMethod(interceptorId, interceptorClass);
// constructor
checkConstructor(interceptorId, interceptorClass);
// arguments
checkArguments(interceptorId, interceptorClass);
// return
checkReturn(interceptorId, interceptorClass);
// exception
checkMethodException(interceptorId, interceptorClass);
checkConstructorException(interceptorId, interceptorClass);
// extend
checkExtends(interceptorId, interceptorClass);
}
private void checkMethod(int interceptorId, Class interceptorClass) throws Exception {
// method
Class<?> clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.MethodClass", interceptorClass);
Class[] parameterTypes = new Class[0];
Object[] args = new Object[0];
invokeMethod(clazz, "publicMethod", interceptorClass, parameterTypes, args, null, false);
invokeMethod(clazz, "publicStaticMethod", interceptorClass, parameterTypes, args, null, false);
invokeMethod(clazz, "publicFinalMethod", interceptorClass, parameterTypes, args, null, false);
invokeMethod(clazz, "publicStaticFinalMethod", interceptorClass, parameterTypes, args, null, false);
invokeMethod(clazz, "publicSynchronizedMethod", interceptorClass, parameterTypes, args, null, false);
invokeMethod(clazz, "publicStaticSynchronizedMethod", interceptorClass, parameterTypes, args, null, false);
invokeMethod(clazz, "publicStaticFinalSynchronizedMethod", interceptorClass, parameterTypes, args, null, false);
}
private void checkConstructor(int interceptorId, Class interceptorClass) throws Exception {
Class<?> clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ConstructorClass", interceptorClass);
invokeMethod(clazz, "<init>", interceptorClass, new Class[0], new Object[0], null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{byte.class}, new Object[]{Byte.parseByte("0")}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{short.class}, new Object[]{Short.parseShort("0")}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{int.class}, new Object[]{Integer.parseInt("0")}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{float.class}, new Object[]{Float.parseFloat("0")}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{double.class}, new Object[]{Double.parseDouble("0")}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{boolean.class}, new Object[]{Boolean.parseBoolean("true")}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{char.class}, new Object[]{Character.forDigit(0, 0)}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{byte[].class}, new Object[]{new byte[]{Byte.parseByte("0"), Byte.parseByte("1")}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{short[].class}, new Object[]{new short[]{Short.parseShort("0"), Short.parseShort("1")}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{int[].class}, new Object[]{new int[]{Integer.parseInt("0"), Integer.parseInt("1")}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{float[].class}, new Object[]{new float[]{Float.parseFloat("0"), Float.parseFloat("1")}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{double[].class}, new Object[]{new double[]{Double.parseDouble("0"), Double.parseDouble("1")}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{boolean[].class}, new Object[]{new boolean[]{Boolean.parseBoolean("true"), Boolean.parseBoolean("false")}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{char[].class}, new Object[]{new char[]{Character.forDigit(0, 0), Character.forDigit(1, 1)}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{byte[][].class}, new Object[]{new byte[][]{{Byte.parseByte("0"), Byte.parseByte("1")}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{short[][].class}, new Object[]{new short[][]{{Short.parseShort("0"), Short.parseShort("1")}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{int[][].class}, new Object[]{new int[][]{{Integer.parseInt("0"), Integer.parseInt("1")}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{float[][].class}, new Object[]{new float[][]{{Float.parseFloat("0"), Float.parseFloat("1")}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{double[][].class}, new Object[]{new double[][]{{Double.parseDouble("0"), Double.parseDouble("1")}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{boolean[][].class}, new Object[]{new boolean[][]{{Boolean.parseBoolean("true"), Boolean.parseBoolean("false")}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{char[][].class}, new Object[]{new char[][]{{Character.forDigit(0, 0), Character.forDigit(1, 1)}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{String.class}, new Object[]{"foo"}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Object.class}, new Object[]{new Object()}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Byte.class}, new Object[]{new Byte("0")}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Short.class}, new Object[]{new Short("0")}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Integer.class}, new Object[]{new Integer(0)}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Long.class}, new Object[]{new Long(0)}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Float.class}, new Object[]{new Float(0)}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Double.class}, new Object[]{new Double(0)}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Boolean.class}, new Object[]{new Boolean("true")}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Character.class}, new Object[]{new Character('0')}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{String[].class}, new Object[]{new String[]{"foo", "bar"}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Object[].class}, new Object[]{new Object[]{new Object(), new Object()}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Byte[].class}, new Object[]{new Byte[]{new Byte("0"), new Byte("1")}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Short[].class}, new Object[]{new Short[]{new Short("0"), new Short("1")}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Integer[].class}, new Object[]{new Integer[]{new Integer(0), new Integer(1)}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Long[].class}, new Object[]{new Long[]{new Long(0), new Long(1)}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Float[].class}, new Object[]{new Float[]{new Float(0), new Float(1)}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Double[].class}, new Object[]{new Double[]{new Double(0), new Double(1)}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Boolean[].class}, new Object[]{new Boolean[]{new Boolean("true"), new Boolean("false")}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Character[].class}, new Object[]{new Character[]{new Character('0'), new Character('1')}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{String[][].class}, new Object[]{new String[][]{{"foo", "bar"}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Object[][].class}, new Object[]{new Object[][]{{new Object(), new Object()}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Byte[][].class}, new Object[]{new Byte[][]{{new Byte("0"), new Byte("1")}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Short[][].class}, new Object[]{new Short[][]{{new Short("0"), new Short("1")}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Integer[][].class}, new Object[]{new Integer[][]{{new Integer(0), new Integer(1)}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Long[][].class}, new Object[]{new Long[][]{{new Long(0), new Long(1)}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Float[][].class}, new Object[]{new Float[][]{{new Float(0), new Float(1)}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Double[][].class}, new Object[]{new Double[][]{{new Double(0), new Double(1)}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Boolean[][].class}, new Object[]{new Boolean[][]{{new Boolean("true"), new Boolean("false")}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Character[][].class}, new Object[]{new Character[][]{{new Character('0'), new Character('1')}}}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Class.class, Method.class, Field.class}, new Object[]{null, null, null}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{String.class, int.class, byte.class, Object.class, Enum.class, char.class, float.class, long.class}, new Object[]{"foo", 1, Byte.parseByte("0"), new Object(), BaseEnum.AGENT, 'a', 1.1f, 1l}, null, false);
}
private void checkArguments(int interceptorId, Class interceptorClass) throws Exception {
Class<?> clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ArgsClass", interceptorClass);
invokeMethod(clazz, "arg", interceptorClass, new Class[0], new Object[0], null, false);
invokeMethod(clazz, "argByteType", interceptorClass, new Class[]{byte.class}, new Object[]{Byte.parseByte("0")}, null, false);
invokeMethod(clazz, "argShortType", interceptorClass, new Class[]{short.class}, new Object[]{Short.parseShort("0")}, null, false);
invokeMethod(clazz, "argIntType", interceptorClass, new Class[]{int.class}, new Object[]{Integer.parseInt("0")}, null, false);
invokeMethod(clazz, "argFloatType", interceptorClass, new Class[]{float.class}, new Object[]{Float.parseFloat("0")}, null, false);
invokeMethod(clazz, "argDoubleType", interceptorClass, new Class[]{double.class}, new Object[]{Double.parseDouble("0")}, null, false);
invokeMethod(clazz, "argBooleanType", interceptorClass, new Class[]{boolean.class}, new Object[]{Boolean.parseBoolean("true")}, null, false);
invokeMethod(clazz, "argCharType", interceptorClass, new Class[]{char.class}, new Object[]{Character.forDigit(0, 0)}, null, false);
invokeMethod(clazz, "argByteArrayType", interceptorClass, new Class[]{byte[].class}, new Object[]{new byte[]{Byte.parseByte("0"), Byte.parseByte("1")}}, null, false);
invokeMethod(clazz, "argShortArrayType", interceptorClass, new Class[]{short[].class}, new Object[]{new short[]{Short.parseShort("0"), Short.parseShort("1")}}, null, false);
invokeMethod(clazz, "argIntArrayType", interceptorClass, new Class[]{int[].class}, new Object[]{new int[]{Integer.parseInt("0"), Integer.parseInt("1")}}, null, false);
invokeMethod(clazz, "argFloatArrayType", interceptorClass, new Class[]{float[].class}, new Object[]{new float[]{Float.parseFloat("0"), Float.parseFloat("1")}}, null, false);
invokeMethod(clazz, "argDoubleArrayType", interceptorClass, new Class[]{double[].class}, new Object[]{new double[]{Double.parseDouble("0"), Double.parseDouble("1")}}, null, false);
invokeMethod(clazz, "argBooleanArrayType", interceptorClass, new Class[]{boolean[].class}, new Object[]{new boolean[]{Boolean.parseBoolean("true"), Boolean.parseBoolean("false")}}, null, false);
invokeMethod(clazz, "argCharArrayType", interceptorClass, new Class[]{char[].class}, new Object[]{new char[]{Character.forDigit(0, 0), Character.forDigit(1, 1)}}, null, false);
invokeMethod(clazz, "argByteArraysType", interceptorClass, new Class[]{byte[][].class}, new Object[]{new byte[][]{{Byte.parseByte("0"), Byte.parseByte("1")}}}, null, false);
invokeMethod(clazz, "argShortArraysType", interceptorClass, new Class[]{short[][].class}, new Object[]{new short[][]{{Short.parseShort("0"), Short.parseShort("1")}}}, null, false);
invokeMethod(clazz, "argIntArraysType", interceptorClass, new Class[]{int[][].class}, new Object[]{new int[][]{{Integer.parseInt("0"), Integer.parseInt("1")}}}, null, false);
invokeMethod(clazz, "argFloatArraysType", interceptorClass, new Class[]{float[][].class}, new Object[]{new float[][]{{Float.parseFloat("0"), Float.parseFloat("1")}}}, null, false);
invokeMethod(clazz, "argDoubleArraysType", interceptorClass, new Class[]{double[][].class}, new Object[]{new double[][]{{Double.parseDouble("0"), Double.parseDouble("1")}}}, null, false);
invokeMethod(clazz, "argBooleanArraysType", interceptorClass, new Class[]{boolean[][].class}, new Object[]{new boolean[][]{{Boolean.parseBoolean("true"), Boolean.parseBoolean("false")}}}, null, false);
invokeMethod(clazz, "argCharArraysType", interceptorClass, new Class[]{char[][].class}, new Object[]{new char[][]{{Character.forDigit(0, 0), Character.forDigit(1, 1)}}}, null, false);
invokeMethod(clazz, "argArgs", interceptorClass, new Class[]{Object[].class}, new Object[]{new Object[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}}, null, false);
invokeMethod(clazz, "argArgs2", interceptorClass, new Class[]{int.class, Object[].class}, new Object[]{1, new Object[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}}, null, false);
invokeMethod(clazz, "argInt3", interceptorClass, new Class[]{int.class, int.class, int.class}, new Object[]{1, 2, 3}, null, false);
invokeMethod(clazz, "argObject4", interceptorClass, new Class[]{String.class, Integer.class, Long.class, Float.class}, new Object[]{"foo", 1, 2l, 3.0f}, null, false);
invokeMethod(clazz, "argString5", interceptorClass, new Class[]{String.class, String.class, String.class, String.class, String.class}, new Object[]{"0", "1", "2", "3", "4"}, null, false);
invokeMethod(clazz, "argEnum", interceptorClass, new Class[]{Enum.class}, new Object[]{BaseEnum.AGENT}, null, false);
invokeMethod(clazz, "argInterface", interceptorClass, new Class[]{Map.class, Map.class, Map.class}, new Object[]{new HashMap(), new HashMap<String, String>(), new HashMap<Object, Object>()}, null, false);
}
private void checkReturn(int interceptorId, Class interceptorClass) throws Exception {
Class<?> clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ReturnClass", interceptorClass);
invokeMethod(clazz, "voidType", interceptorClass, new Class[0], new Object[0], null, false);
invokeMethod(clazz, "returnByte", interceptorClass, new Class[0], new Object[0], Byte.parseByte("0"), false);
invokeMethod(clazz, "returnByteObject", interceptorClass, new Class[0], new Object[0], Byte.valueOf("1"), false);
invokeMethod(clazz, "returnInt", interceptorClass, new Class[0], new Object[0], Integer.parseInt("1"), false);
invokeMethod(clazz, "returnIntObject", interceptorClass, new Class[0], new Object[0], Integer.valueOf("1"), false);
invokeMethod(clazz, "returnFloat", interceptorClass, new Class[0], new Object[0], Float.parseFloat("1.1"), false);
invokeMethod(clazz, "returnFloatObject", interceptorClass, new Class[0], new Object[0], Float.valueOf("1.1"), false);
invokeMethod(clazz, "returnBoolean", interceptorClass, new Class[0], new Object[0], Boolean.parseBoolean("true"), false);
invokeMethod(clazz, "returnBooleanObject", interceptorClass, new Class[0], new Object[0], Boolean.valueOf("true"), false);
invokeMethod(clazz, "returnChar", interceptorClass, new Class[0], new Object[0], Character.forDigit(1, 1), false);
invokeMethod(clazz, "returnCharObject", interceptorClass, new Class[0], new Object[0], Character.valueOf('1'), false);
invokeMethod(clazz, "returnString", interceptorClass, new Class[0], new Object[0], new String("s"), false);
invokeMethod(clazz, "returnEnum", interceptorClass, new Class[0], new Object[0], BaseEnum.AGENT, false);
}
private void checkMethodException(int interceptorId, Class interceptorClass) throws Exception {
Class<?> clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ExceptionClass", interceptorClass);
invokeMethod(clazz, "throwable", interceptorClass, new Class[]{}, new Object[]{}, null, true);
invokeMethod(clazz, "exception", interceptorClass, new Class[]{}, new Object[]{}, null, true);
invokeMethod(clazz, "runtime", interceptorClass, new Class[]{}, new Object[]{}, null, true);
invokeMethod(clazz, "io", interceptorClass, new Class[]{}, new Object[]{}, null, true);
invokeMethod(clazz, "io2", interceptorClass, new Class[]{}, new Object[]{}, null, false);
invokeMethod(clazz, "condition", interceptorClass, new Class[]{}, new Object[]{}, null, true);
}
private void checkConstructorException(int interceptorId, Class interceptorClass) throws Exception {
Class clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ConstructorExceptionClass", interceptorClass);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{String.class, int.class}, new Object[]{"foo", 0}, null, true);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Boolean.class}, new Object[]{Boolean.TRUE}, null, true);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Boolean.class}, new Object[]{Boolean.FALSE}, null, false);
}
private void checkExtends(int interceptorId, Class interceptorClass) throws Exception {
addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ConstructorParentClass", interceptorClass);
Class clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ConstructorChildClass", interceptorClass);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{}, new Object[]{}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{String.class}, new Object[]{"foo"}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{String.class, int.class}, new Object[]{"foo", 1}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{Object.class}, new Object[]{"foo"}, null, false);
invokeMethod(clazz, "<init>", interceptorClass, new Class[]{int.class}, new Object[]{1}, null, false);
}
private void invokeMethod(final Class<?> clazz, final String methodName, final Class interceptorClass, final Class[] parameterTypes, final Object[] args, final Object returnValue, final boolean throwable) throws Exception {
ArgsArrayInterceptor.clear();
StaticInterceptor.clear();
ApiIdAwareInterceptor.clear();
BasicInterceptor.clear();
ExceptionInterceptor.clear();
Constructor<?> constructor = null;
Method method = null;
if (methodName.equals("<init>")) {
constructor = clazz.getConstructor(parameterTypes);
try {
constructor.newInstance(args);
if (throwable) {
fail("can't throw Throwable.");
}
} catch (Throwable t) {
if (!throwable) {
throw new RuntimeException(t.getMessage());
}
}
} else {
method = clazz.getDeclaredMethod(methodName, parameterTypes);
try {
method.invoke(clazz.newInstance(), args);
if (throwable) {
fail("can't throw Throwable.");
}
} catch (Throwable t) {
if (!throwable) {
t.printStackTrace();
throw new RuntimeException(t.getMessage());
}
}
}
final String name = clazz.getName() + "." + methodName;
if (interceptorClass == ArgsArrayInterceptor.class) {
assertEquals(name, true, ArgsArrayInterceptor.before);
assertEquals(name, true, ArgsArrayInterceptor.after);
if (method != null && Modifier.isStatic(method.getModifiers())) {
assertNull(name, ArgsArrayInterceptor.beforeTarget);
assertNull(name, ArgsArrayInterceptor.afterTarget);
} else if (method != null) {
assertNotNull(name, ArgsArrayInterceptor.beforeTarget);
assertNotNull(name, ArgsArrayInterceptor.afterTarget);
}
assertEquals(name, ArgsArrayInterceptor.beforeTarget, ArgsArrayInterceptor.afterTarget);
if(ArgsArrayInterceptor.beforeArgs != null) {
assertEquals(name, args.length, ArgsArrayInterceptor.beforeArgs.length);
}
if(ArgsArrayInterceptor.afterArgs != null) {
assertEquals(name, args.length, ArgsArrayInterceptor.afterArgs.length);
}
assertEquals(name, returnValue, ArgsArrayInterceptor.result);
if (throwable) {
assertNotNull(name, ArgsArrayInterceptor.throwable);
}
} else if (interceptorClass == ExceptionInterceptor.class) {
assertEquals(name, true, ExceptionInterceptor.before);
assertEquals(name, true, ExceptionInterceptor.after);
if (method != null && Modifier.isStatic(method.getModifiers())) {
assertNull(name, ExceptionInterceptor.beforeTarget);
assertNull(name, ExceptionInterceptor.afterTarget);
} else if (method != null) {
assertNotNull(name, ExceptionInterceptor.beforeTarget);
assertNotNull(name, ExceptionInterceptor.afterTarget);
}
assertEquals(name, ExceptionInterceptor.beforeTarget, ExceptionInterceptor.afterTarget);
if(ExceptionInterceptor.beforeArgs != null) {
assertEquals(name, args.length, ExceptionInterceptor.beforeArgs.length);
}
if(ExceptionInterceptor.afterArgs != null) {
assertEquals(name, args.length, ExceptionInterceptor.afterArgs.length);
}
assertEquals(name, returnValue, ExceptionInterceptor.result);
if (throwable) {
assertNotNull(name, ExceptionInterceptor.throwable);
}
} else if (interceptorClass == StaticInterceptor.class) {
assertEquals(true, StaticInterceptor.before);
assertEquals(true, StaticInterceptor.after);
if (method != null && Modifier.isStatic(method.getModifiers())) {
assertNull(name, StaticInterceptor.beforeTarget);
assertNull(name, StaticInterceptor.afterTarget);
} else if (method != null) {
assertNotNull(name, StaticInterceptor.beforeTarget);
assertNotNull(name, StaticInterceptor.afterTarget);
}
assertEquals(StaticInterceptor.beforeTarget, StaticInterceptor.afterTarget);
assertEquals(clazz.getName(), StaticInterceptor.beforeClassName);
assertNotNull(StaticInterceptor.beforeMethodName);
assertNotNull(StaticInterceptor.beforeParameterDescription);
assertNotNull(StaticInterceptor.afterClassName);
assertNotNull(StaticInterceptor.afterMethodName);
assertNotNull(StaticInterceptor.afterParameterDescription);
if(StaticInterceptor.beforeArgs != null) {
assertEquals(args.length, StaticInterceptor.beforeArgs.length);
}
if(StaticInterceptor.afterArgs != null) {
assertEquals(args.length, StaticInterceptor.afterArgs.length);
}
assertEquals(returnValue, StaticInterceptor.result);
if (throwable) {
assertNotNull(name, StaticInterceptor.throwable);
}
} else if (interceptorClass == ApiIdAwareInterceptor.class) {
assertEquals(name, true, ApiIdAwareInterceptor.before);
assertEquals(name, true, ApiIdAwareInterceptor.after);
if (method != null && Modifier.isStatic(method.getModifiers())) {
assertNull(name, ApiIdAwareInterceptor.beforeTarget);
assertNull(name, ApiIdAwareInterceptor.afterTarget);
} else if (method != null) {
assertNotNull(name, ApiIdAwareInterceptor.beforeTarget);
assertNotNull(name, ApiIdAwareInterceptor.afterTarget);
}
assertEquals(name, ApiIdAwareInterceptor.beforeTarget, ApiIdAwareInterceptor.afterTarget);
assertEquals(99, ApiIdAwareInterceptor.beforeApiId);
assertEquals(99, ApiIdAwareInterceptor.afterApiId);
if(ApiIdAwareInterceptor.beforeArgs != null) {
assertEquals(name, args.length, ApiIdAwareInterceptor.beforeArgs.length);
}
if(ApiIdAwareInterceptor.afterArgs != null) {
assertEquals(name, args.length, ApiIdAwareInterceptor.afterArgs.length);
}
assertEquals(name, returnValue, ApiIdAwareInterceptor.result);
if (throwable) {
assertNotNull(name, ApiIdAwareInterceptor.throwable);
}
} else if (interceptorClass == BasicInterceptor.class) {
assertEquals(name, true, BasicInterceptor.before);
assertEquals(name, true, BasicInterceptor.after);
if (method != null && Modifier.isStatic(method.getModifiers())) {
assertNull(name, BasicInterceptor.beforeTarget);
assertNull(name, BasicInterceptor.afterTarget);
} else if (method != null) {
assertNotNull(name, BasicInterceptor.beforeTarget);
assertNotNull(name, BasicInterceptor.afterTarget);
}
assertEquals(name, BasicInterceptor.beforeTarget, BasicInterceptor.afterTarget);
if (args != null && args.length >= 1) {
assertEquals(args[0], BasicInterceptor.beforeArg0);
assertEquals(args[0], BasicInterceptor.afterArg0);
}
if (args != null && args.length >= 2) {
assertEquals(args[1], BasicInterceptor.beforeArg1);
assertEquals(args[1], BasicInterceptor.afterArg1);
}
if (args != null && args.length >= 3) {
assertEquals(args[2], BasicInterceptor.beforeArg2);
assertEquals(args[2], BasicInterceptor.afterArg2);
}
if (args != null && args.length >= 4) {
assertEquals(args[3], BasicInterceptor.beforeArg3);
assertEquals(args[3], BasicInterceptor.afterArg3);
}
if (args != null && args.length >= 5) {
assertEquals(args[4], BasicInterceptor.beforeArg4);
assertEquals(args[4], BasicInterceptor.afterArg4);
}
assertEquals(name, returnValue, BasicInterceptor.result);
if (throwable) {
assertNotNull(name, BasicInterceptor.throwable);
}
}
}
private Class addInterceptor(final int interceptorId, final String targetClassName, final Class<?> interceptorClass) {
final InterceptorDefinition interceptorDefinition = new InterceptorDefinitionFactory().createInterceptorDefinition(interceptorClass);
try {
classLoader.setTrace(false);
classLoader.setVerify(false);
classLoader.setTargetClassName(targetClassName);
classLoader.setCallbackHandler(new ASMClassNodeLoader.CallbackHandler() {
@Override
public void handle(ClassNode classNode) {
List<MethodNode> methodNodes = classNode.methods;
for (MethodNode methodNode : methodNodes) {
if (methodNode.name.equals("<clinit>")) {
continue;
}
ASMMethodNodeAdapter methodNodeAdapter = new ASMMethodNodeAdapter(classNode.name, methodNode);
if (methodNodeAdapter.isAbstract() || methodNodeAdapter.isNative()) {
continue;
}
methodNodeAdapter.addBeforeInterceptor(interceptorId, interceptorDefinition, 99);
methodNodeAdapter.addAfterInterceptor(interceptorId, interceptorDefinition, 99);
}
}
});
return classLoader.loadClass(targetClassName);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}