From 5afd94f90f08ee96967188067cbfa8f0288b6d38 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Tue, 25 Apr 2023 13:15:28 +0200 Subject: [PATCH] Polish SpelParserTests and TemplateExpressionParsingTests --- .../spel/TemplateExpressionParsingTests.java | 39 ++-- .../spel/standard/SpelParserTests.java | 189 ++++++++---------- 2 files changed, 104 insertions(+), 124 deletions(-) diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/TemplateExpressionParsingTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/TemplateExpressionParsingTests.java index 49face8bf7d..0d524050b93 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/TemplateExpressionParsingTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/TemplateExpressionParsingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 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. @@ -34,10 +34,11 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; /** * @author Andy Clement * @author Juergen Hoeller + * @author Sam Brannen */ -public class TemplateExpressionParsingTests extends AbstractExpressionTests { +class TemplateExpressionParsingTests extends AbstractExpressionTests { - public static final ParserContext DEFAULT_TEMPLATE_PARSER_CONTEXT = new ParserContext() { + static final ParserContext DEFAULT_TEMPLATE_PARSER_CONTEXT = new ParserContext() { @Override public String getExpressionPrefix() { return "${"; @@ -52,7 +53,7 @@ public class TemplateExpressionParsingTests extends AbstractExpressionTests { } }; - public static final ParserContext HASH_DELIMITED_PARSER_CONTEXT = new ParserContext() { + static final ParserContext HASH_DELIMITED_PARSER_CONTEXT = new ParserContext() { @Override public String getExpressionPrefix() { return "#{"; @@ -68,25 +69,25 @@ public class TemplateExpressionParsingTests extends AbstractExpressionTests { }; + private final SpelExpressionParser parser = new SpelExpressionParser(); + + @Test - public void testParsingSimpleTemplateExpression01() throws Exception { - SpelExpressionParser parser = new SpelExpressionParser(); + void parsingSimpleTemplateExpression01() { Expression expr = parser.parseExpression("hello ${'world'}", DEFAULT_TEMPLATE_PARSER_CONTEXT); Object o = expr.getValue(); assertThat(o.toString()).isEqualTo("hello world"); } @Test - public void testParsingSimpleTemplateExpression02() throws Exception { - SpelExpressionParser parser = new SpelExpressionParser(); + void parsingSimpleTemplateExpression02() { Expression expr = parser.parseExpression("hello ${'to'} you", DEFAULT_TEMPLATE_PARSER_CONTEXT); Object o = expr.getValue(); assertThat(o.toString()).isEqualTo("hello to you"); } @Test - public void testParsingSimpleTemplateExpression03() throws Exception { - SpelExpressionParser parser = new SpelExpressionParser(); + void parsingSimpleTemplateExpression03() { Expression expr = parser.parseExpression("The quick ${'brown'} fox jumped over the ${'lazy'} dog", DEFAULT_TEMPLATE_PARSER_CONTEXT); Object o = expr.getValue(); @@ -94,8 +95,7 @@ public class TemplateExpressionParsingTests extends AbstractExpressionTests { } @Test - public void testParsingSimpleTemplateExpression04() throws Exception { - SpelExpressionParser parser = new SpelExpressionParser(); + void parsingSimpleTemplateExpression04() { Expression expr = parser.parseExpression("${'hello'} world", DEFAULT_TEMPLATE_PARSER_CONTEXT); Object o = expr.getValue(); assertThat(o.toString()).isEqualTo("hello world"); @@ -114,8 +114,7 @@ public class TemplateExpressionParsingTests extends AbstractExpressionTests { } @Test - public void testCompositeStringExpression() throws Exception { - SpelExpressionParser parser = new SpelExpressionParser(); + void compositeStringExpression() { Expression ex = parser.parseExpression("hello ${'world'}", DEFAULT_TEMPLATE_PARSER_CONTEXT); assertThat(ex.getValue()).isInstanceOf(String.class).isEqualTo("hello world"); assertThat(ex.getValue(String.class)).isInstanceOf(String.class).isEqualTo("hello world"); @@ -154,8 +153,7 @@ public class TemplateExpressionParsingTests extends AbstractExpressionTests { static class Rooty {} @Test - public void testNestedExpressions() throws Exception { - SpelExpressionParser parser = new SpelExpressionParser(); + void nestedExpressions() { // treat the nested ${..} as a part of the expression Expression ex = parser.parseExpression("hello ${listOfNumbersUpToTen.$[#this<5]} world",DEFAULT_TEMPLATE_PARSER_CONTEXT); String s = ex.getValue(TestScenarioCreator.getTestEvaluationContext(),String.class); @@ -185,8 +183,7 @@ public class TemplateExpressionParsingTests extends AbstractExpressionTests { } @Test - - public void testClashingWithSuffixes() throws Exception { + void clashingWithSuffixes() { // Just wanting to use the prefix or suffix within the template: Expression ex = parser.parseExpression("hello ${3+4} world",DEFAULT_TEMPLATE_PARSER_CONTEXT); String s = ex.getValue(TestScenarioCreator.getTestEvaluationContext(),String.class); @@ -202,13 +199,13 @@ public class TemplateExpressionParsingTests extends AbstractExpressionTests { } @Test - public void testParsingNormalExpressionThroughTemplateParser() throws Exception { + void parsingNormalExpressionThroughTemplateParser() { Expression expr = parser.parseExpression("1+2+3"); assertThat(expr.getValue()).isEqualTo(6); } @Test - public void testErrorCases() throws Exception { + void errorCases() { assertThatExceptionOfType(ParseException.class).isThrownBy(() -> parser.parseExpression("hello ${'world'", DEFAULT_TEMPLATE_PARSER_CONTEXT)) .satisfies(pex -> { @@ -224,7 +221,7 @@ public class TemplateExpressionParsingTests extends AbstractExpressionTests { } @Test - public void testTemplateParserContext() { + void testTemplateParserContext() { TemplateParserContext tpc = new TemplateParserContext("abc","def"); assertThat(tpc.getExpressionPrefix()).isEqualTo("abc"); assertThat(tpc.getExpressionSuffix()).isEqualTo("def"); diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java index 9133b7baf00..dfef1d4b85a 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 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. @@ -18,6 +18,8 @@ package org.springframework.expression.spel.standard; import java.util.function.Consumer; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.assertj.core.api.ThrowableAssertAlternative; import org.junit.jupiter.api.Test; import org.springframework.expression.EvaluationContext; @@ -31,16 +33,28 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.springframework.expression.spel.SpelMessage.MISSING_CONSTRUCTOR_ARGS; +import static org.springframework.expression.spel.SpelMessage.NON_TERMINATING_DOUBLE_QUOTED_STRING; +import static org.springframework.expression.spel.SpelMessage.NON_TERMINATING_QUOTED_STRING; +import static org.springframework.expression.spel.SpelMessage.NOT_AN_INTEGER; +import static org.springframework.expression.spel.SpelMessage.NOT_A_LONG; +import static org.springframework.expression.spel.SpelMessage.REAL_CANNOT_BE_LONG; +import static org.springframework.expression.spel.SpelMessage.RUN_OUT_OF_ARGUMENTS; +import static org.springframework.expression.spel.SpelMessage.UNEXPECTED_DATA_AFTER_DOT; +import static org.springframework.expression.spel.SpelMessage.UNEXPECTED_ESCAPE_CHAR; /** * @author Andy Clement * @author Juergen Hoeller + * @author Sam Brannen */ class SpelParserTests { + private final SpelExpressionParser parser = new SpelExpressionParser(); + + @Test void theMostBasic() { - SpelExpressionParser parser = new SpelExpressionParser(); SpelExpression expr = parser.parseRaw("2"); assertThat(expr).isNotNull(); assertThat(expr.getAST()).isNotNull(); @@ -51,7 +65,6 @@ class SpelParserTests { @Test void valueType() { - SpelExpressionParser parser = new SpelExpressionParser(); EvaluationContext ctx = new StandardEvaluationContext(); Class c = parser.parseRaw("2").getValueType(); assertThat(c).isEqualTo(Integer.class); @@ -67,7 +80,6 @@ class SpelParserTests { @Test void whitespace() { - SpelExpressionParser parser = new SpelExpressionParser(); SpelExpression expr = parser.parseRaw("2 + 3"); assertThat(expr.getValue()).isEqualTo(5); expr = parser.parseRaw("2 + 3"); @@ -80,7 +92,6 @@ class SpelParserTests { @Test void arithmeticPlus1() { - SpelExpressionParser parser = new SpelExpressionParser(); SpelExpression expr = parser.parseRaw("2+2"); assertThat(expr).isNotNull(); assertThat(expr.getAST()).isNotNull(); @@ -89,14 +100,12 @@ class SpelParserTests { @Test void arithmeticPlus2() { - SpelExpressionParser parser = new SpelExpressionParser(); SpelExpression expr = parser.parseRaw("37+41"); assertThat(expr.getValue()).isEqualTo(78); } @Test void arithmeticMultiply1() { - SpelExpressionParser parser = new SpelExpressionParser(); SpelExpression expr = parser.parseRaw("2*3"); assertThat(expr).isNotNull(); assertThat(expr.getAST()).isNotNull(); @@ -105,162 +114,120 @@ class SpelParserTests { @Test void arithmeticPrecedence1() { - SpelExpressionParser parser = new SpelExpressionParser(); SpelExpression expr = parser.parseRaw("2*3+5"); assertThat(expr.getValue()).isEqualTo(11); } @Test - void generalExpressions() { - assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> { - SpelExpressionParser parser = new SpelExpressionParser(); - parser.parseRaw("new String"); - }) - .satisfies(parseExceptionRequirements(SpelMessage.MISSING_CONSTRUCTOR_ARGS, 10)); - - assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> { - SpelExpressionParser parser = new SpelExpressionParser(); - parser.parseRaw("new String(3,"); - }) - .satisfies(parseExceptionRequirements(SpelMessage.RUN_OUT_OF_ARGUMENTS, 10)); - - assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> { - SpelExpressionParser parser = new SpelExpressionParser(); - parser.parseRaw("new String(3"); - }) - .satisfies(parseExceptionRequirements(SpelMessage.RUN_OUT_OF_ARGUMENTS, 10)); - - assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> { - SpelExpressionParser parser = new SpelExpressionParser(); - parser.parseRaw("new String("); - }) - .satisfies(parseExceptionRequirements(SpelMessage.RUN_OUT_OF_ARGUMENTS, 10)); - - assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> { - SpelExpressionParser parser = new SpelExpressionParser(); - parser.parseRaw("\"abc"); - }) - .satisfies(parseExceptionRequirements(SpelMessage.NON_TERMINATING_DOUBLE_QUOTED_STRING, 0)); - - assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> { - SpelExpressionParser parser = new SpelExpressionParser(); - parser.parseRaw("'abc"); - }) - .satisfies(parseExceptionRequirements(SpelMessage.NON_TERMINATING_QUOTED_STRING, 0)); - - } - - private Consumer parseExceptionRequirements( - SpelMessage expectedMessage, int expectedPosition) { - return ex -> { - assertThat(ex.getMessageCode()).isEqualTo(expectedMessage); - assertThat(ex.getPosition()).isEqualTo(expectedPosition); - assertThat(ex.getMessage()).contains(ex.getExpressionString()); - }; + void parseExceptions() { + assertParseException(() -> parser.parseRaw("new String"), MISSING_CONSTRUCTOR_ARGS, 10); + assertParseException(() -> parser.parseRaw("new String(3,"), RUN_OUT_OF_ARGUMENTS, 10); + assertParseException(() -> parser.parseRaw("new String(3"), RUN_OUT_OF_ARGUMENTS, 10); + assertParseException(() -> parser.parseRaw("new String("), RUN_OUT_OF_ARGUMENTS, 10); + assertParseException(() -> parser.parseRaw("\"abc"), NON_TERMINATING_DOUBLE_QUOTED_STRING, 0); + assertParseException(() -> parser.parseRaw("'abc"), NON_TERMINATING_QUOTED_STRING, 0); } @Test void arithmeticPrecedence2() { - SpelExpressionParser parser = new SpelExpressionParser(); SpelExpression expr = parser.parseRaw("2+3*5"); assertThat(expr.getValue()).isEqualTo(17); } @Test void arithmeticPrecedence3() { - SpelExpression expr = new SpelExpressionParser().parseRaw("3+10/2"); + SpelExpression expr = parser.parseRaw("3+10/2"); assertThat(expr.getValue()).isEqualTo(8); } @Test void arithmeticPrecedence4() { - SpelExpression expr = new SpelExpressionParser().parseRaw("10/2+3"); + SpelExpression expr = parser.parseRaw("10/2+3"); assertThat(expr.getValue()).isEqualTo(8); } @Test void arithmeticPrecedence5() { - SpelExpression expr = new SpelExpressionParser().parseRaw("(4+10)/2"); + SpelExpression expr = parser.parseRaw("(4+10)/2"); assertThat(expr.getValue()).isEqualTo(7); } @Test void arithmeticPrecedence6() { - SpelExpression expr = new SpelExpressionParser().parseRaw("(3+2)*2"); + SpelExpression expr = parser.parseRaw("(3+2)*2"); assertThat(expr.getValue()).isEqualTo(10); } @Test void booleanOperators() { - SpelExpression expr = new SpelExpressionParser().parseRaw("true"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.TRUE); - expr = new SpelExpressionParser().parseRaw("false"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.FALSE); - expr = new SpelExpressionParser().parseRaw("false and false"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.FALSE); - expr = new SpelExpressionParser().parseRaw("true and (true or false)"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.TRUE); - expr = new SpelExpressionParser().parseRaw("true and true or false"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.TRUE); - expr = new SpelExpressionParser().parseRaw("!true"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.FALSE); - expr = new SpelExpressionParser().parseRaw("!(false or true)"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.FALSE); + SpelExpression expr = parser.parseRaw("true"); + assertThat(expr.getValue(Boolean.class)).isTrue(); + expr = parser.parseRaw("false"); + assertThat(expr.getValue(Boolean.class)).isFalse(); + expr = parser.parseRaw("false and false"); + assertThat(expr.getValue(Boolean.class)).isFalse(); + expr = parser.parseRaw("true and (true or false)"); + assertThat(expr.getValue(Boolean.class)).isTrue(); + expr = parser.parseRaw("true and true or false"); + assertThat(expr.getValue(Boolean.class)).isTrue(); + expr = parser.parseRaw("!true"); + assertThat(expr.getValue(Boolean.class)).isFalse(); + expr = parser.parseRaw("!(false or true)"); + assertThat(expr.getValue(Boolean.class)).isFalse(); } @Test void booleanOperators_symbolic_spr9614() { - SpelExpression expr = new SpelExpressionParser().parseRaw("true"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.TRUE); - expr = new SpelExpressionParser().parseRaw("false"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.FALSE); - expr = new SpelExpressionParser().parseRaw("false && false"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.FALSE); - expr = new SpelExpressionParser().parseRaw("true && (true || false)"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.TRUE); - expr = new SpelExpressionParser().parseRaw("true && true || false"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.TRUE); - expr = new SpelExpressionParser().parseRaw("!true"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.FALSE); - expr = new SpelExpressionParser().parseRaw("!(false || true)"); - assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.FALSE); + SpelExpression expr = parser.parseRaw("true"); + assertThat(expr.getValue(Boolean.class)).isTrue(); + expr = parser.parseRaw("false"); + assertThat(expr.getValue(Boolean.class)).isFalse(); + expr = parser.parseRaw("false && false"); + assertThat(expr.getValue(Boolean.class)).isFalse(); + expr = parser.parseRaw("true && (true || false)"); + assertThat(expr.getValue(Boolean.class)).isTrue(); + expr = parser.parseRaw("true && true || false"); + assertThat(expr.getValue(Boolean.class)).isTrue(); + expr = parser.parseRaw("!true"); + assertThat(expr.getValue(Boolean.class)).isFalse(); + expr = parser.parseRaw("!(false || true)"); + assertThat(expr.getValue(Boolean.class)).isFalse(); } @Test void stringLiterals() { - SpelExpression expr = new SpelExpressionParser().parseRaw("'howdy'"); + SpelExpression expr = parser.parseRaw("'howdy'"); assertThat(expr.getValue()).isEqualTo("howdy"); - expr = new SpelExpressionParser().parseRaw("'hello '' world'"); + expr = parser.parseRaw("'hello '' world'"); assertThat(expr.getValue()).isEqualTo("hello ' world"); } @Test void stringLiterals2() { - SpelExpression expr = new SpelExpressionParser().parseRaw("'howdy'.substring(0,2)"); + SpelExpression expr = parser.parseRaw("'howdy'.substring(0,2)"); assertThat(expr.getValue()).isEqualTo("ho"); } @Test void testStringLiterals_DoubleQuotes_spr9620() { - SpelExpression expr = new SpelExpressionParser().parseRaw("\"double quote: \"\".\""); + SpelExpression expr = parser.parseRaw("\"double quote: \"\".\""); assertThat(expr.getValue()).isEqualTo("double quote: \"."); - expr = new SpelExpressionParser().parseRaw("\"hello \"\" world\""); + expr = parser.parseRaw("\"hello \"\" world\""); assertThat(expr.getValue()).isEqualTo("hello \" world"); } @Test void testStringLiterals_DoubleQuotes_spr9620_2() { - assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> - new SpelExpressionParser().parseRaw("\"double quote: \\\"\\\".\"")) + assertParseExceptionThrownBy(() -> parser.parseRaw("\"double quote: \\\"\\\".\"")) .satisfies(ex -> { assertThat(ex.getPosition()).isEqualTo(17); - assertThat(ex.getMessageCode()).isEqualTo(SpelMessage.UNEXPECTED_ESCAPE_CHAR); + assertThat(ex.getMessageCode()).isEqualTo(UNEXPECTED_ESCAPE_CHAR); }); } @Test void positionalInformation() { - SpelExpression expr = new SpelExpressionParser().parseRaw("true and true or false"); + SpelExpression expr = parser.parseRaw("true and true or false"); SpelNode rootAst = expr.getAST(); OpOr operatorOr = (OpOr) rootAst; OpAnd operatorAnd = (OpAnd) operatorOr.getLeftOperand(); @@ -355,10 +322,10 @@ class SpelParserTests { checkNumber("0xa", 10, Integer.class); checkNumber("0xAL", 10L, Long.class); - checkNumberError("0x", SpelMessage.NOT_AN_INTEGER); - checkNumberError("0xL", SpelMessage.NOT_A_LONG); - checkNumberError(".324", SpelMessage.UNEXPECTED_DATA_AFTER_DOT); - checkNumberError("3.4L", SpelMessage.REAL_CANNOT_BE_LONG); + checkNumberError("0x", NOT_AN_INTEGER); + checkNumberError("0xL", NOT_A_LONG); + checkNumberError(".324", UNEXPECTED_DATA_AFTER_DOT); + checkNumberError("3.4L", REAL_CANNOT_BE_LONG); checkNumber("3.5f", 3.5f, Float.class); checkNumber("1.2e3", 1.2e3d, Double.class); @@ -371,7 +338,6 @@ class SpelParserTests { private void checkNumber(String expression, Object value, Class type) { try { - SpelExpressionParser parser = new SpelExpressionParser(); SpelExpression expr = parser.parseRaw(expression); Object exprVal = expr.getValue(); assertThat(exprVal).isEqualTo(value); @@ -383,9 +349,26 @@ class SpelParserTests { } private void checkNumberError(String expression, SpelMessage expectedMessage) { - SpelExpressionParser parser = new SpelExpressionParser(); - assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> parser.parseRaw(expression)) + assertParseExceptionThrownBy(() -> parser.parseRaw(expression)) .satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(expectedMessage)); } + private static ThrowableAssertAlternative assertParseExceptionThrownBy(ThrowingCallable throwingCallable) { + return assertThatExceptionOfType(SpelParseException.class).isThrownBy(throwingCallable); + } + + private static void assertParseException(ThrowingCallable throwingCallable, SpelMessage expectedMessage, int expectedPosition) { + assertParseExceptionThrownBy(throwingCallable) + .satisfies(parseExceptionRequirements(expectedMessage, expectedPosition)); + } + + private static Consumer parseExceptionRequirements( + SpelMessage expectedMessage, int expectedPosition) { + return ex -> { + assertThat(ex.getMessageCode()).isEqualTo(expectedMessage); + assertThat(ex.getPosition()).isEqualTo(expectedPosition); + assertThat(ex.getMessage()).contains(ex.getExpressionString()); + }; + } + }