/* * Copyright 2012-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.data.solr.core.query; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.hamcrest.collection.IsIterableContainingInOrder; import org.hamcrest.core.Is; import org.hamcrest.core.IsInstanceOf; import org.junit.Assert; import org.junit.Test; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.geo.Distance; import org.springframework.data.geo.Point; import org.springframework.data.solr.core.query.Criteria.OperationKey; import org.springframework.data.solr.core.query.Criteria.Predicate; /** * @author Christoph Strobl * @author John Dorman * @author Philipp Jardas */ public class CriteriaTests { @Test(expected = IllegalArgumentException.class) public void testCriteriaForNullString() { new Criteria((String) null); } @Test(expected = IllegalArgumentException.class) public void testCriteriaForNullField() { new Criteria((Field) null); } @Test(expected = IllegalArgumentException.class) public void testCriteriaForNullFieldName() { new Criteria(new SimpleField(StringUtils.EMPTY)); } @Test public void testIs() { Criteria criteria = new Criteria("field_1").is("is"); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.EQUALS, "is"); } @Test public void testMultipleIs() { Criteria criteria = new Criteria("field_1").is("is").is("another is"); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.EQUALS, "is"); assertPredicate(criteria.getPredicates(), 1, OperationKey.EQUALS, "another is"); } @Test public void testIsWithCollection() { Criteria criteria = new Criteria("field_1").is(Arrays.asList("is", "another is")); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.EQUALS, "is"); assertPredicate(criteria.getPredicates(), 1, OperationKey.EQUALS, "another is"); } @Test public void testIsWithNull() { Criteria criteria = new Criteria("field_1").is((Object) null); Assert.assertEquals("field_1", criteria.getField().getName()); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertNull(((Object[]) entry.getValue())[0]); Assert.assertNull(((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testIsNull() { Criteria criteria = new Criteria("field_1").isNull(); Assert.assertEquals("field_1", criteria.getField().getName()); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertTrue(criteria.isNegating()); Assert.assertNull(((Object[]) entry.getValue())[0]); Assert.assertNull(((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testIsNotNull() { Criteria criteria = new Criteria("field_1").isNotNull(); Assert.assertEquals("field_1", criteria.getField().getName()); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertFalse(criteria.isNegating()); Assert.assertNull(((Object[]) entry.getValue())[0]); Assert.assertNull(((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test(expected = InvalidDataAccessApiUsageException.class) public void testContainsWithBlank() { new Criteria("field_1").contains("no blank"); } @Test(expected = InvalidDataAccessApiUsageException.class) public void testStartsWithBlank() { new Criteria("field_1").startsWith("no blank"); } @Test(expected = InvalidDataAccessApiUsageException.class) public void testEndsWithBlank() { new Criteria("field_1").endsWith("no blank"); } @Test public void testEndsWith() { Criteria criteria = new Criteria("field_1").endsWith("end"); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.ENDS_WITH, "end"); } @Test public void testEndsWithCollection() { Criteria criteria = new Criteria("field_1").endsWith(Arrays.asList("use", "multiple", "values")); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.ENDS_WITH, "use"); assertPredicate(criteria.getPredicates(), 1, OperationKey.ENDS_WITH, "multiple"); assertPredicate(criteria.getPredicates(), 2, OperationKey.ENDS_WITH, "values"); } @Test public void testStartsWith() { Criteria criteria = new Criteria("field_1").startsWith("start"); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.STARTS_WITH, "start"); } @Test public void testStartsWithCollection() { Criteria criteria = new Criteria("field_1").startsWith(Arrays.asList("use", "multiple", "values")); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.STARTS_WITH, "use"); assertPredicate(criteria.getPredicates(), 1, OperationKey.STARTS_WITH, "multiple"); assertPredicate(criteria.getPredicates(), 2, OperationKey.STARTS_WITH, "values"); } @Test public void testContains() { Criteria criteria = new Criteria("field_1").contains("contains"); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.CONTAINS, "contains"); } @Test public void testContainWithCollection() { Criteria criteria = new Criteria("field_1").contains(Arrays.asList("use", "multiple", "values")); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.CONTAINS, "use"); assertPredicate(criteria.getPredicates(), 1, OperationKey.CONTAINS, "multiple"); assertPredicate(criteria.getPredicates(), 2, OperationKey.CONTAINS, "values"); } @Test public void testExpression() { Criteria criteria = new Criteria("field_1").expression("(have fun using +solr && expressions*)"); assertPredicate(criteria.getPredicates(), 0, OperationKey.EXPRESSION, "(have fun using +solr && expressions*)"); } @Test public void testCriteriaChain() { Criteria criteria = new Criteria("field_1").startsWith("start").endsWith("end").contains("contains").is("is"); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.STARTS_WITH, "start"); assertPredicate(criteria.getPredicates(), 1, OperationKey.ENDS_WITH, "end"); assertPredicate(criteria.getPredicates(), 2, OperationKey.CONTAINS, "contains"); assertPredicate(criteria.getPredicates(), 3, OperationKey.EQUALS, "is"); } @Test // DATASOLR-105 public void testAndShouldProduceCrotch() { Criteria criteria = new Criteria("field_1").startsWith("start").endsWith("end").and("field_2").startsWith("2start") .endsWith("2end"); Assert.assertThat(criteria, IsInstanceOf.instanceOf(Crotch.class)); } @Test // DATASOLR-105 public void testCirteriasJoindWihtAndShouldBeSiblingsOfCreatedCrotch() { Criteria c1 = new Criteria("field_1").startsWith("start").endsWith("end"); Criteria c2 = new Criteria("field_2").startsWith("2start"); Crotch crotch = c1.and(c2); Assert.assertThat(crotch.getSiblings(), IsIterableContainingInOrder.<Node> contains(c1, c2)); } @Test // DATASOLR-105 public void testOrShouldProduceCrotch() { Criteria criteria = new Criteria("field_1").startsWith("start").or("field_2").endsWith("end").startsWith("start2"); Assert.assertThat(criteria, IsInstanceOf.instanceOf(Crotch.class)); } @Test // DATASOLR-105 public void testCirteriasJoindWithOrShouldBeSiblingsOfCreatedCrotch() { Criteria c1 = new Criteria("field_1").startsWith("start").endsWith("end"); Criteria c2 = new Criteria("field_2").startsWith("2start"); Crotch crotch = c1.or(c2); Assert.assertThat(crotch.getSiblings(), IsIterableContainingInOrder.<Node> contains(c1, c2)); } @Test // DATASOLR-105 public void testCrotchShouldReturnFieldNameOfMostRecentSibling() { Criteria c1 = new Criteria("field_1").startsWith("start").endsWith("end"); Criteria c2 = new Criteria("field_2").startsWith("2start"); Crotch crotch = c1.or(c2); Assert.assertThat(crotch.getField().getName(), Is.is("field_2")); } @Test public void testIsNot() { Criteria criteria = new Criteria("field_1").is("value_1").not(); Assert.assertTrue(criteria.isNegating()); assertPredicate(criteria.getPredicates(), 0, OperationKey.EQUALS, "value_1"); } @Test public void testFuzzy() { Criteria criteria = new Criteria("field_1").fuzzy("value_1"); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals("value_1", ((Object[]) entry.getValue())[0]); Assert.assertEquals(Float.NaN, ((Object[]) entry.getValue())[1]); } @Test public void testFuzzyWithDistance() { Criteria criteria = new Criteria("field_1").fuzzy("value_1", 0.5f); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals("value_1", ((Object[]) entry.getValue())[0]); Assert.assertEquals(0.5F, ((Object[]) entry.getValue())[1]); } @Test(expected = InvalidDataAccessApiUsageException.class) public void testFuzzyWithNegativeDistance() { new Criteria("field_1").fuzzy("value_1", -0.5f); } @Test(expected = InvalidDataAccessApiUsageException.class) public void testFuzzyWithTooHighDistance() { new Criteria("field_1").fuzzy("value_1", 1.5f); } @Test public void testSloppy() { Criteria criteria = new Criteria("field_1").sloppy("value0 value1", 2); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals("value0 value1", ((Object[]) entry.getValue())[0]); Assert.assertEquals(2, ((Object[]) entry.getValue())[1]); } @Test(expected = InvalidDataAccessApiUsageException.class) public void testSloppyWithNegativeDistance() { new Criteria("field_1").sloppy("value0 value1", 0); } @Test(expected = InvalidDataAccessApiUsageException.class) public void testSloppyWithSingleWordPhrase() { new Criteria("field_1").sloppy("value0", 0); } @Test public void testBoost() { Criteria criteria = new Criteria("field_1").is("value_1").boost(2f); assertPredicate(criteria.getPredicates(), 0, OperationKey.EQUALS, "value_1"); Assert.assertEquals(2f, criteria.getBoost(), 0); } @Test public void testBetween() { Criteria criteria = new Criteria("field_1").between(100, 200); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertEquals(100, ((Object[]) entry.getValue())[0]); Assert.assertEquals(200, ((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testBetweenWithoutUpperBound() { Criteria criteria = new Criteria("field_1").between(100, null); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertEquals(100, ((Object[]) entry.getValue())[0]); Assert.assertNull(((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testBetweenWithoutLowerBound() { Criteria criteria = new Criteria("field_1").between(null, 200); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertNull(((Object[]) entry.getValue())[0]); Assert.assertEquals(200, ((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testBetweenExcludingLowerBound() { Criteria criteria = new Criteria("field_1").between(100, 200, false, true); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertEquals(100, ((Object[]) entry.getValue())[0]); Assert.assertEquals(200, ((Object[]) entry.getValue())[1]); Assert.assertFalse((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testBetweenExcludingUpperBound() { Criteria criteria = new Criteria("field_1").between(100, 200, true, false); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertEquals(100, ((Object[]) entry.getValue())[0]); Assert.assertEquals(200, ((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertFalse((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testBetweenWithoutLowerAndUpperBound() { Criteria criteria = new Criteria("field_1").between(null, null); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertNull(((Object[]) entry.getValue())[0]); Assert.assertNull(((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testLessThan() { Criteria criteria = new Criteria("field_1").lessThan(200); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertNull(((Object[]) entry.getValue())[0]); Assert.assertEquals(200, ((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertFalse((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testLessThanEqual() { Criteria criteria = new Criteria("field_1").lessThanEqual(200); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertNull(((Object[]) entry.getValue())[0]); Assert.assertEquals(200, ((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testLessThanEqualNull() { Criteria criteria = new Criteria("field_1").lessThanEqual(null); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertNull(((Object[]) entry.getValue())[0]); Assert.assertNull(((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testGreaterThan() { Criteria criteria = new Criteria("field_1").greaterThan(100); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertEquals(100, ((Object[]) entry.getValue())[0]); Assert.assertNull(((Object[]) entry.getValue())[1]); Assert.assertFalse((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testGreaterThanEqual() { Criteria criteria = new Criteria("field_1").greaterThanEqual(100); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertEquals(100, ((Object[]) entry.getValue())[0]); Assert.assertNull(((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testGreaterThanEqualNull() { Criteria criteria = new Criteria("field_1").greaterThanEqual(null); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.BETWEEN.getKey(), entry.getKey()); Assert.assertNull(((Object[]) entry.getValue())[0]); Assert.assertNull(((Object[]) entry.getValue())[1]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[2]); Assert.assertTrue((Boolean) ((Object[]) entry.getValue())[3]); } @Test public void testIn() { Criteria criteria = new Criteria("field_1").in(1, 2, 3, 5, 8, 13, 21); Assert.assertEquals("field_1", criteria.getField().getName()); assertPredicate(criteria.getPredicates(), 0, OperationKey.EQUALS, 1); assertPredicate(criteria.getPredicates(), 1, OperationKey.EQUALS, 2); assertPredicate(criteria.getPredicates(), 2, OperationKey.EQUALS, 3); assertPredicate(criteria.getPredicates(), 3, OperationKey.EQUALS, 5); assertPredicate(criteria.getPredicates(), 4, OperationKey.EQUALS, 8); assertPredicate(criteria.getPredicates(), 5, OperationKey.EQUALS, 13); assertPredicate(criteria.getPredicates(), 6, OperationKey.EQUALS, 21); } @Test public void testInWithNestedCollection() { List<List<String>> enclosingList = new ArrayList<>(); enclosingList.add(Arrays.asList("spring", "data")); enclosingList.add(Collections.singletonList("solr")); Criteria criteria = new Criteria("field_1").in(enclosingList); assertPredicate(criteria.getPredicates(), 0, OperationKey.EQUALS, "spring"); assertPredicate(criteria.getPredicates(), 1, OperationKey.EQUALS, "data"); assertPredicate(criteria.getPredicates(), 2, OperationKey.EQUALS, "solr"); } @Test(expected = IllegalArgumentException.class) public void testInWithNull() { new Criteria("field_1").in((Collection<?>) null); } @Test(expected = InvalidDataAccessApiUsageException.class) public void testInWithNoValues() { new Criteria("field_1").in(); } @Test public void testNear() { Point location = new Point(48.303056, 14.290556); Criteria criteria = new Criteria("field_1").near(location, new Distance(5)); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.NEAR.getKey(), entry.getKey()); Assert.assertEquals(location, ((Object[]) entry.getValue())[0]); Assert.assertEquals(5, ((Distance) ((Object[]) entry.getValue())[1]).getValue(), 0); } @Test(expected = IllegalArgumentException.class) public void testNearWithNullLocation() { new Criteria("field_1").near(null, new Distance(5)); } @Test(expected = InvalidDataAccessApiUsageException.class) public void testNearWithNegativeDistance() { new Criteria("field_1").near(new Point(48.303056, 14.290556), new Distance(-1)); } @Test public void testWithin() { Point location = new Point(48.303056, 14.290556); Criteria criteria = new Criteria("field_1").within(location, new Distance(5)); Predicate entry = getPredicateByPosition(criteria.getPredicates(), 0); Assert.assertEquals(OperationKey.WITHIN.getKey(), entry.getKey()); Assert.assertEquals(location, ((Object[]) entry.getValue())[0]); Assert.assertEquals(5, ((Distance) ((Object[]) entry.getValue())[1]).getValue(), 0); } @Test(expected = IllegalArgumentException.class) public void testWithinWithNullLocation() { new Criteria("field_1").within(null, new Distance(5)); } private void assertPredicate(Set<Predicate> entries, int position, OperationKey expectedKey, Object expectedValue) { assertPredicate(entries, position, expectedKey.getKey(), expectedValue); } private void assertPredicate(Set<Predicate> entries, int position, String expectedKey, Object expectedValue) { Predicate predicate = getPredicateByPosition(entries, position); Assert.assertEquals(expectedValue, predicate.getValue()); Assert.assertEquals(expectedKey, predicate.getKey()); } private Predicate getPredicateByPosition(Set<Predicate> entries, int position) { return (Predicate) entries.toArray()[position]; } private static class TestFunction implements Function { @Override public String getOperation() { return "op"; } @Override public Iterable<Object> getArguments() { return null; } @Override public boolean hasArguments() { return false; } } }