Browse Source

reorganizing tests - extracting EvaluationTests out into other test classes. Started work on parser error message tests.

conversation
Andy Clement 16 years ago
parent
commit
a06b5aaa8d
  1. 2
      org.springframework.expression/src/test/java/org/springframework/expression/spel/AllTests.java
  2. 9
      org.springframework.expression/src/test/java/org/springframework/expression/spel/BooleanExpressionTests.java
  3. 147
      org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java
  4. 76
      org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestCase.java
  5. 109
      org.springframework.expression/src/test/java/org/springframework/expression/spel/LiteralTests.java
  6. 39
      org.springframework.expression/src/test/java/org/springframework/expression/spel/ParserErrorMessagesTests.java
  7. 19
      org.springframework.expression/src/test/java/org/springframework/expression/spel/ParsingTests.java

2
org.springframework.expression/src/test/java/org/springframework/expression/spel/AllTests.java

@ -30,7 +30,9 @@ public class AllTests { @@ -30,7 +30,9 @@ public class AllTests {
TestSuite suite = new TestSuite("Spring Expression Language tests");
// $JUnit-BEGIN$
suite.addTestSuite(BooleanExpressionTests.class);
suite.addTestSuite(LiteralTests.class);
suite.addTestSuite(ParsingTests.class);
suite.addTestSuite(ParserErrorMessagesTests.class);
suite.addTestSuite(EvaluationTests.class);
suite.addTestSuite(OperatorTests.class);
suite.addTestSuite(ConstructorInvocationTests.class);

9
org.springframework.expression/src/test/java/org/springframework/expression/spel/BooleanExpressionTests.java

@ -54,4 +54,13 @@ public class BooleanExpressionTests extends ExpressionTestCase { @@ -54,4 +54,13 @@ public class BooleanExpressionTests extends ExpressionTestCase {
evaluate("true and false or true", Boolean.TRUE, Boolean.class);
evaluate("true and false or false", Boolean.FALSE, Boolean.class);
}
public void testBooleanErrors01() {
evaluateAndCheckError("1 or false", SpelMessages.TYPE_CONVERSION_ERROR, 0);
evaluateAndCheckError("false or 39", SpelMessages.TYPE_CONVERSION_ERROR, 9);
evaluateAndCheckError("true and 'hello'", SpelMessages.TYPE_CONVERSION_ERROR, 9);
evaluateAndCheckError(" 'hello' and 'goodbye'", SpelMessages.TYPE_CONVERSION_ERROR, 1);
evaluateAndCheckError("!35", SpelMessages.TYPE_CONVERSION_ERROR, 1);
evaluateAndCheckError("! 'foob'", SpelMessages.TYPE_CONVERSION_ERROR, 2);
}
}

147
org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java

@ -27,98 +27,6 @@ import org.springframework.expression.spel.ast.Lambda; @@ -27,98 +27,6 @@ import org.springframework.expression.spel.ast.Lambda;
*/
public class EvaluationTests extends ExpressionTestCase {
// literals: boolean, integer, string, hex, real, null, date
public void testLiteralBoolean01() {
evaluate("false", "false", Boolean.class);
}
public void testLiteralBoolean02() {
evaluate("true", "true", Boolean.class);
}
public void testLiteralInteger01() {
evaluate("1", "1", Integer.class);
}
public void testLiteralInteger02() {
evaluate("1415", "1415", Integer.class);
}
public void testLiteralString01() {
evaluate("'Hello World'", "Hello World", String.class);
}
public void testLiteralString02() {
evaluate("'joe bloggs'", "joe bloggs", String.class);
}
public void testLiteralString03() {
evaluate("'hello'", "hello", String.class);
}
public void testLiteralString04() {
evaluate("'Tony''s Pizza'", "Tony's Pizza", String.class);
}
public void testLiteralString05() {
evaluate("\"Hello World\"", "Hello World", String.class);
}
public void testLiteralString06() {
evaluate("\"Hello ' World\"", "Hello ' World", String.class);
}
public void testLiteralHex01() {
evaluate("0x7FFFFFFF", "2147483647", Integer.class);
}
public void testLiteralReal01() {
evaluate("6.0221415E+23", "6.0221415E23", Double.class);
}
public void testLiteralNull01() {
evaluate("null", null, null);
}
// TODO 3 'default' format for date varies too much, we need to standardize on a format for EL
// public void testLiteralDate01() {
// eval("date('3-Feb-2008 4:50:20 PM').getTime()>0", "true", Boolean.class);
// }
public void testLiteralDate02() {
evaluate("date('19740824131030','yyyyMMddHHmmss').getHours()", "13", Integer.class);
}
// boolean operators: and or not
public void testBooleanOperators01() {
evaluate("false or false", "false", Boolean.class);
}
public void testBooleanOperators02() {
evaluate("false or true", "true", Boolean.class);
}
public void testBooleanOperators03() {
evaluate("true or false", "true", Boolean.class);
}
public void testBooleanOperators04() {
evaluate("true or true", "true", Boolean.class);
}
public void testBooleanOperators05() {
evaluate("false or true and false", "false", Boolean.class);
}
public void testBooleanErrors01() {
evaluateAndCheckError("1 or false", SpelMessages.TYPE_CONVERSION_ERROR, 0);
evaluateAndCheckError("false or 39", SpelMessages.TYPE_CONVERSION_ERROR, 9);
evaluateAndCheckError("true and 'hello'", SpelMessages.TYPE_CONVERSION_ERROR, 9);
evaluateAndCheckError(" 'hello' and 'goodbye'", SpelMessages.TYPE_CONVERSION_ERROR, 1);
evaluateAndCheckError("!35", SpelMessages.TYPE_CONVERSION_ERROR, 1);
evaluateAndCheckError("! 'foob'", SpelMessages.TYPE_CONVERSION_ERROR, 2);
}
// relational operators: lt, le, gt, ge, eq, ne
public void testRelOperatorGT01() {
evaluate("3 > 6", "false", Boolean.class);
@ -246,14 +154,16 @@ public class EvaluationTests extends ExpressionTestCase { @@ -246,14 +154,16 @@ public class EvaluationTests extends ExpressionTestCase {
// property access
public void testPropertyField01() {
eval("name", "Nikola Tesla", String.class, false); // not writable because (1) name is private (2) there is no setter, only a getter
evaluate("name", "Nikola Tesla", String.class, false); // not writable because (1) name is private (2) there is
// no
// setter, only a getter
evaluateAndCheckError("madeup", SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, 0, "madeup",
"org.springframework.expression.spel.testresources.Inventor");
}
// nested properties
public void testPropertiesNested01() {
eval("placeOfBirth.city", "SmilJan", String.class, true);
evaluate("placeOfBirth.city", "SmilJan", String.class, true);
}
public void testPropertiesNested02() {
@ -284,7 +194,8 @@ public class EvaluationTests extends ExpressionTestCase { @@ -284,7 +194,8 @@ public class EvaluationTests extends ExpressionTestCase {
}
public void testInlineMapCreation02() {
evaluate("#{1:'January', 2:'February', 3:'March'}.size()", 3, Integer.class);//"{2=February, 1=January, 3=March}", HashMap.class);
evaluate("#{1:'January', 2:'February', 3:'March'}.size()", 3, Integer.class);// "{2=February, 1=January,
// 3=March}", HashMap.class);
}
public void testInlineMapCreation03() {
@ -444,7 +355,7 @@ public class EvaluationTests extends ExpressionTestCase { @@ -444,7 +355,7 @@ public class EvaluationTests extends ExpressionTestCase {
}
public void testAssignmentToVariables02() {
eval("(#var1='value1';#var1)", "value1", String.class, true);
evaluate("(#var1='value1';#var1)", "value1", String.class, true);
}
// Property setting
@ -480,11 +391,11 @@ public class EvaluationTests extends ExpressionTestCase { @@ -480,11 +391,11 @@ public class EvaluationTests extends ExpressionTestCase {
// Bean references
public void testReferences01() {
eval("@(apple).name", "Apple", String.class, true);
evaluate("@(apple).name", "Apple", String.class, true);
}
public void testReferences02() {
eval("@(fruits:banana).name", "Banana", String.class, true);
evaluate("@(fruits:banana).name", "Banana", String.class, true);
}
public void testReferences03() {
@ -492,7 +403,7 @@ public class EvaluationTests extends ExpressionTestCase { @@ -492,7 +403,7 @@ public class EvaluationTests extends ExpressionTestCase {
} // null - no context, a.b.c treated as name
public void testReferences05() {
eval("@(a/b/c:orange).name", "Orange", String.class, true);
evaluate("@(a/b/c:orange).name", "Orange", String.class, true);
}
// TODO 4 automatic/default imports for next line?
@ -507,11 +418,11 @@ public class EvaluationTests extends ExpressionTestCase { @@ -507,11 +418,11 @@ public class EvaluationTests extends ExpressionTestCase {
public void testReferences07() {
evaluate("@(apple).color.getRGB().equals(T(java.awt.Color).green.getRGB())", "true", Boolean.class);
}
// value is not public, it is accessed through getRGB()
// public void testStaticRef01() {
// evaluate("T(Color).green.value!=0", "true", Boolean.class);
// }
// value is not public, it is accessed through getRGB()
// public void testStaticRef01() {
// evaluate("T(Color).green.value!=0", "true", Boolean.class);
// }
public void testStaticRef02() {
evaluate("T(Color).green.getRGB()!=0", "true", Boolean.class);
@ -519,7 +430,7 @@ public class EvaluationTests extends ExpressionTestCase { @@ -519,7 +430,7 @@ public class EvaluationTests extends ExpressionTestCase {
// variables and functions
public void testVariableAccess01() {
eval("#answer", "42", Integer.class, true);
evaluate("#answer", "42", Integer.class, true);
}
public void testFunctionAccess01() {
@ -536,7 +447,7 @@ public class EvaluationTests extends ExpressionTestCase { @@ -536,7 +447,7 @@ public class EvaluationTests extends ExpressionTestCase {
}
public void testLambdaNoArgsReferenced() {
eval("(#fn={|| false };#fn)", "{|| false }", Lambda.class, true);
evaluate("(#fn={|| false };#fn)", "{|| false }", Lambda.class, true);
}
public void testLambda01() {
@ -612,8 +523,8 @@ public class EvaluationTests extends ExpressionTestCase { @@ -612,8 +523,8 @@ public class EvaluationTests extends ExpressionTestCase {
}
public void testVariableReferences() {
eval("(#answer=42;#answer)", "42", Integer.class, true);
eval("($answer=42;$answer)", "42", Integer.class, true);
evaluate("(#answer=42;#answer)", "42", Integer.class, true);
evaluate("($answer=42;$answer)", "42", Integer.class, true);
}
// type references
@ -636,15 +547,15 @@ public class EvaluationTests extends ExpressionTestCase { @@ -636,15 +547,15 @@ public class EvaluationTests extends ExpressionTestCase {
evaluate("T(String)", "class java.lang.String", Class.class);
}
public void testStringType() {
evaluateAndAskForReturnType("getPlaceOfBirth().getCity()", "SmilJan", String.class);
public void testStringType() {
evaluateAndAskForReturnType("getPlaceOfBirth().getCity()", "SmilJan", String.class);
}
public void testNumbers01() {
evaluateAndAskForReturnType("3*4+5", 17, Integer.class);
evaluateAndAskForReturnType("3*4+5", 17L, Long.class);
evaluateAndAskForReturnType("65", 'A', Character.class);
evaluateAndAskForReturnType("3*4+5", (short) 17, Short.class);
evaluateAndAskForReturnType("3*4+5", "17", String.class);
}
public void testNumbers01() {
evaluateAndAskForReturnType("3*4+5",17,Integer.class);
evaluateAndAskForReturnType("3*4+5",17L,Long.class);
evaluateAndAskForReturnType("65",'A',Character.class);
evaluateAndAskForReturnType("3*4+5",(short)17,Short.class);
evaluateAndAskForReturnType("3*4+5","17",String.class);
}
}

76
org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestCase.java

@ -140,7 +140,8 @@ public abstract class ExpressionTestCase extends TestCase { @@ -140,7 +140,8 @@ public abstract class ExpressionTestCase extends TestCase {
* @param expectedClassOfResult the expected class of the evaluation result
* @param shouldBeWritable should the parsed expression be writable?
*/
public void eval(String expression, Object expectedValue, Class<?> expectedClassOfResult, boolean shouldBeWritable) {
public void evaluate(String expression, Object expectedValue, Class<?> expectedClassOfResult,
boolean shouldBeWritable) {
try {
SpelExpression e = parser.parseExpression(expression);
if (e == null) {
@ -191,13 +192,33 @@ public abstract class ExpressionTestCase extends TestCase { @@ -191,13 +192,33 @@ public abstract class ExpressionTestCase extends TestCase {
* @param otherProperties The expected inserts within the message
*/
protected void evaluateAndCheckError(String expression, SpelMessages expectedMessage, Object... otherProperties) {
evaluateAndCheckError(expression, null, expectedMessage, otherProperties);
}
/**
* Evaluate the specified expression and ensure the expected message comes out. The message may have inserts and
* they will be checked if otherProperties is specified. The first entry in otherProperties should always be the
* position.
* @param expression The expression to evaluate
* @param expectedReturnType Ask the expression return value to be of this type if possible (null indicates don't
* ask for conversion)
* @param expectedMessage The expected message
* @param otherProperties The expected inserts within the message
*/
protected void evaluateAndCheckError(String expression, Class<?> expectedReturnType, SpelMessages expectedMessage,
Object... otherProperties) {
try {
Expression expr = parser.parseExpression(expression);
if (expr == null) {
fail("Parser returned null for expression");
}
@SuppressWarnings("unused")
Object value = expr.getValue(eContext);
if (expectedReturnType != null) {
@SuppressWarnings("unused")
Object value = expr.getValue(eContext, expectedReturnType);
} else {
@SuppressWarnings("unused")
Object value = expr.getValue(eContext);
}
fail("Should have failed with message " + expectedMessage);
} catch (EvaluationException ee) {
SpelException ex = (SpelException) ee;
@ -236,9 +257,56 @@ public abstract class ExpressionTestCase extends TestCase { @@ -236,9 +257,56 @@ public abstract class ExpressionTestCase extends TestCase {
}
}
/**
* Parse the specified expression and ensure the expected message comes out. The message may have inserts and they
* will be checked if otherProperties is specified. The first entry in otherProperties should always be the
* position.
* @param expression The expression to evaluate
* @param expectedMessage The expected message
* @param otherProperties The expected inserts within the message
*/
protected void parseAndCheckError(String expression, SpelMessages expectedMessage, Object... otherProperties) {
try {
Expression expr = parser.parseExpression(expression);
fail("Parsing should have failed!");
} catch (ParseException pe) {
SpelException ex = (SpelException) pe.getCause();
if (ex.getMessageUnformatted() != expectedMessage) {
System.out.println(ex.getMessage());
ex.printStackTrace();
assertEquals("Failed to get expected message", expectedMessage, ex.getMessageUnformatted());
}
if (otherProperties != null && otherProperties.length != 0) {
// first one is expected position of the error within the string
int pos = ((Integer) otherProperties[0]).intValue();
assertEquals("Did not get correct position reported in error ", pos, ex.getPosition());
if (otherProperties.length > 1) {
// Check inserts match
Object[] inserts = ex.getInserts();
if (inserts == null) {
inserts = new Object[0];
}
if (inserts.length < otherProperties.length - 1) {
ex.printStackTrace();
fail("Cannot check " + (otherProperties.length - 1)
+ " properties of the exception, it only has " + inserts.length + " inserts");
}
for (int i = 1; i < otherProperties.length; i++) {
if (!inserts[i - 1].equals(otherProperties[i])) {
ex.printStackTrace();
fail("Insert does not match, expected '" + otherProperties[i] + "' but insert value was '"
+ inserts[i - 1] + "'");
}
}
}
}
}
}
public static String stringValueOf(Object value) {
// do something nice for arrays
if (value==null) return "null";
if (value == null)
return "null";
if (value.getClass().isArray()) {
StringBuilder sb = new StringBuilder();
if (value.getClass().getComponentType().isPrimitive()) {

109
org.springframework.expression/src/test/java/org/springframework/expression/spel/LiteralTests.java

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
/*
* Copyright 2004-2008 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.
* 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.springframework.expression.spel;
/**
* Tests the evaluation of basic literals: boolean, integer, hex integer, long, real, null, date
*
* @author Andy Clement
*/
public class LiteralTests extends ExpressionTestCase {
public void testLiteralBoolean01() {
evaluate("false", "false", Boolean.class);
}
public void testLiteralBoolean02() {
evaluate("true", "true", Boolean.class);
}
public void testLiteralInteger01() {
evaluate("1", "1", Integer.class);
}
public void testLiteralInteger02() {
evaluate("1415", "1415", Integer.class);
}
public void testLiteralString01() {
evaluate("'Hello World'", "Hello World", String.class);
}
public void testLiteralString02() {
evaluate("'joe bloggs'", "joe bloggs", String.class);
}
public void testLiteralString03() {
evaluate("'hello'", "hello", String.class);
}
public void testLiteralString04() {
evaluate("'Tony''s Pizza'", "Tony's Pizza", String.class);
}
public void testLiteralString05() {
evaluate("\"Hello World\"", "Hello World", String.class);
}
public void testLiteralString06() {
evaluate("\"Hello ' World\"", "Hello ' World", String.class);
}
public void testHexIntLiteral01() {
evaluate("0x7FFFF", "524287", Integer.class);
evaluate("0x7FFFFL", 524287L, Long.class);
evaluate("0X7FFFF", "524287", Integer.class);
evaluate("0X7FFFFl", 524287L, Long.class);
}
public void testLongIntLiteral01() {
evaluate("0xCAFEBABEL", 3405691582L, Long.class);
}
public void testLongIntInteractions01() {
evaluate("0x20 * 2L", 64L, Long.class);
// ask for the result to be made into an Integer
evaluateAndAskForReturnType("0x20 * 2L", 64, Integer.class);
// ask for the result to be made into an Integer knowing that it will not fit
evaluateAndCheckError("0x1220 * 0xffffffffL", Integer.class, SpelMessages.PROBLEM_DURING_TYPE_CONVERSION, -1,
"long value '19928648248800' cannot be represented as an int");
}
public void testSignedIntLiterals() {
evaluate("-1", -1, Integer.class);
evaluate("-0xa", -10, Integer.class);
evaluate("-1L", -1L, Long.class);
evaluate("-0x20l", -32L, Long.class);
}
public void testLiteralReal01() {
evaluate("6.0221415E+23", "6.0221415E23", Double.class);
}
public void testLiteralNull01() {
evaluate("null", null, null);
}
// TODO 3 'default' format for date varies too much, we need to standardize on a format for EL
// public void testLiteralDate01() {
// eval("date('3-Feb-2008 4:50:20 PM').getTime()>0", "true", Boolean.class);
// }
public void testLiteralDate02() {
evaluate("date('19740824131030','yyyyMMddHHmmss').getHours()", "13", Integer.class);
}
}

39
org.springframework.expression/src/test/java/org/springframework/expression/spel/ParserErrorMessagesTests.java

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
/*
* Copyright 2004-2008 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.
* 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.springframework.expression.spel;
/**
* Tests the messages and exceptions that come out for badly formed expressions
*
* @author Andy Clement
*/
public class ParserErrorMessagesTests extends ExpressionTestCase {
public void testBrokenExpression01() {
// Expression: 0xCAFEBABE - too big to be processed as an int, needs the L suffix
parseAndCheckError("0xCAFEBABE", SpelMessages.NOT_AN_INTEGER);
}
// parseCheck("true or ");
// parseCheck("tru or false");
// parseCheck("1 + ");
// parseCheck("0xCAFEBABEG");
// TODO 3 too many close brackets - parser recover
// public void testExpressionLists07a() { parseCheck("((3;4;)+(5;6;)))","((3;4)
// + (5;6))");}
// }
// ---
}

19
org.springframework.expression/src/test/java/org/springframework/expression/spel/ParsingTests.java

@ -29,6 +29,7 @@ public class ParsingTests extends TestCase { @@ -29,6 +29,7 @@ public class ParsingTests extends TestCase {
private SpelExpressionParser parser;
@Override
public void setUp() {
parser = new SpelExpressionParser();
}
@ -37,9 +38,9 @@ public class ParsingTests extends TestCase { @@ -37,9 +38,9 @@ public class ParsingTests extends TestCase {
public void testLiteralBoolean01() {
parseCheck("false");
}
public void testLiteralLong01() {
parseCheck("37L","37");
parseCheck("37L", "37");
}
public void testLiteralBoolean02() {
@ -413,20 +414,6 @@ public class ParsingTests extends TestCase { @@ -413,20 +414,6 @@ public class ParsingTests extends TestCase {
parseCheck("((3;4;)+(5;6;))", "((3;4) + (5;6))");
}
// TODO 3 too many close brackets - parser recover
// public void testExpressionLists07a() { parseCheck("((3;4;)+(5;6;)))","((3;4)
// + (5;6))");}
// parser warnings/errors
// public void testBrokenExpression01() {
// parseCheck("1 + ");
//
// }
// ---
/**
* Parse the supplied expression and then create a string representation of the resultant AST, it should be the same
* as the original expression.

Loading…
Cancel
Save