[TEST] added tests for alternate queries formats

We currently test that our query parsers can parse the format that our query builder outputs in XContent format, but in some cases the parser supports more than that, hence we need more specific tests otherwise we have no coverage for alternate formats.
This commit is contained in:
javanna 2015-08-17 19:16:24 +02:00 committed by Luca Cavanna
parent 2d42839eef
commit 37b2007eb4
9 changed files with 186 additions and 77 deletions

View File

@ -75,14 +75,6 @@ public class OrQueryParser extends BaseQueryParser<OrQueryBuilder> {
queries.add(filter);
}
}
} else {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
queriesFound = true;
QueryBuilder filter = parseContext.parseInnerFilterToQueryBuilder();
if (filter != null) {
queries.add(filter);
}
}
}
} else if (token.isValue()) {
if ("_name".equals(currentFieldName)) {

View File

@ -27,15 +27,9 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.*;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.*;
@SuppressWarnings("deprecation")
public class AndQueryBuilderTest extends BaseQueryTestCase<AndQueryBuilder> {
@ -119,28 +113,14 @@ public class AndQueryBuilderTest extends BaseQueryTestCase<AndQueryBuilder> {
assertValidate(andQuery, totalExpectedErrors);
}
public void testParsingToplevelArray() throws IOException {
QueryParseContext context = createParseContext();
String queryString = "{ \"and\" : [ { \"match_all\" : {} } ] }";
XContentParser parser = XContentFactory.xContent(queryString).createParser(queryString);
context.reset(parser);
assertThat(parser.nextToken(), is(XContentParser.Token.START_OBJECT));
assertThat(parser.nextToken(), is(XContentParser.Token.FIELD_NAME));
assertThat(parser.currentName(), is(AndQueryBuilder.NAME));
parser.nextToken();
AndQueryBuilder queryBuilder = (AndQueryBuilder) context.queryParser(AndQueryBuilder.NAME).fromXContent(context);
assertThat(queryBuilder.innerQueries().get(0), equalTo((QueryBuilder) new MatchAllQueryBuilder()));
}
public void testParsingFiltersArray() throws IOException {
QueryParseContext context = createParseContext();
String queryString = "{ \"and\" : { \"filters\" : [ { \"match_all\" : {} } ], \"boost\" : 0.7 } }";
XContentParser parser = XContentFactory.xContent(queryString).createParser(queryString);
context.reset(parser);
assertQueryHeader(parser, AndQueryBuilder.NAME);
AndQueryBuilder queryBuilder = (AndQueryBuilder) context.queryParser(AndQueryBuilder.NAME).fromXContent(context);
assertThat(queryBuilder.innerQueries().get(0), equalTo((QueryBuilder) new MatchAllQueryBuilder()));
assertThat(queryBuilder.boost(), equalTo(0.7f));
@Override
protected Map<String, AndQueryBuilder> getAlternateVersions() {
Map<String, AndQueryBuilder> alternateVersions = new HashMap<>();
QueryBuilder innerQuery = createTestQueryBuilder().innerQueries().get(0);
AndQueryBuilder expectedQuery = new AndQueryBuilder(innerQuery);
String contentString = "{ \"and\" : [ " + innerQuery + "] }";
alternateVersions.put(contentString, expectedQuery);
return alternateVersions;
}
@Test(expected=QueryParsingException.class)

View File

@ -41,6 +41,8 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule;
import org.elasticsearch.common.unit.Fuzziness;
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.env.Environment;
@ -71,6 +73,8 @@ import org.joda.time.DateTimeZone;
import org.junit.*;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import static org.hamcrest.Matchers.*;
@ -223,16 +227,32 @@ public abstract class BaseQueryTestCase<QB extends AbstractQueryBuilder<QB>> ext
@Test
public void testFromXContent() throws IOException {
QB testQuery = createTestQueryBuilder();
QueryParseContext context = createParseContext();
String contentString = testQuery.toString();
XContentParser parser = XContentFactory.xContent(contentString).createParser(contentString);
context.reset(parser);
assertQueryHeader(parser, testQuery.getName());
assertParsedQuery(testQuery.toString(), testQuery);
for (Map.Entry<String, QB> alternateVersion : getAlternateVersions().entrySet()) {
assertParsedQuery(alternateVersion.getKey(), alternateVersion.getValue());
}
}
QueryBuilder newQuery = queryParserService.queryParser(testQuery.getName()).fromXContent(context);
assertNotSame(newQuery, testQuery);
assertEquals(testQuery, newQuery);
assertEquals(testQuery.hashCode(), newQuery.hashCode());
/**
* Returns alternate string representation of the query that need to be tested as they are never used as output
* of {@link QueryBuilder#toXContent(XContentBuilder, ToXContent.Params)}. By default there are no alternate versions.
*/
protected Map<String, QB> getAlternateVersions() {
return Collections.emptyMap();
}
/**
* Parses the query provided as string argument and compares it with the expected result provided as argument as a {@link QueryBuilder}
*/
protected void assertParsedQuery(String queryAsString, QueryBuilder<?> expectedQuery) throws IOException {
XContentParser parser = XContentFactory.xContent(queryAsString).createParser(queryAsString);
QueryParseContext context = createParseContext();
context.reset(parser);
assertQueryHeader(parser, expectedQuery.getName());
QueryBuilder newQuery = queryParser(expectedQuery).fromXContent(context);
assertNotSame(newQuery, expectedQuery);
assertEquals(expectedQuery, newQuery);
assertEquals(expectedQuery.hashCode(), newQuery.hashCode());
}
/**
@ -307,7 +327,7 @@ public abstract class BaseQueryTestCase<QB extends AbstractQueryBuilder<QB>> ext
try (BytesStreamOutput output = new BytesStreamOutput()) {
testQuery.writeTo(output);
try (StreamInput in = new NamedWriteableAwareStreamInput(StreamInput.wrap(output.bytes()), namedWriteableRegistry)) {
QueryBuilder<?> prototype = queryParserService.queryParser(testQuery.getWriteableName()).getBuilderPrototype();
QueryBuilder<?> prototype = queryParser(testQuery).getBuilderPrototype();
QueryBuilder deserializedQuery = prototype.readFrom(in);
assertEquals(deserializedQuery, testQuery);
assertEquals(deserializedQuery.hashCode(), testQuery.hashCode());
@ -348,12 +368,16 @@ public abstract class BaseQueryTestCase<QB extends AbstractQueryBuilder<QB>> ext
assertThat("different queries should have different hashcode", secondQuery.hashCode(), not(equalTo(firstQuery.hashCode())));
}
protected QueryParser<?> queryParser(QueryBuilder query) {
return queryParserService.queryParser(query.getName());
}
//we use the streaming infra to create a copy of the query provided as argument
private QB copyQuery(QB query) throws IOException {
try (BytesStreamOutput output = new BytesStreamOutput()) {
query.writeTo(output);
try (StreamInput in = new NamedWriteableAwareStreamInput(StreamInput.wrap(output.bytes()), namedWriteableRegistry)) {
QueryBuilder<?> prototype = queryParserService.queryParser(query.getWriteableName()).getBuilderPrototype();
QueryBuilder<?> prototype = queryParser(query).getBuilderPrototype();
@SuppressWarnings("unchecked")
QB secondQuery = (QB)prototype.readFrom(in);
return secondQuery;
@ -381,7 +405,7 @@ public abstract class BaseQueryTestCase<QB extends AbstractQueryBuilder<QB>> ext
assertThat(parser.nextToken(), is(XContentParser.Token.START_OBJECT));
assertThat(parser.nextToken(), is(XContentParser.Token.FIELD_NAME));
assertThat(parser.currentName(), is(expectedParserName));
assertThat(parser.nextToken(), is(XContentParser.Token.START_OBJECT));
assertThat(parser.nextToken(), either(is(XContentParser.Token.START_OBJECT)).or(is(XContentParser.Token.START_ARRAY)));
}
protected static void assertValidate(QueryBuilder queryBuilder, int totalExpectedErrors) {

View File

@ -21,6 +21,9 @@ package org.elasticsearch.index.query;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.is;
public abstract class BaseTermQueryTestCase<QB extends BaseTermQueryBuilder<QB>> extends BaseQueryTestCase<QB> {
@ -88,4 +91,20 @@ public abstract class BaseTermQueryTestCase<QB extends BaseTermQueryBuilder<QB>>
assertNotNull(queryBuilder.validate());
assertThat(queryBuilder.validate().validationErrors().size(), is(2));
}
@Override
protected Map<String, QB> getAlternateVersions() {
HashMap<String, QB> alternateVersions = new HashMap<>();
QB tempQuery = createTestQueryBuilder();
QB testQuery = createQueryBuilder(tempQuery.fieldName(), tempQuery.value());
boolean isString = testQuery.value() instanceof String;
String value = (isString ? "\"" : "") + testQuery.value() + (isString ? "\"" : "");
String contentString = "{\n" +
" \"" + testQuery.getName() + "\" : {\n" +
" \"" + testQuery.fieldName() + "\" : " + value + "\n" +
" }\n" +
"}";
alternateVersions.put(contentString, testQuery);
return alternateVersions;
}
}

View File

@ -26,9 +26,7 @@ import org.apache.lucene.search.Query;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.*;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
@ -114,6 +112,39 @@ public class BoolQueryBuilderTest extends BaseQueryTestCase<BoolQueryBuilder> {
return clauses;
}
@Override
protected Map<String, BoolQueryBuilder> getAlternateVersions() {
Map<String, BoolQueryBuilder> alternateVersions = new HashMap<>();
BoolQueryBuilder tempQueryBuilder = createTestQueryBuilder();
BoolQueryBuilder expectedQuery = new BoolQueryBuilder();
String contentString = "{\n" +
" \"bool\" : {\n";
if (tempQueryBuilder.must().size() > 0) {
QueryBuilder must = tempQueryBuilder.must().get(0);
contentString += "must: " + must.toString() + ",";
expectedQuery.must(must);
}
if (tempQueryBuilder.mustNot().size() > 0) {
QueryBuilder mustNot = tempQueryBuilder.mustNot().get(0);
contentString += (randomBoolean() ? "must_not: " : "mustNot: ") + mustNot.toString() + ",";
expectedQuery.mustNot(mustNot);
}
if (tempQueryBuilder.should().size() > 0) {
QueryBuilder should = tempQueryBuilder.should().get(0);
contentString += "should: " + should.toString() + ",";
expectedQuery.should(should);
}
if (tempQueryBuilder.filter().size() > 0) {
QueryBuilder filter = tempQueryBuilder.filter().get(0);
contentString += "filter: " + filter.toString() + ",";
expectedQuery.filter(filter);
}
contentString = contentString.substring(0, contentString.length() - 1);
contentString += " } \n" + "}";
alternateVersions.put(contentString, expectedQuery);
return alternateVersions;
}
@Test
public void testValidate() {
BoolQueryBuilder booleanQuery = new BoolQueryBuilder();

View File

@ -27,7 +27,9 @@ import org.junit.Test;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
@ -68,6 +70,21 @@ public class DisMaxQueryBuilderTest extends BaseQueryTestCase<DisMaxQueryBuilder
}
}
@Override
protected Map<String, DisMaxQueryBuilder> getAlternateVersions() {
Map<String, DisMaxQueryBuilder> alternateVersions = new HashMap<>();
QueryBuilder innerQuery = createTestQueryBuilder().innerQueries().get(0);
DisMaxQueryBuilder expectedQuery = new DisMaxQueryBuilder();
expectedQuery.add(innerQuery);
String contentString = "{\n" +
" \"dis_max\" : {\n" +
" \"queries\" : " + innerQuery.toString() +
" }\n" +
"}";
alternateVersions.put(contentString, expectedQuery);
return alternateVersions;
}
/**
* test `null`return value for missing inner queries
* @throws IOException

View File

@ -29,6 +29,8 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.junit.Test;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
@ -94,4 +96,35 @@ public class IdsQueryBuilderTest extends BaseQueryTestCase<IdsQueryBuilder> {
assertThat(query, instanceOf(TermsQuery.class));
}
}
@Override
protected Map<String, IdsQueryBuilder> getAlternateVersions() {
Map<String, IdsQueryBuilder> alternateVersions = new HashMap<>();
IdsQueryBuilder tempQuery = createTestQueryBuilder();
if (tempQuery.types() != null && tempQuery.types().length > 0) {
String type = tempQuery.types()[0];
IdsQueryBuilder testQuery = new IdsQueryBuilder(type);
//single value type can also be called _type
String contentString1 = "{\n" +
" \"ids\" : {\n" +
" \"_type\" : \"" + type + "\",\n" +
" \"values\" : []\n" +
" }\n" +
"}";
alternateVersions.put(contentString1, testQuery);
//array of types can also be called type rather than types
String contentString2 = "{\n" +
" \"ids\" : {\n" +
" \"type\" : [\"" + type + "\"],\n" +
" \"values\" : []\n" +
" }\n" +
"}";
alternateVersions.put(contentString2, testQuery);
}
return alternateVersions;
}
}

View File

@ -28,6 +28,8 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.junit.Test;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
@ -72,6 +74,30 @@ public class NotQueryBuilderTest extends BaseQueryTestCase<NotQueryBuilder> {
context.queryParser(NotQueryBuilder.NAME).fromXContent(context);
}
@Override
protected Map<String, NotQueryBuilder> getAlternateVersions() {
Map<String, NotQueryBuilder> alternateVersions = new HashMap<>();
NotQueryBuilder testQuery1 = new NotQueryBuilder(createTestQueryBuilder().innerQuery());
String contentString1 = "{\n" +
" \"not\" : {\n" +
" \"filter\" : " + testQuery1.innerQuery().toString() + "\n" +
" }\n" +
"}";
alternateVersions.put(contentString1, testQuery1);
QueryBuilder innerQuery = createTestQueryBuilder().innerQuery();
//not doesn't support empty query when query/filter element is not specified
if (innerQuery != EmptyQueryBuilder.PROTOTYPE) {
NotQueryBuilder testQuery2 = new NotQueryBuilder(innerQuery);
String contentString2 = "{\n" +
" \"not\" : " + testQuery2.innerQuery().toString() + "\n}";
alternateVersions.put(contentString2, testQuery2);
}
return alternateVersions;
}
@Test
public void testValidate() {
QueryBuilder innerQuery = null;

View File

@ -27,9 +27,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.*;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
@ -38,27 +36,6 @@ import static org.hamcrest.CoreMatchers.nullValue;
@SuppressWarnings("deprecation")
public class OrQueryBuilderTest extends BaseQueryTestCase<OrQueryBuilder> {
/*
@Override
protected Query doCreateExpectedQuery(OrQueryBuilder queryBuilder, QueryCreationContext context) throws QueryCreationException, IOException {
if (queryBuilder.filters().isEmpty()) {
return null;
}
BooleanQuery query = new BooleanQuery();
for (QueryBuilder subQuery : queryBuilder.filters()) {
Query innerQuery = subQuery.toQuery(context);
// ignore queries that are null
if (innerQuery != null) {
query.add(innerQuery, Occur.SHOULD);
}
}
if (query.clauses().isEmpty()) {
return null;
}
return query;
}
*/
/**
* @return an OrQueryBuilder with random limit between 0 and 20
*/
@ -109,6 +86,16 @@ public class OrQueryBuilderTest extends BaseQueryTestCase<OrQueryBuilder> {
assertNull(orQuery.toQuery(createShardContext()));
}
@Override
protected Map<String, OrQueryBuilder> getAlternateVersions() {
Map<String, OrQueryBuilder> alternateVersions = new HashMap<>();
QueryBuilder innerQuery = createTestQueryBuilder().innerQueries().get(0);
OrQueryBuilder expectedQuery = new OrQueryBuilder(innerQuery);
String contentString = "{ \"or\" : [ " + innerQuery + "] }";
alternateVersions.put(contentString, expectedQuery);
return alternateVersions;
}
@Test(expected=QueryParsingException.class)
public void testMissingFiltersSection() throws IOException {
QueryParseContext context = createParseContext();