Skip to content

Commit e260d68

Browse files
committed
Add tests
1 parent 34c7cbb commit e260d68

File tree

4 files changed

+200
-22
lines changed

4 files changed

+200
-22
lines changed

x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/SpecReader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public static List<Object[]> readURLSpec(URL source, Parser parser) throws Excep
8686
lineNumber++;
8787
}
8888
if (testName != null) {
89-
throw new IllegalStateException("Read a test without a body at the end of [" + fileName + "].");
89+
throw new IllegalStateException("Read a test [" + testName + "] without a body at the end of [" + fileName + "].");
9090
}
9191
}
9292
assertNull("Cannot find spec for test " + testName, testName);

x-pack/plugin/esql/qa/testFixtures/src/main/resources/match-function.csv-spec

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,142 @@ emp_no:integer | first_name:keyword | last_name:keyword
197197
10041 | Uri | Lenart
198198
10043 | Yishay | Tzvieli
199199
;
200+
201+
testMatchIpField
202+
required_capability: match_function
203+
204+
from clientips
205+
| where match(client_ip, "172.21.3.15");
206+
207+
client_ip:keyword | env:keyword
208+
172.21.3.15 | Production
209+
;
210+
211+
testMatchDateField
212+
required_capability: match_function
213+
214+
from date_nanos
215+
| where match(millis, "2023-10-23T13:55:01.543Z")
216+
| keep millis;
217+
218+
millis:date
219+
2023-10-23T13:55:01.543Z
220+
;
221+
222+
testMatchPartialDateField
223+
required_capability: match_function
224+
225+
from date_nanos
226+
| where match(millis, "1999-10-22")
227+
| keep millis;
228+
229+
millis:date
230+
1999-10-22T12:15:03.360Z
231+
;
232+
233+
testMatchDateNanosField
234+
required_capability: match_function
235+
236+
from date_nanos
237+
| where match(nanos, "2023-10-23T13:55:01.543123456Z")
238+
| keep nanos;
239+
240+
nanos:date_nanos
241+
2023-10-23T13:55:01.543123456Z
242+
;
243+
244+
testMatchPartialDateNanosField
245+
required_capability: match_function
246+
247+
from date_nanos
248+
| where match(nanos, "2023-10-23T13:55:01")
249+
| keep nanos;
250+
251+
nanos:date_nanos
252+
2023-10-23T13:55:01.543123456Z
253+
;
254+
255+
testMatchBooleanField
256+
required_capability: match_function
257+
258+
from employees
259+
| where match(still_hired, true) and height > 2.08
260+
| keep first_name, still_hired, height;
261+
ignoreOrder:true
262+
263+
first_name:keyword | still_hired:boolean | height:double
264+
Saniya | true | 2.1
265+
Yongqiao | true | 2.1
266+
Kwee | true | 2.1
267+
Amabile | true | 2.09
268+
;
269+
270+
testMatchIntegerField
271+
required_capability: match_function
272+
273+
from employees
274+
| where match(emp_no, 10004)
275+
| keep emp_no, first_name;
276+
277+
emp_no:integer | first_name:keyword
278+
10004 | Chirstian
279+
;
280+
281+
testMatchDoubleField
282+
required_capability: match_function
283+
284+
from employees
285+
| where match(salary_change, 9.07)
286+
| keep emp_no, salary_change;
287+
288+
emp_no:integer | salary_change:double
289+
10014 | [-1.89, 9.07]
290+
;
291+
292+
testMatchDoubleField
293+
required_capability: match_function
294+
295+
from employees
296+
| where match(salary_change, 9.07)
297+
| keep emp_no, salary_change;
298+
299+
emp_no:integer | salary_change:double
300+
10014 | [-1.89, 9.07]
301+
;
302+
303+
testMatchLongField
304+
required_capability: match_function
305+
306+
from date_nanos
307+
| where match(num, 1698069301543123456)
308+
| keep num;
309+
310+
num:long
311+
1698069301543123456
312+
;
313+
314+
testMatchUnsignedLongField
315+
required_capability: match_function
316+
317+
from ul_logs
318+
| where match(bytes_out, 12749081495402663265)
319+
| keep bytes_out;
320+
321+
bytes_out:unsigned_long
322+
12749081495402663265
323+
;
324+
325+
testMatchVersionField
326+
required_capability: match_function
327+
328+
from apps
329+
| where match(version, "2.1")
330+
| keep name, version;
331+
332+
name:keyword | version:version
333+
bbbbb | 2.1
334+
;
335+
336+
337+
338+

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

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@
1212

