Merge pull request #20521 from javanna/test/random_search_ext

introduce test plugin to inject random search ext elements in search request tests
This commit is contained in:
Luca Cavanna 2016-09-16 21:05:55 +02:00 committed by GitHub
commit 7fd66a4a41
5 changed files with 527 additions and 409 deletions

View File

@ -0,0 +1,512 @@
/*
* 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.search;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.SearchPlugin;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilderTests;
import org.elasticsearch.search.rescore.QueryRescoreBuilderTests;
import org.elasticsearch.search.searchafter.SearchAfterBuilder;
import org.elasticsearch.search.slice.SliceBuilder;
import org.elasticsearch.search.sort.ScriptSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.SuggestBuilderTests;
import org.elasticsearch.test.AbstractQueryTestCase;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
public abstract class AbstractSearchTestCase extends ESTestCase {
protected NamedWriteableRegistry namedWriteableRegistry;
protected SearchRequestParsers searchRequestParsers;
private TestSearchExtPlugin searchExtPlugin;
public void setUp() throws Exception {
super.setUp();
IndicesModule indicesModule = new IndicesModule(Collections.emptyList());
searchExtPlugin = new TestSearchExtPlugin();
SearchModule searchModule = new SearchModule(Settings.EMPTY, false, Collections.singletonList(searchExtPlugin));
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
entries.addAll(indicesModule.getNamedWriteables());
entries.addAll(searchModule.getNamedWriteables());
namedWriteableRegistry = new NamedWriteableRegistry(entries);
searchRequestParsers = searchModule.getSearchRequestParsers();
}
protected SearchSourceBuilder createSearchSourceBuilder() throws IOException {
SearchSourceBuilder builder = new SearchSourceBuilder();
if (randomBoolean()) {
builder.from(randomIntBetween(0, 10000));
}
if (randomBoolean()) {
builder.size(randomIntBetween(0, 10000));
}
if (randomBoolean()) {
builder.explain(randomBoolean());
}
if (randomBoolean()) {
builder.version(randomBoolean());
}
if (randomBoolean()) {
builder.trackScores(randomBoolean());
}
if (randomBoolean()) {
builder.minScore(randomFloat() * 1000);
}
if (randomBoolean()) {
builder.timeout(TimeValue.parseTimeValue(randomTimeValue(), null, "timeout"));
}
if (randomBoolean()) {
builder.terminateAfter(randomIntBetween(1, 100000));
}
switch(randomInt(2)) {
case 0:
builder.storedFields();
break;
case 1:
builder.storedField("_none_");
break;
case 2:
int fieldsSize = randomInt(25);
List<String> fields = new ArrayList<>(fieldsSize);
for (int i = 0; i < fieldsSize; i++) {
fields.add(randomAsciiOfLengthBetween(5, 50));
}
builder.storedFields(fields);
break;
default:
throw new IllegalStateException();
}
if (randomBoolean()) {
int scriptFieldsSize = randomInt(25);
for (int i = 0; i < scriptFieldsSize; i++) {
if (randomBoolean()) {
builder.scriptField(randomAsciiOfLengthBetween(5, 50), new Script("foo"), randomBoolean());
} else {
builder.scriptField(randomAsciiOfLengthBetween(5, 50), new Script("foo"));
}
}
}
if (randomBoolean()) {
FetchSourceContext fetchSourceContext;
int branch = randomInt(5);
String[] includes = new String[randomIntBetween(0, 20)];
for (int i = 0; i < includes.length; i++) {
includes[i] = randomAsciiOfLengthBetween(5, 20);
}
String[] excludes = new String[randomIntBetween(0, 20)];
for (int i = 0; i < excludes.length; i++) {
excludes[i] = randomAsciiOfLengthBetween(5, 20);
}
switch (branch) {
case 0:
fetchSourceContext = new FetchSourceContext(randomBoolean());
break;
case 1:
fetchSourceContext = new FetchSourceContext(includes, excludes);
break;
case 2:
fetchSourceContext = new FetchSourceContext(randomAsciiOfLengthBetween(5, 20), randomAsciiOfLengthBetween(5, 20));
break;
case 3:
fetchSourceContext = new FetchSourceContext(true, includes, excludes);
break;
case 4:
fetchSourceContext = new FetchSourceContext(includes);
break;
case 5:
fetchSourceContext = new FetchSourceContext(randomAsciiOfLengthBetween(5, 20));
break;
default:
throw new IllegalStateException();
}
builder.fetchSource(fetchSourceContext);
}
if (randomBoolean()) {
int size = randomIntBetween(0, 20);
List<String> statsGroups = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
statsGroups.add(randomAsciiOfLengthBetween(5, 20));
}
builder.stats(statsGroups);
}
if (randomBoolean()) {
int indexBoostSize = randomIntBetween(1, 10);
for (int i = 0; i < indexBoostSize; i++) {
builder.indexBoost(randomAsciiOfLengthBetween(5, 20), randomFloat() * 10);
}
}
if (randomBoolean()) {
builder.query(QueryBuilders.termQuery(randomAsciiOfLengthBetween(5, 20), randomAsciiOfLengthBetween(5, 20)));
}
if (randomBoolean()) {
builder.postFilter(QueryBuilders.termQuery(randomAsciiOfLengthBetween(5, 20), randomAsciiOfLengthBetween(5, 20)));
}
if (randomBoolean()) {
int numSorts = randomIntBetween(1, 5);
for (int i = 0; i < numSorts; i++) {
int branch = randomInt(5);
switch (branch) {
case 0:
builder.sort(SortBuilders.fieldSort(randomAsciiOfLengthBetween(5, 20)).order(randomFrom(SortOrder.values())));
break;
case 1:
builder.sort(SortBuilders.geoDistanceSort(randomAsciiOfLengthBetween(5, 20),
AbstractQueryTestCase.randomGeohash(1, 12)).order(randomFrom(SortOrder.values())));
break;
case 2:
builder.sort(SortBuilders.scoreSort().order(randomFrom(SortOrder.values())));
break;
case 3:
builder.sort(SortBuilders.scriptSort(new Script("foo"),
ScriptSortBuilder.ScriptSortType.NUMBER).order(randomFrom(SortOrder.values())));
break;
case 4:
builder.sort(randomAsciiOfLengthBetween(5, 20));
break;
case 5:
builder.sort(randomAsciiOfLengthBetween(5, 20), randomFrom(SortOrder.values()));
break;
}
}
}
if (randomBoolean()) {
int numSearchFrom = randomIntBetween(1, 5);
// We build a json version of the search_from first in order to
// ensure that every number type remain the same before/after xcontent (de)serialization.
// This is not a problem because the final type of each field value is extracted from associated sort field.
// This little trick ensure that equals and hashcode are the same when using the xcontent serialization.
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
jsonBuilder.startObject();
jsonBuilder.startArray("search_from");
for (int i = 0; i < numSearchFrom; i++) {
int branch = randomInt(8);
switch (branch) {
case 0:
jsonBuilder.value(randomInt());
break;
case 1:
jsonBuilder.value(randomFloat());
break;
case 2:
jsonBuilder.value(randomLong());
break;
case 3:
jsonBuilder.value(randomDouble());
break;
case 4:
jsonBuilder.value(randomAsciiOfLengthBetween(5, 20));
break;
case 5:
jsonBuilder.value(randomBoolean());
break;
case 6:
jsonBuilder.value(randomByte());
break;
case 7:
jsonBuilder.value(randomShort());
break;
case 8:
jsonBuilder.value(new Text(randomAsciiOfLengthBetween(5, 20)));
break;
}
}
jsonBuilder.endArray();
jsonBuilder.endObject();
XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(jsonBuilder.bytes());
parser.nextToken();
parser.nextToken();
parser.nextToken();
builder.searchAfter(SearchAfterBuilder.fromXContent(parser, null).getSortValues());
}
if (randomBoolean()) {
builder.highlighter(HighlightBuilderTests.randomHighlighterBuilder());
}
if (randomBoolean()) {
builder.suggest(SuggestBuilderTests.randomSuggestBuilder());
}
if (randomBoolean()) {
int numRescores = randomIntBetween(1, 5);
for (int i = 0; i < numRescores; i++) {
builder.addRescorer(QueryRescoreBuilderTests.randomRescoreBuilder());
}
}
if (randomBoolean()) {
builder.aggregation(AggregationBuilders.avg(randomAsciiOfLengthBetween(5, 20)));
}
if (randomBoolean()) {
Set<String> elementNames = new HashSet<>(searchExtPlugin.getSupportedElements().keySet());
int numSearchExts = randomIntBetween(1, elementNames.size());
while(elementNames.size() > numSearchExts) {
elementNames.remove(randomFrom(elementNames));
}
List<SearchExtBuilder> searchExtBuilders = new ArrayList<>();
for (String elementName : elementNames) {
searchExtBuilders.add(searchExtPlugin.getSupportedElements().get(elementName).apply(randomAsciiOfLengthBetween(3, 10)));
}
builder.ext(searchExtBuilders);
}
if (randomBoolean()) {
String field = randomBoolean() ? null : randomAsciiOfLengthBetween(5, 20);
int max = between(2, 1000);
int id = randomInt(max-1);
if (field == null) {
builder.slice(new SliceBuilder(id, max));
} else {
builder.slice(new SliceBuilder(field, id, max));
}
}
return builder;
}
protected SearchRequest createSearchRequest() throws IOException {
SearchRequest searchRequest = new SearchRequest();
if (randomBoolean()) {
searchRequest.indices(generateRandomStringArray(10, 10, false, false));
}
if (randomBoolean()) {
searchRequest.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean()));
}
if (randomBoolean()) {
searchRequest.types(generateRandomStringArray(10, 10, false, false));
}
if (randomBoolean()) {
searchRequest.preference(randomAsciiOfLengthBetween(3, 10));
}
if (randomBoolean()) {
searchRequest.requestCache(randomBoolean());
}
if (randomBoolean()) {
searchRequest.routing(randomAsciiOfLengthBetween(3, 10));
}
if (randomBoolean()) {
searchRequest.scroll(randomPositiveTimeValue());
}
if (randomBoolean()) {
searchRequest.searchType(randomFrom(SearchType.values()));
}
if (randomBoolean()) {
searchRequest.source(createSearchSourceBuilder());
}
return searchRequest;
}
private static class TestSearchExtPlugin extends Plugin implements SearchPlugin {
private final List<SearchExtSpec<? extends SearchExtBuilder>> searchExtSpecs;
private final Map<String, Function<String, ? extends SearchExtBuilder>> supportedElements;
private TestSearchExtPlugin() {
int numSearchExts = randomIntBetween(1, 3);
this.searchExtSpecs = new ArrayList<>(numSearchExts);
this.supportedElements = new HashMap<>();
for (int i = 0; i < numSearchExts; i++) {
switch (randomIntBetween(0, 2)) {
case 0:
if (this.supportedElements.put(TestSearchExtBuilder1.NAME, TestSearchExtBuilder1::new) == null) {
this.searchExtSpecs.add(new SearchExtSpec<>(TestSearchExtBuilder1.NAME, TestSearchExtBuilder1::new,
new TestSearchExtParser<>(TestSearchExtBuilder1::new)));
}
break;
case 1:
if (this.supportedElements.put(TestSearchExtBuilder2.NAME, TestSearchExtBuilder2::new) == null) {
this.searchExtSpecs.add(new SearchExtSpec<>(TestSearchExtBuilder2.NAME, TestSearchExtBuilder2::new,
new TestSearchExtParser<>(TestSearchExtBuilder2::new)));
}
break;
case 2:
if (this.supportedElements.put(TestSearchExtBuilder3.NAME, TestSearchExtBuilder3::new) == null) {
this.searchExtSpecs.add(new SearchExtSpec<>(TestSearchExtBuilder3.NAME, TestSearchExtBuilder3::new,
new TestSearchExtParser<>(TestSearchExtBuilder3::new)));
}
break;
default:
throw new UnsupportedOperationException();
}
}
}
Map<String, Function<String, ? extends SearchExtBuilder>> getSupportedElements() {
return supportedElements;
}
@Override
public List<SearchExtSpec<?>> getSearchExts() {
return searchExtSpecs;
}
}
private static class TestSearchExtParser<T extends SearchExtBuilder> implements SearchExtParser<T> {
private final Function<String, T> searchExtBuilderFunction;
TestSearchExtParser(Function<String, T> searchExtBuilderFunction) {
this.searchExtBuilderFunction = searchExtBuilderFunction;
}
@Override
public T fromXContent(XContentParser parser) throws IOException {
return searchExtBuilderFunction.apply(parseField(parser));
}
String parseField(XContentParser parser) throws IOException {
if (parser.currentToken() != XContentParser.Token.START_OBJECT) {
throw new ParsingException(parser.getTokenLocation(), "start_object expected, found " + parser.currentToken());
}
if (parser.nextToken() != XContentParser.Token.FIELD_NAME) {
throw new ParsingException(parser.getTokenLocation(), "field_name expected, found " + parser.currentToken());
}
String field = parser.currentName();
if (parser.nextToken() != XContentParser.Token.START_OBJECT) {
throw new ParsingException(parser.getTokenLocation(), "start_object expected, found " + parser.currentToken());
}
if (parser.nextToken() != XContentParser.Token.END_OBJECT) {
throw new ParsingException(parser.getTokenLocation(), "end_object expected, found " + parser.currentToken());
}
if (parser.nextToken() != XContentParser.Token.END_OBJECT) {
throw new ParsingException(parser.getTokenLocation(), "end_object expected, found " + parser.currentToken());
}
return field;
}
}
//Would be nice to have a single builder that gets its name as a parameter, but the name wouldn't get a value when the object
//is created reading from the stream (constructor that takes a StreamInput) which is a problem as we check that after reading
//a named writeable its name is the expected one. That's why we go for the following less dynamic approach.
private static class TestSearchExtBuilder1 extends TestSearchExtBuilder {
private static final String NAME = "name1";
TestSearchExtBuilder1(String field) {
super(NAME, field);
}
TestSearchExtBuilder1(StreamInput in) throws IOException {
super(NAME, in);
}
}
private static class TestSearchExtBuilder2 extends TestSearchExtBuilder {
private static final String NAME = "name2";
TestSearchExtBuilder2(String field) {
super(NAME, field);
}
TestSearchExtBuilder2(StreamInput in) throws IOException {
super(NAME, in);
}
}
private static class TestSearchExtBuilder3 extends TestSearchExtBuilder {
private static final String NAME = "name3";
TestSearchExtBuilder3(String field) {
super(NAME, field);
}
TestSearchExtBuilder3(StreamInput in) throws IOException {
super(NAME, in);
}
}
private abstract static class TestSearchExtBuilder extends SearchExtBuilder {
final String objectName;
protected final String name;
TestSearchExtBuilder(String name, String objectName) {
this.name = name;
this.objectName = objectName;
}
TestSearchExtBuilder(String name, StreamInput in) throws IOException {
this.name = name;
this.objectName = in.readString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(objectName);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TestSearchExtBuilder that = (TestSearchExtBuilder) o;
return Objects.equals(objectName, that.objectName) &&
Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(objectName, name);
}
@Override
public String getWriteableName() {
return name;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(name);
builder.startObject(objectName);
builder.endObject();
builder.endObject();
return builder;
}
}
}

View File

@ -24,49 +24,13 @@ import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.search.fetch.FetchSubPhasePluginIT;
import org.elasticsearch.test.ESTestCase;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.emptyList;
import static org.elasticsearch.search.builder.SearchSourceBuilderTests.createSearchSourceBuilder;
public class SearchRequestTests extends ESTestCase {
private static NamedWriteableRegistry namedWriteableRegistry;
@BeforeClass
public static void beforeClass() {
IndicesModule indicesModule = new IndicesModule(emptyList()) {
@Override
protected void configure() {
bindMapperExtension();
}
};
SearchModule searchModule = new SearchModule(Settings.EMPTY, false,
Collections.singletonList(new FetchSubPhasePluginIT.FetchTermVectorsPlugin()));
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
entries.addAll(indicesModule.getNamedWriteables());
entries.addAll(searchModule.getNamedWriteables());
namedWriteableRegistry = new NamedWriteableRegistry(entries);
}
@AfterClass
public static void afterClass() {
namedWriteableRegistry = null;
}
public class SearchRequestTests extends AbstractSearchTestCase {
public void testSerialization() throws Exception {
SearchRequest searchRequest = createSearchRequest();
@ -204,38 +168,6 @@ public class SearchRequestTests extends ESTestCase {
}
}
public static SearchRequest createSearchRequest() throws IOException {
SearchRequest searchRequest = new SearchRequest();
if (randomBoolean()) {
searchRequest.indices(generateRandomStringArray(10, 10, false, false));
}
if (randomBoolean()) {
searchRequest.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean()));
}
if (randomBoolean()) {
searchRequest.types(generateRandomStringArray(10, 10, false, false));
}
if (randomBoolean()) {
searchRequest.preference(randomAsciiOfLengthBetween(3, 10));
}
if (randomBoolean()) {
searchRequest.requestCache(randomBoolean());
}
if (randomBoolean()) {
searchRequest.routing(randomAsciiOfLengthBetween(3, 10));
}
if (randomBoolean()) {
searchRequest.scroll(randomPositiveTimeValue());
}
if (randomBoolean()) {
searchRequest.searchType(randomFrom(SearchType.values()));
}
if (randomBoolean()) {
searchRequest.source(createSearchSourceBuilder());
}
return searchRequest;
}
private static SearchRequest copyRequest(SearchRequest searchRequest) throws IOException {
SearchRequest result = new SearchRequest();
result.indices(searchRequest.indices());

View File

@ -26,297 +26,28 @@ import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.env.Environment;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.SearchModule;
import org.elasticsearch.search.SearchRequestParsers;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.fetch.FetchSubPhasePluginIT;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilderTests;
import org.elasticsearch.search.rescore.QueryRescoreBuilderTests;
import org.elasticsearch.search.AbstractSearchTestCase;
import org.elasticsearch.search.rescore.QueryRescorerBuilder;
import org.elasticsearch.search.searchafter.SearchAfterBuilder;
import org.elasticsearch.search.slice.SliceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.ScriptSortBuilder.ScriptSortType;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.SuggestBuilderTests;
import org.elasticsearch.test.AbstractQueryTestCase;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasToString;
public class SearchSourceBuilderTests extends ESTestCase {
private NamedWriteableRegistry namedWriteableRegistry;
private SearchRequestParsers searchRequestParsers;
private ParseFieldMatcher parseFieldMatcher;
public void setUp() throws Exception {
super.setUp();
// we have to prefer CURRENT since with the range of versions we support
// it's rather unlikely to get the current actually.
Settings settings = Settings.builder()
.put("node.name", AbstractQueryTestCase.class.toString())
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir()).build();
IndicesModule indicesModule = new IndicesModule(Collections.emptyList());
SearchModule searchModule = new SearchModule(settings, false,
Collections.singletonList(new FetchSubPhasePluginIT.FetchTermVectorsPlugin()));
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
entries.addAll(indicesModule.getNamedWriteables());
entries.addAll(searchModule.getNamedWriteables());
namedWriteableRegistry = new NamedWriteableRegistry(entries);
searchRequestParsers = searchModule.getSearchRequestParsers();
parseFieldMatcher = ParseFieldMatcher.STRICT;
}
public static SearchSourceBuilder createSearchSourceBuilder() throws IOException {
SearchSourceBuilder builder = new SearchSourceBuilder();
if (randomBoolean()) {
builder.from(randomIntBetween(0, 10000));
}
if (randomBoolean()) {
builder.size(randomIntBetween(0, 10000));
}
if (randomBoolean()) {
builder.explain(randomBoolean());
}
if (randomBoolean()) {
builder.version(randomBoolean());
}
if (randomBoolean()) {
builder.trackScores(randomBoolean());
}
if (randomBoolean()) {
builder.minScore(randomFloat() * 1000);
}
if (randomBoolean()) {
builder.timeout(TimeValue.parseTimeValue(randomTimeValue(), null, "timeout"));
}
if (randomBoolean()) {
builder.terminateAfter(randomIntBetween(1, 100000));
}
// if (randomBoolean()) {
// builder.defaultRescoreWindowSize(randomIntBetween(1, 100));
// }
switch(randomInt(2)) {
case 0:
builder.storedFields();
break;
case 1:
builder.storedField("_none_");
break;
case 2:
int fieldsSize = randomInt(25);
List<String> fields = new ArrayList<>(fieldsSize);
for (int i = 0; i < fieldsSize; i++) {
fields.add(randomAsciiOfLengthBetween(5, 50));
}
builder.storedFields(fields);
break;
default:
throw new IllegalStateException();
}
if (randomBoolean()) {
int scriptFieldsSize = randomInt(25);
for (int i = 0; i < scriptFieldsSize; i++) {
if (randomBoolean()) {
builder.scriptField(randomAsciiOfLengthBetween(5, 50), new Script("foo"), randomBoolean());
} else {
builder.scriptField(randomAsciiOfLengthBetween(5, 50), new Script("foo"));
}
}
}
if (randomBoolean()) {
FetchSourceContext fetchSourceContext;
int branch = randomInt(5);
String[] includes = new String[randomIntBetween(0, 20)];
for (int i = 0; i < includes.length; i++) {
includes[i] = randomAsciiOfLengthBetween(5, 20);
}
String[] excludes = new String[randomIntBetween(0, 20)];
for (int i = 0; i < excludes.length; i++) {
excludes[i] = randomAsciiOfLengthBetween(5, 20);
}
switch (branch) {
case 0:
fetchSourceContext = new FetchSourceContext(randomBoolean());
break;
case 1:
fetchSourceContext = new FetchSourceContext(includes, excludes);
break;
case 2:
fetchSourceContext = new FetchSourceContext(randomAsciiOfLengthBetween(5, 20), randomAsciiOfLengthBetween(5, 20));
break;
case 3:
fetchSourceContext = new FetchSourceContext(true, includes, excludes);
break;
case 4:
fetchSourceContext = new FetchSourceContext(includes);
break;
case 5:
fetchSourceContext = new FetchSourceContext(randomAsciiOfLengthBetween(5, 20));
break;
default:
throw new IllegalStateException();
}
builder.fetchSource(fetchSourceContext);
}
if (randomBoolean()) {
int size = randomIntBetween(0, 20);
List<String> statsGroups = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
statsGroups.add(randomAsciiOfLengthBetween(5, 20));
}
builder.stats(statsGroups);
}
if (randomBoolean()) {
int indexBoostSize = randomIntBetween(1, 10);
for (int i = 0; i < indexBoostSize; i++) {
builder.indexBoost(randomAsciiOfLengthBetween(5, 20), randomFloat() * 10);
}
}
if (randomBoolean()) {
builder.query(QueryBuilders.termQuery(randomAsciiOfLengthBetween(5, 20), randomAsciiOfLengthBetween(5, 20)));
}
if (randomBoolean()) {
builder.postFilter(QueryBuilders.termQuery(randomAsciiOfLengthBetween(5, 20), randomAsciiOfLengthBetween(5, 20)));
}
if (randomBoolean()) {
int numSorts = randomIntBetween(1, 5);
for (int i = 0; i < numSorts; i++) {
int branch = randomInt(5);
switch (branch) {
case 0:
builder.sort(SortBuilders.fieldSort(randomAsciiOfLengthBetween(5, 20)).order(randomFrom(SortOrder.values())));
break;
case 1:
builder.sort(SortBuilders.geoDistanceSort(randomAsciiOfLengthBetween(5, 20),
AbstractQueryTestCase.randomGeohash(1, 12)).order(randomFrom(SortOrder.values())));
break;
case 2:
builder.sort(SortBuilders.scoreSort().order(randomFrom(SortOrder.values())));
break;
case 3:
builder.sort(SortBuilders.scriptSort(new Script("foo"),
ScriptSortType.NUMBER).order(randomFrom(SortOrder.values())));
break;
case 4:
builder.sort(randomAsciiOfLengthBetween(5, 20));
break;
case 5:
builder.sort(randomAsciiOfLengthBetween(5, 20), randomFrom(SortOrder.values()));
break;
}
}
}
if (randomBoolean()) {
int numSearchFrom = randomIntBetween(1, 5);
// We build a json version of the search_from first in order to
// ensure that every number type remain the same before/after xcontent (de)serialization.
// This is not a problem because the final type of each field value is extracted from associated sort field.
// This little trick ensure that equals and hashcode are the same when using the xcontent serialization.
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
jsonBuilder.startObject();
jsonBuilder.startArray("search_from");
for (int i = 0; i < numSearchFrom; i++) {
int branch = randomInt(8);
switch (branch) {
case 0:
jsonBuilder.value(randomInt());
break;
case 1:
jsonBuilder.value(randomFloat());
break;
case 2:
jsonBuilder.value(randomLong());
break;
case 3:
jsonBuilder.value(randomDouble());
break;
case 4:
jsonBuilder.value(randomAsciiOfLengthBetween(5, 20));
break;
case 5:
jsonBuilder.value(randomBoolean());
break;
case 6:
jsonBuilder.value(randomByte());
break;
case 7:
jsonBuilder.value(randomShort());
break;
case 8:
jsonBuilder.value(new Text(randomAsciiOfLengthBetween(5, 20)));
break;
}
}
jsonBuilder.endArray();
jsonBuilder.endObject();
XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(jsonBuilder.bytes());
parser.nextToken();
parser.nextToken();
parser.nextToken();
builder.searchAfter(SearchAfterBuilder.fromXContent(parser, null).getSortValues());
}
if (randomBoolean()) {
builder.highlighter(HighlightBuilderTests.randomHighlighterBuilder());
}
if (randomBoolean()) {
builder.suggest(SuggestBuilderTests.randomSuggestBuilder());
}
if (randomBoolean()) {
int numRescores = randomIntBetween(1, 5);
for (int i = 0; i < numRescores; i++) {
builder.addRescorer(QueryRescoreBuilderTests.randomRescoreBuilder());
}
}
if (randomBoolean()) {
builder.aggregation(AggregationBuilders.avg(randomAsciiOfLengthBetween(5, 20)));
}
if (randomBoolean()) {
builder.ext(Collections.singletonList(new FetchSubPhasePluginIT.TermVectorsFetchBuilder("test")));
}
if (randomBoolean()) {
String field = randomBoolean() ? null : randomAsciiOfLengthBetween(5, 20);
int max = between(2, 1000);
int id = randomInt(max-1);
if (field == null) {
builder.slice(new SliceBuilder(id, max));
} else {
builder.slice(new SliceBuilder(field, id, max));
}
}
return builder;
}
public class SearchSourceBuilderTests extends AbstractSearchTestCase {
public void testFromXContent() throws IOException {
SearchSourceBuilder testSearchSourceBuilder = createSearchSourceBuilder();
@ -348,7 +79,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
}
private QueryParseContext createParseContext(XContentParser parser) {
return new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher);
return new QueryParseContext(searchRequestParsers.queryParsers, parser, ParseFieldMatcher.STRICT);
}
public void testSerialization() throws IOException {
@ -392,7 +123,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
}
//we use the streaming infra to create a copy of the builder provided as argument
protected SearchSourceBuilder copyBuilder(SearchSourceBuilder builder) throws IOException {
private SearchSourceBuilder copyBuilder(SearchSourceBuilder builder) throws IOException {
try (BytesStreamOutput output = new BytesStreamOutput()) {
builder.writeTo(output);
try (StreamInput in = new NamedWriteableAwareStreamInput(output.bytes().streamInput(), namedWriteableRegistry)) {
@ -595,25 +326,4 @@ public class SearchSourceBuilderTests extends ESTestCase {
String query = "{ \"query\": {} }";
assertParseSearchSource(builder, new BytesArray(query), ParseFieldMatcher.EMPTY);
}
public void testSearchRequestBuilderSerializationWithIndexBoost() throws Exception {
SearchSourceBuilder searchSourceBuilder = createSearchSourceBuilder();
createIndexBoost(searchSourceBuilder);
try (BytesStreamOutput output = new BytesStreamOutput()) {
searchSourceBuilder.writeTo(output);
try (StreamInput in = new NamedWriteableAwareStreamInput(output.bytes().streamInput(), namedWriteableRegistry)) {
SearchSourceBuilder deserializedSearchSourceBuilder = new SearchSourceBuilder(in);
BytesStreamOutput deserializedOutput = new BytesStreamOutput();
deserializedSearchSourceBuilder.writeTo(deserializedOutput);
assertEquals(output.bytes(), deserializedOutput.bytes());
}
}
}
private void createIndexBoost(SearchSourceBuilder searchSourceBuilder) {
int indexBoostSize = randomIntBetween(1, 10);
for (int i = 0; i < indexBoostSize; i++) {
searchSourceBuilder.indexBoost(randomAsciiOfLengthBetween(5, 20), randomFloat() * 10);
}
}
}

View File

@ -118,7 +118,7 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
}
}
public static final class TermVectorsFetchSubPhase implements FetchSubPhase {
private static final class TermVectorsFetchSubPhase implements FetchSubPhase {
private static final String NAME = "term_vectors_fetch";
@Override
@ -153,7 +153,7 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
}
}
public static final class TermVectorsFetchParser implements SearchExtParser<TermVectorsFetchBuilder> {
private static final class TermVectorsFetchParser implements SearchExtParser<TermVectorsFetchBuilder> {
private static final TermVectorsFetchParser INSTANCE = new TermVectorsFetchParser();
@ -176,18 +176,18 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
}
}
public static final class TermVectorsFetchBuilder extends SearchExtBuilder {
private static final class TermVectorsFetchBuilder extends SearchExtBuilder {
private final String field;
public TermVectorsFetchBuilder(String field) {
private TermVectorsFetchBuilder(String field) {
this.field = field;
}
public TermVectorsFetchBuilder(StreamInput in) throws IOException {
private TermVectorsFetchBuilder(StreamInput in) throws IOException {
this.field = in.readString();
}
public String getField() {
private String getField() {
return field;
}

View File

@ -27,49 +27,13 @@ import org.elasticsearch.cluster.routing.UnassignedInfo;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.search.SearchModule;
import org.elasticsearch.search.SearchRequestTests;
import org.elasticsearch.search.fetch.FetchSubPhasePluginIT;
import org.elasticsearch.test.ESTestCase;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.elasticsearch.search.AbstractSearchTestCase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.emptyList;
public class ShardSearchTransportRequestTests extends ESTestCase {
private static NamedWriteableRegistry namedWriteableRegistry;
@BeforeClass
public static void beforeClass() {
IndicesModule indicesModule = new IndicesModule(emptyList()) {
@Override
protected void configure() {
bindMapperExtension();
}
};
SearchModule searchModule = new SearchModule(Settings.EMPTY, false,
Collections.singletonList(new FetchSubPhasePluginIT.FetchTermVectorsPlugin()));
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
entries.addAll(indicesModule.getNamedWriteables());
entries.addAll(searchModule.getNamedWriteables());
namedWriteableRegistry = new NamedWriteableRegistry(entries);
}
@AfterClass
public static void afterClass() {
namedWriteableRegistry = null;
}
public class ShardSearchTransportRequestTests extends AbstractSearchTestCase {
public void testSerialization() throws Exception {
ShardSearchTransportRequest shardSearchTransportRequest = createShardSearchTransportRequest();
@ -95,8 +59,8 @@ public class ShardSearchTransportRequestTests extends ESTestCase {
}
}
private static ShardSearchTransportRequest createShardSearchTransportRequest() throws IOException {
SearchRequest searchRequest = SearchRequestTests.createSearchRequest();
private ShardSearchTransportRequest createShardSearchTransportRequest() throws IOException {
SearchRequest searchRequest = createSearchRequest();
ShardId shardId = new ShardId(randomAsciiOfLengthBetween(2, 10), randomAsciiOfLengthBetween(2, 10), randomInt());
ShardRouting shardRouting = TestShardRouting.newShardRouting(shardId, null, null, randomBoolean(), ShardRoutingState.UNASSIGNED,
new UnassignedInfo(randomFrom(UnassignedInfo.Reason.values()), "reason"));