blob: 6b6b7f66151398bcb48ed19972dc59d50e8fe125 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.dubbo.common.utils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class ReflectUtilsTest {
@Test
public void testIsPrimitives() throws Exception {
assertTrue(ReflectUtils.isPrimitives(boolean[].class));
assertTrue(ReflectUtils.isPrimitives(byte.class));
assertFalse(ReflectUtils.isPrimitive(Map[].class));
}
@Test
public void testIsPrimitive() throws Exception {
assertTrue(ReflectUtils.isPrimitive(boolean.class));
assertTrue(ReflectUtils.isPrimitive(String.class));
assertTrue(ReflectUtils.isPrimitive(Boolean.class));
assertTrue(ReflectUtils.isPrimitive(Character.class));
assertTrue(ReflectUtils.isPrimitive(Number.class));
assertTrue(ReflectUtils.isPrimitive(Date.class));
assertFalse(ReflectUtils.isPrimitive(Map.class));
}
@Test
public void testGetBoxedClass() throws Exception {
assertThat(ReflectUtils.getBoxedClass(int.class), sameInstance(Integer.class));
assertThat(ReflectUtils.getBoxedClass(boolean.class), sameInstance(Boolean.class));
assertThat(ReflectUtils.getBoxedClass(long.class), sameInstance(Long.class));
assertThat(ReflectUtils.getBoxedClass(float.class), sameInstance(Float.class));
assertThat(ReflectUtils.getBoxedClass(double.class), sameInstance(Double.class));
assertThat(ReflectUtils.getBoxedClass(char.class), sameInstance(Character.class));
assertThat(ReflectUtils.getBoxedClass(byte.class), sameInstance(Byte.class));
assertThat(ReflectUtils.getBoxedClass(short.class), sameInstance(Short.class));
assertThat(ReflectUtils.getBoxedClass(String.class), sameInstance(String.class));
}
@Test
public void testIsCompatible() throws Exception {
assertTrue(ReflectUtils.isCompatible(short.class, (short) 1));
assertTrue(ReflectUtils.isCompatible(int.class, 1));
assertTrue(ReflectUtils.isCompatible(double.class, 1.2));
assertTrue(ReflectUtils.isCompatible(Object.class, 1.2));
assertTrue(ReflectUtils.isCompatible(List.class, new ArrayList<String>()));
}
@Test
public void testIsCompatibleWithArray() throws Exception {
assertFalse(ReflectUtils.isCompatible(new Class[]{short.class, int.class}, new Object[]{(short) 1}));
assertFalse(ReflectUtils.isCompatible(new Class[]{double.class}, new Object[]{"hello"}));
assertTrue(ReflectUtils.isCompatible(new Class[]{double.class}, new Object[]{1.2}));
}
@Test
public void testGetCodeBase() throws Exception {
assertNull(ReflectUtils.getCodeBase(null));
assertNull(ReflectUtils.getCodeBase(String.class));
assertNotNull(ReflectUtils.getCodeBase(ReflectUtils.class));
}
@Test
public void testGetName() throws Exception {
// getName
assertEquals("boolean", ReflectUtils.getName(boolean.class));
assertEquals("int[][][]", ReflectUtils.getName(int[][][].class));
assertEquals("java.lang.Object[][]", ReflectUtils.getName(Object[][].class));
// getDesc
assertEquals("Z", ReflectUtils.getDesc(boolean.class));
assertEquals("[[[I", ReflectUtils.getDesc(int[][][].class));
assertEquals("[[Ljava/lang/Object;", ReflectUtils.getDesc(Object[][].class));
// name2desc
assertEquals("Z", ReflectUtils.name2desc(ReflectUtils.getName(boolean.class)));
assertEquals("[[[I", ReflectUtils.name2desc(ReflectUtils.getName(int[][][].class)));
assertEquals("[[Ljava/lang/Object;", ReflectUtils.name2desc(ReflectUtils.getName(Object[][].class)));
// desc2name
assertEquals("short[]", ReflectUtils.desc2name(ReflectUtils.getDesc(short[].class)));
assertEquals("boolean[]", ReflectUtils.desc2name(ReflectUtils.getDesc(boolean[].class)));
assertEquals("byte[]", ReflectUtils.desc2name(ReflectUtils.getDesc(byte[].class)));
assertEquals("char[]", ReflectUtils.desc2name(ReflectUtils.getDesc(char[].class)));
assertEquals("double[]", ReflectUtils.desc2name(ReflectUtils.getDesc(double[].class)));
assertEquals("float[]", ReflectUtils.desc2name(ReflectUtils.getDesc(float[].class)));
assertEquals("int[]", ReflectUtils.desc2name(ReflectUtils.getDesc(int[].class)));
assertEquals("long[]", ReflectUtils.desc2name(ReflectUtils.getDesc(long[].class)));
assertEquals("int", ReflectUtils.desc2name(ReflectUtils.getDesc(int.class)));
assertEquals("void", ReflectUtils.desc2name(ReflectUtils.getDesc(void.class)));
assertEquals("java.lang.Object[][]", ReflectUtils.desc2name(ReflectUtils.getDesc(Object[][].class)));
}
@Test
public void testGetGenericClass() throws Exception {
assertThat(ReflectUtils.getGenericClass(Foo1.class), sameInstance(String.class));
}
@Test
public void testGetGenericClassWithIndex() throws Exception {
assertThat(ReflectUtils.getGenericClass(Foo1.class, 0), sameInstance(String.class));
assertThat(ReflectUtils.getGenericClass(Foo1.class, 1), sameInstance(Integer.class));
assertThat(ReflectUtils.getGenericClass(Foo2.class, 0), sameInstance(List.class));
assertThat(ReflectUtils.getGenericClass(Foo2.class, 1), sameInstance(int.class));
assertThat(ReflectUtils.getGenericClass(Foo3.class, 0), sameInstance(Foo1.class));
assertThat(ReflectUtils.getGenericClass(Foo3.class, 1), sameInstance(Foo2.class));
}
@Test
public void testGetMethodName() throws Exception {
assertThat(ReflectUtils.getName(Foo2.class.getDeclaredMethod("hello", int[].class)),
equalTo("java.util.List hello(int[])"));
}
@Test
public void testGetSignature() throws Exception {
Method m = Foo2.class.getDeclaredMethod("hello", int[].class);
assertThat(ReflectUtils.getSignature("greeting", m.getParameterTypes()), equalTo("greeting([I)"));
}
@Test
public void testGetConstructorName() throws Exception {
Constructor c = Foo2.class.getConstructors()[0];
assertThat(ReflectUtils.getName(c), equalTo("(java.util.List,int[])"));
}
@Test
public void testName2Class() throws Exception {
assertEquals(boolean.class, ReflectUtils.name2class("boolean"));
assertEquals(boolean[].class, ReflectUtils.name2class("boolean[]"));
assertEquals(int[][].class, ReflectUtils.name2class(ReflectUtils.getName(int[][].class)));
assertEquals(ReflectUtilsTest[].class, ReflectUtils.name2class(ReflectUtils.getName(ReflectUtilsTest[].class)));
}
@Test
public void testGetDescMethod() throws Exception {
assertThat(ReflectUtils.getDesc(Foo2.class.getDeclaredMethod("hello", int[].class)),
equalTo("hello([I)Ljava/util/List;"));
}
@Test
public void testGetDescConstructor() throws Exception {
assertThat(ReflectUtils.getDesc(Foo2.class.getConstructors()[0]), equalTo("(Ljava/util/List;[I)V"));
}
@Test
public void testGetDescWithoutMethodName() throws Exception {
assertThat(ReflectUtils.getDescWithoutMethodName(Foo2.class.getDeclaredMethod("hello", int[].class)),
equalTo("([I)Ljava/util/List;"));
}
@Test
public void testFindMethodByMethodName1() throws Exception {
assertNotNull(ReflectUtils.findMethodByMethodName(Foo.class, "hello"));
}
@Test
public void testFindMethodByMethodName2() {
Assertions.assertThrows(IllegalStateException.class, () -> {
ReflectUtils.findMethodByMethodName(Foo2.class, "hello");
});
}
@Test
public void testFindConstructor() throws Exception {
Constructor constructor = ReflectUtils.findConstructor(Foo3.class, Foo2.class);
assertNotNull(constructor);
}
@Test
public void testIsInstance() throws Exception {
assertTrue(ReflectUtils.isInstance(new Foo1(), Foo.class.getName()));
}
@Test
public void testIsBeanPropertyReadMethod() throws Exception {
Method method = EmptyClass.class.getMethod("getProperty");
assertTrue(ReflectUtils.isBeanPropertyReadMethod(method));
method = EmptyClass.class.getMethod("getProperties");
assertFalse(ReflectUtils.isBeanPropertyReadMethod(method));
method = EmptyClass.class.getMethod("isProperty");
assertFalse(ReflectUtils.isBeanPropertyReadMethod(method));
method = EmptyClass.class.getMethod("getPropertyIndex", int.class);
assertFalse(ReflectUtils.isBeanPropertyReadMethod(method));
}
@Test
public void testGetPropertyNameFromBeanReadMethod() throws Exception {
Method method = EmptyClass.class.getMethod("getProperty");
assertEquals(ReflectUtils.getPropertyNameFromBeanReadMethod(method), "property");
method = EmptyClass.class.getMethod("isSet");
assertEquals(ReflectUtils.getPropertyNameFromBeanReadMethod(method), "set");
}
@Test
public void testIsBeanPropertyWriteMethod() throws Exception {
Method method = EmptyClass.class.getMethod("setProperty", EmptyProperty.class);
assertTrue(ReflectUtils.isBeanPropertyWriteMethod(method));
method = EmptyClass.class.getMethod("setSet", boolean.class);
assertTrue(ReflectUtils.isBeanPropertyWriteMethod(method));
}
@Test
public void testGetPropertyNameFromBeanWriteMethod() throws Exception {
Method method = EmptyClass.class.getMethod("setProperty", EmptyProperty.class);
assertEquals(ReflectUtils.getPropertyNameFromBeanWriteMethod(method), "property");
}
@Test
public void testIsPublicInstanceField() throws Exception {
Field field = EmptyClass.class.getDeclaredField("set");
assertTrue(ReflectUtils.isPublicInstanceField(field));
field = EmptyClass.class.getDeclaredField("property");
assertFalse(ReflectUtils.isPublicInstanceField(field));
}
@Test
public void testGetBeanPropertyFields() throws Exception {
Map<String, Field> map = ReflectUtils.getBeanPropertyFields(EmptyClass.class);
assertThat(map.size(), is(2));
assertThat(map, hasKey("set"));
assertThat(map, hasKey("property"));
for (Field f : map.values()) {
if (!f.isAccessible()) {
fail();
}
}
}
@Test
public void testGetBeanPropertyReadMethods() throws Exception {
Map<String, Method> map = ReflectUtils.getBeanPropertyReadMethods(EmptyClass.class);
assertThat(map.size(), is(2));
assertThat(map, hasKey("set"));
assertThat(map, hasKey("property"));
for (Method m : map.values()) {
if (!m.isAccessible()) {
fail();
}
}
}
@Test
public void testDesc2Class() throws Exception {
assertEquals(void.class, ReflectUtils.desc2class("V"));
assertEquals(boolean.class, ReflectUtils.desc2class("Z"));
assertEquals(boolean[].class, ReflectUtils.desc2class("[Z"));
assertEquals(byte.class, ReflectUtils.desc2class("B"));
assertEquals(char.class, ReflectUtils.desc2class("C"));
assertEquals(double.class, ReflectUtils.desc2class("D"));
assertEquals(float.class, ReflectUtils.desc2class("F"));
assertEquals(int.class, ReflectUtils.desc2class("I"));
assertEquals(long.class, ReflectUtils.desc2class("J"));
assertEquals(short.class, ReflectUtils.desc2class("S"));
assertEquals(String.class, ReflectUtils.desc2class("Ljava.lang.String;"));
assertEquals(int[][].class, ReflectUtils.desc2class(ReflectUtils.getDesc(int[][].class)));
assertEquals(ReflectUtilsTest[].class, ReflectUtils.desc2class(ReflectUtils.getDesc(ReflectUtilsTest[].class)));
String desc;
Class<?>[] cs;
cs = new Class<?>[]{int.class, getClass(), String.class, int[][].class, boolean[].class};
desc = ReflectUtils.getDesc(cs);
assertSame(cs, ReflectUtils.desc2classArray(desc));
cs = new Class<?>[]{};
desc = ReflectUtils.getDesc(cs);
assertSame(cs, ReflectUtils.desc2classArray(desc));
cs = new Class<?>[]{void.class, String[].class, int[][].class, ReflectUtilsTest[][].class};
desc = ReflectUtils.getDesc(cs);
assertSame(cs, ReflectUtils.desc2classArray(desc));
}
protected void assertSame(Class<?>[] cs1, Class<?>[] cs2) throws Exception {
assertEquals(cs1.length, cs2.length);
for (int i = 0; i < cs1.length; i++)
assertEquals(cs1[i], cs2[i]);
}
@Test
public void testFindMethodByMethodSignature() throws Exception {
Method m = ReflectUtils.findMethodByMethodSignature(TestedClass.class, "method1", null);
assertEquals("method1", m.getName());
Class<?>[] parameterTypes = m.getParameterTypes();
assertEquals(1, parameterTypes.length);
assertEquals(int.class, parameterTypes[0]);
}
@Test
public void testFindMethodByMethodSignature_override() throws Exception {
{
Method m = ReflectUtils.findMethodByMethodSignature(TestedClass.class,
"overrideMethod", new String[]{"int"});
assertEquals("overrideMethod", m.getName());
Class<?>[] parameterTypes = m.getParameterTypes();
assertEquals(1, parameterTypes.length);
assertEquals(int.class, parameterTypes[0]);
}
{
Method m = ReflectUtils.findMethodByMethodSignature(TestedClass.class,
"overrideMethod", new String[]{"java.lang.Integer"});
assertEquals("overrideMethod", m.getName());
Class<?>[] parameterTypes = m.getParameterTypes();
assertEquals(1, parameterTypes.length);
assertEquals(Integer.class, parameterTypes[0]);
}
}
@Test
public void testFindMethodByMethodSignatureOverrideMoreThan1() throws Exception {
try {
ReflectUtils.findMethodByMethodSignature(TestedClass.class, "overrideMethod", null);
fail();
} catch (IllegalStateException expected) {
assertThat(expected.getMessage(), containsString("Not unique method for method name("));
}
}
@Test
public void testFindMethodByMethodSignatureNotFound() throws Exception {
try {
ReflectUtils.findMethodByMethodSignature(TestedClass.class, "notExsited", null);
fail();
} catch (NoSuchMethodException expected) {
assertThat(expected.getMessage(), containsString("No such method "));
assertThat(expected.getMessage(), containsString("in class"));
}
}
@Test
public void testGetEmptyObject() throws Exception {
assertTrue(ReflectUtils.getEmptyObject(Collection.class) instanceof Collection);
assertTrue(ReflectUtils.getEmptyObject(List.class) instanceof List);
assertTrue(ReflectUtils.getEmptyObject(Set.class) instanceof Set);
assertTrue(ReflectUtils.getEmptyObject(Map.class) instanceof Map);
assertTrue(ReflectUtils.getEmptyObject(Object[].class) instanceof Object[]);
assertEquals(ReflectUtils.getEmptyObject(String.class), "");
assertEquals(ReflectUtils.getEmptyObject(short.class), (short) 0);
assertEquals(ReflectUtils.getEmptyObject(byte.class), (byte) 0);
assertEquals(ReflectUtils.getEmptyObject(int.class), 0);
assertEquals(ReflectUtils.getEmptyObject(long.class), 0L);
assertEquals(ReflectUtils.getEmptyObject(float.class), (float) 0);
assertEquals(ReflectUtils.getEmptyObject(double.class), (double) 0);
assertEquals(ReflectUtils.getEmptyObject(char.class), '\0');
assertEquals(ReflectUtils.getEmptyObject(boolean.class), Boolean.FALSE);
EmptyClass object = (EmptyClass) ReflectUtils.getEmptyObject(EmptyClass.class);
assertNotNull(object);
assertNotNull(object.getProperty());
}
@Test
public void testForName1() throws Exception {
assertThat(ReflectUtils.forName(ReflectUtils.class.getName()), sameInstance(ReflectUtils.class));
}
@Test
public void testForName2() {
Assertions.assertThrows(IllegalStateException.class, () -> {
ReflectUtils.forName("a.c.d.e.F");
});
}
@Test
public void testGetReturnTypes () throws Exception{
Class clazz = TypeClass.class;
Type[] types = ReflectUtils.getReturnTypes(clazz.getMethod("getFuture"));
Assertions.assertEquals("java.lang.String", types[0].getTypeName());
Assertions.assertEquals("java.lang.String", types[1].getTypeName());
Type[] types1 = ReflectUtils.getReturnTypes(clazz.getMethod("getString"));
Assertions.assertEquals("java.lang.String", types1[0].getTypeName());
Assertions.assertEquals("java.lang.String", types1[1].getTypeName());
Type[] types2 = ReflectUtils.getReturnTypes(clazz.getMethod("getListFuture"));
Assertions.assertEquals("java.util.List", types2[0].getTypeName());
Assertions.assertEquals("java.util.List<java.lang.String>", types2[1].getTypeName());
}
public interface TypeClass {
CompletableFuture<String> getFuture();
String getString();
CompletableFuture<List<String>> getListFuture();
}
public static class EmptyClass {
private EmptyProperty property;
public boolean set;
public static String s;
private transient int i;
public EmptyProperty getProperty() {
return property;
}
public EmptyProperty getPropertyIndex(int i) {
return property;
}
public static EmptyProperty getProperties() {
return null;
}
public void isProperty() {
}
public boolean isSet() {
return set;
}
public void setProperty(EmptyProperty property) {
this.property = property;
}
public void setSet(boolean set) {
this.set = set;
}
}
public static class EmptyProperty {
}
static class TestedClass {
public void method1(int x) {
}
public void overrideMethod(int x) {
}
public void overrideMethod(Integer x) {
}
public void overrideMethod(String s) {
}
public void overrideMethod(String s1, String s2) {
}
}
interface Foo<A, B> {
A hello(B b);
}
static class Foo1 implements Foo<String, Integer> {
@Override
public String hello(Integer integer) {
return null;
}
}
static class Foo2 implements Foo<List<String>, int[]> {
public Foo2(List<String> list, int[] ints) {
}
@Override
public List<String> hello(int[] ints) {
return null;
}
}
static class Foo3 implements Foo<Foo1, Foo2> {
public Foo3(Foo foo) {
}
@Override
public Foo1 hello(Foo2 foo2) {
return null;
}
}
}