Skip to content

Commit fc671cb

Browse files
authored
ESQL: Evaluator check function tests (#117715)
Multiple scalar function tests were being ignored if they had any non-representable child (counters, durations, periods...). Here, I'm making that "can have an evaluator" a bit more explicit in every test, as many of the ignored tests cases were actually "working".
1 parent 655090b commit fc671cb

File tree

10 files changed

+42
-41
lines changed

10 files changed

+42
-41
lines changed

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractScalarFunctionTestCase.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ public final void testEvaluate() {
104104
assertTypeResolutionFailure(expression);
105105
return;
106106
}
107-
assumeTrue("Expected type must be representable to build an evaluator", DataType.isRepresentable(testCase.expectedType()));
108107
logger.info(
109108
"Test Values: " + testCase.getData().stream().map(TestCaseSupplier.TypedData::toString).collect(Collectors.joining(","))
110109
);
@@ -209,7 +208,6 @@ private void testEvaluateBlock(BlockFactory inputBlockFactory, DriverContext con
209208
return;
210209
}
211210
assumeTrue("Can't build evaluator", testCase.canBuildEvaluator());
212-
assumeTrue("Expected type must be representable to build an evaluator", DataType.isRepresentable(testCase.expectedType()));
213211
int positions = between(1, 1024);
214212
List<TestCaseSupplier.TypedData> data = testCase.getData();
215213
Page onePositionPage = row(testCase.getDataValues());
@@ -275,7 +273,6 @@ public final void testEvaluateInManyThreads() throws ExecutionException, Interru
275273
return;
276274
}
277275
assumeTrue("Can't build evaluator", testCase.canBuildEvaluator());
278-
assumeTrue("Expected type must be representable to build an evaluator", DataType.isRepresentable(testCase.expectedType()));
279276
int count = 10_000;
280277
int threads = 5;
281278
var evalSupplier = evaluator(expression);
@@ -338,14 +335,13 @@ public final void testFactoryToString() {
338335
assertThat(factory.toString(), testCase.evaluatorToString());
339336
}
340337

341-
public final void testFold() {
338+
public void testFold() {
342339
Expression expression = buildLiteralExpression(testCase);
343340
if (testCase.getExpectedTypeError() != null) {
344341
assertTypeResolutionFailure(expression);
345342
return;
346343
}
347344
assertFalse("expected resolved", expression.typeResolved().unresolved());
348-
assumeTrue("Can't build evaluator", testCase.canBuildEvaluator());
349345
Expression nullOptimized = new FoldNull().rule(expression);
350346
assertThat(nullOptimized.dataType(), equalTo(testCase.expectedType()));
351347
assertTrue(nullOptimized.foldable());

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/TestCaseSupplier.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,9 @@ private static TestCaseSupplier testCaseSupplier(
278278
for (String warning : warnings.apply(lhsTyped, rhsTyped)) {
279279
testCase = testCase.withWarning(warning);
280280
}
281+
if (DataType.isRepresentable(expectedType) == false) {
282+
testCase = testCase.withoutEvaluator();
283+
}
281284
return testCase;
282285
});
283286
}
@@ -1438,7 +1441,7 @@ public static TestCase typeError(List<TypedData> data, String expectedTypeError)
14381441
foldingExceptionClass,
14391442
foldingExceptionMessage,
14401443
extra,
1441-
data.stream().allMatch(d -> d.forceLiteral || DataType.isRepresentable(d.type))
1444+
true
14421445
);
14431446
}
14441447

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/grouping/CategorizeTests.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,9 @@ public static Iterable<Object[]> parameters() {
5858
protected Expression build(Source source, List<Expression> args) {
5959
return new Categorize(source, args.get(0));
6060
}
61+
62+
@Override
63+
public void testFold() {
64+
// Cannot be folded
65+
}
6166
}

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDatePeriodTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static Iterable<Object[]> parameters() {
5050
matchesPattern("LiteralsEvaluator.*"),
5151
DATE_PERIOD,
5252
equalTo(field)
53-
);
53+
).withoutEvaluator();
5454
}));
5555

5656
for (EsqlDataTypeConverter.INTERVALS interval : DATE_PERIODS) {
@@ -67,7 +67,7 @@ public static Iterable<Object[]> parameters() {
6767
matchesPattern("LiteralsEvaluator.*"),
6868
DATE_PERIOD,
6969
equalTo(result)
70-
);
70+
).withoutEvaluator();
7171
}));
7272
}
7373
}

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDoubleTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public static Iterable<Object[]> parameters() {
126126
);
127127
TestCaseSupplier.unary(
128128
suppliers,
129-
evaluatorName.apply("Integer"),
129+
evaluatorName.apply("Int"),
130130
List.of(new TestCaseSupplier.TypedDataSupplier("counter", () -> randomInt(1000), DataType.COUNTER_INTEGER)),
131131
DataType.DOUBLE,
132132
l -> ((Integer) l).doubleValue(),

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ public static Iterable<Object[]> parameters() {
230230
);
231231
TestCaseSupplier.unary(
232232
suppliers,
233-
evaluatorName.apply("Integer"),
233+
evaluatorName.apply("Int"),
234234
List.of(new TestCaseSupplier.TypedDataSupplier("counter", ESTestCase::randomInt, DataType.COUNTER_INTEGER)),
235235
DataType.LONG,
236236
l -> ((Integer) l).longValue(),

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToTimeDurationTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static Iterable<Object[]> parameters() {
5050
matchesPattern("LiteralsEvaluator.*"),
5151
TIME_DURATION,
5252
equalTo(field)
53-
);
53+
).withoutEvaluator();
5454
}));
5555

