Skip to content

Commit

Permalink
added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
piergm committed Dec 9, 2024
1 parent 63ab8f8 commit cfd3113
Show file tree
Hide file tree
Showing 6 changed files with 318 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,28 @@

package org.elasticsearch.http;

import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.action.search.MultiSearchRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.Request;
import org.elasticsearch.test.rest.ObjectPath;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.transport.TransportMessageListener;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xcontent.XContentType;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.concurrent.atomic.AtomicBoolean;

import static org.elasticsearch.index.query.QueryBuilders.simpleQueryStringQuery;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFailures;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertResponse;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;

public class ErrorTraceIT extends HttpSmokeTestCase {
private AtomicBoolean hasStackTrace;

private void createIndexWithDivergentFieldType(Consumer<SearchResponse> consumer) {
createIndex("test1", "test2");
indexRandom(
true,
prepareIndex("test1").setId("1").setSource("field", "foo"),
prepareIndex("test2").setId("10").setSource("field", 5)
);
refresh();

assertResponse(prepareSearch().setQuery(simpleQueryStringQuery("foo").field("field")), consumer);
}

public void testStandardFailingQueryErrorTraceDefault() throws Exception {
private void setupMessageListener() {
internalCluster().getDataNodeInstances(TransportService.class).forEach(ts -> {
ts.addMessageListener(new TransportMessageListener() {
@Override
Expand All @@ -53,48 +41,168 @@ public void onResponseSent(long requestId, String action, Exception error) {
error,
t -> t.getStackTrace().length > 0
);
assertTrue(throwable.isEmpty());
hasStackTrace.set(throwable.isPresent());
}
}
});
});
createIndexWithDivergentFieldType(response -> {
assertFailures(response);
for (ShardSearchFailure failedShard : response.getShardFailures()) {
assertThat(failedShard.getStackTrace().length, is(not(equalTo(0))));
}
});
}

public void testBase() throws IOException {

}

