Polishing

This commit is contained in:
Juergen Hoeller
2018-03-21 16:12:42 +01:00
parent ba5ef6456f
commit c1405ef140
3 changed files with 97 additions and 107 deletions

View File

@@ -38,7 +38,7 @@ import org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMat
import static org.junit.Assert.*;
/**
* Tests for any helper code.
* Tests for reflection helper code.
*
* @author Andy Clement
*/
@@ -46,23 +46,14 @@ public class ReflectionHelperTests extends AbstractExpressionTests {
@Test
public void testFormatHelperForClassName() {
assertEquals("java.lang.String",FormatHelper.formatClassNameForMessage(String.class));
assertEquals("java.lang.String[]",FormatHelper.formatClassNameForMessage(new String[1].getClass()));
assertEquals("java.lang.String[][]",FormatHelper.formatClassNameForMessage(new String[1][1].getClass()));
assertEquals("int[]",FormatHelper.formatClassNameForMessage(new int[1].getClass()));
assertEquals("int[][]",FormatHelper.formatClassNameForMessage(new int[1][2].getClass()));
assertEquals("null",FormatHelper.formatClassNameForMessage(null));
assertEquals("java.lang.String", FormatHelper.formatClassNameForMessage(String.class));
assertEquals("java.lang.String[]", FormatHelper.formatClassNameForMessage(String[].class));
assertEquals("java.lang.String[][]", FormatHelper.formatClassNameForMessage(String[][].class));
assertEquals("int[]", FormatHelper.formatClassNameForMessage(int[].class));
assertEquals("int[][]", FormatHelper.formatClassNameForMessage(int[][].class));
assertEquals("null", FormatHelper.formatClassNameForMessage(null));
}
/*
@Test
public void testFormatHelperForMethod() {
assertEquals("foo(java.lang.String)",FormatHelper.formatMethodForMessage("foo", String.class));
assertEquals("goo(java.lang.String,int[])",FormatHelper.formatMethodForMessage("goo", String.class, new int[1].getClass()));
assertEquals("boo()",FormatHelper.formatMethodForMessage("boo"));
}
*/
@Test
public void testUtilities() throws ParseException {
SpelExpression expr = (SpelExpression)parser.parseExpression("3+4+5+6+7-2");
@@ -159,47 +150,45 @@ public class ReflectionHelperTests extends AbstractExpressionTests {
StandardTypeConverter typeConverter = new StandardTypeConverter();
// Passing (Super,String) on call to foo(Sub,String) is not a match
checkMatch(new Class<?>[] {Super.class,String.class}, new Class<?>[] {Sub.class,String.class},typeConverter,null);
checkMatch(new Class<?>[] {Super.class,String.class}, new Class<?>[] {Sub.class,String.class}, typeConverter, null);
}
@Test
public void testReflectionHelperCompareArguments_Varargs_ExactMatching() {
StandardTypeConverter tc = new StandardTypeConverter();
Class<?> stringArrayClass = new String[0].getClass();
Class<?> integerArrayClass = new Integer[0].getClass();
// Passing (String[]) on call to (String[]) is exact match
checkMatch2(new Class<?>[] {stringArrayClass}, new Class<?>[] {stringArrayClass}, tc, ArgumentsMatchKind.EXACT);
checkMatch2(new Class<?>[] {String[].class}, new Class<?>[] {String[].class}, tc, ArgumentsMatchKind.EXACT);
// Passing (Integer, String[]) on call to (Integer, String[]) is exact match
checkMatch2(new Class<?>[] {Integer.class, stringArrayClass}, new Class<?>[] {Integer.class, stringArrayClass}, tc, ArgumentsMatchKind.EXACT);
checkMatch2(new Class<?>[] {Integer.class, String[].class}, new Class<?>[] {Integer.class, String[].class}, tc, ArgumentsMatchKind.EXACT);
// Passing (String, Integer, String[]) on call to (String, String, String[]) is exact match
checkMatch2(new Class<?>[] {String.class, Integer.class, stringArrayClass}, new Class<?>[] {String.class,Integer.class, stringArrayClass}, tc, ArgumentsMatchKind.EXACT);
checkMatch2(new Class<?>[] {String.class, Integer.class, String[].class}, new Class<?>[] {String.class,Integer.class, String[].class}, tc, ArgumentsMatchKind.EXACT);
// Passing (Sub, String[]) on call to (Super, String[]) is exact match
checkMatch2(new Class<?>[] {Sub.class, stringArrayClass}, new Class<?>[] {Super.class,stringArrayClass}, tc, ArgumentsMatchKind.CLOSE);
checkMatch2(new Class<?>[] {Sub.class, String[].class}, new Class<?>[] {Super.class,String[].class}, tc, ArgumentsMatchKind.CLOSE);
// Passing (Integer, String[]) on call to (String, String[]) is exact match
checkMatch2(new Class<?>[] {Integer.class, stringArrayClass}, new Class<?>[] {String.class, stringArrayClass}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
checkMatch2(new Class<?>[] {Integer.class, String[].class}, new Class<?>[] {String.class, String[].class}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
// Passing (Integer, Sub, String[]) on call to (String, Super, String[]) is exact match
checkMatch2(new Class<?>[] {Integer.class, Sub.class, String[].class}, new Class<?>[] {String.class,Super .class, String[].class}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
// Passing (String) on call to (String[]) is exact match
checkMatch2(new Class<?>[] {String.class}, new Class<?>[] {stringArrayClass}, tc, ArgumentsMatchKind.EXACT);
checkMatch2(new Class<?>[] {String.class}, new Class<?>[] {String[].class}, tc, ArgumentsMatchKind.EXACT);
// Passing (Integer,String) on call to (Integer,String[]) is exact match
checkMatch2(new Class<?>[] {Integer.class, String.class}, new Class<?>[] {Integer.class, stringArrayClass}, tc, ArgumentsMatchKind.EXACT);
checkMatch2(new Class<?>[] {Integer.class, String.class}, new Class<?>[] {Integer.class, String[].class}, tc, ArgumentsMatchKind.EXACT);
// Passing (String) on call to (Integer[]) is conversion match (String to Integer)
checkMatch2(new Class<?>[] {String.class}, new Class<?>[] {integerArrayClass}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
checkMatch2(new Class<?>[] {String.class}, new Class<?>[] {Integer[].class}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
// Passing (Sub) on call to (Super[]) is close match
checkMatch2(new Class<?>[] {Sub.class}, new Class<?>[] {new Super[0].getClass()}, tc, ArgumentsMatchKind.CLOSE);
checkMatch2(new Class<?>[] {Sub.class}, new Class<?>[] {Super[].class}, tc, ArgumentsMatchKind.CLOSE);
// Passing (Super) on call to (Sub[]) is not a match
checkMatch2(new Class<?>[] {Super.class}, new Class<?>[] {new Sub[0].getClass()}, tc, null);
checkMatch2(new Class<?>[] {Super.class}, new Class<?>[] {Sub[].class}, tc, null);
checkMatch2(new Class<?>[] {Unconvertable.class, String.class}, new Class<?>[] {Sub.class, Super[].class}, tc, null);
@@ -234,12 +223,12 @@ public class ReflectionHelperTests extends AbstractExpressionTests {
// varargs with nothing needing conversion
args = new Object[] {3, "abc", "abc"};
ReflectionHelper.convertArguments(tc, args, twoArg, 1);
checkArguments(args, "3","abc","abc");
checkArguments(args, "3", "abc", "abc");
// varargs with conversion required
args = new Object[] {3, false ,3.0d};
ReflectionHelper.convertArguments(tc, args, twoArg, 1);
checkArguments(args, "3","false","3.0");
checkArguments(args, "3", "false", "3.0");
}
@Test
@@ -251,33 +240,33 @@ public class ReflectionHelperTests extends AbstractExpressionTests {
// Simple conversion: int to string
Object[] args = new Object[] {3};
ReflectionHelper.convertAllArguments(tc, args, oneArg);
checkArguments(args,"3");
checkArguments(args, "3");
// varargs conversion
args = new Object[] {3, false, 3.0f};
ReflectionHelper.convertAllArguments(tc, args, twoArg);
checkArguments(args,"3","false","3.0");
checkArguments(args, "3", "false", "3.0");
// varargs conversion but no varargs
args = new Object[] {3};
ReflectionHelper.convertAllArguments(tc, args, twoArg);
checkArguments(args,"3");
checkArguments(args, "3");
// null value
args = new Object[] {3, null, 3.0f};
ReflectionHelper.convertAllArguments(tc, args, twoArg);
checkArguments(args,"3",null,"3.0");
checkArguments(args, "3", null, "3.0");
}
@Test
public void testSetupArguments() {
Object[] newArray = ReflectionHelper.setupArgumentsForVarargsInvocation(
new Class<?>[] {new String[0].getClass()},"a","b","c");
new Class<?>[] {String[].class}, "a", "b", "c");
assertEquals(1, newArray.length);
Object firstParam = newArray[0];
assertEquals(String.class,firstParam.getClass().getComponentType());
Object[] firstParamArray = (Object[])firstParam;
Object[] firstParamArray = (Object[]) firstParam;
assertEquals(3,firstParamArray.length);
assertEquals("a",firstParamArray[0]);
assertEquals("b",firstParamArray[1]);
@@ -285,75 +274,75 @@ public class ReflectionHelperTests extends AbstractExpressionTests {
}
@Test
public void testReflectivePropertyResolver() throws Exception {
ReflectivePropertyAccessor rpr = new ReflectivePropertyAccessor();
public void testReflectivePropertyAccessor() throws Exception {
ReflectivePropertyAccessor rpa = new ReflectivePropertyAccessor();
Tester t = new Tester();
t.setProperty("hello");
EvaluationContext ctx = new StandardEvaluationContext(t);
assertTrue(rpr.canRead(ctx, t, "property"));
assertEquals("hello",rpr.read(ctx, t, "property").getValue());
assertEquals("hello",rpr.read(ctx, t, "property").getValue()); // cached accessor used
assertTrue(rpa.canRead(ctx, t, "property"));
assertEquals("hello",rpa.read(ctx, t, "property").getValue());
assertEquals("hello",rpa.read(ctx, t, "property").getValue()); // cached accessor used
assertTrue(rpr.canRead(ctx, t, "field"));
assertEquals(3,rpr.read(ctx, t, "field").getValue());
assertEquals(3,rpr.read(ctx, t, "field").getValue()); // cached accessor used
assertTrue(rpa.canRead(ctx, t, "field"));
assertEquals(3,rpa.read(ctx, t, "field").getValue());
assertEquals(3,rpa.read(ctx, t, "field").getValue()); // cached accessor used
assertTrue(rpr.canWrite(ctx, t, "property"));
rpr.write(ctx, t, "property","goodbye");
rpr.write(ctx, t, "property","goodbye"); // cached accessor used
assertTrue(rpa.canWrite(ctx, t, "property"));
rpa.write(ctx, t, "property", "goodbye");
rpa.write(ctx, t, "property", "goodbye"); // cached accessor used
assertTrue(rpr.canWrite(ctx, t, "field"));
rpr.write(ctx, t, "field",12);
rpr.write(ctx, t, "field",12);
assertTrue(rpa.canWrite(ctx, t, "field"));
rpa.write(ctx, t, "field", 12);
rpa.write(ctx, t, "field", 12);
// Attempted write as first activity on this field and property to drive testing
// of populating type descriptor cache
rpr.write(ctx,t,"field2",3);
rpr.write(ctx, t, "property2","doodoo");
assertEquals(3,rpr.read(ctx,t,"field2").getValue());
rpa.write(ctx, t, "field2", 3);
rpa.write(ctx, t, "property2", "doodoo");
assertEquals(3,rpa.read(ctx, t, "field2").getValue());
// Attempted read as first activity on this field and property (no canRead before them)
assertEquals(0,rpr.read(ctx,t,"field3").getValue());
assertEquals("doodoo",rpr.read(ctx,t,"property3").getValue());
assertEquals(0,rpa.read(ctx, t, "field3").getValue());
assertEquals("doodoo",rpa.read(ctx, t, "property3").getValue());
// Access through is method
// assertEquals(0,rpr.read(ctx,t,"field3").getValue());
assertEquals(false,rpr.read(ctx,t,"property4").getValue());
assertTrue(rpr.canRead(ctx,t,"property4"));
assertEquals(0,rpa .read(ctx, t, "field3").getValue());
assertEquals(false,rpa.read(ctx, t, "property4").getValue());
assertTrue(rpa.canRead(ctx, t, "property4"));
// repro SPR-9123, ReflectivePropertyAccessor JavaBean property names compliance tests
assertEquals("iD",rpr.read(ctx,t,"iD").getValue());
assertTrue(rpr.canRead(ctx,t,"iD"));
assertEquals("id",rpr.read(ctx,t,"id").getValue());
assertTrue(rpr.canRead(ctx,t,"id"));
assertEquals("ID",rpr.read(ctx,t,"ID").getValue());
assertTrue(rpr.canRead(ctx,t,"ID"));
assertEquals("iD",rpa.read(ctx, t, "iD").getValue());
assertTrue(rpa.canRead(ctx, t, "iD"));
assertEquals("id",rpa.read(ctx, t, "id").getValue());
assertTrue(rpa.canRead(ctx, t, "id"));
assertEquals("ID",rpa.read(ctx, t, "ID").getValue());
assertTrue(rpa.canRead(ctx, t, "ID"));
// note: "Id" is not a valid JavaBean name, nevertheless it is treated as "id"
assertEquals("id",rpr.read(ctx,t,"Id").getValue());
assertTrue(rpr.canRead(ctx,t,"Id"));
assertEquals("id",rpa.read(ctx, t, "Id").getValue());
assertTrue(rpa.canRead(ctx, t, "Id"));
// repro SPR-10994
assertEquals("xyZ",rpr.read(ctx,t,"xyZ").getValue());
assertTrue(rpr.canRead(ctx,t,"xyZ"));
assertEquals("xY",rpr.read(ctx,t,"xY").getValue());
assertTrue(rpr.canRead(ctx,t,"xY"));
assertEquals("xyZ",rpa.read(ctx, t, "xyZ").getValue());
assertTrue(rpa.canRead(ctx, t, "xyZ"));
assertEquals("xY",rpa.read(ctx, t, "xY").getValue());
assertTrue(rpa.canRead(ctx, t, "xY"));
// SPR-10122, ReflectivePropertyAccessor JavaBean property names compliance tests - setters
rpr.write(ctx, t, "pEBS","Test String");
assertEquals("Test String",rpr.read(ctx,t,"pEBS").getValue());
rpa.write(ctx, t, "pEBS", "Test String");
assertEquals("Test String",rpa.read(ctx, t, "pEBS").getValue());
}
@Test
public void testOptimalReflectivePropertyResolver() throws Exception {
ReflectivePropertyAccessor rpr = new ReflectivePropertyAccessor();
public void testOptimalReflectivePropertyAccessor() throws Exception {
ReflectivePropertyAccessor rpa = new ReflectivePropertyAccessor();
Tester t = new Tester();
t.setProperty("hello");
EvaluationContext ctx = new StandardEvaluationContext(t);
// assertTrue(rpr.canRead(ctx, t, "property"));
// assertEquals("hello",rpr.read(ctx, t, "property").getValue());
// assertEquals("hello",rpr.read(ctx, t, "property").getValue()); // cached accessor used
assertTrue(rpa.canRead(ctx, t, "property"));
assertEquals("hello", rpa.read(ctx, t, "property").getValue());
assertEquals("hello", rpa.read(ctx, t, "property").getValue()); // cached accessor used
PropertyAccessor optA = rpr.createOptimalAccessor(ctx, t, "property");
PropertyAccessor optA = rpa.createOptimalAccessor(ctx, t, "property");
assertTrue(optA.canRead(ctx, t, "property"));
assertFalse(optA.canRead(ctx, t, "property2"));
try {
@@ -381,14 +370,14 @@ public class ReflectionHelperTests extends AbstractExpressionTests {
// success
}
try {
optA.write(ctx,t,"property",null);
optA.write(ctx, t, "property", null);
fail();
}
catch (UnsupportedOperationException uoe) {
// success
}
optA = rpr.createOptimalAccessor(ctx, t, "field");
optA = rpa.createOptimalAccessor(ctx, t, "field");
assertTrue(optA.canRead(ctx, t, "field"));
assertFalse(optA.canRead(ctx, t, "field2"));
try {
@@ -406,7 +395,7 @@ public class ReflectionHelperTests extends AbstractExpressionTests {
// success
}
assertEquals(3,optA.read(ctx, t, "field").getValue());
assertEquals(3,optA.read(ctx, t, "field").getValue()); // cached accessor used
assertEquals(3,optA.read(ctx, t, "field").getValue()); // cached accessor used
try {
optA.getSpecificTargetClasses();
@@ -416,7 +405,7 @@ public class ReflectionHelperTests extends AbstractExpressionTests {
// success
}
try {
optA.write(ctx,t,"field",null);
optA.write(ctx, t, "field", null);
fail();
}
catch (UnsupportedOperationException uoe) {