// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchdefinition;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import com.yahoo.document.DataType;
import com.yahoo.searchdefinition.document.SDField;
import com.yahoo.searchdefinition.parser.ParseException;
/**
* @author Lester Solbakken
* @since 5.2
*/
public class PredicateDataTypeTestCase {
private String searchSd(String field) {
return "search p {\n document p {\n" + field + "}\n}\n";
}
private String predicateFieldSd(String index) {
return "field pf type predicate {\n" + index + "}\n";
}
private String arrayPredicateFieldSd(String index) {
return "field apf type array {\n" + index + "}\n";
}
private String stringFieldSd(String index) {
return "field sf type string {\n" + index + "}\n";
}
private String attributeFieldSd(String terms) {
return "indexing: attribute\n index {\n" + terms + "}\n";
}
private String arityParameter(int arity) {
return "arity: " + arity + "\n";
}
private String lowerBoundParameter(long bound) {
return "lower-bound: " + bound + "\n";
}
private String upperBoundParameter(long bound) {
return "upper-bound: " + bound + "\n";
}
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void requireThatBuilderSetsIndexParametersCorrectly() throws ParseException {
int arity = 2;
long lowerBound = -100;
long upperBound = 100;
String sd = searchSd(
predicateFieldSd(
attributeFieldSd(
arityParameter(arity) +
lowerBoundParameter(lowerBound) +
upperBoundParameter(upperBound))));
SearchBuilder sb = SearchBuilder.createFromString(sd);
for (SDField field : sb.getSearch().allConcreteFields()) {
if (field.getDataType() == DataType.PREDICATE) {
for (Index index : field.getIndices().values()) {
assertEquals(true, index.getBooleanIndexDefiniton().hasArity());
assertEquals(arity, index.getBooleanIndexDefiniton().getArity());
assertEquals(true, index.getBooleanIndexDefiniton().hasLowerBound());
assertEquals(lowerBound, index.getBooleanIndexDefiniton().getLowerBound());
assertEquals(true, index.getBooleanIndexDefiniton().hasUpperBound());
assertEquals(upperBound, index.getBooleanIndexDefiniton().getUpperBound());
}
}
}
}
@Test
public void requireThatBuilderHandlesLongValues() throws ParseException {
int arity = 2;
long lowerBound = -100000000000000000L;
long upperBound = 1000000000000000000L;
String sd = searchSd(
predicateFieldSd(
attributeFieldSd(
arityParameter(arity) +
"lower-bound: -100000000000000000L\n" + // +'L'
upperBoundParameter(upperBound))));
SearchBuilder sb = SearchBuilder.createFromString(sd);
for (SDField field : sb.getSearch().allConcreteFields()) {
if (field.getDataType() == DataType.PREDICATE) {
for (Index index : field.getIndices().values()) {
assertEquals(arity, index.getBooleanIndexDefiniton().getArity());
assertEquals(lowerBound, index.getBooleanIndexDefiniton().getLowerBound());
assertEquals(upperBound, index.getBooleanIndexDefiniton().getUpperBound());
}
}
}
}
@Test
public void requireThatBuilderHandlesMissingParameters() throws ParseException {
String sd = searchSd(
predicateFieldSd(
attributeFieldSd(
arityParameter(2))));
SearchBuilder sb = SearchBuilder.createFromString(sd);
for (SDField field : sb.getSearch().allConcreteFields()) {
if (field.getDataType() == DataType.PREDICATE) {
for (Index index : field.getIndices().values()) {
assertEquals(true, index.getBooleanIndexDefiniton().hasArity());
assertEquals(false, index.getBooleanIndexDefiniton().hasLowerBound());
assertEquals(false, index.getBooleanIndexDefiniton().hasUpperBound());
}
}
}
}
@Test
public void requireThatBuilderFailsIfNoArityValue() throws ParseException {
String sd = searchSd(predicateFieldSd(attributeFieldSd("")));
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Missing arity value in predicate field.");
SearchBuilder.createFromString(sd);
assertTrue(false);
}
@Test
public void requireThatBuilderFailsIfBothIndexAndAttribute() throws ParseException {
String sd = searchSd(predicateFieldSd("indexing: summary | index | attribute\nindex { arity: 2 }"));
exception.expect(IllegalArgumentException.class);
exception.expectMessage("For search 'p', field 'pf': Use 'attribute' instead of 'index'. This will require a refeed if you have upgraded.");
SearchBuilder.createFromString(sd);
}
@Test
public void requireThatBuilderFailsIfIndex() throws ParseException {
String sd = searchSd(predicateFieldSd("indexing: summary | index \nindex { arity: 2 }"));
exception.expect(IllegalArgumentException.class);
exception.expectMessage("For search 'p', field 'pf': Use 'attribute' instead of 'index'. This will require a refeed if you have upgraded.");
SearchBuilder.createFromString(sd);
}
@Test
public void requireThatBuilderFailsIfIllegalArityValue() throws ParseException {
String sd = searchSd(predicateFieldSd(attributeFieldSd(arityParameter(0))));
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Invalid arity value in predicate field, must be greater than 1.");
SearchBuilder.createFromString(sd);
}
@Test
public void requireThatBuilderFailsIfArityParameterExistButNotPredicateField() throws ParseException {
String sd = searchSd(stringFieldSd(attributeFieldSd(arityParameter(2))));
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Arity parameter is used only for predicate type fields.");
SearchBuilder.createFromString(sd);
}
@Test
public void requireThatBuilderFailsIfBoundParametersExistButNotPredicateField() throws ParseException {
String sd = searchSd(
stringFieldSd(
attributeFieldSd(
lowerBoundParameter(100) + upperBoundParameter(1000))));
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Parameters lower-bound and upper-bound are used only for predicate type fields.");
SearchBuilder.createFromString(sd);
}
@Test
public void requireThatArrayOfPredicateFails() throws ParseException {
String sd = searchSd(
arrayPredicateFieldSd(
attributeFieldSd(
arityParameter(1))));
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Collections of predicates are not allowed.");
SearchBuilder.createFromString(sd);
}
}