Add Location header and improve REST testing

This adds a header that looks like `Location: /test/test/1` to the
response for the index/create/update API. The requirement for the header
comes from https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

https://tools.ietf.org/html/rfc7231#section-7.1.2 claims that relative
URIs are OK. So we use an absolute path which should resolve to the
appropriate location.

Closes #19079

This makes large changes to our rest test infrastructure, allowing us
to write junit tests that test a running cluster via the rest client.
It does this by splitting ESRestTestCase into two classes:
* ESRestTestCase is the superclass of all tests that use the rest client
to interact with a running cluster.
* ESClientYamlSuiteTestCase is the superclass of all tests that use the
rest client to run the yaml tests. These tests are shared across all
official clients, thus the `ClientYamlSuite` part of the name.
This commit is contained in:
Nik Everett 2016-07-19 18:31:19 -04:00
parent b90dff7292
commit a95d4f4ee7
58 changed files with 762 additions and 535 deletions

View File

@ -535,7 +535,6 @@
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]cat[/\\]RestShardsAction.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]cat[/\\]RestThreadPoolAction.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]get[/\\]RestMultiGetAction.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]index[/\\]RestIndexAction.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]script[/\\]RestDeleteIndexedScriptAction.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]script[/\\]RestPutIndexedScriptAction.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]search[/\\]RestClearScrollAction.java" checks="LineLength" />

View File

@ -22,6 +22,7 @@ import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.support.WriteResponse;
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.StatusToXContent;
@ -109,6 +110,30 @@ public abstract class DocWriteResponse extends ReplicationResponse implements Wr
return getShardInfo().status();
}
/**
* Gets the location of the written document as a string suitable for a {@code Location} header.
* @param routing any routing used in the request. If null the location doesn't include routing information.
*/
public String getLocation(@Nullable String routing) {
// Absolute path for the location of the document. This should be allowed as of HTTP/1.1:
// https://tools.ietf.org/html/rfc7231#section-7.1.2
String index = getIndex();
String type = getType();
String id = getId();
String routingStart = "?routing=";
int bufferSize = 3 + index.length() + type.length() + id.length();
if (routing != null) {
bufferSize += routingStart.length() + routing.length();
}
StringBuilder location = new StringBuilder(bufferSize);
location.append('/').append(index);
location.append('/').append(type);
location.append('/').append(id);
if (routing != null) {
location.append(routingStart).append(routing);
}
return location.toString();
}
@Override
public void readFrom(StreamInput in) throws IOException {

View File

@ -21,7 +21,8 @@ package org.elasticsearch.common.xcontent;
import org.elasticsearch.rest.RestStatus;
/**
*
* Objects that can both render themselves in as json/yaml/etc and can provide a {@link RestStatus} for their response. Usually should be
* implemented by top level responses sent back to users from REST endpoints.
*/
public interface StatusToXContent extends ToXContent {

View File

@ -90,7 +90,8 @@ public class RestIndexAction extends BaseRestHandler {
} catch (IllegalArgumentException eia){
try {
XContentBuilder builder = channel.newErrorBuilder();
channel.sendResponse(new BytesRestResponse(BAD_REQUEST, builder.startObject().field("error", eia.getMessage()).endObject()));
channel.sendResponse(
new BytesRestResponse(BAD_REQUEST, builder.startObject().field("error", eia.getMessage()).endObject()));
} catch (IOException e1) {
logger.warn("Failed to send response", e1);
return;
@ -101,6 +102,6 @@ public class RestIndexAction extends BaseRestHandler {
if (consistencyLevel != null) {
indexRequest.consistencyLevel(WriteConsistencyLevel.fromString(consistencyLevel));
}
client.index(indexRequest, new RestStatusToXContentListener<>(channel));
client.index(indexRequest, new RestStatusToXContentListener<>(channel, r -> r.getLocation(indexRequest.routing())));
}
}

View File

@ -23,14 +23,30 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestResponse;
import org.elasticsearch.rest.RestStatus;
import java.util.function.Function;
/**
*
* Content listener that extracts that {@link RestStatus} from the response.
*/
public class RestStatusToXContentListener<Response extends StatusToXContent> extends RestResponseListener<Response> {
private final Function<Response, String> extractLocation;
/**
* Build an instance that doesn't support responses with the status {@code 201 CREATED}.
*/
public RestStatusToXContentListener(RestChannel channel) {
// TODO switch this to throwing an exception?
this(channel, r -> null);
}
/**
* Build an instance that does support responses with the status {@code 201 CREATED}.
*/
public RestStatusToXContentListener(RestChannel channel, Function<Response, String> extractLocation) {
super(channel);
this.extractLocation = extractLocation;
}
@Override
@ -42,7 +58,13 @@ public class RestStatusToXContentListener<Response extends StatusToXContent> ext
builder.startObject();
response.toXContent(builder, channel.request());
builder.endObject();
return new BytesRestResponse(response.status(), builder);
BytesRestResponse restResponse = new BytesRestResponse(response.status(), builder);
if (RestStatus.CREATED == restResponse.status()) {
String location = extractLocation.apply(response);
if (location != null) {
restResponse.addHeader("Location", location);
}
}
return restResponse;
}
}

View File

@ -97,6 +97,6 @@ public class RestUpdateAction extends BaseRestHandler {
}
}
client.update(updateRequest, new RestStatusToXContentListener<>(channel));
client.update(updateRequest, new RestStatusToXContentListener<>(channel, r -> r.getLocation(updateRequest.routing())));
}
}

View File

@ -0,0 +1,33 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.test.ESTestCase;
public class DocWriteResponseTests extends ESTestCase {
public void testGetLocation() {
DocWriteResponse response = new DocWriteResponse(new ShardId("index", "uuid", 0), "type", "id", 0) {
// DocWriteResponse is abstract so we have to sneak a subclass in here to test it.
};
assertEquals("/index/type/id", response.getLocation(null));
assertEquals("/index/type/id?routing=test_routing", response.getLocation("test_routing"));
}
}

View File

