Browse Source

Merge pull request #20521 from javanna/test/random_search_ext

introduce test plugin to inject random search ext elements in search request tests
Luca Cavanna 9 years ago
parent
commit
7fd66a4a41

+ 512 - 0
core/src/test/java/org/elasticsearch/search/AbstractSearchTestCase.java

@@ -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;
+        }
+    }
+}

+ 1 - 69
core/src/test/java/org/elasticsearch/search/SearchRequestTests.java

@@ -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());

+ 4 - 294
core/src/test/java/org/elasticsearch/search/builder/SearchSourceBuilderTests.java

@@ -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);
-        }
-    }
 }

+ 6 - 6
core/src/test/java/org/elasticsearch/search/fetch/FetchSubPhasePluginIT.java

@@ -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;
         }
 

+ 4 - 40
core/src/test/java/org/elasticsearch/search/internal/ShardSearchTransportRequestTests.java

@@ -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"));