@ -40,15 +40,22 @@ import org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMat
@@ -40,15 +40,22 @@ import org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMat
import static org.assertj.core.api.Assertions.assertThat ;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType ;
import static org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMatchKind.CLOSE ;
import static org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMatchKind.EXACT ;
import static org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMatchKind.REQUIRES_CONVERSION ;
/ * *
* Tests for reflection helper code .
* Tests for { @link ReflectionHelper } , { @link SpelUtilities } , { @link TypedValue } ,
* { @link ReflectivePropertyAccessor } , . . .
*
* @author Andy Clement
* @author Sam Brannen
* /
class ReflectionHelperTests extends AbstractExpressionTests {
private final StandardTypeConverter tc = new StandardTypeConverter ( ) ;
@Test
void utilities ( ) throws ParseException {
SpelExpression expr = ( SpelExpression ) parser . parseExpression ( "3+4+5+6+7-2" ) ;
@ -100,44 +107,38 @@ class ReflectionHelperTests extends AbstractExpressionTests {
@@ -100,44 +107,38 @@ class ReflectionHelperTests extends AbstractExpressionTests {
@Test
void reflectionHelperCompareArguments_ExactMatching ( ) {
StandardTypeConverter tc = new StandardTypeConverter ( ) ;
// Calling foo(String) with (String) is exact match
checkMatch ( new Class < ? > [ ] { String . class } , new Class < ? > [ ] { String . class } , tc , ReflectionHelper . ArgumentsMatchKind . EXACT ) ;
checkMatch ( new Class < ? > [ ] { String . class } , new Class < ? > [ ] { String . class } , tc , EXACT ) ;
// Calling foo(String,Integer) with (String,Integer) is exact match
checkMatch ( new Class < ? > [ ] { String . class , Integer . class } , new Class < ? > [ ] { String . class , Integer . class } , tc , ArgumentsMatchKind . EXACT ) ;
checkMatch ( new Class < ? > [ ] { String . class , Integer . class } , new Class < ? > [ ] { String . class , Integer . class } , tc , EXACT ) ;
}
@Test
void reflectionHelperCompareArguments_CloseMatching ( ) {
StandardTypeConverter tc = new StandardTypeConverter ( ) ;
// Calling foo(List) with (ArrayList) is close match (no conversion required)
checkMatch ( new Class < ? > [ ] { ArrayList . class } , new Class < ? > [ ] { List . class } , tc , ArgumentsMatchKind . CLOSE ) ;
checkMatch ( new Class < ? > [ ] { ArrayList . class } , new Class < ? > [ ] { List . class } , tc , CLOSE ) ;
// Passing (Sub,String) on call to foo(Super,String) is close match
checkMatch ( new Class < ? > [ ] { Sub . class , String . class } , new Class < ? > [ ] { Super . class , String . class } , tc , ArgumentsMatchKind . CLOSE ) ;
checkMatch ( new Class < ? > [ ] { Sub . class , String . class } , new Class < ? > [ ] { Super . class , String . class } , tc , CLOSE ) ;
// Passing (String,Sub) on call to foo(String,Super) is close match
checkMatch ( new Class < ? > [ ] { String . class , Sub . class } , new Class < ? > [ ] { String . class , Super . class } , tc , ArgumentsMatchKind . CLOSE ) ;
checkMatch ( new Class < ? > [ ] { String . class , Sub . class } , new Class < ? > [ ] { String . class , Super . class } , tc , CLOSE ) ;
}
@Test
void reflectionHelperCompareArguments_RequiresConversionMatching ( ) {
StandardTypeConverter tc = new StandardTypeConverter ( ) ;
void reflectionHelperCompareArguments_CloseMatching_WithAutoBoxing ( ) {
// Calling foo(String,int) with (String,Integer) requires boxing conversion of argument one
checkMatch ( new Class < ? > [ ] { String . class , int . class } , new Class < ? > [ ] { String . class , Integer . class } , tc , ArgumentsMatchKind . CLOSE ) ;
checkMatch ( new Class < ? > [ ] { String . class , int . class } , new Class < ? > [ ] { String . class , Integer . class } , tc , CLOSE ) ;
// Passing (int,String) on call to foo(Integer,String) requires boxing conversion of argument zero
checkMatch ( new Class < ? > [ ] { int . class , String . class } , new Class < ? > [ ] { Integer . class , String . class } , tc , ArgumentsMatchKind . CLOSE ) ;
checkMatch ( new Class < ? > [ ] { int . class , String . class } , new Class < ? > [ ] { Integer . class , String . class } , tc , CLOSE ) ;
// Passing (int,Sub) on call to foo(Integer,Super) requires boxing conversion of argument zero
checkMatch ( new Class < ? > [ ] { int . class , Sub . class } , new Class < ? > [ ] { Integer . class , Super . class } , tc , ArgumentsMatchKind . CLOSE ) ;
checkMatch ( new Class < ? > [ ] { int . class , Sub . class } , new Class < ? > [ ] { Integer . class , Super . class } , tc , CLOSE ) ;
// Passing (int,Sub,boolean) on call to foo(Integer,Super,Boolean) requires boxing conversion of arguments zero and two
// TODO checkMatch(new Class<?>[] {int.class, Sub.class, boolean.class}, new Class<?>[] {Integer.class, Super.class, Boolean.class}, tc, ArgsMatchKind.REQUIRES_CONVERSION);
checkMatch ( new Class < ? > [ ] { int . class , Sub . class , boolean . class } , new Class < ? > [ ] { Integer . class , Super . class , Boolean . class } , tc , CLOSE ) ;
}
@Test
@ -149,59 +150,56 @@ class ReflectionHelperTests extends AbstractExpressionTests {
@@ -149,59 +150,56 @@ class ReflectionHelperTests extends AbstractExpressionTests {
}
@Test
void reflectionHelperCompareArguments_Varargs_ExactMatching ( ) {
StandardTypeConverter tc = new StandardTypeConverter ( ) ;
void reflectionHelperCompareArguments_Varargs ( ) {
// Passing (String[]) on call to (String[]) is exact match
checkMatch2 ( new Class < ? > [ ] { String [ ] . class } , new Class < ? > [ ] { String [ ] . class } , tc , ArgumentsMatchKind . EXACT ) ;
checkMatchVarargs ( new Class < ? > [ ] { String [ ] . class } , new Class < ? > [ ] { String [ ] . class } , tc , EXACT ) ;
// Passing (Integer, String[]) on call to (Integer, String[]) is exact match
checkMatch2 ( new Class < ? > [ ] { Integer . class , String [ ] . class } , new Class < ? > [ ] { Integer . class , String [ ] . class } , tc , ArgumentsMatchKind . EXACT ) ;
checkMatchVarargs ( new Class < ? > [ ] { Integer . class , String [ ] . class } , new Class < ? > [ ] { Integer . class , String [ ] . class } , tc , EXACT ) ;
// Passing (String, Integer, String[]) on call to (String, String, String[]) is exact match
checkMatch2 ( new Class < ? > [ ] { String . class , Integer . class , String [ ] . class } , new Class < ? > [ ] { String . class , Integer . class , String [ ] . class } , tc , ArgumentsMatchKind . EXACT ) ;
checkMatchVarargs ( new Class < ? > [ ] { String . class , Integer . class , String [ ] . class } , new Class < ? > [ ] { String . class , Integer . class , String [ ] . class } , tc , EXACT ) ;
// Passing (Sub, String[]) on call to (Super, String[]) is exact match
checkMatch2 ( new Class < ? > [ ] { Sub . class , String [ ] . class } , new Class < ? > [ ] { Super . class , String [ ] . class } , tc , ArgumentsMatchKind . CLOSE ) ;
checkMatchVarargs ( new Class < ? > [ ] { Sub . class , String [ ] . class } , new Class < ? > [ ] { Super . class , String [ ] . class } , tc , CLOSE ) ;
// Passing (Integer, String[]) on call to (String, String[]) is exact match
checkMatch2 ( new Class < ? > [ ] { Integer . class , String [ ] . class } , new Class < ? > [ ] { String . class , String [ ] . class } , tc , ArgumentsMatchKind . REQUIRES_CONVERSION ) ;
checkMatchVarargs ( new Class < ? > [ ] { Integer . class , String [ ] . class } , new Class < ? > [ ] { String . class , String [ ] . class } , tc , 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 ) ;
checkMatchVarargs ( new Class < ? > [ ] { Integer . class , Sub . class , String [ ] . class } , new Class < ? > [ ] { String . class , Super . class , String [ ] . class } , tc , REQUIRES_CONVERSION ) ;
// Passing (String) on call to (String[]) is exact match
checkMatch2 ( new Class < ? > [ ] { String . class } , new Class < ? > [ ] { String [ ] . class } , tc , ArgumentsMatchKind . EXACT ) ;
checkMatchVarargs ( new Class < ? > [ ] { String . class } , new Class < ? > [ ] { String [ ] . class } , tc , EXACT ) ;
// Passing (Integer,String) on call to (Integer,String[]) is exact match
checkMatch2 ( new Class < ? > [ ] { Integer . class , String . class } , new Class < ? > [ ] { Integer . class , String [ ] . class } , tc , ArgumentsMatchKind . EXACT ) ;
checkMatchVarargs ( new Class < ? > [ ] { Integer . class , String . class } , new Class < ? > [ ] { Integer . class , String [ ] . class } , tc , EXACT ) ;
// Passing (String) on call to (Integer[]) is conversion match (String to Integer)
checkMatch2 ( new Class < ? > [ ] { String . class } , new Class < ? > [ ] { Integer [ ] . class } , tc , ArgumentsMatchKind . REQUIRES_CONVERSION ) ;
checkMatchVarargs ( new Class < ? > [ ] { String . class } , new Class < ? > [ ] { Integer [ ] . class } , tc , REQUIRES_CONVERSION ) ;
// Passing (Sub) on call to (Super[]) is close match
checkMatch2 ( new Class < ? > [ ] { Sub . class } , new Class < ? > [ ] { Super [ ] . class } , tc , ArgumentsMatchKind . CLOSE ) ;
checkMatchVarargs ( new Class < ? > [ ] { Sub . class } , new Class < ? > [ ] { Super [ ] . class } , tc , CLOSE ) ;
// Passing (Super) on call to (Sub[]) is not a match
checkMatch2 ( new Class < ? > [ ] { Super . class } , new Class < ? > [ ] { Sub [ ] . class } , tc , null ) ;
checkMatchVarargs ( 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 ) ;
checkMatchVarargs ( new Class < ? > [ ] { Unconvertable . class , String . class } , new Class < ? > [ ] { Sub . class , Super [ ] . class } , tc , null ) ;
checkMatch2 ( new Class < ? > [ ] { Integer . class , Integer . class , String . class } , new Class < ? > [ ] { String . class , String . class , Super [ ] . class } , tc , null ) ;
checkMatchVarargs ( new Class < ? > [ ] { Integer . class , Integer . class , String . class } , new Class < ? > [ ] { String . class , String . class , Super [ ] . class } , tc , null ) ;
checkMatch2 ( new Class < ? > [ ] { Unconvertable . class , String . class } , new Class < ? > [ ] { Sub . class , Super [ ] . class } , tc , null ) ;
checkMatchVarargs ( new Class < ? > [ ] { Unconvertable . class , String . class } , new Class < ? > [ ] { Sub . class , Super [ ] . class } , tc , null ) ;
checkMatch2 ( new Class < ? > [ ] { Integer . class , Integer . class , String . class } , new Class < ? > [ ] { String . class , String . class , Super [ ] . class } , tc , null ) ;
checkMatchVarargs ( new Class < ? > [ ] { Integer . class , Integer . class , String . class } , new Class < ? > [ ] { String . class , String . class , Super [ ] . class } , tc , null ) ;
checkMatch2 ( new Class < ? > [ ] { Integer . class , Integer . class , Sub . class } , new Class < ? > [ ] { String . class , String . class , Super [ ] . class } , tc , ArgumentsMatchKind . REQUIRES_CONVERSION ) ;
checkMatchVarargs ( new Class < ? > [ ] { Integer . class , Integer . class , Sub . class } , new Class < ? > [ ] { String . class , String . class , Super [ ] . class } , tc , REQUIRES_CONVERSION ) ;
checkMatch2 ( new Class < ? > [ ] { Integer . class , Integer . class , Integer . class } , new Class < ? > [ ] { Integer . class , String [ ] . class } , tc , ArgumentsMatchKind . REQUIRES_CONVERSION ) ;
checkMatchVarargs ( new Class < ? > [ ] { Integer . class , Integer . class , Integer . class } , new Class < ? > [ ] { Integer . class , String [ ] . class } , tc , REQUIRES_CONVERSION ) ;
// what happens on (Integer,String) passed to (Integer[]) ?
}
@Test
void convertArguments ( ) throws Exception {
StandardTypeConverter tc = new StandardTypeConverter ( ) ;
Method oneArg = TestInterface . class . getMethod ( "oneArg" , String . class ) ;
Method twoArg = TestInterface . class . getMethod ( "twoArg" , String . class , String [ ] . class ) ;
@ -227,8 +225,7 @@ class ReflectionHelperTests extends AbstractExpressionTests {
@@ -227,8 +225,7 @@ class ReflectionHelperTests extends AbstractExpressionTests {
}
@Test
void convertArguments2 ( ) throws Exception {
StandardTypeConverter tc = new StandardTypeConverter ( ) ;
void convertAllArguments ( ) throws Exception {
Method oneArg = TestInterface . class . getMethod ( "oneArg" , String . class ) ;
Method twoArg = TestInterface . class . getMethod ( "twoArg" , String . class , String [ ] . class ) ;
@ -254,7 +251,7 @@ class ReflectionHelperTests extends AbstractExpressionTests {
@@ -254,7 +251,7 @@ class ReflectionHelperTests extends AbstractExpressionTests {
}
@Test
void setupArguments ( ) {
void setupArgumentsForVarargsInvocation ( ) {
Object [ ] newArray = ReflectionHelper . setupArgumentsForVarargsInvocation (
new Class < ? > [ ] { String [ ] . class } , "a" , "b" , "c" ) ;
@ -402,21 +399,21 @@ class ReflectionHelperTests extends AbstractExpressionTests {
@@ -402,21 +399,21 @@ class ReflectionHelperTests extends AbstractExpressionTests {
assertThat ( matchInfo ) . as ( "Should not be a null match" ) . isNotNull ( ) ;
}
if ( expectedMatchKind = = ArgumentsMatchKind . EXACT ) {
if ( expectedMatchKind = = EXACT ) {
assertThat ( matchInfo . isExactMatch ( ) ) . isTrue ( ) ;
}
else if ( expectedMatchKind = = ArgumentsMatchKind . CLOSE ) {
else if ( expectedMatchKind = = CLOSE ) {
assertThat ( matchInfo . isCloseMatch ( ) ) . isTrue ( ) ;
}
else if ( expectedMatchKind = = ArgumentsMatchKind . REQUIRES_CONVERSION ) {
else if ( expectedMatchKind = = REQUIRES_CONVERSION ) {
assertThat ( matchInfo . isMatchRequiringConversion ( ) ) . as ( "expected to be a match requiring conversion, but was " + matchInfo ) . isTrue ( ) ;
}
}
/ * *
* Used to validate the match returned from a compareArguments call .
* Used to validate the match returned from a compareArgumentsVarargs call .
* /
private static void checkMatch2 ( Class < ? > [ ] inputTypes , Class < ? > [ ] expectedTypes ,
private static void checkMatchVarargs ( Class < ? > [ ] inputTypes , Class < ? > [ ] expectedTypes ,
StandardTypeConverter typeConverter , ArgumentsMatchKind expectedMatchKind ) {
ReflectionHelper . ArgumentsMatchInfo matchInfo =
@ -438,14 +435,10 @@ class ReflectionHelperTests extends AbstractExpressionTests {
@@ -438,14 +435,10 @@ class ReflectionHelperTests extends AbstractExpressionTests {
private static void checkArguments ( Object [ ] args , Object . . . expected ) {
assertThat ( args ) . hasSize ( expected . length ) ;
for ( int i = 0 ; i < expected . length ; i + + ) {
checkArgument ( expected [ i ] , args [ i ] ) ;
assertThat ( args [ i ] ) . isEqualTo ( expected [ i ] ) ;
}
}
private static void checkArgument ( Object expected , Object actual ) {
assertThat ( actual ) . isEqualTo ( expected ) ;
}
private static List < TypeDescriptor > typeDescriptors ( Class < ? > . . . types ) {
return Arrays . stream ( types ) . map ( TypeDescriptor : : valueOf ) . toList ( ) ;
}