Skip to content

Commit 067ffe6

Browse files
authored
Move query error and retry integration tests into embedded suite (#18786)
Description ----------- This patch continues the effort to move query group tests to the embedded test suite. Note ----- - The queries have been simplified since they just need to verify the error thrown - TLS-based tests are not being migrated here. Key changed classes --------------------- * `ITQueryErrorTest` * `QueryErrorTest` * `ITQueryRetryTestOnMissingSegments` * `QueryRetryOnMissingSegmentTest` * `QueryTestBase`
1 parent 71fbba6 commit 067ffe6

File tree

15 files changed

+1135
-623
lines changed

15 files changed

+1135
-623
lines changed
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.druid.testing.embedded.query;
21+
22+
import com.google.common.util.concurrent.ListenableFuture;
23+
import org.apache.druid.client.broker.BrokerClient;
24+
import org.apache.druid.error.ExceptionMatcher;
25+
import org.apache.druid.java.util.common.StringUtils;
26+
import org.apache.druid.query.Druids;
27+
import org.apache.druid.query.QueryContexts;
28+
import org.apache.druid.query.http.ClientSqlQuery;
29+
import org.apache.druid.query.http.SqlTaskStatus;
30+
import org.apache.druid.rpc.HttpResponseException;
31+
import org.apache.druid.testing.embedded.EmbeddedClusterApis;
32+
import org.apache.druid.testing.embedded.EmbeddedDruidCluster;
33+
import org.apache.druid.testing.embedded.msq.EmbeddedMSQApis;
34+
import org.hamcrest.MatcherAssert;
35+
import org.junit.jupiter.api.Assertions;
36+
import org.junit.jupiter.api.Test;
37+
38+
import java.util.HashMap;
39+
import java.util.List;
40+
import java.util.Map;
41+
42+
import static org.apache.druid.testing.embedded.query.ServerManagerForQueryErrorTest.QUERY_CAPACITY_EXCEEDED_TEST_CONTEXT_KEY;
43+
import static org.apache.druid.testing.embedded.query.ServerManagerForQueryErrorTest.QUERY_FAILURE_TEST_CONTEXT_KEY;
44+
import static org.apache.druid.testing.embedded.query.ServerManagerForQueryErrorTest.QUERY_TIMEOUT_TEST_CONTEXT_KEY;
45+
import static org.apache.druid.testing.embedded.query.ServerManagerForQueryErrorTest.QUERY_UNSUPPORTED_TEST_CONTEXT_KEY;
46+
import static org.apache.druid.testing.embedded.query.ServerManagerForQueryErrorTest.RESOURCE_LIMIT_EXCEEDED_TEST_CONTEXT_KEY;
47+
48+
/**
49+
* This class tests various query failures.
50+
* <p>
51+
* - SQL planning failures. Both {@link org.apache.calcite.sql.parser.SqlParseException}
52+
* and {@link org.apache.calcite.tools.ValidationException} are tested using SQLs that must fail.
53+
* - Various query errors from historicals. These tests use {@link ServerManagerForQueryErrorTest} to make
54+
* the query to always throw an exception.
55+
*/
56+
public class QueryErrorTest extends QueryTestBase
57+
{
58+
// Introduce onAnyRouter(...) and use it; add TLS tests in the follow-up patches
59+
protected String tableName;
60+
61+
@Override
62+
protected EmbeddedDruidCluster createCluster()
63+
{
64+
overlord.addProperty("druid.manager.segments.pollDuration", "PT0.1s");
65+
indexer.setServerMemory(600_000_000)
66+
.addProperty("druid.worker.capacity", "4")
67+
.addProperty("druid.processing.numThreads", "2")
68+
.addProperty("druid.segment.handoff.pollDuration", "PT0.1s");
69+
70+
return EmbeddedDruidCluster.withEmbeddedDerbyAndZookeeper()
71+
.useLatchableEmitter()
72+
.addServer(overlord)
73+
.addServer(coordinator)
74+
.addServer(broker)
75+
.addServer(router)
76+
.addServer(indexer)
77+
.addServer(historical)
78+
.addExtension(ServerManagerForQueryErrorTestModule.class);
79+
}
80+
81+
@Override
82+
protected void beforeAll()
83+
{
84+
tableName = EmbeddedClusterApis.createTestDatasourceName();
85+
EmbeddedMSQApis msqApi = new EmbeddedMSQApis(cluster, overlord);
86+
SqlTaskStatus ingestionStatus = msqApi.submitTaskSql(StringUtils.format(
87+
"REPLACE INTO %s\n"
88+
+ "OVERWRITE ALL\n"
89+
+ "SELECT CURRENT_TIMESTAMP AS __time, 1 AS d PARTITIONED BY ALL",
90+
tableName
91+
));
92+
93+
cluster.callApi().waitForTaskToSucceed(ingestionStatus.getTaskId(), overlord);
94+
cluster.callApi().waitForAllSegmentsToBeAvailable(tableName, coordinator, broker);
95+
}
96+
97+
@Test
98+
public void testSqlParseException()
99+
{
100+
MatcherAssert.assertThat(
101+
Assertions.assertThrows(
102+
Exception.class,
103+
() -> cluster.runSql("FROM foo_bar")
104+
),
105+
ExceptionMatcher.of(HttpResponseException.class)
106+
.expectMessageContains("400 Bad Request")
107+
);
108+
}
109+
110+
@Test
111+
public void testSqlValidationException()
112+
{
113+
MatcherAssert.assertThat(
114+
Assertions.assertThrows(
115+
Exception.class,
116+
() -> cluster.runSql("SELECT * FROM foo_bar")
117+
),
118+
ExceptionMatcher.of(HttpResponseException.class)
119+
.expectMessageContains("400 Bad Request")
120+
);
121+
}
122+
123+
@Test
124+
public void testQueryTimeout()
125+
{
126+
MatcherAssert.assertThat(
127+
Assertions.assertThrows(
128+
Exception.class,
129+
() -> cluster.callApi().onAnyBroker(
130+
b -> sqlQueryFuture(b, QUERY_TIMEOUT_TEST_CONTEXT_KEY)
131+
)
132+
),
133+
ExceptionMatcher.of(HttpResponseException.class)
134+
.expectMessageContains("504")
135+
);
136+
137+
MatcherAssert.assertThat(
138+
Assertions.assertThrows(
139+
Exception.class,
140+
() -> cluster.callApi().onAnyBroker(
141+
b -> nativeQueryFuture(b, QUERY_TIMEOUT_TEST_CONTEXT_KEY)
142+
)
143+
),
144+
ExceptionMatcher.of(HttpResponseException.class)
145+
.expectMessageContains("504")
146+
);
147+
}
148+
149+
@Test
150+
public void testQueryCapacityExceeded()
151+
{
152+
MatcherAssert.assertThat(
153+
Assertions.assertThrows(
154+
Exception.class,
155+
() -> cluster.callApi().onAnyBroker(
156+
b -> sqlQueryFuture(b, QUERY_CAPACITY_EXCEEDED_TEST_CONTEXT_KEY)
157+
)
158+
),
159+
ExceptionMatcher.of(HttpResponseException.class)
160+
.expectMessageContains("429")
161+
);
162+
163+
MatcherAssert.assertThat(
164+
Assertions.assertThrows(
165+
Exception.class,
166+
() -> cluster.callApi().onAnyBroker(
167+
b -> nativeQueryFuture(b, QUERY_CAPACITY_EXCEEDED_TEST_CONTEXT_KEY)
168+
)
169+
),
170+
ExceptionMatcher.of(HttpResponseException.class)
171+
.expectMessageContains("429")
172+
);
173+
}
174+
175+
@Test
176+
public void testQueryUnsupported()
177+
{
178+
MatcherAssert.assertThat(
179+
Assertions.assertThrows(
180+
Exception.class,
181+
() -> cluster.callApi().onAnyBroker(
182+
b -> sqlQueryFuture(b, QUERY_UNSUPPORTED_TEST_CONTEXT_KEY)
183+
)
184+
),
185+
ExceptionMatcher.of(HttpResponseException.class)
186+
.expectMessageContains("501")
187+
);
188+
189+
MatcherAssert.assertThat(
190+
Assertions.assertThrows(
191+
Exception.class,
192+
() -> cluster.callApi().onAnyBroker(
193+
b -> nativeQueryFuture(b, QUERY_UNSUPPORTED_TEST_CONTEXT_KEY)
194+
)
195+
),
196+
ExceptionMatcher.of(HttpResponseException.class)
197+
.expectMessageContains("501")
198+
);
199+
}
200+
201+
@Test
202+
public void testQueryResourceLimitExceeded()
203+
{
204+
// SQL
205+
MatcherAssert.assertThat(
206+
Assertions.assertThrows(
207+
Exception.class,
208+
() -> cluster.callApi().onAnyBroker(
209+
b -> sqlQueryFuture(b, RESOURCE_LIMIT_EXCEEDED_TEST_CONTEXT_KEY)
210+
)
211+
),
212+
ExceptionMatcher.of(HttpResponseException.class)
213+
.expectMessageContains("400")
214+
);
215+
216+
// Native
217+
MatcherAssert.assertThat(
218+
Assertions.assertThrows(
219+
Exception.class,
220+
() -> cluster.callApi().onAnyBroker(
221+
b -> nativeQueryFuture(b, RESOURCE_LIMIT_EXCEEDED_TEST_CONTEXT_KEY)
222+
)
223+
),
224+
ExceptionMatcher.of(HttpResponseException.class)
225+
.expectMessageContains("400")
226+
);
227+
}
228+
229+
@Test
230+
public void testQueryFailure()
231+
{
232+
MatcherAssert.assertThat(
233+
Assertions.assertThrows(
234+
Exception.class,
235+
() -> cluster.callApi().onAnyBroker(
236+
b -> sqlQueryFuture(b, QUERY_FAILURE_TEST_CONTEXT_KEY)
237+
)
238+
),
239+
ExceptionMatcher.of(HttpResponseException.class)
240+
.expectMessageContains("500")
241+
);
242+
243+
MatcherAssert.assertThat(
244+
Assertions.assertThrows(
245+
Exception.class,
246+
() -> cluster.callApi().onAnyBroker(
247+
b -> nativeQueryFuture(b, QUERY_FAILURE_TEST_CONTEXT_KEY)
248+
)
249+
),
250+
ExceptionMatcher.of(HttpResponseException.class)
251+
.expectMessageContains("500")
252+
);
253+
}
254+
255+
private static Map<String, Object> buildTestContext(String key)
256+
{
257+
final Map<String, Object> context = new HashMap<>();
258+
// Disable cache so that each run hits historical.
259+
context.put(QueryContexts.USE_CACHE_KEY, false);
260+
context.put(key, true);
261+
return context;
262+
}
263+
264+
/**
265+
* Set up a SQL query future for the test.
266+
*/
267+
private ListenableFuture<String> sqlQueryFuture(BrokerClient b, String contextKey)
268+
{
269+
return b.submitSqlQuery(new ClientSqlQuery(
270+
StringUtils.format("SELECT * FROM %s LIMIT 1", tableName),
271+
null,
272+
false,
273+
false,
274+
false,
275+
buildTestContext(contextKey),
276+
List.of()
277+
));
278+
}
279+
280+
/**
281+
* Set up a native query future for the test.
282+
*/
283+
private ListenableFuture<String> nativeQueryFuture(BrokerClient b, String contextKey)
284+
{
285+
return b.submitNativeQuery(new Druids.ScanQueryBuilder()
286+
.dataSource(tableName)
287+
.eternityInterval()
288+
.limit(1)
289+
.context(buildTestContext(contextKey))
290+
.build()
291+
);
292+
}
293+
}

0 commit comments

Comments
 (0)