@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
/ *
* Copyright 2002 - 2022 the original author or authors .
* Copyright 2002 - 2023 the original author or authors .
*
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
@ -16,7 +16,6 @@
@@ -16,7 +16,6 @@
package org.springframework.expression.spel ;
import java.util.HashMap ;
import java.util.Map ;
import org.junit.jupiter.api.Test ;
@ -34,27 +33,31 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -34,27 +33,31 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException ;
/ * *
* Tests for the expression state object - some features are not yet exploited in the language ( eg nested scopes )
* Tests for { @link ExpressionState } .
*
* < p > Some features are not yet exploited in the language , such as nested scopes
* or local variables scoped to the currently evaluated expression .
*
* < p > Local variables are in variable scopes which come and go during evaluation .
* Normal / global variables are accessible through the { @link EvaluationContext } .
*
* @author Andy Clement
* @author Juergen Hoeller
* /
public class ExpressionStateTests extends AbstractExpressionTests {
class ExpressionStateTests extends AbstractExpressionTests {
private ExpressionState state = new ExpressionState ( TestScenarioCreator . getTestEvaluationContext ( ) ) ;
@Test
public void testConstruction ( ) {
void c onstruction( ) {
EvaluationContext context = TestScenarioCreator . getTestEvaluationContext ( ) ;
ExpressionState state = new ExpressionState ( context ) ;
assertThat ( state . getEvaluationContext ( ) ) . isEqualTo ( context ) ;
}
// Local variables are in variable scopes which come and go during evaluation. Normal variables are
// accessible through the evaluation context
@Test
public void testLocalVariables ( ) {
ExpressionState state = getState ( ) ;
void localVariables ( ) {
Object value = state . lookupLocalVariable ( "foo" ) ;
assertThat ( value ) . isNull ( ) ;
@ -68,8 +71,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
@@ -68,8 +71,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testVariables ( ) {
ExpressionState state = getState ( ) ;
void globalVariables ( ) {
TypedValue typedValue = state . lookupVariable ( "foo" ) ;
assertThat ( typedValue ) . isEqualTo ( TypedValue . NULL ) ;
@ -85,8 +87,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
@@ -85,8 +87,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testNoVariableInterference ( ) {
ExpressionState state = getState ( ) ;
void noVariableInterference ( ) {
TypedValue typedValue = state . lookupVariable ( "foo" ) ;
assertThat ( typedValue ) . isEqualTo ( TypedValue . NULL ) ;
@ -99,8 +100,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
@@ -99,8 +100,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testLocalVariableNestedScopes ( ) {
ExpressionState state = getState ( ) ;
void localVariableNestedScopes ( ) {
assertThat ( state . lookupLocalVariable ( "foo" ) ) . isNull ( ) ;
state . setLocalVariable ( "foo" , 12 ) ;
@ -120,30 +120,26 @@ public class ExpressionStateTests extends AbstractExpressionTests {
@@ -120,30 +120,26 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testRootContextObject ( ) {
ExpressionState state = getState ( ) ;
void rootContextObject ( ) {
assertThat ( state . getRootContextObject ( ) . getValue ( ) . getClass ( ) ) . isEqualTo ( Inventor . class ) ;
// although the root object is being set on the evaluation context, the value in the 'state' remains what it was when constructed
// Although the root object is being set on the evaluation context,
// the value in the 'state' remains what it was when constructed.
( ( StandardEvaluationContext ) state . getEvaluationContext ( ) ) . setRootObject ( null ) ;
assertThat ( state . getRootContextObject ( ) . getValue ( ) . getClass ( ) ) . isEqualTo ( Inventor . class ) ;
// assertEquals(null, state.getRootContextObject().getValue());
assertThat ( state . getRootContextObject ( ) . getValue ( ) ) . isInstanceOf ( Inventor . class ) ;
state = new ExpressionState ( new StandardEvaluationContext ( ) ) ;
assertThat ( state . getRootContextObject ( ) ) . isEqualTo ( TypedValue . NULL ) ;
( ( StandardEvaluationContext ) state . getEvaluationContext ( ) ) . setRootObject ( null ) ;
assertThat ( state . getRootContextObject ( ) . getValue ( ) ) . isNull ( ) ;
}
@Test
public void testActiveContextObject ( ) {
ExpressionState state = getState ( ) ;
void activeContextObject ( ) {
assertThat ( state . getActiveContextObject ( ) . getValue ( ) ) . isEqualTo ( state . getRootContextObject ( ) . getValue ( ) ) ;
assertThatIllegalStateException ( ) . isThrownBy (
state : : popActiveContextObject ) ;
assertThatIllegalStateException ( ) . isThrownBy ( state : : popActiveContextObject ) ;
state . pushActiveContextObject ( new TypedValue ( 34 ) ) ;
assertThat ( state . getActiveContextObject ( ) . getValue ( ) ) . isEqualTo ( 34 ) ;
@ -162,8 +158,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
@@ -162,8 +158,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testPopulatedNestedScopes ( ) {
ExpressionState state = getState ( ) ;
void populatedNestedScopes ( ) {
assertThat ( state . lookupLocalVariable ( "foo" ) ) . isNull ( ) ;
state . enterScope ( "foo" , 34 ) ;
@ -181,27 +176,22 @@ public class ExpressionStateTests extends AbstractExpressionTests {
@@ -181,27 +176,22 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testR ootObjectConstructor( ) {
EvaluationContext ctx = getContext ( ) ;
void r ootObjectConstructor( ) {
EvaluationContext ctx = TestScenarioCreator . getTestEvaluation Context ( ) ;
// TypedValue root = ctx.getRootObject();
// supplied should override root on context
ExpressionState state = new ExpressionState ( ctx , new TypedValue ( "i am a string" ) ) ;
ExpressionState state = new ExpressionState ( ctx , new TypedValue ( "i am a string" ) ) ;
TypedValue stateRoot = state . getRootContextObject ( ) ;
assertThat ( stateRoot . getTypeDescriptor ( ) . getType ( ) ) . isEqualTo ( String . class ) ;
assertThat ( stateRoot . getValue ( ) ) . isEqualTo ( "i am a string" ) ;
}
@Test
public void testPopulatedNestedScopesMap ( ) {
ExpressionState state = getState ( ) ;
void populatedNestedScopesMap ( ) {
assertThat ( state . lookupLocalVariable ( "foo" ) ) . isNull ( ) ;
assertThat ( state . lookupLocalVariable ( "goo" ) ) . isNull ( ) ;
Map < String , Object > m = new HashMap < > ( ) ;
m . put ( "foo" , 34 ) ;
m . put ( "goo" , "abc" ) ;
state . enterScope ( m ) ;
state . enterScope ( Map . of ( "foo" , 34 , "goo" , "abc" ) ) ;
assertThat ( state . lookupLocalVariable ( "foo" ) ) . isEqualTo ( 34 ) ;
assertThat ( state . lookupLocalVariable ( "goo" ) ) . isEqualTo ( "abc" ) ;
@ -217,61 +207,42 @@ public class ExpressionStateTests extends AbstractExpressionTests {
@@ -217,61 +207,42 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testOperators ( ) {
ExpressionState state = getState ( ) ;
assertThatExceptionOfType ( SpelEvaluationException . class ) . isThrownBy ( ( ) - >
state . operate ( Operation . ADD , 1 , 2 ) )
void operators ( ) {
assertThatExceptionOfType ( SpelEvaluationException . class )
. isThrownBy ( ( ) - > state . operate ( Operation . ADD , 1 , 2 ) )
. satisfies ( ex - > assertThat ( ex . getMessageCode ( ) ) . isEqualTo ( SpelMessage . OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES ) ) ;
assertThatExceptionOfType ( SpelEvaluationException . class ) . isThrownBy ( ( ) - >
state . operate ( Operation . ADD , null , null ) )
assertThatExceptionOfType ( SpelEvaluationException . class )
. isThrownBy ( ( ) - > state . operate ( Operation . ADD , null , null ) )
. satisfies ( ex - > assertThat ( ex . getMessageCode ( ) ) . isEqualTo ( SpelMessage . OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES ) ) ;
}
@Test
public void testComparator ( ) {
ExpressionState state = getState ( ) ;
void comparator ( ) {
assertThat ( state . getTypeComparator ( ) ) . isEqualTo ( state . getEvaluationContext ( ) . getTypeComparator ( ) ) ;
}
@Test
public void testTypeLocator ( ) throws EvaluationException {
ExpressionState state = getState ( ) ;
void typeLocator ( ) throws EvaluationException {
assertThat ( state . getEvaluationContext ( ) . getTypeLocator ( ) ) . isNotNull ( ) ;
assertThat ( state . findType ( "java.lang.Integer" ) ) . isEqualTo ( Integer . class ) ;
assertThatExceptionOfType ( SpelEvaluationException . class ) . isThrownBy ( ( ) - >
state . findType ( "someMadeUpName" ) )
assertThatExceptionOfType ( SpelEvaluationException . class )
. isThrownBy ( ( ) - > state . findType ( "someMadeUpName" ) )
. satisfies ( ex - > assertThat ( ex . getMessageCode ( ) ) . isEqualTo ( SpelMessage . TYPE_NOT_FOUND ) ) ;
}
@Test
public void testTypeConversion ( ) throws EvaluationException {
ExpressionState state = getState ( ) ;
void typeConversion ( ) throws EvaluationException {
String s = ( String ) state . convertValue ( 34 , TypeDescriptor . valueOf ( String . class ) ) ;
assertThat ( s ) . isEqualTo ( "34" ) ;
s = ( String ) state . convertValue ( new TypedValue ( 34 ) , TypeDescriptor . valueOf ( String . class ) ) ;
s = ( String ) state . convertValue ( new TypedValue ( 34 ) , TypeDescriptor . valueOf ( String . class ) ) ;
assertThat ( s ) . isEqualTo ( "34" ) ;
}
@Test
public void testPropertyAccessors ( ) {
ExpressionState state = getState ( ) ;
void propertyAccessors ( ) {
assertThat ( state . getPropertyAccessors ( ) ) . isEqualTo ( state . getEvaluationContext ( ) . getPropertyAccessors ( ) ) ;
}
/ * *
* @return a new ExpressionState
* /
private ExpressionState getState ( ) {
EvaluationContext context = TestScenarioCreator . getTestEvaluationContext ( ) ;
ExpressionState state = new ExpressionState ( context ) ;
return state ;
}
private EvaluationContext getContext ( ) {
return TestScenarioCreator . getTestEvaluationContext ( ) ;
}
}