public void testWithRestRequest() throws IOException {
internalCluster().getDataNodeInstances(TransportService.class).forEach(ts -> {
ts.addMessageListener(new TransportMessageListener() {
@Override
public void onResponseSent(long requestId, String action, Exception error) {
TransportMessageListener.super.onResponseSent(requestId, action, error);
if (action.startsWith("indices:data/read/search")) {
Optional<Throwable> throwable = ExceptionsHelper.unwrapCausesAndSuppressed(
error,
t -> t.getStackTrace().length > 0
);
assertTrue(throwable.isEmpty());
}
}
});
});
private void setupIndexWithDocs() {
createIndex("test1", "test2");
indexRandom(
true,
prepareIndex("test1").setId("1").setSource("field", "foo"),
prepareIndex("test2").setId("10").setSource("field", 5)
);
refresh();
}

public void testSearchFailingQueryErrorTraceDefault() throws IOException {
hasStackTrace = new AtomicBoolean();
setupMessageListener();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_search");
searchRequest.setJsonEntity("""
{
"query": {
"simple_query_string" : {
"query": "foo",
"fields": ["field"]
}
}
}
""");
getRestClient().performRequest(searchRequest);
assertFalse(hasStackTrace.get());
}

public void testSearchFailingQueryErrorTraceTrue() throws IOException {
hasStackTrace = new AtomicBoolean();
setupMessageListener();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_search");
searchRequest.setJsonEntity("""
{
"query": {
"simple_query_string" : {
"query": "foo",
"fields": ["field"]
}
}
}
""");
searchRequest.addParameter("error_trace", "true");
getRestClient().performRequest(searchRequest);
assertTrue(hasStackTrace.get());
}

public void testSearchFailingQueryErrorTraceFalse() throws IOException {
hasStackTrace = new AtomicBoolean();
setupMessageListener();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_search");
searchRequest.setJsonEntity("""
{
"query": {
"simple_query_string" : {
"query": "foo",
"fields": ["field"]
}
}
}
""");
searchRequest.addParameter("error_trace", "false");
getRestClient().performRequest(searchRequest);
assertFalse(hasStackTrace.get());
}

public void testMultiSearchFailingQueryErrorTraceDefault() throws IOException {
hasStackTrace = new AtomicBoolean();
setupMessageListener();
setupIndexWithDocs();

XContentType contentType = XContentType.JSON;
MultiSearchRequest multiSearchRequest = new MultiSearchRequest().add(
new SearchRequest("test*").source(new SearchSourceBuilder().query(simpleQueryStringQuery("foo").field("field")))
);
Request searchRequest = new Request("POST", "/_msearch");
byte[] requestBody = MultiSearchRequest.writeMultiLineFormat(multiSearchRequest, contentType.xContent());
searchRequest.setEntity(
new NByteArrayEntity(requestBody, ContentType.create(contentType.mediaTypeWithoutParameters(), (Charset) null))
);
getRestClient().performRequest(searchRequest);
assertFalse(hasStackTrace.get());
}

public void testMultiSearchFailingQueryErrorTraceTrue() throws IOException {
hasStackTrace = new AtomicBoolean();
setupMessageListener();
setupIndexWithDocs();

XContentType contentType = XContentType.JSON;
MultiSearchRequest multiSearchRequest = new MultiSearchRequest().add(
new SearchRequest("test*").source(new SearchSourceBuilder().query(simpleQueryStringQuery("foo").field("field")))
);
Request searchRequest = new Request("POST", "/_msearch");
byte[] requestBody = MultiSearchRequest.writeMultiLineFormat(multiSearchRequest, contentType.xContent());
searchRequest.setEntity(
new NByteArrayEntity(requestBody, ContentType.create(contentType.mediaTypeWithoutParameters(), (Charset) null))
);
searchRequest.addParameter("error_trace", "true");
getRestClient().performRequest(searchRequest);
assertTrue(hasStackTrace.get());
}

public void testMultiSearchFailingQueryErrorTraceFalse() throws IOException {
hasStackTrace = new AtomicBoolean();
setupMessageListener();
setupIndexWithDocs();

XContentType contentType = XContentType.JSON;
MultiSearchRequest multiSearchRequest = new MultiSearchRequest().add(
new SearchRequest("test*").source(new SearchSourceBuilder().query(simpleQueryStringQuery("foo").field("field")))
);
Request searchRequest = new Request("POST", "/_msearch");
byte[] requestBody = MultiSearchRequest.writeMultiLineFormat(multiSearchRequest, contentType.xContent());
searchRequest.setEntity(
new NByteArrayEntity(requestBody, ContentType.create(contentType.mediaTypeWithoutParameters(), (Charset) null))
);
searchRequest.addParameter("error_trace", "false");
getRestClient().performRequest(searchRequest);

assertFalse(hasStackTrace.get());
}

public void testAsyncSearchFailingQueryErrorTraceDefault() throws IOException {
hasStackTrace = new AtomicBoolean();
setupMessageListener();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_async_search");
searchRequest.setJsonEntity("""
{
"query": {
"simple_query_string" : {
"query": "foo",
"fields": ["field"]
}
}
}
""");
getRestClient().performRequest(searchRequest);
assertFalse(hasStackTrace.get());
}

public void testAsyncSearchFailingQueryErrorTraceTrue() throws IOException {
hasStackTrace = new AtomicBoolean();
setupMessageListener();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_async_search");
searchRequest.setJsonEntity("""
{
"query": {
Expand All @@ -106,6 +214,28 @@ public void onResponseSent(long requestId, String action, Exception error) {
}
""");
searchRequest.addParameter("error_trace", "true");
ObjectPath response = ObjectPath.createFromResponse(getRestClient().performRequest(searchRequest));
getRestClient().performRequest(searchRequest);
assertTrue(hasStackTrace.get());
}

public void testAsyncSearchFailingQueryErrorTraceFalse() throws IOException {
hasStackTrace = new AtomicBoolean();
setupMessageListener();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_async_search");
searchRequest.setJsonEntity("""
{
"query": {
"simple_query_string" : {
"query": "foo",
"fields": ["field"]
}
}
}
""");
searchRequest.addParameter("error_trace", "false");
getRestClient().performRequest(searchRequest);
assertFalse(hasStackTrace.get());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,8 @@ public String getName() {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
// set weather data nodes should send back stack trace based on the `error_trace` query parameter
if (request.param("error_trace", "false").equals("true")) {
context.putHeader("error_trace", "true");
}
context.putHeader("error_trace", request.param("error_trace", "false"));

final MultiSearchRequest multiSearchRequest = parseRequest(request, allowExplicitIndex, searchUsageHolder, clusterSupportsFeature);
return channel -> {
final RestCancellableNodeClient cancellableClient = new RestCancellableNodeClient(client, request.getHttpChannel());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,8 @@ public Set<String> supportedCapabilities() {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
// set weather data nodes should send back stack trace based on the `error_trace` query parameter
if (request.param("error_trace", "true").equals("false")) {
context.putHeader("error_trace", "false");
}
context.putHeader("error_trace", request.param("error_trace", "false"));

SearchRequest searchRequest = new SearchRequest();
// access the BwC param, but just drop it
// this might be set by old clients
Expand Down
Loading

0 comments on commit cfd3113

Please sign in to comment.