@ -25,7 +25,7 @@ import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
/** Rest integration test. Runs against a cluster started by {@code gradle integTest} */
public class RestIT extends ESRestTestCase {
public class RestIT extends ESClientYamlSuiteTestCase {
public RestIT(RestTestCandidate testCandidate) {
super(testCandidate);
}

View File

@ -0,0 +1,65 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.test.rest;
import org.apache.http.entity.StringEntity;
import org.elasticsearch.client.Response;
import java.io.IOException;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.startsWith;
/**
* Tests for the "Location" header returned when returning {@code 201 CREATED}.
*/
public class CreatedLocationHeaderIT extends ESRestTestCase {
public void testCreate() throws IOException {
locationTestCase("PUT", "test/test/1");
}
public void testIndexWithId() throws IOException {
locationTestCase("PUT", "test/test/1");
}
public void testIndexWithoutId() throws IOException {
locationTestCase("POST", "test/test");
}
public void testUpsert() throws IOException {
locationTestCase(client().performRequest("POST", "test/test/1/_update", emptyMap(), new StringEntity("{"
+ "\"doc\": {\"test\": \"test\"},"
+ "\"doc_as_upsert\": true}")));
}
private void locationTestCase(String method, String url) throws IOException {
locationTestCase(client().performRequest(method, url, emptyMap(), new StringEntity("{\"test\": \"test\"}")));
locationTestCase(client().performRequest(method, url + "?routing=cat", emptyMap(), new StringEntity("{\"test\": \"test\"}")));
}
private void locationTestCase(Response response) throws IOException {
assertEquals(201, response.getStatusLine().getStatusCode());
String location = response.getHeader("Location");
assertThat(location, startsWith("/test/test/"));
Response getResponse = client().performRequest("GET", location);
assertEquals(singletonMap("test", "test"), entityAsMap(getResponse).get("_source"));
}
}

View File

@ -25,7 +25,7 @@ import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
/** Rest integration test. Runs against a cluster started by {@code gradle integTest} */
public class RestIT extends ESRestTestCase {
public class RestIT extends ESClientYamlSuiteTestCase {
public RestIT(RestTestCandidate testCandidate) {
super(testCandidate);
}

View File

@ -25,7 +25,7 @@ import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
/** Rest integration test. Runs against a cluster started by {@code gradle integTest} */
public class RestIT extends ESRestTestCase {
public class RestIT extends ESClientYamlSuiteTestCase {
public RestIT(RestTestCandidate testCandidate) {
super(testCandidate);
}

View File

@ -25,7 +25,7 @@ import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
/** Rest integration test. Runs against a cluster started by {@code gradle integTest} */
public class RestIT extends ESRestTestCase {
public class RestIT extends ESClientYamlSuiteTestCase {
public RestIT(RestTestCandidate testCandidate) {
super(testCandidate);
}

View File

@ -25,7 +25,7 @@ import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
/** Rest integration test. Runs against a cluster started by {@code gradle integTest} */
public class RestIT extends ESRestTestCase {
public class RestIT extends ESClientYamlSuiteTestCase {
public RestIT(RestTestCandidate testCandidate) {
super(testCandidate);
}

View File

@ -22,14 +22,14 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
import java.util.List;
public class SmokeTestDocsIT extends ESRestTestCase {
public class SmokeTestDocsIT extends ESClientYamlSuiteTestCase {
public SmokeTestDocsIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -37,7 +37,7 @@ public class SmokeTestDocsIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
@Override

View File

@ -20,7 +20,7 @@ package org.elasticsearch.search.aggregations.matrix;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
@ -29,13 +29,13 @@ import java.io.IOException;
/**
*
*/
public class MatrixAggregationRestIT extends ESRestTestCase {
public class MatrixAggregationRestIT extends ESClientYamlSuiteTestCase {
public MatrixAggregationRestIT(@Name("yaml")RestTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.ingest.common;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class IngestCommonRestIT extends ESRestTestCase {
public class IngestCommonRestIT extends ESClientYamlSuiteTestCase {
public IngestCommonRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class IngestCommonRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.script.expression;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class ExpressionRestIT extends ESRestTestCase {
public class ExpressionRestIT extends ESClientYamlSuiteTestCase {
public ExpressionRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class ExpressionRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.script.groovy;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class GroovyRestIT extends ESRestTestCase {
public class GroovyRestIT extends ESClientYamlSuiteTestCase {
public GroovyRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class GroovyRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.script.mustache;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class MustacheRestIT extends ESRestTestCase {
public class MustacheRestIT extends ESClientYamlSuiteTestCase {
public MustacheRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class MustacheRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,14 +21,14 @@ package org.elasticsearch.painless;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
/** Runs yaml rest tests */
public class PainlessRestIT extends ESRestTestCase {
public class PainlessRestIT extends ESClientYamlSuiteTestCase {
public PainlessRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -36,7 +36,7 @@ public class PainlessRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,19 +21,19 @@ package org.elasticsearch.percolator;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class PercolatorRestIT extends ESRestTestCase {
public class PercolatorRestIT extends ESClientYamlSuiteTestCase {
public PercolatorRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -22,19 +22,19 @@ package org.elasticsearch.index.reindex;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class ReindexRestIT extends ESRestTestCase {
public class ReindexRestIT extends ESClientYamlSuiteTestCase {
public ReindexRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,14 @@ package org.elasticsearch.http.netty3;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class Netty3RestIT extends ESRestTestCase {
public class Netty3RestIT extends ESClientYamlSuiteTestCase {
public Netty3RestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,6 +36,6 @@ public class Netty3RestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,14 @@ package org.elasticsearch.http.netty4;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class Netty4RestIT extends ESRestTestCase {
public class Netty4RestIT extends ESClientYamlSuiteTestCase {
public Netty4RestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +36,7 @@ public class Netty4RestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.index.analysis;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class AnalysisICURestIT extends ESRestTestCase {
public class AnalysisICURestIT extends ESClientYamlSuiteTestCase {
public AnalysisICURestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class AnalysisICURestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.index.analysis;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class AnalysisKuromojiRestIT extends ESRestTestCase {
public class AnalysisKuromojiRestIT extends ESClientYamlSuiteTestCase {
public AnalysisKuromojiRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class AnalysisKuromojiRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.index.analysis;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class AnalysisPhoneticRestIT extends ESRestTestCase {
public class AnalysisPhoneticRestIT extends ESClientYamlSuiteTestCase {
public AnalysisPhoneticRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class AnalysisPhoneticRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.index.analysis;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class AnalysisSmartChineseRestIT extends ESRestTestCase {
public class AnalysisSmartChineseRestIT extends ESClientYamlSuiteTestCase {
public AnalysisSmartChineseRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class AnalysisSmartChineseRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.index.analysis;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class AnalysisPolishRestIT extends ESRestTestCase {
public class AnalysisPolishRestIT extends ESClientYamlSuiteTestCase {
public AnalysisPolishRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class AnalysisPolishRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.discovery.azure.classic;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class AzureDiscoveryRestIT extends ESRestTestCase {
public class AzureDiscoveryRestIT extends ESClientYamlSuiteTestCase {
public AzureDiscoveryRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class AzureDiscoveryRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.cloud.aws;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class DiscoveryEc2RestIT extends ESRestTestCase {
public class DiscoveryEc2RestIT extends ESClientYamlSuiteTestCase {
public DiscoveryEc2RestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class DiscoveryEc2RestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.discovery.gce;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class DiscoveryGCERestIT extends ESRestTestCase {
public class DiscoveryGCERestIT extends ESClientYamlSuiteTestCase {
public DiscoveryGCERestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class DiscoveryGCERestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.ingest.attachment;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class IngestAttachmentRestIT extends ESRestTestCase {
public class IngestAttachmentRestIT extends ESClientYamlSuiteTestCase {
public IngestAttachmentRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class IngestAttachmentRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -22,14 +22,14 @@ package org.elasticsearch.ingest.geoip;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
import java.util.Collection;
public class IngestGeoIpRestIT extends ESRestTestCase {
public class IngestGeoIpRestIT extends ESClientYamlSuiteTestCase {
public IngestGeoIpRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -37,7 +37,7 @@ public class IngestGeoIpRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.ingest.useragent;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class UserAgentRestIT extends ESRestTestCase {
public class UserAgentRestIT extends ESClientYamlSuiteTestCase {
public UserAgentRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,6 +35,6 @@ public class UserAgentRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.plugin.example;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class JvmExampleRestIT extends ESRestTestCase {
public class JvmExampleRestIT extends ESClientYamlSuiteTestCase {
public JvmExampleRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class JvmExampleRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.script.javascript;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class LangJavaScriptRestIT extends ESRestTestCase {
public class LangJavaScriptRestIT extends ESClientYamlSuiteTestCase {
public LangJavaScriptRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class LangJavaScriptRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.script.python;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class LangPythonScriptRestIT extends ESRestTestCase {
public class LangPythonScriptRestIT extends ESClientYamlSuiteTestCase {
public LangPythonScriptRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class LangPythonScriptRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.mapper.attachments;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class MapperAttachmentsRestIT extends ESRestTestCase {
public class MapperAttachmentsRestIT extends ESClientYamlSuiteTestCase {
public MapperAttachmentsRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);

View File

@ -21,13 +21,13 @@ package org.elasticsearch.index.mapper.murmur3;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class MapperMurmur3RestIT extends ESRestTestCase {
public class MapperMurmur3RestIT extends ESClientYamlSuiteTestCase {
public MapperMurmur3RestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);

View File

@ -21,13 +21,13 @@ package org.elasticsearch.index.mapper.size;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class MapperSizeRestIT extends ESRestTestCase {
public class MapperSizeRestIT extends ESClientYamlSuiteTestCase {
public MapperSizeRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);

View File

@ -21,13 +21,13 @@ package org.elasticsearch.repositories.azure;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class AzureRepositoryRestIT extends ESRestTestCase {
public class AzureRepositoryRestIT extends ESClientYamlSuiteTestCase {
public AzureRepositoryRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class AzureRepositoryRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.repositories.gcs;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class GoogleCloudStorageRepositoryRestIT extends ESRestTestCase {
public class GoogleCloudStorageRepositoryRestIT extends ESClientYamlSuiteTestCase {
public GoogleCloudStorageRepositoryRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);

View File

@ -22,11 +22,11 @@ import java.io.IOException;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
public class HdfsRepositoryRestIT extends ESRestTestCase {
public class HdfsRepositoryRestIT extends ESClientYamlSuiteTestCase {
public HdfsRepositoryRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -34,6 +34,6 @@ public class HdfsRepositoryRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.repositories.s3;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class RepositoryS3RestIT extends ESRestTestCase {
public class RepositoryS3RestIT extends ESClientYamlSuiteTestCase {
public RepositoryS3RestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class RepositoryS3RestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.index.store;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class SMBStoreRestIT extends ESRestTestCase {
public class SMBStoreRestIT extends ESClientYamlSuiteTestCase {
public SMBStoreRestIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class SMBStoreRestIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -22,14 +22,14 @@ package org.elasticsearch.backwards;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite;
import org.apache.lucene.util.TimeUnits;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
@TimeoutSuite(millis = 40 * TimeUnits.MINUTE) // some of the windows test VMs are slow as hell
public class MultiNodeBackwardsIT extends ESRestTestCase {
public class MultiNodeBackwardsIT extends ESClientYamlSuiteTestCase {
public MultiNodeBackwardsIT(RestTestCandidate testCandidate) {
super(testCandidate);

View File

@ -21,13 +21,13 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class IngestDisabledIT extends ESRestTestCase {
public class IngestDisabledIT extends ESClientYamlSuiteTestCase {
public IngestDisabledIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class IngestDisabledIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class IngestWithDependenciesIT extends ESRestTestCase {
public class IngestWithDependenciesIT extends ESClientYamlSuiteTestCase {
public IngestWithDependenciesIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class IngestWithDependenciesIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class SmokeTestMultiIT extends ESRestTestCase {
public class SmokeTestMultiIT extends ESClientYamlSuiteTestCase {
public SmokeTestMultiIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class SmokeTestMultiIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,13 +21,13 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class SmokeTestPluginsIT extends ESRestTestCase {
public class SmokeTestPluginsIT extends ESClientYamlSuiteTestCase {
public SmokeTestPluginsIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
@ -35,7 +35,7 @@ public class SmokeTestPluginsIT extends ESRestTestCase {
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -21,19 +21,19 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import java.io.IOException;
public class SmokeTestReindexWithPainlessIT extends ESRestTestCase {
public class SmokeTestReindexWithPainlessIT extends ESClientYamlSuiteTestCase {
public SmokeTestReindexWithPainlessIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
return ESClientYamlSuiteTestCase.createParameters(0, 1);
}
}

View File

@ -24,7 +24,7 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.ESClientYamlSuiteTestCase;
import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
@ -37,9 +37,9 @@ import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_ITERATIONS;
import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_PREFIX;
import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_TESTMETHOD;
import static org.elasticsearch.test.ESIntegTestCase.TESTS_CLUSTER;
import static org.elasticsearch.test.rest.ESRestTestCase.REST_TESTS_BLACKLIST;
import static org.elasticsearch.test.rest.ESRestTestCase.REST_TESTS_SPEC;
import static org.elasticsearch.test.rest.ESRestTestCase.REST_TESTS_SUITE;
import static org.elasticsearch.test.rest.ESClientYamlSuiteTestCase.REST_TESTS_BLACKLIST;
import static org.elasticsearch.test.rest.ESClientYamlSuiteTestCase.REST_TESTS_SPEC;
import static org.elasticsearch.test.rest.ESClientYamlSuiteTestCase.REST_TESTS_SUITE;
/**
* A {@link RunListener} that emits a command you can use to re-run a failing test with the failing random seed to
@ -81,9 +81,9 @@ public class ReproduceInfoPrinter extends RunListener {
GradleMessageBuilder gradleMessageBuilder = new GradleMessageBuilder(b);
gradleMessageBuilder.appendAllOpts(failure.getDescription());
//Rest tests are a special case as they allow for additional parameters
if (ESRestTestCase.class.isAssignableFrom(failure.getDescription().getTestClass())) {
gradleMessageBuilder.appendRestTestsProperties();
// Client yaml suite tests are a special case as they allow for additional parameters
if (ESClientYamlSuiteTestCase.class.isAssignableFrom(failure.getDescription().getTestClass())) {
gradleMessageBuilder.appendClientYamlSuiteProperties();
}
System.err.println(b.toString());
@ -152,7 +152,7 @@ public class ReproduceInfoPrinter extends RunListener {
return this;
}
public ReproduceErrorMessageBuilder appendRestTestsProperties() {
public ReproduceErrorMessageBuilder appendClientYamlSuiteProperties() {
return appendProperties(REST_TESTS_SUITE, REST_TESTS_SPEC, REST_TESTS_BLACKLIST);
}

View File

@ -0,0 +1,319 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.test.rest;
import com.carrotsearch.randomizedtesting.RandomizedTest;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import org.elasticsearch.test.rest.parser.RestTestSuiteParser;
import org.elasticsearch.test.rest.section.DoSection;
import org.elasticsearch.test.rest.section.ExecutableSection;
import org.elasticsearch.test.rest.section.RestTestSuite;
import org.elasticsearch.test.rest.section.SkipSection;
import org.elasticsearch.test.rest.section.TestSection;
import org.elasticsearch.test.rest.spec.RestApi;
import org.elasticsearch.test.rest.spec.RestSpec;
import org.elasticsearch.test.rest.support.FileUtils;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Runs a suite of yaml tests shared with all the official Elasticsearch clients against against an elasticsearch cluster.
*/
public abstract class ESClientYamlSuiteTestCase extends ESRestTestCase {
/**
* Property that allows to control which REST tests get run. Supports comma separated list of tests
* or directories that contain tests e.g. -Dtests.rest.suite=index,get,create/10_with_id
*/
public static final String REST_TESTS_SUITE = "tests.rest.suite";
/**
* Property that allows to blacklist some of the REST tests based on a comma separated list of globs
* e.g. -Dtests.rest.blacklist=get/10_basic/*
*/
public static final String REST_TESTS_BLACKLIST = "tests.rest.blacklist";
/**
* Property that allows to control whether spec validation is enabled or not (default true).
*/
public static final String REST_TESTS_VALIDATE_SPEC = "tests.rest.validate_spec";
/**
* Property that allows to control where the REST spec files need to be loaded from
*/
public static final String REST_TESTS_SPEC = "tests.rest.spec";
public static final String REST_LOAD_PACKAGED_TESTS = "tests.rest.load_packaged";
private static final String DEFAULT_TESTS_PATH = "/rest-api-spec/test";
private static final String DEFAULT_SPEC_PATH = "/rest-api-spec/api";
/**
* This separator pattern matches ',' except it is preceded by a '\'.
* This allows us to support ',' within paths when it is escaped with a slash.
*
* For example, the path string "/a/b/c\,d/e/f,/foo/bar,/baz" is separated to "/a/b/c\,d/e/f", "/foo/bar" and "/baz".
*
* For reference, this regular expression feature is known as zero-width negative look-behind.
*
*/
private static final String PATHS_SEPARATOR = "(?<!\\\\),";
private final List<BlacklistedPathPatternMatcher> blacklistPathMatchers = new ArrayList<>();
private static RestTestExecutionContext restTestExecutionContext;
private static RestTestExecutionContext adminExecutionContext;
private final RestTestCandidate testCandidate;
public ESClientYamlSuiteTestCase(RestTestCandidate testCandidate) {
this.testCandidate = testCandidate;
String[] blacklist = resolvePathsProperty(REST_TESTS_BLACKLIST, null);
for (String entry : blacklist) {
this.blacklistPathMatchers.add(new BlacklistedPathPatternMatcher(entry));
}
}
@Override
protected void afterIfFailed(List<Throwable> errors) {
logger.info("Stash dump on failure [{}]", XContentHelper.toString(restTestExecutionContext.stash()));
super.afterIfFailed(errors);
}
public static Iterable<Object[]> createParameters(int id, int count) throws IOException, RestTestParseException {
//parse tests only if rest test group is enabled, otherwise rest tests might not even be available on file system
List<RestTestCandidate> restTestCandidates = collectTestCandidates(id, count);
List<Object[]> objects = new ArrayList<>();
for (RestTestCandidate restTestCandidate : restTestCandidates) {
objects.add(new Object[]{restTestCandidate});
}
return objects;
}
private static List<RestTestCandidate> collectTestCandidates(int id, int count) throws RestTestParseException, IOException {
List<RestTestCandidate> testCandidates = new ArrayList<>();
FileSystem fileSystem = getFileSystem();
// don't make a try-with, getFileSystem returns null
// ... and you can't close() the default filesystem
try {
String[] paths = resolvePathsProperty(REST_TESTS_SUITE, DEFAULT_TESTS_PATH);
Map<String, Set<Path>> yamlSuites = FileUtils.findYamlSuites(fileSystem, DEFAULT_TESTS_PATH, paths);
RestTestSuiteParser restTestSuiteParser = new RestTestSuiteParser();
//yaml suites are grouped by directory (effectively by api)
for (String api : yamlSuites.keySet()) {
List<Path> yamlFiles = new ArrayList<>(yamlSuites.get(api));
for (Path yamlFile : yamlFiles) {
String key = api + yamlFile.getFileName().toString();
if (mustExecute(key, id, count)) {
RestTestSuite restTestSuite = restTestSuiteParser.parse(api, yamlFile);
for (TestSection testSection : restTestSuite.getTestSections()) {
testCandidates.add(new RestTestCandidate(restTestSuite, testSection));
}
}
}
}
} finally {
IOUtils.close(fileSystem);
}
//sort the candidates so they will always be in the same order before being shuffled, for repeatability
Collections.sort(testCandidates, new Comparator<RestTestCandidate>() {
@Override
public int compare(RestTestCandidate o1, RestTestCandidate o2) {
return o1.getTestPath().compareTo(o2.getTestPath());
}
});
return testCandidates;
}
private static boolean mustExecute(String test, int id, int count) {
int hash = (int) (Math.abs((long)test.hashCode()) % count);
return hash == id;
}
private static String[] resolvePathsProperty(String propertyName, String defaultValue) {
String property = System.getProperty(propertyName);
if (!Strings.hasLength(property)) {
return defaultValue == null ? Strings.EMPTY_ARRAY : new String[]{defaultValue};
} else {
return property.split(PATHS_SEPARATOR);
}
}
/**
* Returns a new FileSystem to read REST resources, or null if they
* are available from classpath.
*/
@SuppressForbidden(reason = "proper use of URL, hack around a JDK bug")
static FileSystem getFileSystem() throws IOException {
// REST suite handling is currently complicated, with lots of filtering and so on
// For now, to work embedded in a jar, return a ZipFileSystem over the jar contents.
URL codeLocation = FileUtils.class.getProtectionDomain().getCodeSource().getLocation();
boolean loadPackaged = RandomizedTest.systemPropertyAsBoolean(REST_LOAD_PACKAGED_TESTS, true);
if (codeLocation.getFile().endsWith(".jar") && loadPackaged) {
try {
// hack around a bug in the zipfilesystem implementation before java 9,
// its checkWritable was incorrect and it won't work without write permissions.
// if we add the permission, it will open jars r/w, which is too scary! so copy to a safe r-w location.
Path tmp = Files.createTempFile(null, ".jar");
try (InputStream in = codeLocation.openStream()) {
Files.copy(in, tmp, StandardCopyOption.REPLACE_EXISTING);
}
return FileSystems.newFileSystem(new URI("jar:" + tmp.toUri()), Collections.<String,Object>emptyMap());
} catch (URISyntaxException e) {
throw new IOException("couldn't open zipfilesystem: ", e);
}
} else {
return null;
}
}
@BeforeClass
public static void initExecutionContext() throws IOException {
String[] specPaths = resolvePathsProperty(REST_TESTS_SPEC, DEFAULT_SPEC_PATH);
RestSpec restSpec = null;
FileSystem fileSystem = getFileSystem();
// don't make a try-with, getFileSystem returns null
// ... and you can't close() the default filesystem
try {
restSpec = RestSpec.parseFrom(fileSystem, DEFAULT_SPEC_PATH, specPaths);
} finally {
IOUtils.close(fileSystem);
}
validateSpec(restSpec);
restTestExecutionContext = new RestTestExecutionContext(restSpec);
adminExecutionContext = new RestTestExecutionContext(restSpec);
}
protected RestTestExecutionContext getAdminExecutionContext() {
return adminExecutionContext;
}
private static void validateSpec(RestSpec restSpec) {
boolean validateSpec = RandomizedTest.systemPropertyAsBoolean(REST_TESTS_VALIDATE_SPEC, true);
if (validateSpec) {
StringBuilder errorMessage = new StringBuilder();
for (RestApi restApi : restSpec.getApis()) {
if (restApi.getMethods().contains("GET") && restApi.isBodySupported()) {
if (!restApi.getMethods().contains("POST")) {
errorMessage.append("\n- ").append(restApi.getName()).append(" supports GET with a body but doesn't support POST");
}
}
}
if (errorMessage.length() > 0) {
throw new IllegalArgumentException(errorMessage.toString());
}
}
}
@AfterClass
public static void clearStatic() {
restTestExecutionContext = null;
adminExecutionContext = null;
}
@Before
public void reset() throws IOException {
// admin context must be available for @After always, regardless of whether the test was blacklisted
adminExecutionContext.initClient(adminClient(), getClusterHosts());
adminExecutionContext.clear();
//skip test if it matches one of the blacklist globs
for (BlacklistedPathPatternMatcher blacklistedPathMatcher : blacklistPathMatchers) {
String testPath = testCandidate.getSuitePath() + "/" + testCandidate.getTestSection().getName();
assumeFalse("[" + testCandidate.getTestPath() + "] skipped, reason: blacklisted", blacklistedPathMatcher
.isSuffixMatch(testPath));
}
//The client needs non static info to get initialized, therefore it can't be initialized in the before class
restTestExecutionContext.initClient(client(), getClusterHosts());
restTestExecutionContext.clear();
//skip test if the whole suite (yaml file) is disabled
assumeFalse(buildSkipMessage(testCandidate.getSuitePath(), testCandidate.getSetupSection().getSkipSection()),
testCandidate.getSetupSection().getSkipSection().skip(restTestExecutionContext.esVersion()));
//skip test if the whole suite (yaml file) is disabled
assumeFalse(buildSkipMessage(testCandidate.getSuitePath(), testCandidate.getTeardownSection().getSkipSection()),
testCandidate.getTeardownSection().getSkipSection().skip(restTestExecutionContext.esVersion()));
//skip test if test section is disabled
assumeFalse(buildSkipMessage(testCandidate.getTestPath(), testCandidate.getTestSection().getSkipSection()),
testCandidate.getTestSection().getSkipSection().skip(restTestExecutionContext.esVersion()));
}
private static String buildSkipMessage(String description, SkipSection skipSection) {
StringBuilder messageBuilder = new StringBuilder();
if (skipSection.isVersionCheck()) {
messageBuilder.append("[").append(description).append("] skipped, reason: [").append(skipSection.getReason()).append("] ");
} else {
messageBuilder.append("[").append(description).append("] skipped, reason: features ")
.append(skipSection.getFeatures()).append(" not supported");
}
return messageBuilder.toString();
}
public void test() throws IOException {
//let's check that there is something to run, otherwise there might be a problem with the test section
if (testCandidate.getTestSection().getExecutableSections().size() == 0) {
throw new IllegalArgumentException("No executable sections loaded for [" + testCandidate.getTestPath() + "]");
}
if (!testCandidate.getSetupSection().isEmpty()) {
logger.debug("start setup test [{}]", testCandidate.getTestPath());
for (DoSection doSection : testCandidate.getSetupSection().getDoSections()) {
doSection.execute(restTestExecutionContext);
}
logger.debug("end setup test [{}]", testCandidate.getTestPath());
}
restTestExecutionContext.clear();
try {
for (ExecutableSection executableSection : testCandidate.getTestSection().getExecutableSections()) {
executableSection.execute(restTestExecutionContext);
}
} finally {
logger.debug("start teardown test [{}]", testCandidate.getTestPath());
for (DoSection doSection : testCandidate.getTeardownSection().getDoSections()) {
doSection.execute(restTestExecutionContext);
}
logger.debug("end teardown test [{}]", testCandidate.getTestPath());
}
}
}

View File

@ -19,289 +19,149 @@
package org.elasticsearch.test.rest;
import com.carrotsearch.randomizedtesting.RandomizedTest;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.message.BasicHeader;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.http.ssl.SSLContexts;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksAction;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.rest.client.RestTestResponse;
import org.elasticsearch.test.rest.client.RestTestResponseException;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import org.elasticsearch.test.rest.parser.RestTestSuiteParser;
import org.elasticsearch.test.rest.section.DoSection;
import org.elasticsearch.test.rest.section.ExecutableSection;
import org.elasticsearch.test.rest.section.RestTestSuite;
import org.elasticsearch.test.rest.section.SkipSection;
import org.elasticsearch.test.rest.section.TestSection;
import org.elasticsearch.test.rest.spec.RestApi;
import org.elasticsearch.test.rest.spec.RestSpec;
import org.elasticsearch.test.rest.support.FileUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import javax.net.ssl.SSLContext;
import static java.util.Collections.sort;
import static java.util.Collections.unmodifiableList;
/**
* Runs the clients test suite against an elasticsearch cluster.
* Superclass for tests that interact with an external test cluster using Elasticsearch's {@link RestClient}.
*/
public abstract class ESRestTestCase extends ESTestCase {
public class ESRestTestCase extends ESTestCase {
public static final String TRUSTSTORE_PATH = "truststore.path";
public static final String TRUSTSTORE_PASSWORD = "truststore.password";
/**
* Property that allows to control which REST tests get run. Supports comma separated list of tests
* or directories that contain tests e.g. -Dtests.rest.suite=index,get,create/10_with_id
* Convert the entity from a {@link Response} into a map of maps.
*/
public static final String REST_TESTS_SUITE = "tests.rest.suite";
/**
* Property that allows to blacklist some of the REST tests based on a comma separated list of globs
* e.g. -Dtests.rest.blacklist=get/10_basic/*
*/
public static final String REST_TESTS_BLACKLIST = "tests.rest.blacklist";
/**
* Property that allows to control whether spec validation is enabled or not (default true).
*/
public static final String REST_TESTS_VALIDATE_SPEC = "tests.rest.validate_spec";
/**
* Property that allows to control where the REST spec files need to be loaded from
*/
public static final String REST_TESTS_SPEC = "tests.rest.spec";
public static final String REST_LOAD_PACKAGED_TESTS = "tests.rest.load_packaged";
private static final String DEFAULT_TESTS_PATH = "/rest-api-spec/test";
private static final String DEFAULT_SPEC_PATH = "/rest-api-spec/api";
/**
* This separator pattern matches ',' except it is preceded by a '\'.
* This allows us to support ',' within paths when it is escaped with a slash.
*
* For example, the path string "/a/b/c\,d/e/f,/foo/bar,/baz" is separated to "/a/b/c\,d/e/f", "/foo/bar" and "/baz".
*
* For reference, this regular expression feature is known as zero-width negative look-behind.
*
*/
private static final String PATHS_SEPARATOR = "(?<!\\\\),";
private final List<BlacklistedPathPatternMatcher> blacklistPathMatchers = new ArrayList<>();
private final URL[] clusterUrls;
private static RestTestExecutionContext restTestExecutionContext;
private static RestTestExecutionContext adminExecutionContext;
private final RestTestCandidate testCandidate;
public ESRestTestCase(RestTestCandidate testCandidate) {
this.testCandidate = testCandidate;
String[] blacklist = resolvePathsProperty(REST_TESTS_BLACKLIST, null);
for (String entry : blacklist) {
this.blacklistPathMatchers.add(new BlacklistedPathPatternMatcher(entry));
public static Map<String, Object> entityAsMap(Response response) throws IOException {
XContentType xContentType = XContentType.fromMediaTypeOrFormat(response.getEntity().getContentType().getValue());
try (XContentParser parser = xContentType.xContent().createParser(response.getEntity().getContent())) {
return parser.map();
}
}
private final List<HttpHost> clusterHosts;
/**
* A client for the running Elasticsearch cluster. Lazily initialized on first use.
*/
private final RestClient client;
/**
* A client for the running Elasticsearch cluster configured to take test administrative actions like remove all indexes after the test
* completes. Lazily initialized on first use.
*/
private final RestClient adminClient;
public ESRestTestCase() {
String cluster = System.getProperty("tests.rest.cluster");
if (cluster == null) {
throw new RuntimeException("Must specify tests.rest.cluster for rest tests");
throw new RuntimeException("Must specify [tests.rest.cluster] system property with a comma delimited list of [host:port] "
+ "to which to send REST requests");
}
String[] stringUrls = cluster.split(",");
clusterUrls = new URL[stringUrls.length];
int i = 0;
try {
for (String stringUrl : stringUrls) {
clusterUrls[i++] = new URL("http://" + stringUrl);
List<HttpHost> clusterHosts = new ArrayList<>(stringUrls.length);
for (String stringUrl : stringUrls) {
int portSeparator = stringUrl.lastIndexOf(':');
if (portSeparator < 0) {
throw new IllegalArgumentException("Illegal cluster url [" + stringUrl + "]");
}
String host = stringUrl.substring(0, portSeparator);
int port = Integer.valueOf(stringUrl.substring(portSeparator + 1));
clusterHosts.add(new HttpHost(host, port, getProtocol()));
}
this.clusterHosts = unmodifiableList(clusterHosts);
try {
client = buildClient(restClientSettings());
adminClient = buildClient(restAdminSettings());
} catch (IOException e) {
throw new RuntimeException("Failed to parse cluster addresses for rest test", e);
}
}
@Override
protected void afterIfFailed(List<Throwable> errors) {
logger.info("Stash dump on failure [{}]", XContentHelper.toString(restTestExecutionContext.stash()));
super.afterIfFailed(errors);
}
public static Iterable<Object[]> createParameters(int id, int count) throws IOException, RestTestParseException {
//parse tests only if rest test group is enabled, otherwise rest tests might not even be available on file system
List<RestTestCandidate> restTestCandidates = collectTestCandidates(id, count);
List<Object[]> objects = new ArrayList<>();
for (RestTestCandidate restTestCandidate : restTestCandidates) {
objects.add(new Object[]{restTestCandidate});
}
return objects;
}
private static List<RestTestCandidate> collectTestCandidates(int id, int count) throws RestTestParseException, IOException {
List<RestTestCandidate> testCandidates = new ArrayList<>();
FileSystem fileSystem = getFileSystem();
// don't make a try-with, getFileSystem returns null
// ... and you can't close() the default filesystem
try {
String[] paths = resolvePathsProperty(REST_TESTS_SUITE, DEFAULT_TESTS_PATH);
Map<String, Set<Path>> yamlSuites = FileUtils.findYamlSuites(fileSystem, DEFAULT_TESTS_PATH, paths);
RestTestSuiteParser restTestSuiteParser = new RestTestSuiteParser();
//yaml suites are grouped by directory (effectively by api)
for (String api : yamlSuites.keySet()) {
List<Path> yamlFiles = new ArrayList<>(yamlSuites.get(api));
for (Path yamlFile : yamlFiles) {
String key = api + yamlFile.getFileName().toString();
if (mustExecute(key, id, count)) {
RestTestSuite restTestSuite = restTestSuiteParser.parse(api, yamlFile);
for (TestSection testSection : restTestSuite.getTestSections()) {
testCandidates.add(new RestTestCandidate(restTestSuite, testSection));
}
}
}
}
} finally {
IOUtils.close(fileSystem);
}
//sort the candidates so they will always be in the same order before being shuffled, for repeatability
Collections.sort(testCandidates, new Comparator<RestTestCandidate>() {
@Override
public int compare(RestTestCandidate o1, RestTestCandidate o2) {
return o1.getTestPath().compareTo(o2.getTestPath());
}
});
return testCandidates;
}
private static boolean mustExecute(String test, int id, int count) {
int hash = (int) (Math.abs((long)test.hashCode()) % count);
return hash == id;
}
private static String[] resolvePathsProperty(String propertyName, String defaultValue) {
String property = System.getProperty(propertyName);
if (!Strings.hasLength(property)) {
return defaultValue == null ? Strings.EMPTY_ARRAY : new String[]{defaultValue};
} else {
return property.split(PATHS_SEPARATOR);
// Wrap the IOException so children don't have to declare a constructor just to rethrow it.
throw new RuntimeException("Error building clients", e);
}
}
/**
* Returns a new FileSystem to read REST resources, or null if they
* are available from classpath.
* Clean up after the test case.
*/
@SuppressForbidden(reason = "proper use of URL, hack around a JDK bug")
static FileSystem getFileSystem() throws IOException {
// REST suite handling is currently complicated, with lots of filtering and so on
// For now, to work embedded in a jar, return a ZipFileSystem over the jar contents.
URL codeLocation = FileUtils.class.getProtectionDomain().getCodeSource().getLocation();
boolean loadPackaged = RandomizedTest.systemPropertyAsBoolean(REST_LOAD_PACKAGED_TESTS, true);
if (codeLocation.getFile().endsWith(".jar") && loadPackaged) {
try {
// hack around a bug in the zipfilesystem implementation before java 9,
// its checkWritable was incorrect and it won't work without write permissions.
// if we add the permission, it will open jars r/w, which is too scary! so copy to a safe r-w location.
Path tmp = Files.createTempFile(null, ".jar");
try (InputStream in = codeLocation.openStream()) {
Files.copy(in, tmp, StandardCopyOption.REPLACE_EXISTING);
}
return FileSystems.newFileSystem(new URI("jar:" + tmp.toUri()), Collections.<String,Object>emptyMap());
} catch (URISyntaxException e) {
throw new IOException("couldn't open zipfilesystem: ", e);
}
} else {
return null;
}
}
@BeforeClass
public static void initExecutionContext() throws IOException {
String[] specPaths = resolvePathsProperty(REST_TESTS_SPEC, DEFAULT_SPEC_PATH);
RestSpec restSpec = null;
FileSystem fileSystem = getFileSystem();
// don't make a try-with, getFileSystem returns null
// ... and you can't close() the default filesystem
try {
restSpec = RestSpec.parseFrom(fileSystem, DEFAULT_SPEC_PATH, specPaths);
} finally {
IOUtils.close(fileSystem);
}
validateSpec(restSpec);
restTestExecutionContext = new RestTestExecutionContext(restSpec);
adminExecutionContext = new RestTestExecutionContext(restSpec);
}
protected RestTestExecutionContext getAdminExecutionContext() {
return adminExecutionContext;
}
private static void validateSpec(RestSpec restSpec) {
boolean validateSpec = RandomizedTest.systemPropertyAsBoolean(REST_TESTS_VALIDATE_SPEC, true);
if (validateSpec) {
StringBuilder errorMessage = new StringBuilder();
for (RestApi restApi : restSpec.getApis()) {
if (restApi.getMethods().contains("GET") && restApi.isBodySupported()) {
if (!restApi.getMethods().contains("POST")) {
errorMessage.append("\n- ").append(restApi.getName()).append(" supports GET with a body but doesn't support POST");
}
}
}
if (errorMessage.length() > 0) {
throw new IllegalArgumentException(errorMessage.toString());
}
}
}
@After
public void wipeCluster() throws IOException {
public final void after() throws Exception {
wipeCluster();
logIfThereAreRunningTasks();
closeClients();
}
/**
* Get a client, building it if it hasn't been built for this test.
*/
protected final RestClient client() {
return client;
}
/**
* Get the client used for test administrative actions. Do not use this while writing a test. Only use it for cleaning up after tests.
*/
protected final RestClient adminClient() {
return adminClient;
}
private void wipeCluster() throws IOException {
// wipe indices
Map<String, String> deleteIndicesArgs = new HashMap<>();
deleteIndicesArgs.put("index", "*");
try {
adminExecutionContext.callApi("indices.delete", deleteIndicesArgs, Collections.emptyList(), Collections.emptyMap());
} catch (RestTestResponseException e) {
adminClient().performRequest("DELETE", "*");
} catch (ResponseException e) {
// 404 here just means we had no indexes
if (e.getResponseException().getResponse().getStatusLine().getStatusCode() != 404) {
if (e.getResponse().getStatusLine().getStatusCode() != 404) {
throw e;
}
}
// wipe index templates
Map<String, String> deleteTemplatesArgs = new HashMap<>();
deleteTemplatesArgs.put("name", "*");
adminExecutionContext.callApi("indices.delete_template", deleteTemplatesArgs, Collections.emptyList(), Collections.emptyMap());
adminClient().performRequest("DELETE", "_template/*");
// wipe snapshots
Map<String, String> deleteSnapshotsArgs = new HashMap<>();
deleteSnapshotsArgs.put("repository", "*");
adminExecutionContext.callApi("snapshot.delete_repository", deleteSnapshotsArgs, Collections.emptyList(), Collections.emptyMap());
// Technically this deletes all repositories and leave the snapshots in the repository. OK.
adminClient().performRequest("DELETE", "_snapshot/*");
}
/**
* Logs a message if there are still running tasks. The reasoning is that any tasks still running are state the is trying to bleed into
* other tests.
*/
@After
public void logIfThereAreRunningTasks() throws IOException {
RestTestResponse tasks = adminExecutionContext.callApi("tasks.list", emptyMap(), emptyList(), emptyMap());
Set<String> runningTasks = runningTasks(tasks);
private void logIfThereAreRunningTasks() throws InterruptedException, IOException {
Set<String> runningTasks = runningTasks(adminClient().performRequest("GET", "_tasks"));
// Ignore the task list API - it doens't count against us
runningTasks.remove(ListTasksAction.NAME);
runningTasks.remove(ListTasksAction.NAME + "[n]");
@ -318,14 +178,8 @@ public abstract class ESRestTestCase extends ESTestCase {
*/
}
@AfterClass
public static void close() {
if (restTestExecutionContext != null) {
restTestExecutionContext.close();
adminExecutionContext.close();
restTestExecutionContext = null;
adminExecutionContext = null;
}
private void closeClients() throws IOException {
IOUtils.close(client, adminClient);
}
/**
@ -335,82 +189,69 @@ public abstract class ESRestTestCase extends ESTestCase {
return Settings.EMPTY;
}
/** Returns the REST client settings used for admin actions like cleaning up after the test has completed. */
/**
* Returns the REST client settings used for admin actions like cleaning up after the test has completed.
*/
protected Settings restAdminSettings() {
return restClientSettings(); // default to the same client settings
}
@Before
public void reset() throws Exception {
// admin context must be available for @After always, regardless of whether the test was blacklisted
adminExecutionContext.initClient(clusterUrls, restAdminSettings());
adminExecutionContext.clear();
//skip test if it matches one of the blacklist globs
for (BlacklistedPathPatternMatcher blacklistedPathMatcher : blacklistPathMatchers) {
String testPath = testCandidate.getSuitePath() + "/" + testCandidate.getTestSection().getName();
assumeFalse("[" + testCandidate.getTestPath() + "] skipped, reason: blacklisted", blacklistedPathMatcher
.isSuffixMatch(testPath));
}
//The client needs non static info to get initialized, therefore it can't be initialized in the before class
restTestExecutionContext.initClient(clusterUrls, restClientSettings());
restTestExecutionContext.clear();
//skip test if the whole suite (yaml file) is disabled
assumeFalse(buildSkipMessage(testCandidate.getSuitePath(), testCandidate.getSetupSection().getSkipSection()),
testCandidate.getSetupSection().getSkipSection().skip(restTestExecutionContext.esVersion()));
//skip test if the whole suite (yaml file) is disabled
assumeFalse(buildSkipMessage(testCandidate.getSuitePath(), testCandidate.getTeardownSection().getSkipSection()),
testCandidate.getTeardownSection().getSkipSection().skip(restTestExecutionContext.esVersion()));
//skip test if test section is disabled
assumeFalse(buildSkipMessage(testCandidate.getTestPath(), testCandidate.getTestSection().getSkipSection()),
testCandidate.getTestSection().getSkipSection().skip(restTestExecutionContext.esVersion()));
/**
* Get the list of hosts in the cluster.
*/
protected final List<HttpHost> getClusterHosts() {
return clusterHosts;
}
private static String buildSkipMessage(String description, SkipSection skipSection) {
StringBuilder messageBuilder = new StringBuilder();
if (skipSection.isVersionCheck()) {
messageBuilder.append("[").append(description).append("] skipped, reason: [").append(skipSection.getReason()).append("] ");
} else {
messageBuilder.append("[").append(description).append("] skipped, reason: features ")
.append(skipSection.getFeatures()).append(" not supported");
}
return messageBuilder.toString();
/**
* Override this to switch to testing https.
*/
protected String getProtocol() {
return "http";
}
public void test() throws IOException {
//let's check that there is something to run, otherwise there might be a problem with the test section
if (testCandidate.getTestSection().getExecutableSections().size() == 0) {
throw new IllegalArgumentException("No executable sections loaded for [" + testCandidate.getTestPath() + "]");
private RestClient buildClient(Settings settings) throws IOException {
RestClientBuilder builder = RestClient.builder(clusterHosts.toArray(new HttpHost[0])).setMaxRetryTimeoutMillis(30000)
.setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder.setSocketTimeout(30000));
String keystorePath = settings.get(TRUSTSTORE_PATH);
if (keystorePath != null) {
final String keystorePass = settings.get(TRUSTSTORE_PASSWORD);
if (keystorePass == null) {
throw new IllegalStateException(TRUSTSTORE_PATH + " is provided but not " + TRUSTSTORE_PASSWORD);
}
Path path = PathUtils.get(keystorePath);
if (!Files.exists(path)) {
throw new IllegalStateException(TRUSTSTORE_PATH + " is set but points to a non-existing file");
}
try {
KeyStore keyStore = KeyStore.getInstance("jks");
try (InputStream is = Files.newInputStream(path)) {
keyStore.load(is, keystorePass.toCharArray());
}
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keyStore, null).build();
SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sslcontext);
builder.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setSSLStrategy(sessionStrategy));
} catch (KeyStoreException|NoSuchAlgorithmException|KeyManagementException|CertificateException e) {
throw new RuntimeException("Error setting up ssl", e);
}
}
if (!testCandidate.getSetupSection().isEmpty()) {
logger.debug("start setup test [{}]", testCandidate.getTestPath());
for (DoSection doSection : testCandidate.getSetupSection().getDoSections()) {
doSection.execute(restTestExecutionContext);
try (ThreadContext threadContext = new ThreadContext(settings)) {
Header[] defaultHeaders = new Header[threadContext.getHeaders().size()];
int i = 0;
for (Map.Entry<String, String> entry : threadContext.getHeaders().entrySet()) {
defaultHeaders[i++] = new BasicHeader(entry.getKey(), entry.getValue());
}
logger.debug("end setup test [{}]", testCandidate.getTestPath());
}
restTestExecutionContext.clear();
try {
for (ExecutableSection executableSection : testCandidate.getTestSection().getExecutableSections()) {
executableSection.execute(restTestExecutionContext);
}
} finally {
logger.debug("start teardown test [{}]", testCandidate.getTestPath());
for (DoSection doSection : testCandidate.getTeardownSection().getDoSections()) {
doSection.execute(restTestExecutionContext);
}
logger.debug("end teardown test [{}]", testCandidate.getTestPath());
builder.setDefaultHeaders(defaultHeaders);
}
return builder.build();
}
@SuppressWarnings("unchecked")
public Set<String> runningTasks(RestTestResponse response) throws IOException {
private Set<String> runningTasks(Response response) throws IOException {
Set<String> runningTasks = new HashSet<>();
Map<String, Object> nodes = (Map<String, Object>) response.evaluate("nodes");
Map<String, Object> nodes = (Map<String, Object>) entityAsMap(response).get("nodes");
for (Map.Entry<String, Object> node : nodes.entrySet()) {
Map<String, Object> nodeInfo = (Map<String, Object>) node.getValue();
Map<String, Object> nodeTasks = (Map<String, Object>) nodeInfo.get("tasks");

View File

@ -18,19 +18,18 @@
*/
package org.elasticsearch.test.rest;
import org.apache.http.HttpHost;
import org.elasticsearch.Version;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.test.rest.client.RestTestClient;
import org.elasticsearch.test.rest.client.RestTestResponse;
import org.elasticsearch.test.rest.client.RestTestResponseException;
import org.elasticsearch.test.rest.spec.RestSpec;
import java.io.Closeable;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -41,7 +40,7 @@ import java.util.Map;
* Caches the last obtained test response and allows to stash part of it within variables
* that can be used as input values in following requests.
*/
public class RestTestExecutionContext implements Closeable {
public class RestTestExecutionContext {
private static final ESLogger logger = Loggers.getLogger(RestTestExecutionContext.class);
@ -119,10 +118,8 @@ public class RestTestExecutionContext implements Closeable {
/**
* Creates the embedded REST client when needed. Needs to be called before each test.
*/
public void initClient(URL[] urls, Settings settings) throws Exception {
if (restTestClient == null) {
restTestClient = new RestTestClient(restSpec, settings, urls);
}
public void initClient(RestClient client, List<HttpHost> hosts) throws IOException {
restTestClient = new RestTestClient(restSpec, client, hosts);
}
/**
@ -145,13 +142,4 @@ public class RestTestExecutionContext implements Closeable {
return restTestClient.getEsVersion();
}
/**
* Closes the execution context and releases the underlying resources
*/
@Override
public void close() {
if (restTestClient != null) {
restTestClient.close();
}
}
}

View File

@ -19,44 +19,27 @@
package org.elasticsearch.test.rest.client;
import com.carrotsearch.randomizedtesting.RandomizedTest;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.http.ssl.SSLContexts;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.Version;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.test.rest.spec.RestApi;
import org.elasticsearch.test.rest.spec.RestSpec;
import javax.net.ssl.SSLContext;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -70,35 +53,29 @@ import java.util.Set;
* Wraps a {@link RestClient} instance used to send the REST requests.
* Holds the {@link RestSpec} used to translate api calls into REST calls
*/
public class RestTestClient implements Closeable {
public static final String PROTOCOL = "protocol";
public static final String TRUSTSTORE_PATH = "truststore.path";
public static final String TRUSTSTORE_PASSWORD = "truststore.password";
public class RestTestClient {
private static final ESLogger logger = Loggers.getLogger(RestTestClient.class);
//query_string params that don't need to be declared in the spec, thay are supported by default
//query_string params that don't need to be declared in the spec, they are supported by default
private static final Set<String> ALWAYS_ACCEPTED_QUERY_STRING_PARAMS = Sets.newHashSet("pretty", "source", "filter_path");
private final RestSpec restSpec;
private final RestClient restClient;
private final Version esVersion;
public RestTestClient(RestSpec restSpec, Settings settings, URL[] urls) throws IOException {
assert urls.length > 0;
public RestTestClient(RestSpec restSpec, RestClient restClient, List<HttpHost> hosts) throws IOException {
assert hosts.size() > 0;
this.restSpec = restSpec;
this.restClient = createRestClient(urls, settings);
this.esVersion = readAndCheckVersion(urls);
logger.info("REST client initialized {}, elasticsearch version: [{}]", urls, esVersion);
this.restClient = restClient;
this.esVersion = readAndCheckVersion(hosts);
}
private Version readAndCheckVersion(URL[] urls) throws IOException {
private Version readAndCheckVersion(List<HttpHost> hosts) throws IOException {
RestApi restApi = restApi("info");
assert restApi.getPaths().size() == 1;
assert restApi.getMethods().size() == 1;
String version = null;
for (URL ignored : urls) {
for (HttpHost ignored : hosts) {
//we don't really use the urls here, we rely on the client doing round-robin to touch all the nodes in the cluster
String method = restApi.getMethods().get(0);
String endpoint = restApi.getPaths().get(0);
@ -264,56 +241,4 @@ public class RestTestClient implements Closeable {
}
return restApi;
}
private static RestClient createRestClient(URL[] urls, Settings settings) throws IOException {
String protocol = settings.get(PROTOCOL, "http");
HttpHost[] hosts = new HttpHost[urls.length];
for (int i = 0; i < hosts.length; i++) {
URL url = urls[i];
hosts[i] = new HttpHost(url.getHost(), url.getPort(), protocol);
}
RestClientBuilder builder = RestClient.builder(hosts).setMaxRetryTimeoutMillis(30000)
.setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder.setSocketTimeout(30000));
String keystorePath = settings.get(TRUSTSTORE_PATH);
if (keystorePath != null) {
final String keystorePass = settings.get(TRUSTSTORE_PASSWORD);
if (keystorePass == null) {
throw new IllegalStateException(TRUSTSTORE_PATH + " is provided but not " + TRUSTSTORE_PASSWORD);
}
Path path = PathUtils.get(keystorePath);
if (!Files.exists(path)) {
throw new IllegalStateException(TRUSTSTORE_PATH + " is set but points to a non-existing file");
}
try {
KeyStore keyStore = KeyStore.getInstance("jks");
try (InputStream is = Files.newInputStream(path)) {
keyStore.load(is, keystorePass.toCharArray());
}
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keyStore, null).build();
SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sslcontext);
builder.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setSSLStrategy(sessionStrategy));
} catch (KeyStoreException|NoSuchAlgorithmException|KeyManagementException|CertificateException e) {
throw new RuntimeException(e);
}
}
try (ThreadContext threadContext = new ThreadContext(settings)) {
Header[] defaultHeaders = new Header[threadContext.getHeaders().size()];
int i = 0;
for (Map.Entry<String, String> entry : threadContext.getHeaders().entrySet()) {
defaultHeaders[i++] = new BasicHeader(entry.getKey(), entry.getValue());
}
builder.setDefaultHeaders(defaultHeaders);
}
return builder.build();
}
/**
* Closes the REST client and the underlying http client
*/
@Override
public void close() {
IOUtils.closeWhileHandlingException(restClient);
}
}

View File

@ -24,6 +24,8 @@ import org.elasticsearch.test.ESIntegTestCase;
import java.util.Arrays;
import java.util.List;
import static java.util.Collections.unmodifiableList;
/**
* Allows to register additional features supported by the tests runner.
* This way any runner can add extra features and use proper skip sections to avoid
@ -34,8 +36,12 @@ import java.util.List;
*/
public final class Features {
private static final List<String> SUPPORTED =
Arrays.asList("stash_in_path", "groovy_scripting", "headers", "embedded_stash_key", "yaml");
private static final List<String> SUPPORTED = unmodifiableList(Arrays.asList(
"embedded_stash_key",
"groovy_scripting",
"headers",
"stash_in_path",
"yaml"));
private Features() {