Skip to content

Commit cc54010

Browse files
ES|QL: enable generative tests (#126097)
1 parent 15899af commit cc54010

File tree

3 files changed

+78
-19
lines changed

3 files changed

+78
-19
lines changed

x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/GenerativeIT.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,22 @@
99

1010
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
1111

12-
import org.apache.lucene.tests.util.LuceneTestCase.AwaitsFix;
1312
import org.elasticsearch.test.TestClustersThreadFilter;
1413
import org.elasticsearch.test.cluster.ElasticsearchCluster;
1514
import org.elasticsearch.xpack.esql.qa.rest.generative.GenerativeRestTest;
1615
import org.junit.ClassRule;
1716

18-
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/121754")
17+
/**
18+
* This test generates random queries, runs them agains the CSV test dataset and checks that they don't throw unexpected exceptions.
19+
*
20+
* If muted, please:
21+
* <ul>
22+
* <li>see the error message reported in the failure and the corresponding query (it's in the logs right before the error)</li>
23+
* <li>update the corresponding issue with the query (if there is no issue for that failure yet, create one)</li>
24+
* <li>add a pattern that matches the error message to {@link GenerativeRestTest#ALLOWED_ERRORS}; also link the issue</li>
25+
* <li>unmute (and possibly check that the test doesn't fail anymore)</li>
26+
* </ul>
27+
*/
1928
@ThreadLeakFilters(filters = TestClustersThreadFilter.class)
2029
public class GenerativeIT extends GenerativeRestTest {
2130
@ClassRule

x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/EsqlQueryGenerator.java

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
import org.elasticsearch.xpack.esql.CsvTestsDataLoader;
1111

1212
import java.util.ArrayList;
13+
import java.util.HashMap;
1314
import java.util.HashSet;
1415
import java.util.List;
16+
import java.util.Map;
1517
import java.util.Set;
1618
import java.util.stream.Collectors;
1719

@@ -160,7 +162,11 @@ private static String grok(List<Column> previousOutput) {
160162
if (randomBoolean()) {
161163
result.append(randomAlphaOfLength(5));
162164
} else {
163-
result.append(randomName(previousOutput));
165+
String fieldName = randomRawName(previousOutput);
166+
if (fieldName.isEmpty()) { // it's a bug, managed later, skipping for now
167+
randomAlphaOfLength(5);
168+
}
169+
result.append(fieldName);
164170
}
165171
result.append("}");
166172
}
@@ -184,7 +190,11 @@ private static String dissect(List<Column> previousOutput) {
184190
if (randomBoolean()) {
185191
result.append(randomAlphaOfLength(5));
186192
} else {
187-
result.append(randomName(previousOutput));
193+
String fieldName = randomRawName(previousOutput);
194+
if (fieldName.isEmpty()) { // it's a bug, managed later, skipping for now
195+
fieldName = randomAlphaOfLength(5);
196+
}
197+
result.append(fieldName);
188198
}
189199
result.append("}");
190200
}
@@ -200,7 +210,7 @@ private static String keep(List<Column> previousOutput) {
200210
proj.add("*");
201211
} else {
202212
String name = randomName(previousOutput);
203-
if (name.length() > 1 && randomIntBetween(0, 100) < 10) {
213+
if (name.length() > 1 && name.startsWith("`") == false && randomIntBetween(0, 100) < 10) {
204214
if (randomBoolean()) {
205215
name = name.substring(0, randomIntBetween(1, name.length() - 1)) + "*";
206216
} else {
@@ -214,9 +224,19 @@ private static String keep(List<Column> previousOutput) {
214224
}
215225

216226
private static String randomName(List<Column> previousOutput) {
227+
String result = randomRawName(previousOutput);
228+
if (result.isEmpty() // bug https://github.com/elastic/elasticsearch/issues/125870, we'll manage it as an error later
229+
|| (randomBoolean() && result.contains("*") == false)) {
230+
result = "`" + result + "`";
231+
}
232+
return result;
233+
}
234+
235+
private static String randomRawName(List<Column> previousOutput) {
217236
// we need to exclude <all-fields-projected>
218237
// https://github.com/elastic/elasticsearch/issues/121741
219-
return randomFrom(previousOutput.stream().filter(x -> x.name().equals("<all-fields-projected>") == false).toList()).name();
238+
String result = randomFrom(previousOutput.stream().filter(x -> x.name().equals("<all-fields-projected>") == false).toList()).name();
239+
return result;
220240
}
221241

222242
private static String randomGroupableName(List<Column> previousOutput) {
@@ -266,21 +286,39 @@ private static boolean sortable(Column col) {
266286
private static String rename(List<Column> previousOutput) {
267287
int n = randomIntBetween(1, Math.min(3, previousOutput.size()));
268288
List<String> proj = new ArrayList<>();
289+
290+
Map<String, String> nameToType = new HashMap<>();
291+
for (Column column : previousOutput) {
292+
nameToType.put(column.name, column.type);
293+
}
269294
List<String> names = new ArrayList<>(previousOutput.stream().map(Column::name).collect(Collectors.toList()));
270295
for (int i = 0; i < n; i++) {
271-
var colN = randomIntBetween(0, names.size() - 1);
272-
if (previousOutput.get(colN).type().endsWith("_range")) {
296+
var name = randomFrom(names);
297+
if (name.equals("<all-fields-projected>") || nameToType.get(name).endsWith("_range")) {
273298
// ranges are not fully supported yet
274299
continue;
275300
}
276-
String name = names.remove(colN);
301+
names.remove(name);
302+
277303
String newName;
278304
if (names.isEmpty() || randomBoolean()) {
279305
newName = randomAlphaOfLength(5);
306+
names.add(newName);
280307
} else {
281308
newName = names.get(randomIntBetween(0, names.size() - 1));
282309
}
283-
names.add(newName);
310+
if (newName.equals("<all-fields-projected>")) { // it's a bug, managed as an error later
311+
continue;
312+
}
313+
nameToType.put(newName, nameToType.get(name));
314+
if (name.length() == 0 // https://github.com/elastic/elasticsearch/issues/125870, we'll manage it as an error later
315+
|| (randomBoolean() && name.startsWith("`") == false)) {
316+
name = "`" + name + "`";
317+
}
318+
if (newName.length() == 0 // https://github.com/elastic/elasticsearch/issues/125870, we'll manage it as an error later
319+
|| (randomBoolean() && newName.startsWith("`") == false)) {
320+
newName = "`" + newName + "`";
321+
}
284322
proj.add(name + " AS " + newName);
285323
}
286324
if (proj.isEmpty()) {
@@ -296,15 +334,17 @@ private static String drop(List<Column> previousOutput) {
296334
int n = randomIntBetween(1, previousOutput.size() - 1);
297335
Set<String> proj = new HashSet<>();
298336
for (int i = 0; i < n; i++) {
299-
String name = randomName(previousOutput);
300-
if (name.length() > 1 && randomIntBetween(0, 100) < 10) {
337+
String name = randomRawName(previousOutput);
338+
if (name.length() > 1 && name.startsWith("`") == false && randomIntBetween(0, 100) < 10) {
301339
if (randomBoolean()) {
302340
name = name.substring(0, randomIntBetween(1, name.length() - 1)) + "*";
303341
} else {
304342
name = "*" + name.substring(randomIntBetween(1, name.length() - 1));
305343
}
344+
} else if (name.startsWith("`") == false && (randomBoolean() || name.isEmpty())) {
345+
name = "`" + name + "`";
306346
}
307-
proj.add(name.contains("*") ? name : "`" + name + "`");
347+
proj.add(name);
308348
}
309349
return " | drop " + proj.stream().collect(Collectors.joining(", "));
310350
}

x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeRestTest.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,33 @@
2929

3030
public abstract class GenerativeRestTest extends ESRestTestCase {
3131

32-
public static final int ITERATIONS = 50;
33-
public static final int MAX_DEPTH = 10;
32+
public static final int ITERATIONS = 100;
33+
public static final int MAX_DEPTH = 20;
3434

3535
public static final Set<String> ALLOWED_ERRORS = Set.of(
3636
"Reference \\[.*\\] is ambiguous",
3737
"Cannot use field \\[.*\\] due to ambiguities",
3838
"cannot sort on .*",
3939
"argument of \\[count_distinct\\(.*\\)\\] must",
4040
"Cannot use field \\[.*\\] with unsupported type \\[.*_range\\]",
41+
"Unbounded sort not supported yet",
42+
"The field names are too complex to process", // field_caps problem
43+
"must be \\[any type except counter types\\]", // TODO refine the generation of count()
44+
4145
// warnings
4246
"Field '.*' shadowed by field at line .*",
4347
"evaluation of \\[.*\\] failed, treating result as null", // TODO investigate?
48+
4449
// Awaiting fixes
45-
"estimated row size \\[0\\] wasn't set", // https://github.com/elastic/elasticsearch/issues/121739
46-
"unknown physical plan node \\[OrderExec\\]", // https://github.com/elastic/elasticsearch/issues/120817
47-
"Unknown column \\[<all-fields-projected>\\]", // https://github.com/elastic/elasticsearch/issues/121741
48-
//
50+
"Unknown column \\[<all-fields-projected>\\]", // https://github.com/elastic/elasticsearch/issues/121741,
51+
"Plan \\[ProjectExec\\[\\[<no-fields>.* optimized incorrectly due to missing references", // https://github.com/elastic/elasticsearch/issues/125866
52+
"only supports KEYWORD or TEXT values, found expression", // https://github.com/elastic/elasticsearch/issues/126017
53+
"token recognition error at: '``", // https://github.com/elastic/elasticsearch/issues/125870
54+
"Unknown column \\[.*\\]", // https://github.com/elastic/elasticsearch/issues/126026
55+
"Expected \\[.*\\] but was \\[.*\\]", // https://github.com/elastic/elasticsearch/issues/126030
56+
"trying to encode an unsupported data type value for TopN", // still https://github.com/elastic/elasticsearch/issues/126030 probably
57+
"Block cannot be cast to", // https://github.com/elastic/elasticsearch/issues/126036
58+
"optimized incorrectly due to missing references", // https://github.com/elastic/elasticsearch/issues/116781
4959
"The incoming YAML document exceeds the limit:" // still to investigate, but it seems to be specific to the test framework
5060
);
5161

0 commit comments

Comments
 (0)