[Tests] Add tests for CompletionSuggestionBuilder#build() (#25575)

This adds a unit test that checks the CompletionSuggestionContext that is 
the output of CompletionSuggestionBuilder#build.
This commit is contained in:
Christoph Büscher 2017-07-07 16:18:25 +02:00 committed by GitHub
parent 5762bce4b8
commit 0e8d7582ec
5 changed files with 55 additions and 34 deletions

View File

@ -24,10 +24,12 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.mapper.CompletionFieldMapper;
@ -52,6 +54,7 @@ import java.util.Objects;
* indexing.
*/
public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSuggestionBuilder> {
private static final XContentType CONTEXT_BYTES_XCONTENT_TYPE = XContentType.JSON;
static final String SUGGESTION_NAME = "completion";
static final ParseField CONTEXTS_FIELD = new ParseField("contexts", "context");
@ -86,7 +89,7 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
PARSER.declareInt(CompletionSuggestionBuilder.InnerBuilder::shardSize, SHARDSIZE_FIELD);
PARSER.declareField((p, v, c) -> {
// Copy the current structure. We will parse, once the mapping is provided
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON);
XContentBuilder builder = XContentFactory.contentBuilder(CONTEXT_BYTES_XCONTENT_TYPE);
builder.copyCurrentStructure(p);
v.contextBytes = builder.bytes();
p.skipChildren();
@ -186,7 +189,7 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
public CompletionSuggestionBuilder contexts(Map<String, List<? extends ToXContent>> queryContexts) {
Objects.requireNonNull(queryContexts, "contexts must not be null");
try {
XContentBuilder contentBuilder = XContentFactory.jsonBuilder();
XContentBuilder contentBuilder = XContentFactory.contentBuilder(CONTEXT_BYTES_XCONTENT_TYPE);
contentBuilder.startObject();
for (Map.Entry<String, List<? extends ToXContent>> contextEntry : queryContexts.entrySet()) {
contentBuilder.startArray(contextEntry.getKey());
@ -255,33 +258,16 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
suggestionContext.setFuzzyOptions(fuzzyOptions);
suggestionContext.setRegexOptions(regexOptions);
MappedFieldType mappedFieldType = mapperService.fullName(suggestionContext.getField());
if (mappedFieldType == null ||
mappedFieldType instanceof CompletionFieldMapper.CompletionFieldType == false) {
if (mappedFieldType == null || mappedFieldType instanceof CompletionFieldMapper.CompletionFieldType == false) {
throw new IllegalArgumentException("Field [" + suggestionContext.getField() + "] is not a completion suggest field");
}
if (mappedFieldType instanceof CompletionFieldMapper.CompletionFieldType) {
CompletionFieldMapper.CompletionFieldType type = (CompletionFieldMapper.CompletionFieldType) mappedFieldType;
suggestionContext.setFieldType(type);
if (type.hasContextMappings() && contextBytes != null) {
try (XContentParser contextParser = XContentFactory.xContent(contextBytes).createParser(context.getXContentRegistry(),
contextBytes)) {
if (type.hasContextMappings() && contextParser != null) {
ContextMappings contextMappings = type.getContextMappings();
contextParser.nextToken();
Map<String, List<ContextMapping.InternalQueryContext>> queryContexts = new HashMap<>(contextMappings.size());
assert contextParser.currentToken() == XContentParser.Token.START_OBJECT;
XContentParser.Token currentToken;
String currentFieldName;
while ((currentToken = contextParser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (currentToken == XContentParser.Token.FIELD_NAME) {
currentFieldName = contextParser.currentName();
final ContextMapping mapping = contextMappings.get(currentFieldName);
queryContexts.put(currentFieldName, mapping.parseQueryContext(contextParser));
}
}
suggestionContext.setQueryContexts(queryContexts);
}
}
Map<String, List<ContextMapping.InternalQueryContext>> queryContexts = parseContextBytes(contextBytes,
context.getXContentRegistry(), type.getContextMappings());
suggestionContext.setQueryContexts(queryContexts);
} else if (contextBytes != null) {
throw new IllegalArgumentException("suggester [" + type.name() + "] doesn't expect any context");
}
@ -290,6 +276,25 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
return suggestionContext;
}
static Map<String, List<ContextMapping.InternalQueryContext>> parseContextBytes(BytesReference contextBytes,
NamedXContentRegistry xContentRegistry, ContextMappings contextMappings) throws IOException {
try (XContentParser contextParser = XContentHelper.createParser(xContentRegistry, contextBytes, CONTEXT_BYTES_XCONTENT_TYPE)) {
contextParser.nextToken();
Map<String, List<ContextMapping.InternalQueryContext>> queryContexts = new HashMap<>(contextMappings.size());
assert contextParser.currentToken() == XContentParser.Token.START_OBJECT;
XContentParser.Token currentToken;
String currentFieldName;
while ((currentToken = contextParser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (currentToken == XContentParser.Token.FIELD_NAME) {
currentFieldName = contextParser.currentName();
final ContextMapping<?> mapping = contextMappings.get(currentFieldName);
queryContexts.put(currentFieldName, mapping.parseQueryContext(contextParser));
}
}
return queryContexts;
}
}
@Override
public String getWriteableName() {
return SUGGESTION_NAME;

View File

@ -201,14 +201,14 @@ public abstract class AbstractSuggestionBuilderTestCase<SB extends SuggestionBui
} else {
assertEquals("mapperServiceSearchAnalyzer", ((NamedAnalyzer) suggestionContext.getAnalyzer()).name());
}
assertSuggester(suggestionBuilder, suggestionContext);
assertSuggestionContext(suggestionBuilder, suggestionContext);
}
}
/**
* put suggester dependent assertions in the sub type test
* put implementation dependent assertions in the sub-type test
*/
protected abstract void assertSuggester(SB builder, SuggestionContext context);
protected abstract void assertSuggestionContext(SB builder, SuggestionContext context) throws IOException;
protected MappedFieldType mockFieldType() {
return mock(MappedFieldType.class);

View File

@ -29,17 +29,19 @@ import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContex
import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext;
import org.elasticsearch.search.suggest.completion.context.ContextBuilder;
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
import org.elasticsearch.search.suggest.completion.context.ContextMapping.InternalQueryContext;
import org.elasticsearch.search.suggest.completion.context.ContextMappings;
import org.elasticsearch.search.suggest.completion.context.GeoQueryContext;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.hamcrest.Matchers.instanceOf;
public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTestCase<CompletionSuggestionBuilder> {
private static final String[] SHUFFLE_PROTECTED_FIELDS = new String[] { CompletionSuggestionBuilder.CONTEXTS_FIELD.getPreferredName() };
@ -54,7 +56,7 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
}
public static CompletionSuggestionBuilder randomCompletionSuggestionBuilder() {
// lazy initialization of context names and mappings, cannot be done in init method because other test
// lazy initialization of context names and mappings, cannot be done in some init method because other test
// also create random CompletionSuggestionBuilder instances
if (categoryContextName == null) {
categoryContextName = randomAlphaOfLength(10);
@ -62,9 +64,9 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
if (geoQueryContextName == null) {
geoQueryContextName = randomAlphaOfLength(10);
}
if (contextMappings == null) {
contextMappings = Arrays.asList(new ContextMapping[] { ContextBuilder.category(categoryContextName).build(),
ContextBuilder.geo(geoQueryContextName).build() });
if (contextMappings.isEmpty()) {
contextMappings.add(ContextBuilder.category(categoryContextName).build());
contextMappings.add(ContextBuilder.geo(geoQueryContextName).build());
}
// lazy initialization of context names and mappings, cannot be done in some init method because other test
// also create random CompletionSuggestionBuilder instances
@ -165,6 +167,20 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
}
@Override
protected void assertSuggester(CompletionSuggestionBuilder builder, SuggestionContext context) {
protected void assertSuggestionContext(CompletionSuggestionBuilder builder, SuggestionContext context) throws IOException {
assertThat(context, instanceOf(CompletionSuggestionContext.class));
assertThat(context.getSuggester(), instanceOf(CompletionSuggester.class));
CompletionSuggestionContext completionSuggestionCtx = (CompletionSuggestionContext) context;
assertThat(completionSuggestionCtx.getFieldType(), instanceOf(CompletionFieldType.class) );
assertEquals(builder.fuzzyOptions, completionSuggestionCtx.getFuzzyOptions());
Map<String, List<InternalQueryContext>> parsedContextBytes;
parsedContextBytes = CompletionSuggestionBuilder.parseContextBytes(builder.contextBytes, xContentRegistry(),
new ContextMappings(contextMappings));
Map<String, List<InternalQueryContext>> queryContexts = completionSuggestionCtx.getQueryContexts();
assertEquals(parsedContextBytes.keySet(), queryContexts.keySet());
for (String contextName : queryContexts.keySet()) {
assertEquals(parsedContextBytes.get(contextName), queryContexts.get(contextName));
}
assertEquals(builder.regexOptions, completionSuggestionCtx.getRegexOptions());
}
}

View File

@ -188,7 +188,7 @@ public class PhraseSuggestionBuilderTests extends AbstractSuggestionBuilderTestC
}
@Override
protected void assertSuggester(PhraseSuggestionBuilder builder, SuggestionContext context) {
protected void assertSuggestionContext(PhraseSuggestionBuilder builder, SuggestionContext context) {
assertThat(context, instanceOf(PhraseSuggestionContext.class));
assertThat(context.getSuggester(), instanceOf(PhraseSuggester.class));
PhraseSuggestionContext phraseSuggesterCtx = (PhraseSuggestionContext) context;

View File

@ -227,7 +227,7 @@ public class TermSuggestionBuilderTests extends AbstractSuggestionBuilderTestCas
}
@Override
protected void assertSuggester(TermSuggestionBuilder builder, SuggestionContext context) {
protected void assertSuggestionContext(TermSuggestionBuilder builder, SuggestionContext context) {
assertThat(context, instanceOf(TermSuggestionContext.class));
assertThat(context.getSuggester(), instanceOf(TermSuggester.class));
TermSuggestionContext termSuggesterCtx = (TermSuggestionContext) context;