package querqy.rewrite.commonrules;
import static org.junit.Assert.*;
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.hamcrest.Matchers.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Test;
import querqy.parser.WhiteSpaceQuerqyParserFactory;
import querqy.rewrite.commonrules.model.*;
import querqy.rewrite.commonrules.model.BoostInstruction.BoostDirection;
public class LineParserTest {
@Test
public void testParseTermValueOnly() {
Term term = LineParser.parseTerm("abc");
assertEquals(3, term.length());
assertArrayEquals(new char[] {'a', 'b', 'c'},new char[] {term.charAt(0), term.charAt(1), term.charAt(2)});
assertFalse(term instanceof PrefixTerm);
assertNull(term.getFieldNames());
}
@Test
public void testParseSingleLetterValue() throws Exception {
Term term = LineParser.parseTerm("a");
assertEquals(1, term.length());
assertArrayEquals(new char[] {'a'},new char[] {term.charAt(0)});
assertFalse(term instanceof PrefixTerm);
assertNull(term.getFieldNames());
}
@Test
public void testParseTermWithFieldName() throws Exception {
Term term = LineParser.parseTerm("f1:abc");
assertEquals(3, term.length());
assertArrayEquals(new char[] {'a', 'b', 'c'},new char[] {term.charAt(0), term.charAt(1), term.charAt(2)});
assertFalse(term instanceof PrefixTerm);
assertEquals(Arrays.asList("f1"), term.getFieldNames());
}
@Test
public void testParseSingleLetterValueWithFieldName() throws Exception {
Term term = LineParser.parseTerm("f1:a");
assertEquals(1, term.length());
assertArrayEquals(new char[] {'a'},new char[] {term.charAt(0)});
assertFalse(term instanceof PrefixTerm);
assertEquals(Arrays.asList("f1"), term.getFieldNames());
}
@Test
public void testParseTermWithFieldNames() throws Exception {
Term term = LineParser.parseTerm("{f1,f2}:abc");
assertEquals(3, term.length());
assertArrayEquals(new char[] {'a', 'b', 'c'},new char[] {term.charAt(0), term.charAt(1), term.charAt(2)});
assertFalse(term instanceof PrefixTerm);
assertThat(term.getFieldNames(), containsInAnyOrder("f1", "f2"));
}
@Test
public void testParseTermWithFieldNamesContainingSpace() throws Exception {
assertThat(LineParser.parseTerm("{ f1 , f2 }:abc"), term("abc", "f1", "f2"));
}
@Test
public void testParsePrefixOnly() {
Term term = LineParser.parseTerm("abc*");
assertEquals(3, term.length());
assertArrayEquals(new char[] {'a', 'b', 'c'},new char[] {term.charAt(0), term.charAt(1), term.charAt(2)});
assertTrue(term instanceof PrefixTerm);
assertNull(term.getFieldNames());
}
@Test
public void testParseSingleLetterPrefix() throws Exception {
assertThat(LineParser.parseTerm("a*"), prefix("a"));
}
@Test
public void testParsePrefixWithFieldName() throws Exception {
assertThat(LineParser.parseTerm("f1:abc*"), prefix("abc", "f1"));
}
@Test
public void testParsePrefixWithFieldNames() throws Exception {
assertThat(LineParser.parseTerm("{f1,f2}:abc*"), prefix("abc", "f1", "f2"));
}
@Test
public void testThatWildcardOnlyTermIsNotAllowed() throws Exception {
try {
LineParser.parseTerm("*");
fail("Wildcard-only term must not be allowed");
} catch (IllegalArgumentException e) {
// expected
}
}
@Test
public void testThatWildcardOnlyTermIsNotAllowedWithFieldName() throws Exception {
try {
LineParser.parseTerm("f1:*");
fail("Wildcard-only term must not be allowed with fieldname");
} catch (IllegalArgumentException e) {
// expected
}
}
@Test
public void testThatWildcardOnlyTermIsNotAllowedWithFieldNames() throws Exception {
try {
LineParser.parseTerm("{f1,f2}:*");
fail("Wildcard-only term must not be allowed with fieldname");
} catch (IllegalArgumentException e) {
// expected
}
}
@Test
public void testThatWildcardCannotBeFollowedByRightBoundary() throws Exception {
Object parseResult = LineParser.parseInput("a" + LineParser.WILDCARD + LineParser.BOUNDARY);
assertEquals("Wildcard should not be allowed before right boundary",
new ValidationError(LineParser.WILDCARD + " cannot be combined with right boundary"), parseResult);
}
@Test
public void testThatWildcardCanBeCombinedWithLeftBoundary() throws Exception {
Object parseResult = LineParser.parseInput(LineParser.BOUNDARY + "a" + LineParser.WILDCARD);
assertTrue(parseResult instanceof Input);
Input input = (Input) parseResult;
assertTrue(input.requiresLeftBoundary());
assertFalse(input.requiresRightBoundary());
}
@Test
public void testThatBoundariesAreParsedInInput() throws Exception {
Object parseResult = LineParser.parseInput(LineParser.BOUNDARY + "a" + LineParser.BOUNDARY);
assertTrue(parseResult instanceof Input);
Input input = (Input) parseResult;
assertTrue(input.requiresLeftBoundary());
assertTrue(input.requiresRightBoundary());
}
@Test
public void testThatBoundariesAreParsedInOtherwiseEmptyInput() throws Exception {
Object parseResult = LineParser.parseInput(LineParser.BOUNDARY + "" + LineParser.BOUNDARY);
assertTrue(parseResult instanceof Input);
Input input = (Input) parseResult;
assertTrue(input.requiresLeftBoundary());
assertTrue(input.requiresRightBoundary());
}
@Test
public void testThatBoostInstructionWithSingleLetterTermIsAccepted() throws Exception {
String line = "UP: x";
String lcLine = line.toLowerCase();
final Object instruction = LineParser
.parseBoostInstruction(line, lcLine, 2, BoostDirection.UP, new WhiteSpaceQuerqyParserFactory());
assertTrue(instruction instanceof BoostInstruction);
}
@Test
public void testThatBoostInstructionWithSingleLetterTermAndBoostFactorIsAccepted() throws Exception {
String line = "UP(5): x";
String lcLine = line.toLowerCase();
final Object instruction = LineParser
.parseBoostInstruction(line, lcLine, 2, BoostDirection.UP, new WhiteSpaceQuerqyParserFactory());
assertTrue(instruction instanceof BoostInstruction);
}
@Test
public void testThatPlayholdersAreParsedForBoostInstruction() throws Exception {
String line = "UP(500): 3$1";
String lcLine = line.toLowerCase();
final Object instruction = LineParser
.parseBoostInstruction(line, lcLine, 2, BoostDirection.UP, new WhiteSpaceQuerqyParserFactory());
assertTrue(instruction instanceof BoostInstruction);
assertTrue(((BoostInstruction) instruction).hasPlaceHolderInBoostQuery());
}
@SuppressWarnings("unchecked")
@Test
public void testParseTermExpressionSingleTerm() {
assertThat((List<Term>) LineParser.parseTermExpression("abc"), contains(term("abc")));
}
@SuppressWarnings("unchecked")
@Test
public void testParseTermExpressionSingleLetter() {
assertThat((List<Term>) LineParser.parseTermExpression("a"), contains(term("a")));
}
@SuppressWarnings("unchecked")
@Test
public void testParseTermExpressionMultipleTerms() {
assertThat((List<Term>) LineParser.parseTermExpression("abc def"), contains(term("abc"), term("def")));
}
@SuppressWarnings("unchecked")
@Test
public void testParseTermExpressionMultiplePrefixes() {
assertThat((List<Term>) LineParser.parseTermExpression("abc* def*"), contains(prefix("abc"), prefix("def")));
}
@SuppressWarnings("unchecked")
@Test
public void testParseTermExpressionMixed() {
assertThat((List<Term>) LineParser.parseTermExpression("abc* def ghij* klmn"), contains(prefix("abc"), term("def"), prefix("ghij"), term("klmn")));
}
@Test
public void testInputWithWildcard() {
assertTrue("parseInput must not allow wildcard in the middle", LineParser.parseInput("abc* def ghij*") instanceof ValidationError);
}
@Test
public void testParseTermExpressionDoesNotAllowAWildCardOnly() {
assertTrue("parseTermExpression must not allow single wild card", LineParser.parseTermExpression("*") instanceof ValidationError);
}
@Test
public void testThatCaseIsPreservedInDecorateInstruction() throws Exception {
Input input = (Input) LineParser.parseInput("in");
assertEquals(new DecorateInstruction("Some Deco"), LineParser.parse("DECORATE: Some Deco", input, null));
}
TermMatcher term(String value, String...fieldNames) {
return new TermMatcher(Term.class, value, fieldNames);
}
TermMatcher prefix(String value, String...fieldNames) {
return new TermMatcher(PrefixTerm.class, value, fieldNames);
}
private static class TermMatcher extends TypeSafeMatcher<Term> {
final String value;
final String[] fieldNames;
final Class<?> clazz;
public TermMatcher(Class<?> clazz, String value, String...fieldNames) {
this.clazz = clazz;
this.fieldNames = fieldNames.length == 0 ? null : fieldNames;
this.value = value;
}
@Override
public void describeTo(Description description) {
description.appendText("value: ").appendValue(value).appendText("fieldNames: " ).appendValue(fieldNames);
}
@Override
protected boolean matchesSafely(Term item) {
return item.getClass().equals(clazz)
&& item.compareTo(value) == 0
&& ((fieldNames == null && null == item.getFieldNames())
||
((fieldNames != null)
&& (item.getFieldNames() != null)
&& new HashSet<String>(Arrays.asList(fieldNames)).equals(new HashSet<>(item.getFieldNames()))))
;
}
}
}