Fix random failure on SearchQueryIT#testTermExpansionExceptionOnSpanFailure

This change moves an integration test that relies on setting
the value of a static variable (boolean max clause count) to
an unit test where we are sure that the same jvm is used to access
the static variable.
This commit is contained in:
Jim Ferenczi 2018-06-07 13:37:29 +02:00
parent 6ad7217656
commit 280a2f55d6
3 changed files with 70 additions and 67 deletions

View File

@ -137,47 +137,42 @@ public class SpanMultiTermQueryBuilder extends AbstractQueryBuilder<SpanMultiTer
return new SpanMultiTermQueryBuilder(subQuery).queryName(queryName).boost(boost);
}
public static class TopTermSpanBooleanQueryRewriteWithMaxClause extends SpanMultiTermQueryWrapper.SpanRewriteMethod {
private MultiTermQuery multiTermQuery;
static class TopTermSpanBooleanQueryRewriteWithMaxClause extends SpanMultiTermQueryWrapper.SpanRewriteMethod {
private final long maxExpansions;
TopTermSpanBooleanQueryRewriteWithMaxClause(long max) {
maxExpansions = max;
TopTermSpanBooleanQueryRewriteWithMaxClause() {
this.maxExpansions = BooleanQuery.getMaxClauseCount();
}
@Override
public SpanQuery rewrite(IndexReader reader, MultiTermQuery query) throws IOException {
multiTermQuery = query;
return (SpanQuery) this.delegate.rewrite(reader, multiTermQuery);
}
final ScoringRewrite<List<SpanQuery>> delegate = new ScoringRewrite<List<SpanQuery>>() {
@Override
protected List<SpanQuery> getTopLevelBuilder() {
return new ArrayList();
}
@Override
protected Query build(List<SpanQuery> builder) {
return new SpanOrQuery((SpanQuery[]) builder.toArray(new SpanQuery[builder.size()]));
}
@Override
protected void checkMaxClauseCount(int count) {
if (count > maxExpansions) {
throw new ElasticsearchException("[" + multiTermQuery.toString() + " ] " +
"exceeds maxClauseCount [ Boolean maxClauseCount is set to " + BooleanQuery.getMaxClauseCount() + "]");
final MultiTermQuery.RewriteMethod delegate = new ScoringRewrite<List<SpanQuery>>() {
@Override
protected List<SpanQuery> getTopLevelBuilder() {
return new ArrayList();
}
}
@Override
protected void addClause(List<SpanQuery> topLevel, Term term, int docCount, float boost, TermContext states) {
SpanTermQuery q = new SpanTermQuery(term, states);
topLevel.add(q);
}
};
@Override
protected Query build(List<SpanQuery> builder) {
return new SpanOrQuery((SpanQuery[]) builder.toArray(new SpanQuery[builder.size()]));
}
@Override
protected void checkMaxClauseCount(int count) {
if (count > maxExpansions) {
throw new RuntimeException("[" + query.toString() + " ] " +
"exceeds maxClauseCount [ Boolean maxClauseCount is set to " + BooleanQuery.getMaxClauseCount() + "]");
}
}
@Override
protected void addClause(List<SpanQuery> topLevel, Term term, int docCount, float boost, TermContext states) {
SpanTermQuery q = new SpanTermQuery(term, states);
topLevel.add(q);
}
};
return (SpanQuery) delegate.rewrite(reader, query);
}
}
@Override
@ -222,6 +217,7 @@ public class SpanMultiTermQueryBuilder extends AbstractQueryBuilder<SpanMultiTer
QueryParsers.parseRewriteMethod(prefixBuilder.rewrite(), null, LoggingDeprecationHandler.INSTANCE);
prefixQuery.setRewriteMethod(rewriteMethod);
}
subQuery = prefixQuery;
spanQuery = new SpanMultiTermQueryWrapper<>(prefixQuery);
} else {
String origFieldName = ((PrefixQueryBuilder) multiTermQueryBuilder).fieldName();
@ -240,9 +236,12 @@ public class SpanMultiTermQueryBuilder extends AbstractQueryBuilder<SpanMultiTer
+ MultiTermQuery.class.getName() + " but was " + subQuery.getClass().getName());
}
spanQuery = new SpanMultiTermQueryWrapper<>((MultiTermQuery) subQuery);
if (((MultiTermQuery) subQuery).getRewriteMethod() instanceof TopTermsRewrite == false) {
((SpanMultiTermQueryWrapper<MultiTermQuery>) spanQuery).setRewriteMethod(new
TopTermSpanBooleanQueryRewriteWithMaxClause(BooleanQuery.getMaxClauseCount()));
}
if (subQuery instanceof MultiTermQuery) {
MultiTermQuery multiTermQuery = (MultiTermQuery) subQuery;
SpanMultiTermQueryWrapper<?> wrapper = (SpanMultiTermQueryWrapper<?>) spanQuery;
if (multiTermQuery.getRewriteMethod() instanceof TopTermsRewrite == false) {
wrapper.setRewriteMethod(new TopTermSpanBooleanQueryRewriteWithMaxClause());
}
}
if (boost != AbstractQueryBuilder.DEFAULT_BOOST) {

View File

@ -19,7 +19,13 @@
package org.elasticsearch.index.query;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.PrefixQuery;
@ -30,6 +36,7 @@ import org.apache.lucene.search.spans.SpanBoostQuery;
import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.lucene.store.Directory;
import org.elasticsearch.Version;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.compress.CompressedXContent;
@ -41,6 +48,7 @@ import org.elasticsearch.test.AbstractQueryTestCase;
import java.io.IOException;
import static java.util.Collections.singleton;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
@ -251,14 +259,37 @@ public class SpanMultiTermQueryBuilderTests extends AbstractQueryTestCase<SpanMu
MultiTermQuery.RewriteMethod rewriteMethod = ((SpanMultiTermQueryWrapper)query).getRewriteMethod();
assertTrue(rewriteMethod instanceof SpanMultiTermQueryBuilder.TopTermSpanBooleanQueryRewriteWithMaxClause);
}
}
public void testTermExpansionExceptionOnSpanFailure() throws Exception {
try (Directory directory = newDirectory()) {
try (RandomIndexWriter iw = new RandomIndexWriter(random(), directory, new WhitespaceAnalyzer())) {
for (int i = 0; i < 3; i++) {
iw.addDocument(singleton(new TextField("body", "foo bar" + Integer.toString(i), Field.Store.NO)));
}
try (IndexReader reader = iw.getReader()) {
int origBoolMaxClauseCount = BooleanQuery.getMaxClauseCount();
BooleanQuery.setMaxClauseCount(1);
try {
QueryBuilder queryBuilder = new SpanMultiTermQueryBuilder(
QueryBuilders.prefixQuery("body", "bar")
);
Query query = queryBuilder.toQuery(createShardContext(reader));
RuntimeException exc = expectThrows(RuntimeException.class, () -> query.rewrite(reader));
assertThat(exc.getMessage(), containsString("maxClauseCount"));
} finally {
BooleanQuery.setMaxClauseCount(origBoolMaxClauseCount);
}
}
}
}
}
public void testTopNMultiTermsRewriteInsideSpan() throws Exception {
Query query = QueryBuilders.spanMultiTermQueryBuilder(QueryBuilders.prefixQuery("foo", "b").rewrite
("top_terms_boost_2000")).
toQuery(createShardContext());
Query query = QueryBuilders.spanMultiTermQueryBuilder(
QueryBuilders.prefixQuery("foo", "b").rewrite("top_terms_boost_2000")
).toQuery(createShardContext());
if (query instanceof SpanBoostQuery) {
query = ((SpanBoostQuery)query).getQuery();

View File

@ -1825,31 +1825,4 @@ public class SearchQueryIT extends ESIntegTestCase {
SearchResponse searchResponse = client().prepareSearch("test").setQuery(range).get();
assertHitCount(searchResponse, 1);
}
public void testTermExpansionExceptionOnSpanFailure() throws ExecutionException, InterruptedException {
Settings.Builder builder = Settings.builder();
builder.put(SETTING_NUMBER_OF_SHARDS, 1).build();
createIndex("test", builder.build());
ArrayList<IndexRequestBuilder> reqs = new ArrayList<>();
int origBoolMaxClauseCount = BooleanQuery.getMaxClauseCount();
try {
BooleanQuery.setMaxClauseCount(2);
for (int i = 0; i < BooleanQuery.getMaxClauseCount() + 1; i++) {
reqs.add(client().prepareIndex("test", "_doc", Integer.toString(i)).setSource("body", "foo" +
Integer.toString(i) + " bar baz"));
}
indexRandom(true, false, reqs);
QueryBuilder queryBuilder = new SpanNearQueryBuilder(new SpanMultiTermQueryBuilder(QueryBuilders.wildcardQuery
("body", "f*")), 0).addClause(new SpanTermQueryBuilder("body", "bar"));
expectThrows(ElasticsearchException.class, () ->
client().prepareSearch().setIndices("test").setQuery(queryBuilder).get());
} finally {
BooleanQuery.setMaxClauseCount(origBoolMaxClauseCount);
}
}
}