1313
import org.apache.lucene.util.BytesRef;
1414
import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.FieldExpression;
15+
import org.elasticsearch.xpack.esql.EsqlTestUtils;
1516
import org.elasticsearch.xpack.esql.core.expression.Expression;
1617
import org.elasticsearch.xpack.esql.core.tree.Source;
1718
import org.elasticsearch.xpack.esql.core.type.DataType;
1819
import org.elasticsearch.xpack.esql.expression.function.AbstractFunctionTestCase;
1920
import org.elasticsearch.xpack.esql.expression.function.FunctionName;
2021
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
22+
import org.elasticsearch.xpack.versionfield.Version;
2123

24+
import java.net.InetAddress;
25+
import java.net.UnknownHostException;
2226
import java.util.ArrayList;
2327
import java.util.LinkedList;
2428
import java.util.List;
@@ -38,8 +42,8 @@ public MatchTests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCase
3842
public static Iterable<Object[]> parameters() {
3943
List<Set<DataType>> supportedPerPosition = supportedParams();
4044
List<TestCaseSupplier> suppliers = new LinkedList<>();
41-
for (DataType fieldType : DataType.stringTypes()) {
42-
for (DataType queryType : DataType.stringTypes()) {
45+
for (DataType fieldType : Match.DATA_TYPES) {
46+
for (DataType queryType : Match.DATA_TYPES) {
4347
addPositiveTestCase(List.of(fieldType, queryType), suppliers);
4448
addNonFieldTestCase(List.of(fieldType, queryType), supportedPerPosition, suppliers);
4549
}
@@ -55,13 +59,9 @@ public static Iterable<Object[]> parameters() {
5559

5660
protected static List<Set<DataType>> supportedParams() {
5761
Set<DataType> supportedTextParams = Set.of(DataType.KEYWORD, DataType.TEXT);
58-
Set<DataType> supportedNumericParams = Set.of(DataType.DOUBLE, DataType.INTEGER);
59-
Set<DataType> supportedFuzzinessParams = Set.of(DataType.INTEGER, DataType.KEYWORD, DataType.TEXT);
6062
List<Set<DataType>> supportedPerPosition = List.of(
6163
supportedTextParams,
62-
supportedTextParams,
63-
supportedNumericParams,
64-
supportedFuzzinessParams
64+
Match.DATA_TYPES
6565
);
6666
return supportedPerPosition;
6767
}
@@ -108,10 +108,34 @@ private static List<TestCaseSupplier.TypedData> getTestParams(List<DataType> par
108108
"field"
109109
)
110110
);
111-
params.add(new TestCaseSupplier.TypedData(new BytesRef(randomAlphaOfLength(10)), paramDataTypes.get(1), "query"));
111+
final Object value = randomQuery(paramDataTypes.get(1));
112+
params.add(new TestCaseSupplier.TypedData(new BytesRef(String.valueOf(value)), paramDataTypes.get(1), "query"));
112113
return params;
113114
}
114115

116+
public static Object randomQuery(DataType dataType) {
117+
if (Match.DATA_TYPES.contains(dataType) == false) {
118+
throw new IllegalArgumentException("Unsupported type in tests: " + dataType);
119+
}
120+
Object value = EsqlTestUtils.randomLiteral(dataType).value();
121+
if (value instanceof BytesRef bytesRef) {
122+
switch (dataType) {
123+
case TEXT, KEYWORD -> value = bytesRef.utf8ToString();
124+
case VERSION -> value = new Version(bytesRef).toString();
125+
case IP -> {
126+
try {
127+
value = InetAddress.getByAddress(bytesRef.bytes).getHostAddress();
128+
} catch (UnknownHostException e) {
129+
throw new IllegalArgumentException(e);
130+
}
131+
}
132+
default -> throw new IllegalArgumentException("Unexpected type: " + dataType + " has BytesRef as value");
133+
}
134+
}
135+
136+
return value;
137+
}
138+
115139
private static String getTestCaseName(List<DataType> paramDataTypes, String fieldType) {
116140
StringBuilder sb = new StringBuilder();
117141
sb.append("<");

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@
3939
import org.elasticsearch.xpack.esql.core.util.Holder;
4040
import org.elasticsearch.xpack.esql.enrich.ResolvedEnrichPolicy;
4141
import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry;
42+
import org.elasticsearch.xpack.esql.expression.function.fulltext.Match;
43+
import org.elasticsearch.xpack.esql.expression.function.fulltext.MatchTests;
4244
import org.elasticsearch.xpack.esql.index.EsIndex;
4345
import org.elasticsearch.xpack.esql.index.IndexResolution;
46+
import org.elasticsearch.xpack.esql.parser.ParsingException;
4447
import org.elasticsearch.xpack.esql.plan.logical.Enrich;
4548
import org.elasticsearch.xpack.esql.plan.physical.AggregateExec;
4649
import org.elasticsearch.xpack.esql.plan.physical.EsQueryExec;
@@ -1092,19 +1095,31 @@ public void testMissingFieldsDoNotGetExtracted() {
10921095
* estimatedRowSize[324]
10931096
*/
10941097
public void testSingleMatchFilterPushdown() {
1095-
var plan = plannerOptimizer.plan("""
1096-
from test
1097-
| where first_name:"Anna"
1098-
""");
1099-
1100-
var limit = as(plan, LimitExec.class);
1101-
var exchange = as(limit.child(), ExchangeExec.class);
1102-
var project = as(exchange.child(), ProjectExec.class);
1103-
var fieldExtract = as(project.child(), FieldExtractExec.class);
1104-
var actualLuceneQuery = as(fieldExtract.child(), EsQueryExec.class).query();
1105-
1106-
var expectedLuceneQuery = new MatchQueryBuilder("first_name", "Anna");
1107-
assertThat(actualLuceneQuery, equalTo(expectedLuceneQuery));
1098+
// Check for every possible query data type
1099+
for (DataType queryDataType : Match.DATA_TYPES) {
1100+
var query = MatchTests.randomQuery(queryDataType);
1101+
var queryText = query;
1102+
if (query instanceof String) {
1103+
queryText = "\"" + query + "\"";
1104+
}
1105+
var esqlQuery = """
1106+
from test
1107+
| where first_name:""" + queryText;
1108+
try {
1109+
var plan = plannerOptimizer.plan(esqlQuery);
1110+
1111+
var limit = as(plan, LimitExec.class);
1112+
var exchange = as(limit.child(), ExchangeExec.class);
1113+
var project = as(exchange.child(), ProjectExec.class);
1114+
var fieldExtract = as(project.child(), FieldExtractExec.class);
1115+
var actualLuceneQuery = as(fieldExtract.child(), EsQueryExec.class).query();
1116+
1117+
var expectedLuceneQuery = new MatchQueryBuilder("first_name", query);
1118+
assertThat("Unexpected match query for data type " + queryDataType, actualLuceneQuery, equalTo(expectedLuceneQuery));
1119+
} catch (ParsingException e) {
1120+
fail("Error parsing ESQL query: " + esqlQuery + "\n" + e.getMessage());
1121+
}
1122+
}
11081123
}
11091124

11101125
/**

0 commit comments

Comments
 (0)