5656
for (EsqlDataTypeConverter.INTERVALS interval : TIME_DURATIONS) {
@@ -66,7 +66,7 @@ public static Iterable<Object[]> parameters() {
6666
matchesPattern("LiteralsEvaluator.*"),
6767
TIME_DURATION,
6868
equalTo(result)
69-
);
69+
).withoutEvaluator();
7070
}));
7171
}
7272
}

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateTruncTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,10 @@ private static TestCaseSupplier randomSecond() {
136136
+ pad(randomIntBetween(0, 59));
137137
return new TestCaseSupplier.TestCase(
138138
List.of(
139-
new TestCaseSupplier.TypedData(Duration.ofSeconds(1), DataType.TIME_DURATION, "interval"),
139+
new TestCaseSupplier.TypedData(Duration.ofSeconds(1), DataType.TIME_DURATION, "interval").forceLiteral(),
140140
new TestCaseSupplier.TypedData(toMillis(dateFragment + ".38Z"), DataType.DATETIME, "date")
141141
),
142-
"DateTruncDatetimeEvaluator[date=Attribute[channel=1], interval=Attribute[channel=0]]",
142+
Matchers.startsWith("DateTruncDatetimeEvaluator[fieldVal=Attribute[channel=0], rounding=Rounding["),
143143
DataType.DATETIME,
144144
equalTo(toMillis(dateFragment + ".00Z"))
145145
);

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/NegTests.java

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,21 @@
1010
import com.carrotsearch.randomizedtesting.annotations.Name;
1111
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
1212

13-
import org.elasticsearch.compute.data.Block;
1413
import org.elasticsearch.xpack.esql.VerificationException;
1514
import org.elasticsearch.xpack.esql.core.expression.Expression;
1615
import org.elasticsearch.xpack.esql.core.expression.Literal;
1716
import org.elasticsearch.xpack.esql.core.tree.Source;
1817
import org.elasticsearch.xpack.esql.core.type.DataType;
1918
import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase;
2019
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
20+
import org.hamcrest.Matchers;
2121

2222
import java.time.Duration;
2323
import java.time.Period;
2424
import java.util.ArrayList;
2525
import java.util.List;
2626
import java.util.function.Supplier;
2727

28-
import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
2928
import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomLiteral;
3029
import static org.hamcrest.Matchers.equalTo;
3130

@@ -97,19 +96,19 @@ public static Iterable<Object[]> parameters() {
9796
suppliers.addAll(List.of(new TestCaseSupplier("Duration", List.of(DataType.TIME_DURATION), () -> {
9897
Duration arg = (Duration) randomLiteral(DataType.TIME_DURATION).value();
9998
return new TestCaseSupplier.TestCase(
100-
List.of(new TestCaseSupplier.TypedData(arg, DataType.TIME_DURATION, "arg")),
101-
"No evaluator since this expression is only folded",
99+
List.of(new TestCaseSupplier.TypedData(arg, DataType.TIME_DURATION, "arg").forceLiteral()),
100+
Matchers.startsWith("LiteralsEvaluator[lit="),
102101
DataType.TIME_DURATION,
103102
equalTo(arg.negated())
104-
);
103+
).withoutEvaluator();
105104
}), new TestCaseSupplier("Period", List.of(DataType.DATE_PERIOD), () -> {
106105
Period arg = (Period) randomLiteral(DataType.DATE_PERIOD).value();
107106
return new TestCaseSupplier.TestCase(
108-
List.of(new TestCaseSupplier.TypedData(arg, DataType.DATE_PERIOD, "arg")),
109-
"No evaluator since this expression is only folded",
107+
List.of(new TestCaseSupplier.TypedData(arg, DataType.DATE_PERIOD, "arg").forceLiteral()),
108+
Matchers.startsWith("LiteralsEvaluator[lit="),
110109
DataType.DATE_PERIOD,
111110
equalTo(arg.negated())
112-
);
111+
).withoutEvaluator();
113112
})));
114113
return parameterSuppliersFromTypedDataWithDefaultChecks(false, suppliers, (v, p) -> "numeric, date_period or time_duration");
115114
}
@@ -126,25 +125,25 @@ public void testEdgeCases() {
126125
if (testCaseType == DataType.DATE_PERIOD) {
127126
Period maxPeriod = Period.of(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
128127
Period negatedMaxPeriod = Period.of(-Integer.MAX_VALUE, -Integer.MAX_VALUE, -Integer.MAX_VALUE);
129-
assertEquals(negatedMaxPeriod, process(maxPeriod));
128+
assertEquals(negatedMaxPeriod, foldTemporalAmount(maxPeriod));
130129

131130
Period minPeriod = Period.of(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
132131
VerificationException e = expectThrows(
133132
VerificationException.class,
134133
"Expected exception when negating minimal date period.",
135-
() -> process(minPeriod)
134+
() -> foldTemporalAmount(minPeriod)
136135
);
137136
assertEquals(e.getMessage(), "arithmetic exception in expression []: [integer overflow]");
138137
} else if (testCaseType == DataType.TIME_DURATION) {
139138
Duration maxDuration = Duration.ofSeconds(Long.MAX_VALUE, 0);
140139
Duration negatedMaxDuration = Duration.ofSeconds(-Long.MAX_VALUE, 0);
141-
assertEquals(negatedMaxDuration, process(maxDuration));
140+
assertEquals(negatedMaxDuration, foldTemporalAmount(maxDuration));
142141

143142
Duration minDuration = Duration.ofSeconds(Long.MIN_VALUE, 0);
144143
VerificationException e = expectThrows(
145144
VerificationException.class,
146145
"Expected exception when negating minimal time duration.",
147-
() -> process(minDuration)
146+
() -> foldTemporalAmount(minDuration)
148147
);
149148
assertEquals(
150149
e.getMessage(),
@@ -153,16 +152,9 @@ public void testEdgeCases() {
153152
}
154153
}
155154

156-
private Object process(Object val) {
157-
if (testCase.canBuildEvaluator()) {
158-
Neg neg = new Neg(Source.EMPTY, field("val", typeOf(val)));
159-
try (Block block = evaluator(neg).get(driverContext()).eval(row(List.of(val)))) {
160-
return toJavaObject(block, 0);
161-
}
162-
} else { // just fold if type is not representable
163-
Neg neg = new Neg(Source.EMPTY, new Literal(Source.EMPTY, val, typeOf(val)));
164-
return neg.fold();
165-
}
155+
private Object foldTemporalAmount(Object val) {
156+
Neg neg = new Neg(Source.EMPTY, new Literal(Source.EMPTY, val, typeOf(val)));
157+
return neg.fold();
166158
}
167159

168160
private static DataType typeOf(Object val) {

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/SubTests.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,12 @@ public static Iterable<Object[]> parameters() {
169169
return new TestCaseSupplier.TestCase(
170170
List.of(
171171
new TestCaseSupplier.TypedData(lhs, DataType.DATE_PERIOD, "lhs"),
172-
new TestCaseSupplier.TypedData(rhs, DataType.DATE_PERIOD, "rhs")
172+
new TestCaseSupplier.TypedData(rhs, DataType.DATE_PERIOD, "rhs").forceLiteral()
173173
),
174174
"Only folding possible, so there's no evaluator",
175175
DataType.DATE_PERIOD,
176176
equalTo(lhs.minus(rhs))
177-
);
177+
).withoutEvaluator();
178178
}));
179179
suppliers.add(new TestCaseSupplier("Datetime - Duration", List.of(DataType.DATETIME, DataType.TIME_DURATION), () -> {
180180
long lhs = (Long) randomLiteral(DataType.DATETIME).value();
@@ -196,12 +196,12 @@ public static Iterable<Object[]> parameters() {
196196
return new TestCaseSupplier.TestCase(
197197
List.of(
198198
new TestCaseSupplier.TypedData(lhs, DataType.TIME_DURATION, "lhs"),
199-
new TestCaseSupplier.TypedData(rhs, DataType.TIME_DURATION, "rhs")
199+
new TestCaseSupplier.TypedData(rhs, DataType.TIME_DURATION, "rhs").forceLiteral()
200200
),
201201
"Only folding possible, so there's no evaluator",
202202
DataType.TIME_DURATION,
203203
equalTo(lhs.minus(rhs))
204-
);
204+
).withoutEvaluator();
205205
}));
206206

207207
// exact math arithmetic exceptions
@@ -250,7 +250,12 @@ public static Iterable<Object[]> parameters() {
250250
return original.getData().get(nullPosition == 0 ? 1 : 0).type();
251251
}
252252
return original.expectedType();
253-
}, (nullPosition, nullData, original) -> nullData.isForceLiteral() ? equalTo("LiteralsEvaluator[lit=null]") : original);
253+
}, (nullPosition, nullData, original) -> {
254+
if (DataType.isTemporalAmount(nullData.type())) {
255+
return equalTo("LiteralsEvaluator[lit=null]");
256+
}
257+
return original;
258+
});
254259

255260
suppliers.add(new TestCaseSupplier("MV", List.of(DataType.INTEGER, DataType.INTEGER), () -> {
256261
// Ensure we don't have an overflow

0 commit comments

Comments
 (0)