Browse Source

Add tests for collection selection with Iterables

pull/32215/head
Sam Brannen 2 years ago
parent
commit
43bbe8f3e8
  1. 71
      spring-expression/src/test/java/org/springframework/expression/spel/SelectionAndProjectionTests.java

71
spring-expression/src/test/java/org/springframework/expression/spel/SelectionAndProjectionTests.java

@ -24,6 +24,7 @@ import java.util.List; @@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.IntStream;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@ -38,7 +39,6 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; @@ -38,7 +39,6 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.InstanceOfAssertFactories.LIST;
import static org.assertj.core.api.InstanceOfAssertFactories.array;
import static org.springframework.expression.spel.SpelMessage.INVALID_TYPE_FOR_SELECTION;
import static org.springframework.expression.spel.SpelMessage.PROJECTION_NOT_SUPPORTED_ON_TYPE;
@ -141,11 +141,56 @@ class SelectionAndProjectionTests { @@ -141,11 +141,56 @@ class SelectionAndProjectionTests {
}
@ParameterizedTest
@ValueSource(strings = {"#root.?[#this < 3]", "?[#this < 3]"})
@ValueSource(strings = {"#root.?[#this <= 3]", "?[#this <= 3]"})
@SuppressWarnings("unchecked")
void selectionWithIterable(String expressionString) {
Expression expression = new SpelExpressionParser().parseRaw(expressionString);
EvaluationContext context = new StandardEvaluationContext(new IterableTestBean());
assertThat(expression.getValue(context)).asInstanceOf(LIST).containsExactly(1, 2);
EvaluationContext context = new StandardEvaluationContext(new Counter(5));
assertThat(expression.getValue(context, List.class)).containsExactly(1, 2, 3);
}
@ParameterizedTest
@ValueSource(strings = {"#root.^[#this <= 3]", "^[#this <= 3]"})
void selectFirstItemInIterable(String expressionString) {
Expression expression = new SpelExpressionParser().parseRaw(expressionString);
EvaluationContext context = new StandardEvaluationContext(new Counter(5));
assertThat(expression.getValue(context, Integer.class)).isEqualTo(1);
}
@ParameterizedTest
@ValueSource(strings = {"#root.$[#this <= 3]", "$[#this <= 3]"})
void selectLastItemInIterable(String expressionString) {
Expression expression = new SpelExpressionParser().parseRaw(expressionString);
EvaluationContext context = new StandardEvaluationContext(new Counter(5));
assertThat(expression.getValue(context, Integer.class)).isEqualTo(3);
}
@Test
void indexIntoIterableSelection() {
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("counter", new Counter(5));
ExpressionParser parser = new SpelExpressionParser();
// Select first (selection expression is hard-coded to true)
Expression expression = parser.parseExpression("#counter.^[true]");
assertThat(expression.getValue(context, Integer.class)).isEqualTo(1);
// Select last (selection expression is hard-coded to true)
expression = parser.parseExpression("#counter.$[true]");
assertThat(expression.getValue(context, Integer.class)).isEqualTo(5);
// Select index (selection expression is hard-coded to true)
// The following will not work, since we cannot index into an Iterable.
// expression = parser.parseExpression("#counter[1]");
// The following works, since project selection with a selection expression
// that always evaluates to true results in a List containing all elements
// of the Iterable, and we can index into that List.
expression = parser.parseExpression("#counter.?[true][1]");
assertThat(expression.getValue(context, Integer.class)).isEqualTo(2);
expression = parser.parseExpression("#counter.?[true][2]");
assertThat(expression.getValue(context, Integer.class)).isEqualTo(3);
}
@Test
@ -273,10 +318,11 @@ class SelectionAndProjectionTests { @@ -273,10 +318,11 @@ class SelectionAndProjectionTests {
@ParameterizedTest
@ValueSource(strings = {"#root.![#this * 2]", "![#this * 2]"})
@SuppressWarnings("unchecked")
void projectionWithIterable(String expressionString) {
Expression expression = new SpelExpressionParser().parseRaw(expressionString);
EvaluationContext context = new StandardEvaluationContext(new IterableTestBean());
assertThat(expression.getValue(context)).asInstanceOf(LIST).containsExactly(2, 4, 6, 8, 10);
EvaluationContext context = new StandardEvaluationContext(new Counter(5));
assertThat(expression.getValue(context, List.class)).containsExactly(2, 4, 6, 8, 10);
}
@Test
@ -323,13 +369,20 @@ class SelectionAndProjectionTests { @@ -323,13 +369,20 @@ class SelectionAndProjectionTests {
}
static class IterableTestBean implements Iterable<Integer> {
/**
* Simulates a custom {@link Iterable} which is itself not a {@link Collection}.
*/
class Counter implements Iterable<Integer> {
private final Collection<Integer> integers = List.of(1, 2, 3, 4, 5);
private final List<Integer> list = new ArrayList<>();
Counter(int size) {
IntStream.rangeClosed(1, size).forEach(this.list::add);
}
@Override
public Iterator<Integer> iterator() {
return integers.iterator();
return this.list.iterator();
}
}

Loading…
Cancel
Save