|
@@ -19,178 +19,31 @@
|
|
|
|
|
|
|
|
package org.elasticsearch.index.mapper;
|
|
package org.elasticsearch.index.mapper;
|
|
|
|
|
|
|
|
-import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
|
|
|
|
-import org.apache.lucene.index.IndexReader;
|
|
|
|
|
-import org.apache.lucene.index.IndexWriterConfig;
|
|
|
|
|
-import org.apache.lucene.index.RandomIndexWriter;
|
|
|
|
|
-import org.apache.lucene.store.Directory;
|
|
|
|
|
-import org.elasticsearch.Version;
|
|
|
|
|
-import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
|
|
|
-import org.elasticsearch.common.CheckedConsumer;
|
|
|
|
|
import org.elasticsearch.common.Strings;
|
|
import org.elasticsearch.common.Strings;
|
|
|
import org.elasticsearch.common.bytes.BytesReference;
|
|
import org.elasticsearch.common.bytes.BytesReference;
|
|
|
-import org.elasticsearch.common.compress.CompressedXContent;
|
|
|
|
|
-import org.elasticsearch.common.settings.Settings;
|
|
|
|
|
import org.elasticsearch.common.xcontent.ToXContent;
|
|
import org.elasticsearch.common.xcontent.ToXContent;
|
|
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
|
-import org.elasticsearch.common.xcontent.XContentFactory;
|
|
|
|
|
import org.elasticsearch.common.xcontent.XContentHelper;
|
|
import org.elasticsearch.common.xcontent.XContentHelper;
|
|
|
-import org.elasticsearch.common.xcontent.XContentType;
|
|
|
|
|
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
|
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
|
|
-import org.elasticsearch.index.IndexSettings;
|
|
|
|
|
-import org.elasticsearch.index.analysis.AnalyzerScope;
|
|
|
|
|
-import org.elasticsearch.index.analysis.IndexAnalyzers;
|
|
|
|
|
-import org.elasticsearch.index.analysis.NamedAnalyzer;
|
|
|
|
|
-import org.elasticsearch.index.mapper.MapperService.MergeReason;
|
|
|
|
|
-import org.elasticsearch.index.query.QueryShardContext;
|
|
|
|
|
-import org.elasticsearch.index.similarity.SimilarityService;
|
|
|
|
|
-import org.elasticsearch.indices.IndicesModule;
|
|
|
|
|
-import org.elasticsearch.indices.mapper.MapperRegistry;
|
|
|
|
|
-import org.elasticsearch.plugins.MapperPlugin;
|
|
|
|
|
-import org.elasticsearch.plugins.Plugin;
|
|
|
|
|
-import org.elasticsearch.script.ScriptService;
|
|
|
|
|
import org.elasticsearch.search.lookup.SourceLookup;
|
|
import org.elasticsearch.search.lookup.SourceLookup;
|
|
|
-import org.elasticsearch.test.ESTestCase;
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
-import java.util.Collection;
|
|
|
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
-import static java.util.Collections.emptyList;
|
|
|
|
|
-import static java.util.Collections.emptyMap;
|
|
|
|
|
-import static java.util.stream.Collectors.toList;
|
|
|
|
|
import static org.hamcrest.Matchers.containsString;
|
|
import static org.hamcrest.Matchers.containsString;
|
|
|
-import static org.mockito.Matchers.anyObject;
|
|
|
|
|
-import static org.mockito.Matchers.anyString;
|
|
|
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.mock;
|
|
|
import static org.mockito.Mockito.when;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Base class for testing {@link Mapper}s.
|
|
* Base class for testing {@link Mapper}s.
|
|
|
*/
|
|
*/
|
|
|
-public abstract class MapperTestCase extends ESTestCase {
|
|
|
|
|
- protected static final Settings SETTINGS = Settings.builder().put("index.version.created", Version.CURRENT).build();
|
|
|
|
|
-
|
|
|
|
|
- protected Collection<? extends Plugin> getPlugins() {
|
|
|
|
|
- return emptyList();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected Settings getIndexSettings() {
|
|
|
|
|
- return SETTINGS;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected IndexAnalyzers createIndexAnalyzers(IndexSettings indexSettings) {
|
|
|
|
|
- return new IndexAnalyzers(
|
|
|
|
|
- Map.of("default", new NamedAnalyzer("default", AnalyzerScope.INDEX, new StandardAnalyzer())),
|
|
|
|
|
- Map.of(),
|
|
|
|
|
- Map.of()
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected final String randomIndexOptions() {
|
|
|
|
|
- return randomFrom(new String[] { "docs", "freqs", "positions", "offsets" });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected final DocumentMapper createDocumentMapper(XContentBuilder mappings) throws IOException {
|
|
|
|
|
- return createMapperService(mappings).documentMapper();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected final MapperService createMapperService(XContentBuilder mappings) throws IOException {
|
|
|
|
|
- return createMapperService(getIndexSettings(), mappings);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Create a {@link MapperService} like we would for an index.
|
|
|
|
|
- */
|
|
|
|
|
- protected final MapperService createMapperService(Settings settings, XContentBuilder mapping) throws IOException {
|
|
|
|
|
- IndexMetadata meta = IndexMetadata.builder("index")
|
|
|
|
|
- .settings(Settings.builder().put("index.version.created", Version.CURRENT))
|
|
|
|
|
- .numberOfReplicas(0)
|
|
|
|
|
- .numberOfShards(1)
|
|
|
|
|
- .build();
|
|
|
|
|
- IndexSettings indexSettings = new IndexSettings(meta, Settings.EMPTY);
|
|
|
|
|
- MapperRegistry mapperRegistry = new IndicesModule(
|
|
|
|
|
- getPlugins().stream().filter(p -> p instanceof MapperPlugin).map(p -> (MapperPlugin) p).collect(toList())
|
|
|
|
|
- ).getMapperRegistry();
|
|
|
|
|
- ScriptService scriptService = new ScriptService(Settings.EMPTY, emptyMap(), emptyMap());
|
|
|
|
|
- SimilarityService similarityService = new SimilarityService(indexSettings, scriptService, Map.of());
|
|
|
|
|
- MapperService mapperService = new MapperService(
|
|
|
|
|
- indexSettings,
|
|
|
|
|
- createIndexAnalyzers(indexSettings),
|
|
|
|
|
- xContentRegistry(),
|
|
|
|
|
- similarityService,
|
|
|
|
|
- mapperRegistry,
|
|
|
|
|
- () -> { throw new UnsupportedOperationException(); },
|
|
|
|
|
- () -> true
|
|
|
|
|
- );
|
|
|
|
|
- merge(mapperService, mapping);
|
|
|
|
|
- return mapperService;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected final void withLuceneIndex(
|
|
|
|
|
- MapperService mapperService,
|
|
|
|
|
- CheckedConsumer<RandomIndexWriter, IOException> builder,
|
|
|
|
|
- CheckedConsumer<IndexReader, IOException> test
|
|
|
|
|
- ) throws IOException {
|
|
|
|
|
- try (
|
|
|
|
|
- Directory dir = newDirectory();
|
|
|
|
|
- RandomIndexWriter iw = new RandomIndexWriter(random(), dir, new IndexWriterConfig(mapperService.indexAnalyzer()))
|
|
|
|
|
- ) {
|
|
|
|
|
- builder.accept(iw);
|
|
|
|
|
- try (IndexReader reader = iw.getReader()) {
|
|
|
|
|
- test.accept(reader);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected final SourceToParse source(CheckedConsumer<XContentBuilder, IOException> build) throws IOException {
|
|
|
|
|
- XContentBuilder builder = JsonXContent.contentBuilder().startObject();
|
|
|
|
|
- build.accept(builder);
|
|
|
|
|
- builder.endObject();
|
|
|
|
|
- return new SourceToParse("test", "1", BytesReference.bytes(builder), XContentType.JSON);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Merge a new mapping into the one in the provided {@link MapperService}.
|
|
|
|
|
- */
|
|
|
|
|
- protected final void merge(MapperService mapperService, XContentBuilder mapping) throws IOException {
|
|
|
|
|
- mapperService.merge(null, new CompressedXContent(BytesReference.bytes(mapping)), MergeReason.MAPPING_UPDATE);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected final XContentBuilder mapping(CheckedConsumer<XContentBuilder, IOException> buildFields) throws IOException {
|
|
|
|
|
- XContentBuilder builder = XContentFactory.jsonBuilder().startObject().startObject("_doc").startObject("properties");
|
|
|
|
|
- buildFields.accept(builder);
|
|
|
|
|
- return builder.endObject().endObject().endObject();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected final XContentBuilder fieldMapping(CheckedConsumer<XContentBuilder, IOException> buildField) throws IOException {
|
|
|
|
|
- return mapping(b -> {
|
|
|
|
|
- b.startObject("field");
|
|
|
|
|
- buildField.accept(b);
|
|
|
|
|
- b.endObject();
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- QueryShardContext createQueryShardContext(MapperService mapperService) {
|
|
|
|
|
- QueryShardContext queryShardContext = mock(QueryShardContext.class);
|
|
|
|
|
- when(queryShardContext.getMapperService()).thenReturn(mapperService);
|
|
|
|
|
- when(queryShardContext.fieldMapper(anyString())).thenAnswer(inv -> mapperService.fieldType(inv.getArguments()[0].toString()));
|
|
|
|
|
- when(queryShardContext.getIndexAnalyzers()).thenReturn(mapperService.getIndexAnalyzers());
|
|
|
|
|
- when(queryShardContext.getSearchQuoteAnalyzer(anyObject())).thenCallRealMethod();
|
|
|
|
|
- when(queryShardContext.getSearchAnalyzer(anyObject())).thenCallRealMethod();
|
|
|
|
|
- when(queryShardContext.getIndexSettings()).thenReturn(mapperService.getIndexSettings());
|
|
|
|
|
- when(queryShardContext.simpleMatchToIndexNames(anyObject())).thenAnswer(
|
|
|
|
|
- inv -> mapperService.simpleMatchToFullName(inv.getArguments()[0].toString())
|
|
|
|
|
- );
|
|
|
|
|
- return queryShardContext;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+public abstract class MapperTestCase extends MapperServiceTestCase {
|
|
|
|
|
|
|
|
protected abstract void minimalMapping(XContentBuilder b) throws IOException;
|
|
protected abstract void minimalMapping(XContentBuilder b) throws IOException;
|
|
|
|
|
|
|
|
- public final void testEmptyName() throws IOException {
|
|
|
|
|
|
|
+ public final void testEmptyName() {
|
|
|
MapperParsingException e = expectThrows(MapperParsingException.class, () -> createMapperService(mapping(b -> {
|
|
MapperParsingException e = expectThrows(MapperParsingException.class, () -> createMapperService(mapping(b -> {
|
|
|
b.startObject("");
|
|
b.startObject("");
|
|
|
minimalMapping(b);
|
|
minimalMapping(b);
|