Skip to content

Commit 983ce28

Browse files
committed
Adding more tests.
1 parent 1a6161b commit 983ce28

File tree

5 files changed

+299
-8
lines changed

5 files changed

+299
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.esql.qa.multi_node;
9+
10+
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
11+
12+
import org.elasticsearch.test.TestClustersThreadFilter;
13+
import org.elasticsearch.test.cluster.ElasticsearchCluster;
14+
import org.elasticsearch.xpack.esql.qa.rest.RestRerankTestCase;
15+
import org.junit.ClassRule;
16+
17+
@ThreadLeakFilters(filters = TestClustersThreadFilter.class)
18+
public class RestRerankIT extends RestRerankTestCase {
19+
@ClassRule
20+
public static ElasticsearchCluster cluster = Clusters.testCluster(spec -> spec.plugin("inference-service-test"));
21+
22+
@Override
23+
protected String getTestRestCluster() {
24+
return cluster.getHttpAddresses();
25+
}
26+
27+
@Override
28+
protected boolean preserveClusterUponCompletion() {
29+
return true;
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.esql.qa.single_node;
9+
10+
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
11+
12+
import org.elasticsearch.test.TestClustersThreadFilter;
13+
import org.elasticsearch.test.cluster.ElasticsearchCluster;
14+
import org.elasticsearch.xpack.esql.qa.rest.RestRerankTestCase;
15+
import org.junit.ClassRule;
16+
17+
@ThreadLeakFilters(filters = TestClustersThreadFilter.class)
18+
public class RestRerankIT extends RestRerankTestCase {
19+
@ClassRule
20+
public static ElasticsearchCluster cluster = Clusters.testCluster(spec -> spec.plugin("inference-service-test"));
21+
22+
@Override
23+
protected String getTestRestCluster() {
24+
return cluster.getHttpAddresses();
25+
}
26+
27+
@Override
28+
protected boolean preserveClusterUponCompletion() {
29+
return true;
30+
}
31+
}

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,11 @@
6666
import static org.elasticsearch.xpack.esql.CsvTestUtils.loadCsvSpecValues;
6767
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.availableDatasetsForEs;
6868
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.clusterHasInferenceEndpoint;
69-
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.createInferenceEndpoints;
69+
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.clusterHasRerankInferenceEndpoint;
70+
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.createInferenceEndpoint;
71+
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.createRerankInferenceEndpoint;
7072
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.deleteInferenceEndpoint;
73+
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.deleteRerankInferenceEndpoint;
7174
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.loadDataSetIntoEs;
7275
import static org.elasticsearch.xpack.esql.EsqlTestUtils.classpathResources;
7376
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.SOURCE_FIELD_MAPPING;
@@ -130,7 +133,11 @@ protected EsqlSpecTestCase(
130133
@Before
131134
public void setup() throws IOException {
132135
if (supportsInferenceTestService() && clusterHasInferenceEndpoint(client()) == false) {
133-
createInferenceEndpoints(client());
136+
createInferenceEndpoint(client());
137+
}
138+
139+
if (supportsInferenceTestService() && clusterHasRerankInferenceEndpoint(client()) == false) {
140+
createRerankInferenceEndpoint(client());
134141
}
135142

136143
boolean supportsLookup = supportsIndexModeLookup();
@@ -152,6 +159,7 @@ public static void wipeTestData() throws IOException {
152159
}
153160

154161
deleteInferenceEndpoint(client());
162+
deleteRerankInferenceEndpoint(client());
155163
}
156164

157165
public boolean logResults() {
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.esql.qa.rest;
9+
10+
import org.elasticsearch.client.Request;
11+
import org.elasticsearch.client.ResponseException;
12+
import org.elasticsearch.test.rest.ESRestTestCase;
13+
import org.elasticsearch.xpack.esql.action.EsqlCapabilities;
14+
import org.junit.After;
15+
import org.junit.Before;
16+
17+
import java.io.IOException;
18+
import java.util.List;
19+
import java.util.Map;
20+
21+
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.createRerankInferenceEndpoint;
22+
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.deleteRerankInferenceEndpoint;
23+
import static org.hamcrest.core.StringContains.containsString;
24+
25+
public class RestRerankTestCase extends ESRestTestCase {
26+
27+
@Before
28+
@After
29+
public void assertRequestBreakerEmpty() throws Exception {
30+
EsqlSpecTestCase.assertRequestBreakerEmpty();
31+
}
32+
33+
@Before
34+
public void setUpInferenceEndpoint() throws IOException {
35+
createRerankInferenceEndpoint(adminClient());
36+
}
37+
38+
@Before
39+
public void setUpTestIndex() throws IOException {
40+
Request request = new Request("PUT", "/rerank-test-index");
41+
request.setJsonEntity("""
42+
{
43+
"mappings": {
44+
"properties": {
45+
"title": { "type": "text" },
46+
"author": { "type": "text" }
47+
}
48+
}
49+
}""");
50+
assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode());
51+
52+
request = new Request("POST", "/rerank-test-index/_bulk");
53+
request.addParameter("refresh", "true");
54+
request.setJsonEntity("""
55+
{ "index": {"_id": 1} }
56+
{ "title": "The Future of Exploration", "author": "John Doe" }
57+
{ "index": {"_id": 2} }
58+
{ "title": "Deep Sea Exploration", "author": "Jane Smith" }
59+
{ "index": {"_id": 3} }
60+
{ "title": "History of Space Exploration", "author": "Alice Johnson" }
61+
""");
62+
assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode());
63+
}
64+
65+
@After
66+
public void wipeData() throws IOException {
67+
try {
68+
adminClient().performRequest(new Request("DELETE", "/rerank-test-index"));
69+
} catch (ResponseException e) {
70+
// 404 here just means we had no indexes
71+
if (e.getResponse().getStatusLine().getStatusCode() != 404) {
72+
throw e;
73+
}
74+
}
75+
76+
deleteRerankInferenceEndpoint(adminClient());
77+
}
78+
79+
public void testRerankWithSingleField() throws IOException {
80+
assumeTrue("semantic text capability not available", EsqlCapabilities.Cap.RERANK.isEnabled());
81+
82+
String query = """
83+
FROM rerank-test-index
84+
| WHERE match(title, "exploration")
85+
| RERANK "exploration" ON title WITH test_reranker
86+
| EVAL _score = ROUND(_score, 5)
87+
""";
88+
89+
Map<String, Object> result = runEsqlQuery(query);
90+
91+
var expectedValues = List.of(
92+
List.of("Jane Smith", "Deep Sea Exploration", 0.02941),
93+
List.of("John Doe", "The Future of Exploration", 0.02632),
94+
List.of("Alice Johnson", "History of Space Exploration", 0.02381)
95+
);
96+
97+
assertResultMap(result, defaultOutputColumns(), expectedValues);
98+
}
99+
100+
public void testRerankWithMultipleFields() throws IOException {
101+
assumeTrue("semantic text capability not available", EsqlCapabilities.Cap.RERANK.isEnabled());
102+
103+
String query = """
104+
FROM rerank-test-index
105+
| WHERE match(title, "exploration")
106+
| RERANK "exploration" ON title, author WITH test_reranker
107+
| EVAL _score = ROUND(_score, 5)
108+
""";
109+
110+
Map<String, Object> result = runEsqlQuery(query);
111+
;
112+
var expectedValues = List.of(
113+
List.of("Jane Smith", "Deep Sea Exploration", 0.01818),
114+
List.of("John Doe", "The Future of Exploration", 0.01754),
115+
List.of("Alice Johnson", "History of Space Exploration", 0.01515)
116+
);
117+
118+
assertResultMap(result, defaultOutputColumns(), expectedValues);
119+
}
120+
121+
public void testRerankWithPositionalParams() throws IOException {
122+
assumeTrue("semantic text capability not available", EsqlCapabilities.Cap.RERANK.isEnabled());
123+
124+
String query = """
125+
FROM rerank-test-index
126+
| WHERE match(title, "exploration")
127+
| RERANK ? ON title WITH ?
128+
| EVAL _score = ROUND(_score, 5)
129+
""";
130+
131+
Map<String, Object> result = runEsqlQuery(query, "[\"exploration\", \"test_reranker\"]");
132+
133+
var expectedValues = List.of(
134+
List.of("Jane Smith", "Deep Sea Exploration", 0.02941),
135+
List.of("John Doe", "The Future of Exploration", 0.02632),
136+
List.of("Alice Johnson", "History of Space Exploration", 0.02381)
137+
);
138+
139+
assertResultMap(result, defaultOutputColumns(), expectedValues);
140+
}
141+
142+
143+
public void testRerankWithNamedParams() throws IOException {
144+
assumeTrue("semantic text capability not available", EsqlCapabilities.Cap.RERANK.isEnabled());
145+
146+
String query = """
147+
FROM rerank-test-index
148+
| WHERE match(title, ?queryText)
149+
| RERANK ?queryText ON title WITH ?inferenceId
150+
| EVAL _score = ROUND(_score, 5)
151+
""";
152+
153+
Map<String, Object> result = runEsqlQuery(query, "[{\"queryText\": \"exploration\"}, {\"inferenceId\": \"test_reranker\"}]");
154+
155+
var expectedValues = List.of(
156+
List.of("Jane Smith", "Deep Sea Exploration", 0.02941),
157+
List.of("John Doe", "The Future of Exploration", 0.02632),
158+
List.of("Alice Johnson", "History of Space Exploration", 0.02381)
159+
);
160+
161+
assertResultMap(result, defaultOutputColumns(), expectedValues);
162+
}
163+
164+
public void testRerankWithMissingInferenceId() {
165+
assumeTrue("semantic text capability not available", EsqlCapabilities.Cap.RERANK.isEnabled());
166+
167+
String query = """
168+
FROM rerank-test-index
169+
| WHERE match(title, "exploration")
170+
| RERANK "exploration" ON title WITH test_missing
171+
| EVAL _score = ROUND(_score, 5)
172+
""";
173+
174+
ResponseException re = expectThrows(ResponseException.class, () -> runEsqlQuery(query));
175+
assertThat(re.getMessage(), containsString("Inference endpoint not found"));
176+
}
177+
178+
private static List<Map<String, String>> defaultOutputColumns() {
179+
return List.of(
180+
Map.of("name", "author", "type", "text"),
181+
Map.of("name", "title", "type", "text"),
182+
Map.of("name", "_score", "type", "double")
183+
);
184+
}
185+
186+
private Map<String, Object> runEsqlQuery(String query) throws IOException {
187+
RestEsqlTestCase.RequestObjectBuilder builder = RestEsqlTestCase.requestObjectBuilder().query(query);
188+
return RestEsqlTestCase.runEsqlSync(builder);
189+
}
190+
191+
private Map<String, Object> runEsqlQuery(String query, String params) throws IOException {
192+
RestEsqlTestCase.RequestObjectBuilder builder = RestEsqlTestCase.requestObjectBuilder().query(query).params(params);
193+
return RestEsqlTestCase.runEsqlSync(builder);
194+
}
195+
}

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

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ private static void loadDataSetIntoEs(
357357
}
358358

359359
/** The semantic_text mapping type require an inference endpoint that needs to be setup before creating the index. */
360-
public static void createInferenceEndpoints(RestClient client) throws IOException {
360+
public static void createInferenceEndpoint(RestClient client) throws IOException {
361361
Request request = new Request("PUT", "_inference/sparse_embedding/test_sparse_inference");
362362
request.setJsonEntity("""
363363
{
@@ -371,8 +371,34 @@ public static void createInferenceEndpoints(RestClient client) throws IOExceptio
371371
}
372372
""");
373373
client.performRequest(request);
374+
}
374375

375-
request = new Request("PUT", "_inference/rerank/test_reranker");
376+
public static void deleteInferenceEndpoint(RestClient client) throws IOException {
377+
try {
378+
client.performRequest(new Request("DELETE", "_inference/test_sparse_inference"));
379+
} catch (ResponseException e) {
380+
// 404 here means the endpoint was not created
381+
if (e.getResponse().getStatusLine().getStatusCode() != 404) {
382+
throw e;
383+
}
384+
}
385+
}
386+
387+
public static boolean clusterHasInferenceEndpoint(RestClient client) throws IOException {
388+
Request request = new Request("GET", "_inference/sparse_embedding/test_sparse_inference");
389+
try {
390+
client.performRequest(request);
391+
} catch (ResponseException e) {
392+
if (e.getResponse().getStatusLine().getStatusCode() == 404) {
393+
return false;
394+
}
395+
throw e;
396+
}
397+
return true;
398+
}
399+
400+
public static void createRerankInferenceEndpoint(RestClient client) throws IOException {
401+
Request request = new Request("PUT", "_inference/rerank/test_reranker");
376402
request.setJsonEntity("""
377403
{
378404
"service": "test_reranking_service",
@@ -388,9 +414,9 @@ public static void createInferenceEndpoints(RestClient client) throws IOExceptio
388414
client.performRequest(request);
389415
}
390416

391-
public static void deleteInferenceEndpoint(RestClient client) throws IOException {
417+
public static void deleteRerankInferenceEndpoint(RestClient client) throws IOException {
392418
try {
393-
client.performRequest(new Request("DELETE", "_inference/test_sparse_inference"));
419+
client.performRequest(new Request("DELETE", "_inference/rerank/test_reranker"));
394420
} catch (ResponseException e) {
395421
// 404 here means the endpoint was not created
396422
if (e.getResponse().getStatusLine().getStatusCode() != 404) {
@@ -399,8 +425,8 @@ public static void deleteInferenceEndpoint(RestClient client) throws IOException
399425
}
400426
}
401427

402-
public static boolean clusterHasInferenceEndpoint(RestClient client) throws IOException {
403-
Request request = new Request("GET", "_inference/sparse_embedding/test_sparse_inference");
428+
public static boolean clusterHasRerankInferenceEndpoint(RestClient client) throws IOException {
429+
Request request = new Request("GET", "_inference/rerank/test_reranker");
404430
try {
405431
client.performRequest(request);
406432
} catch (ResponseException e) {

0 commit comments

Comments
 (0)