Skip to content

Commit 2bf79f9

Browse files
committed
REST test
1 parent 5ae8ef1 commit 2bf79f9

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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.RestSampleTestCase;
15+
import org.junit.ClassRule;
16+
17+
@ThreadLeakFilters(filters = TestClustersThreadFilter.class)
18+
public class RestSampleIT extends RestSampleTestCase {
19+
@ClassRule
20+
public static ElasticsearchCluster cluster = Clusters.testCluster();
21+
22+
@Override
23+
protected String getTestRestCluster() {
24+
return cluster.getHttpAddresses();
25+
}
26+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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.hamcrest.Description;
15+
import org.hamcrest.TypeSafeMatcher;
16+
import org.junit.After;
17+
import org.junit.Before;
18+
19+
import java.io.IOException;
20+
import java.util.HashSet;
21+
import java.util.List;
22+
import java.util.Map;
23+
import java.util.Set;
24+
import java.util.stream.IntStream;
25+
26+
import static org.hamcrest.Matchers.both;
27+
import static org.hamcrest.Matchers.greaterThan;
28+
import static org.hamcrest.Matchers.lessThan;
29+
30+
public class RestSampleTestCase extends ESRestTestCase {
31+
32+
@Before
33+
public void skipWhenSampleDisabled() throws IOException {
34+
assumeTrue(
35+
"Requires SAMPLE capability",
36+
EsqlSpecTestCase.hasCapabilities(adminClient(), List.of(EsqlCapabilities.Cap.SAMPLE.capabilityName()))
37+
);
38+
}
39+
40+
@Before
41+
@After
42+
public void assertRequestBreakerEmpty() throws Exception {
43+
EsqlSpecTestCase.assertRequestBreakerEmpty();
44+
}
45+
46+
/**
47+
* Matcher for the results of sampling 50% of the elements 0,1,2,...,998,999.
48+
* The results should consist of unique numbers in [0,999]. Furthermore, the
49+
* size should on average be 500. Allowing for 10 stddev deviations, the size
50+
* should be in [250,750].
51+
*/
52+
private static final TypeSafeMatcher<List<List<Integer>>> RESULT_MATCHER = new TypeSafeMatcher<>() {
53+
@Override
54+
public void describeTo(Description description) {
55+
description.appendText("a list with between 250 and 750 unique elements in [0,999]");
56+
}
57+
58+
@Override
59+
protected boolean matchesSafely(List<List<Integer>> lists) {
60+
if (lists.size() < 250 || lists.size() > 750) {
61+
return false;
62+
}
63+
Set<Integer> values = new HashSet<>();
64+
for (List<Integer> list : lists) {
65+
if (list.size() != 1) {
66+
return false;
67+
}
68+
Integer value = list.get(0);
69+
if (value == null || value < 0 || value >= 1000) {
70+
return false;
71+
}
72+
values.add(value);
73+
}
74+
return values.size() == lists.size();
75+
}
76+
};
77+
78+
public void testSample_withFrom() throws IOException {
79+
createTestIndex();
80+
test("FROM sample-test-index | SAMPLE 0.5 | LIMIT 1000");
81+
deleteTestIndex();
82+
}
83+
84+
public void testSample_withRow() throws IOException {
85+
List<Integer> numbers = IntStream.range(0, 999).boxed().toList();
86+
test("ROW value = " + numbers + " | MV_EXPAND value | SAMPLE 0.5 | LIMIT 1000");
87+
}
88+
89+
private void test(String query) throws IOException {
90+
int iterationCount = 1000;
91+
int totalResultSize = 0;
92+
for (int iteration = 0; iteration < iterationCount; iteration++) {
93+
Map<String, Object> result = runEsqlQuery(query);
94+
assertResultMap(result, defaultOutputColumns(), RESULT_MATCHER);
95+
totalResultSize += ((List<?>) result.get("values")).size();
96+
}
97+
// On average there's 500 elements in the results set.
98+
// Allowing for 10 stddev deviations, it should be in [490,510].
99+
assertThat(totalResultSize / iterationCount, both(greaterThan(490)).and(lessThan(510)));
100+
}
101+
102+
private static List<Map<String, String>> defaultOutputColumns() {
103+
return List.of(Map.of("name", "value", "type", "integer"));
104+
}
105+
106+
private Map<String, Object> runEsqlQuery(String query) throws IOException {
107+
RestEsqlTestCase.RequestObjectBuilder builder = RestEsqlTestCase.requestObjectBuilder().query(query);
108+
return RestEsqlTestCase.runEsqlSync(builder);
109+
}
110+
111+
private void createTestIndex() throws IOException {
112+
Request request = new Request("PUT", "/sample-test-index");
113+
request.setJsonEntity("""
114+
{
115+
"mappings": {
116+
"properties": {
117+
"value": { "type": "integer" }
118+
}
119+
}
120+
}""");
121+
assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode());
122+
123+
StringBuilder requestJsonEntity = new StringBuilder();
124+
for (int i = 0; i < 1000; i++) {
125+
requestJsonEntity.append("{ \"index\": {\"_id\": " + i + "} }\n");
126+
requestJsonEntity.append("{ \"value\": " + i + " }\n");
127+
}
128+
129+
request = new Request("POST", "/sample-test-index/_bulk");
130+
request.addParameter("refresh", "true");
131+
request.setJsonEntity(requestJsonEntity.toString());
132+
assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode());
133+
}
134+
135+
private void deleteTestIndex() throws IOException {
136+
try {
137+
adminClient().performRequest(new Request("DELETE", "/sample-test-index"));
138+
} catch (ResponseException e) {
139+
throw e;
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)