From c695d00dbefaf06162097179f7d53ea799ed79a8 Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Sat, 4 Apr 2009 01:04:31 +0000 Subject: [PATCH] More test coverage for the expression AST --- .../spel/ast/OperatorGreaterThan.java | 21 +++++------ .../expression/spel/ast/OperatorLessThan.java | 22 +++++------- .../spel/ast/OperatorLessThanOrEqual.java | 21 +++++------ .../expression/spel/ast/Ternary.java | 15 +++----- .../expression/spel/EvaluationTests.java | 15 ++++++++ .../expression/spel/OperatorTests.java | 35 ++++++++++++++++++- .../expression/spel/ParsingTests.java | 6 ++++ 7 files changed, 84 insertions(+), 51 deletions(-) diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorGreaterThan.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorGreaterThan.java index a545dd52159..0636b9e4871 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorGreaterThan.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorGreaterThan.java @@ -43,19 +43,14 @@ public class OperatorGreaterThan extends Operator { Object left = getLeftOperand().getValueInternal(state).getValue(); Object right = getRightOperand().getValueInternal(state).getValue(); if (left instanceof Number && right instanceof Number) { - Number op1 = (Number) left; - Number op2 = (Number) right; - if (op1 instanceof Double || op2 instanceof Double) { - return BooleanTypedValue.forValue(op1.doubleValue() > op2.doubleValue()); - } - else if (op1 instanceof Float || op2 instanceof Float) { - return BooleanTypedValue.forValue(op1.floatValue() > op2.floatValue()); - } - else if (op1 instanceof Long || op2 instanceof Long) { - return BooleanTypedValue.forValue(op1.longValue() > op2.longValue()); - } - else { - return BooleanTypedValue.forValue(op1.intValue() > op2.intValue()); + Number leftNumber = (Number) left; + Number rightNumber = (Number) right; + if (leftNumber instanceof Double || rightNumber instanceof Double) { + return BooleanTypedValue.forValue(leftNumber.doubleValue() > rightNumber.doubleValue()); + } else if (leftNumber instanceof Long || rightNumber instanceof Long) { + return BooleanTypedValue.forValue(leftNumber.longValue() > rightNumber.longValue()); + } else { + return BooleanTypedValue.forValue(leftNumber.intValue() > rightNumber.intValue()); } } return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) > 0); diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorLessThan.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorLessThan.java index d1b760931b8..1917d1f4fc9 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorLessThan.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorLessThan.java @@ -42,20 +42,16 @@ public class OperatorLessThan extends Operator { public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException { Object left = getLeftOperand().getValueInternal(state).getValue(); Object right = getRightOperand().getValueInternal(state).getValue(); + // TODO could leave all of these to the comparator - just seems quicker to do some here if (left instanceof Number && right instanceof Number) { - Number op1 = (Number) left; - Number op2 = (Number) right; - if (op1 instanceof Double || op2 instanceof Double) { - return BooleanTypedValue.forValue(op1.doubleValue() < op2.doubleValue()); - } - else if (op1 instanceof Float || op2 instanceof Float) { - return BooleanTypedValue.forValue(op1.floatValue() < op2.floatValue()); - } - else if (op1 instanceof Long || op2 instanceof Long) { - return BooleanTypedValue.forValue(op1.longValue() < op2.longValue()); - } - else { - return BooleanTypedValue.forValue(op1.intValue() < op2.intValue()); + Number leftNumber = (Number) left; + Number rightNumber = (Number) right; + if (leftNumber instanceof Double || rightNumber instanceof Double) { + return BooleanTypedValue.forValue(leftNumber.doubleValue() < rightNumber.doubleValue()); + } else if (leftNumber instanceof Long || rightNumber instanceof Long) { + return BooleanTypedValue.forValue(leftNumber.longValue() < rightNumber.longValue()); + } else { + return BooleanTypedValue.forValue(leftNumber.intValue() < rightNumber.intValue()); } } return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) < 0); diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorLessThanOrEqual.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorLessThanOrEqual.java index aaf2d3333a3..54555d18674 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorLessThanOrEqual.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorLessThanOrEqual.java @@ -38,19 +38,14 @@ public class OperatorLessThanOrEqual extends Operator { Object left = getLeftOperand().getValueInternal(state).getValue(); Object right = getRightOperand().getValueInternal(state).getValue(); if (left instanceof Number && right instanceof Number) { - Number op1 = (Number) left; - Number op2 = (Number) right; - if (op1 instanceof Double || op2 instanceof Double) { - return BooleanTypedValue.forValue(op1.doubleValue() <= op2.doubleValue()); - } - else if (op1 instanceof Float || op2 instanceof Float) { - return BooleanTypedValue.forValue(op1.floatValue() <= op2.floatValue()); - } - else if (op1 instanceof Long || op2 instanceof Long) { - return BooleanTypedValue.forValue(op1.longValue() <= op2.longValue()); - } - else { - return BooleanTypedValue.forValue(op1.intValue() <= op2.intValue()); + Number leftNumber = (Number) left; + Number rightNumber = (Number) right; + if (leftNumber instanceof Double || rightNumber instanceof Double) { + return BooleanTypedValue.forValue(leftNumber.doubleValue() <= rightNumber.doubleValue()); + } else if (leftNumber instanceof Long || rightNumber instanceof Long) { + return BooleanTypedValue.forValue(leftNumber.longValue() <= rightNumber.longValue()); + } else { + return BooleanTypedValue.forValue(leftNumber.intValue() <= rightNumber.intValue()); } } return BooleanTypedValue.forValue( state.getTypeComparator().compare(left, right) <= 0); diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Ternary.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Ternary.java index b601641571e..0989313aaba 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Ternary.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Ternary.java @@ -44,17 +44,10 @@ public class Ternary extends SpelNodeImpl { @Override public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { Boolean value = getChild(0).getValue(state, Boolean.class); - try { - if (Boolean.TRUE.equals(value)) { - return getChild(1).getValueInternal(state); - } - else { - return getChild(2).getValueInternal(state); - } - } - catch (SpelException ex) { - ex.setPosition(getChild(0).getCharPositionInLine()); - throw ex; + if (value.booleanValue()) { + return getChild(1).getValueInternal(state); + } else { + return getChild(2).getValueInternal(state); } } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java index 7c61beb229f..6427fa7eb21 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java @@ -16,6 +16,8 @@ package org.springframework.expression.spel; +import org.springframework.expression.Expression; + /** * Tests the evaluation of real expressions in a real context. * @@ -323,10 +325,23 @@ public class EvaluationTests extends ExpressionTestCase { // evaluate("{2}.#isEven(#this[0]) == 'y'?'it is even':'it is odd'", "it is even", String.class); // } + public void testTernaryOperator01() { + evaluate("2>4?1:2",2,Integer.class); + } + + public void testTernaryOperator02() { + evaluate("'abc'=='abc'?1:2",1,Integer.class); + } + public void testTernaryOperator03() { evaluateAndCheckError("'hello'?1:2", SpelMessages.TYPE_CONVERSION_ERROR); // cannot convert String to boolean } + public void testTernaryOperator04() throws Exception { + Expression expr = parser.parseExpression("1>2?3:4"); + assertFalse(expr.isWritable(eContext)); + } + // Indexer // public void testCutProcessor01() { // evaluate("{1,2,3,4,5}.cut(1,3)", "[2, 3, 4]", ArrayList.class); diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java index 17796351eaa..9a8a8b7d87d 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java @@ -36,12 +36,27 @@ public class OperatorTests extends ExpressionTestCase { public void testLessThan() { evaluate("3 < 5", true, Boolean.class); evaluate("5 < 3", false, Boolean.class); + evaluate("3L < 5L", true, Boolean.class); + evaluate("5L < 3L", false, Boolean.class); + evaluate("3.0d < 5.0d", true, Boolean.class); + evaluate("5.0d < 3.0d", false, Boolean.class); + evaluate("'abc' < 'def'",true,Boolean.class); + evaluate("'def' < 'abc'",false,Boolean.class); } public void testLessThanOrEqual() { evaluate("3 <= 5", true, Boolean.class); evaluate("5 <= 3", false, Boolean.class); evaluate("6 <= 6", true, Boolean.class); + evaluate("3L <= 5L", true, Boolean.class); + evaluate("5L <= 3L", false, Boolean.class); + evaluate("5L <= 5L", true, Boolean.class); + evaluate("3.0d < 5.0d", true, Boolean.class); + evaluate("5.0d < 3.0d", false, Boolean.class); + evaluate("5.0d <= 5.0d", true, Boolean.class); + evaluate("'abc' <= 'def'",true,Boolean.class); + evaluate("'def' <= 'abc'",false,Boolean.class); + evaluate("'abc' <= 'abc'",true,Boolean.class); } public void testEqual() { @@ -64,7 +79,13 @@ public class OperatorTests extends ExpressionTestCase { public void testGreaterThan() { evaluate("3 > 5", false, Boolean.class); - evaluate("5 > 3", true, Boolean.class); + evaluate("5 > 3", true, Boolean.class); + evaluate("3L > 5L", false, Boolean.class); + evaluate("5L > 3L", true, Boolean.class); + evaluate("3.0d > 5.0d", false, Boolean.class); + evaluate("5.0d > 3.0d", true, Boolean.class); + evaluate("'abc' > 'def'",false,Boolean.class); + evaluate("'def' > 'abc'",true,Boolean.class); } public void testMultiplyStringInt() { @@ -136,6 +157,18 @@ public class OperatorTests extends ExpressionTestCase { node = getOperatorNode((SpelExpression)parser.parseExpression("3/3")); assertEquals("/",node.getOperatorName()); + + node = getOperatorNode((SpelExpression)parser.parseExpression("3+3")); + assertEquals("+",node.getOperatorName()); + + node = getOperatorNode((SpelExpression)parser.parseExpression("3-3")); + assertEquals("-",node.getOperatorName()); + + node = getOperatorNode((SpelExpression)parser.parseExpression("3<4")); + assertEquals("<",node.getOperatorName()); + + node = getOperatorNode((SpelExpression)parser.parseExpression("3<=4")); + assertEquals("<=",node.getOperatorName()); } public void testMixedOperands_FloatsAndDoubles() { diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/ParsingTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/ParsingTests.java index 641d485f3cb..29a1354c5c5 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/ParsingTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/ParsingTests.java @@ -346,7 +346,13 @@ public class ParsingTests extends TestCase { parseCheck("#var1='value1'"); } + // ternary operator + + public void testTernaryOperator01() { + parseCheck("1>2?3:4","(1 > 2) ? 3 : 4"); + } + // public void testTernaryOperator01() { // parseCheck("{1}.#isEven(#this) == 'y'?'it is even':'it is odd'", // "({1}.#isEven(#this) == 'y') ? 'it is even' : 'it is odd'");