Merge branch '6.1.x'

This commit is contained in:
Sam Brannen
2024-07-10 12:04:26 +02:00
6 changed files with 184 additions and 76 deletions

View File

@@ -293,6 +293,46 @@ class MethodInvocationTests extends AbstractExpressionTests {
evaluate("aVarargsMethod3('foo', 'bar,baz')", "foo-bar,baz", String.class);
}
@Test // gh-33013
void testVarargsWithObjectArrayType() {
// Calling 'public String formatObjectVarargs(String format, Object... args)' -> String.format(format, args)
// No var-args and no conversion necessary
evaluate("formatObjectVarargs('x')", "x", String.class);
// No var-args but conversion necessary
evaluate("formatObjectVarargs(9)", "9", String.class);
// No conversion necessary
evaluate("formatObjectVarargs('x -> %s', '')", "x -> ", String.class);
evaluate("formatObjectVarargs('x -> %s', ' ')", "x -> ", String.class);
evaluate("formatObjectVarargs('x -> %s', 'a')", "x -> a", String.class);
evaluate("formatObjectVarargs('x -> %s %s %s', 'a', 'b', 'c')", "x -> a b c", String.class);
evaluate("formatObjectVarargs('x -> %s', new Object[]{''})", "x -> ", String.class);
evaluate("formatObjectVarargs('x -> %s', new String[]{''})", "x -> ", String.class);
evaluate("formatObjectVarargs('x -> %s', new Object[]{' '})", "x -> ", String.class);
evaluate("formatObjectVarargs('x -> %s', new String[]{' '})", "x -> ", String.class);
evaluate("formatObjectVarargs('x -> %s', new Object[]{'a'})", "x -> a", String.class);
evaluate("formatObjectVarargs('x -> %s', new String[]{'a'})", "x -> a", String.class);
evaluate("formatObjectVarargs('x -> %s %s %s', new Object[]{'a', 'b', 'c'})", "x -> a b c", String.class);
evaluate("formatObjectVarargs('x -> %s %s %s', new String[]{'a', 'b', 'c'})", "x -> a b c", String.class);
// Conversion necessary
evaluate("formatObjectVarargs('x -> %s %s', 2, 3)", "x -> 2 3", String.class);
evaluate("formatObjectVarargs('x -> %s %s', 'a', 3.0d)", "x -> a 3.0", String.class);
// Individual string contains a comma with multiple varargs arguments
evaluate("formatObjectVarargs('foo -> %s %s', ',', 'baz')", "foo -> , baz", String.class);
evaluate("formatObjectVarargs('foo -> %s %s', 'bar', ',baz')", "foo -> bar ,baz", String.class);
evaluate("formatObjectVarargs('foo -> %s %s', 'bar,', 'baz')", "foo -> bar, baz", String.class);
// Individual string contains a comma with single varargs argument.
evaluate("formatObjectVarargs('foo -> %s', ',')", "foo -> ,", String.class);
evaluate("formatObjectVarargs('foo -> %s', ',bar')", "foo -> ,bar", String.class);
evaluate("formatObjectVarargs('foo -> %s', 'bar,')", "foo -> bar,", String.class);
evaluate("formatObjectVarargs('foo -> %s', 'bar,baz')", "foo -> bar,baz", String.class);
}
@Test
void testVarargsOptionalInvocation() {
// Calling 'public String optionalVarargsMethod(Optional<String>... values)'

View File

@@ -69,6 +69,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatException;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.InstanceOfAssertFactories.list;
/**
* Reproduction tests cornering various reported SpEL issues.
@@ -1436,13 +1437,20 @@ class SpelReproTests extends AbstractExpressionTests {
assertThat(expression.getValue(new NamedUser())).isEqualTo(NamedUser.class.getName());
}
@Test
void SPR12522() {
@Test // gh-17127, SPR-12522
void arraysAsListWithNoArguments() {
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("T(java.util.Arrays).asList()");
List<?> value = expression.getValue(List.class);
assertThat(value).isEmpty();
}
@Test // gh-33013
void arraysAsListWithSingleEmptyStringArgument() {
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("T(java.util.Arrays).asList('')");
Object value = expression.getValue();
assertThat(value).isInstanceOf(List.class);
assertThat(((List<?>) value)).isEmpty();
List<?> value = expression.getValue(List.class);
assertThat(value).asInstanceOf(list(String.class)).containsExactly("");
}
@Test

View File

@@ -100,7 +100,12 @@ class TestScenarioCreator {
MethodHandle messageStaticFullyBound = messageStaticPartiallyBound
.bindTo(new String[] { "prerecorded", "3", "Oh Hello World", "ignored"});
testContext.registerFunction("messageStaticBound", messageStaticFullyBound);
}
// #formatObjectVarargs(format, args...)
MethodHandle formatObjectVarargs = MethodHandles.lookup().findStatic(TestScenarioCreator.class,
"formatObjectVarargs", MethodType.methodType(String.class, String.class, Object[].class));
testContext.registerFunction("formatObjectVarargs", formatObjectVarargs);
}
/**
* Register some variables that can be referenced from the tests
@@ -154,4 +159,8 @@ class TestScenarioCreator {
return template.formatted((Object[]) args);
}
public static String formatObjectVarargs(String format, Object... args) {
return String.format(format, args);
}
}

View File

@@ -16,6 +16,7 @@
package org.springframework.expression.spel;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -101,6 +102,54 @@ class VariableAndFunctionTests extends AbstractExpressionTests {
evaluate("#varargsFunction2(9,'a',null,'b')", "9-[a, null, b]", String.class);
}
@Disabled("Disabled until bugs are reported and fixed")
@Test
void functionWithVarargsViaMethodHandle_CurrentlyFailing() {
// Calling 'public static String formatObjectVarargs(String format, Object... args)' -> String.format(format, args)
// No var-args and no conversion necessary
evaluate("#formatObjectVarargs('x')", "x", String.class);
// No var-args but conversion necessary
evaluate("#formatObjectVarargs(9)", "9", String.class);
// No conversion necessary
evaluate("#formatObjectVarargs('x -> %s', new Object[]{''})", "x -> ", String.class);
evaluate("#formatObjectVarargs('x -> %s', new String[]{''})", "x -> ", String.class);
evaluate("#formatObjectVarargs('x -> %s', new Object[]{' '})", "x -> ", String.class);
evaluate("#formatObjectVarargs('x -> %s', new String[]{' '})", "x -> ", String.class);
evaluate("#formatObjectVarargs('x -> %s', new Object[]{'a'})", "x -> a", String.class);
evaluate("#formatObjectVarargs('x -> %s', new String[]{'a'})", "x -> a", String.class);
evaluate("#formatObjectVarargs('x -> %s %s %s', new Object[]{'a', 'b', 'c'})", "x -> a b c", String.class);
evaluate("#formatObjectVarargs('x -> %s %s %s', new String[]{'a', 'b', 'c'})", "x -> a b c", String.class);
}
@Test // gh-33013
void functionWithVarargsViaMethodHandle() {
// Calling 'public static String formatObjectVarargs(String format, Object... args)' -> String.format(format, args)
// No conversion necessary
evaluate("#formatObjectVarargs('x -> %s', '')", "x -> ", String.class);
evaluate("#formatObjectVarargs('x -> %s', ' ')", "x -> ", String.class);
evaluate("#formatObjectVarargs('x -> %s', 'a')", "x -> a", String.class);
evaluate("#formatObjectVarargs('x -> %s %s %s', 'a', 'b', 'c')", "x -> a b c", String.class);
// Conversion necessary
evaluate("#formatObjectVarargs('x -> %s %s', 2, 3)", "x -> 2 3", String.class);
evaluate("#formatObjectVarargs('x -> %s %s', 'a', 3.0d)", "x -> a 3.0", String.class);
// Individual string contains a comma with multiple varargs arguments
evaluate("#formatObjectVarargs('foo -> %s %s', ',', 'baz')", "foo -> , baz", String.class);
evaluate("#formatObjectVarargs('foo -> %s %s', 'bar', ',baz')", "foo -> bar ,baz", String.class);
evaluate("#formatObjectVarargs('foo -> %s %s', 'bar,', 'baz')", "foo -> bar, baz", String.class);
// Individual string contains a comma with single varargs argument.
evaluate("#formatObjectVarargs('foo -> %s', ',')", "foo -> ,", String.class);
evaluate("#formatObjectVarargs('foo -> %s', ',bar')", "foo -> ,bar", String.class);
evaluate("#formatObjectVarargs('foo -> %s', 'bar,')", "foo -> bar,", String.class);
evaluate("#formatObjectVarargs('foo -> %s', 'bar,baz')", "foo -> bar,baz", String.class);
}
@Test
void functionMethodMustBeStatic() throws Exception {
SpelExpressionParser parser = new SpelExpressionParser();

View File

@@ -217,6 +217,11 @@ public class Inventor {
return str1 + "-" + String.join("-", strings);
}
public String formatObjectVarargs(String format, Object... args) {
return String.format(format, args);
}
public Inventor(String... strings) {
if (strings.length > 0) {
this.name = strings[0];