Skip to content

Commit

Permalink
HSEARCH-3958 Use as much shared code as possible to test the spatial-…
Browse files Browse the repository at this point in the history
…within-circle predicate
  • Loading branch information
yrodiere committed Jul 1, 2020
1 parent 307d03c commit 7737e2c
Show file tree
Hide file tree
Showing 8 changed files with 414 additions and 447 deletions.
Expand Up @@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.integrationtest.backend.tck.search.spatial;
package org.hibernate.search.integrationtest.backend.tck.search.predicate;

import org.hibernate.search.engine.backend.document.IndexFieldReference;
import org.hibernate.search.engine.backend.document.model.dsl.IndexSchemaElement;
Expand Down Expand Up @@ -88,15 +88,15 @@ protected void initData() {
.join();
}

protected static class IndexBinding {
final IndexFieldReference<GeoPoint> geoPoint;
final IndexFieldReference<GeoPoint> geoPoint_1;
final IndexFieldReference<GeoPoint> geoPoint_2;
final IndexFieldReference<GeoPoint> geoPoint_with_longName;
final IndexFieldReference<GeoPoint> nonProjectableGeoPoint;
final IndexFieldReference<GeoPoint> unsortableGeoPoint;
final IndexFieldReference<GeoPoint> projectableUnsortableGeoPoint;
final IndexFieldReference<String> string;
public static class IndexBinding {
public final IndexFieldReference<GeoPoint> geoPoint;
public final IndexFieldReference<GeoPoint> geoPoint_1;
public final IndexFieldReference<GeoPoint> geoPoint_2;
public final IndexFieldReference<GeoPoint> geoPoint_with_longName;
public final IndexFieldReference<GeoPoint> nonProjectableGeoPoint;
public final IndexFieldReference<GeoPoint> unsortableGeoPoint;
public final IndexFieldReference<GeoPoint> projectableUnsortableGeoPoint;
public final IndexFieldReference<String> string;

IndexBinding(IndexSchemaElement root) {
geoPoint = root.field(
Expand Down
@@ -0,0 +1,307 @@
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.integrationtest.backend.tck.search.predicate;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.search.engine.search.predicate.dsl.PredicateFinalStep;
import org.hibernate.search.engine.search.predicate.dsl.SearchPredicateFactory;
import org.hibernate.search.engine.spatial.GeoPoint;
import org.hibernate.search.integrationtest.backend.tck.testsupport.types.FieldTypeDescriptor;
import org.hibernate.search.integrationtest.backend.tck.testsupport.types.GeoPointFieldTypeDescriptor;
import org.hibernate.search.integrationtest.backend.tck.testsupport.util.rule.SearchSetupHelper;
import org.hibernate.search.util.impl.integrationtest.mapper.stub.BulkIndexer;
import org.hibernate.search.util.impl.integrationtest.mapper.stub.SimpleMappedIndex;

import org.junit.AssumptionViolatedException;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Enclosed.class)
public class SpatialWithinCirclePredicateBaseIT {

private static final GeoPointFieldTypeDescriptor supportedFieldType;
private static final List<FieldTypeDescriptor<GeoPoint>> supportedFieldTypes = new ArrayList<>();
private static final List<FieldTypeDescriptor<?>> unsupportedFieldTypes = new ArrayList<>();
static {
supportedFieldType = GeoPointFieldTypeDescriptor.INSTANCE;
supportedFieldTypes.add( supportedFieldType );
for ( FieldTypeDescriptor<?> fieldType : FieldTypeDescriptor.getAll() ) {
if ( !supportedFieldType.equals( fieldType ) ) {
unsupportedFieldTypes.add( fieldType );
}
}
}

@ClassRule
public static SearchSetupHelper setupHelper = new SearchSetupHelper();

@BeforeClass
public static void setup() {
setupHelper.start()
.withIndexes(
SingleFieldIT.index, MultiFieldIT.index,
ScoreIT.index,
InvalidFieldIT.index, UnsupportedTypeIT.index,
SearchableIT.searchableYesIndex, SearchableIT.searchableNoIndex,
ArgumentCheckingIT.index
)
.setup();

final BulkIndexer singleFieldIndexer = SingleFieldIT.index.bulkIndexer();
SingleFieldIT.dataSet.contribute( SingleFieldIT.index, singleFieldIndexer );

final BulkIndexer multiFieldIndexer = MultiFieldIT.index.bulkIndexer();
MultiFieldIT.dataSet.contribute( MultiFieldIT.index, multiFieldIndexer );

final BulkIndexer scoreIndexer = ScoreIT.index.bulkIndexer();
ScoreIT.dataSet.contribute( ScoreIT.index, scoreIndexer );

singleFieldIndexer.join(
multiFieldIndexer,
scoreIndexer
);
}

private static SpatialWithinCirclePredicateTestValues testValues() {
return new SpatialWithinCirclePredicateTestValues();
}

@Test
public void takariCpSuiteWorkaround() {
// Workaround to get Takari-CPSuite to run this test.
}

public static class SingleFieldIT extends AbstractPredicateSingleFieldIT<SpatialWithinCirclePredicateTestValues> {
private static final DataSet<GeoPoint, SpatialWithinCirclePredicateTestValues> dataSet = new DataSet<>( testValues() );

private static final SimpleMappedIndex<IndexBinding> index =
SimpleMappedIndex.of( root -> new IndexBinding( root, supportedFieldTypes ) )
.name( "singleField" );

public SingleFieldIT() {
super( index, dataSet );
}

@Override
protected PredicateFinalStep predicate(SearchPredicateFactory f, String fieldPath, int matchingDocOrdinal) {
return f.spatial().within().field( fieldPath )
.circle( dataSet.values.matchingCenter( matchingDocOrdinal ),
dataSet.values.matchingRadius( matchingDocOrdinal ) );
}
}

public static class MultiFieldIT extends AbstractPredicateMultiFieldIT<SpatialWithinCirclePredicateTestValues> {
private static final DataSet<GeoPoint, SpatialWithinCirclePredicateTestValues> dataSet = new DataSet<>( testValues() );

private static final SimpleMappedIndex<IndexBinding> index =
SimpleMappedIndex.of( root -> new IndexBinding( root, supportedFieldTypes ) )
.name( "multiField" );

public MultiFieldIT() {
super( index, dataSet );
}

@Override
protected PredicateFinalStep predicateOnFieldAndField(SearchPredicateFactory f, String fieldPath,
String otherFieldPath, int matchingDocOrdinal) {
return f.spatial().within().field( fieldPath ).field( otherFieldPath )
.circle( dataSet.values.matchingCenter( matchingDocOrdinal ),
dataSet.values.matchingRadius( matchingDocOrdinal ) );
}

@Override
protected PredicateFinalStep predicateOnFields(SearchPredicateFactory f, String[] fieldPaths, int matchingDocOrdinal) {
return f.spatial().within().fields( fieldPaths )
.circle( dataSet.values.matchingCenter( matchingDocOrdinal ),
dataSet.values.matchingRadius( matchingDocOrdinal ) );
}

@Override
protected PredicateFinalStep predicateOnFieldAndFields(SearchPredicateFactory f, String fieldPath,
String[] fieldPaths, int matchingDocOrdinal) {
return f.spatial().within().field( fieldPath ).fields( fieldPaths )
.circle( dataSet.values.matchingCenter( matchingDocOrdinal ),
dataSet.values.matchingRadius( matchingDocOrdinal ) );
}
}

public static class ScoreIT extends AbstractPredicateFieldScoreIT<SpatialWithinCirclePredicateTestValues> {
private static final DataSet<GeoPoint, SpatialWithinCirclePredicateTestValues> dataSet = new DataSet<>( testValues() );

private static final SimpleMappedIndex<IndexBinding> index =
SimpleMappedIndex.of( root -> new IndexBinding( root, supportedFieldTypes ) )
.name( "score" );

public ScoreIT() {
super( index, dataSet );
}

@Override
protected PredicateFinalStep predicate(SearchPredicateFactory f, String fieldPath, int matchingDocOrdinal) {
return f.spatial().within().field( fieldPath )
.circle( dataSet.values.matchingCenter( matchingDocOrdinal ),
dataSet.values.matchingRadius( matchingDocOrdinal ) );
}

@Override
protected PredicateFinalStep predicateWithConstantScore(SearchPredicateFactory f, String[] fieldPaths,
int matchingDocOrdinal) {
throw scoreIsAlwaysConstant();
}

@Override
protected PredicateFinalStep predicateWithPredicateLevelBoost(SearchPredicateFactory f, String[] fieldPaths,
int matchingDocOrdinal, float predicateBoost) {
return f.spatial().within().fields( fieldPaths )
.circle( dataSet.values.matchingCenter( matchingDocOrdinal ),
dataSet.values.matchingRadius( matchingDocOrdinal ) )
.boost( predicateBoost );
}

@Override
protected PredicateFinalStep predicateWithConstantScoreAndPredicateLevelBoost(SearchPredicateFactory f,
String[] fieldPaths, int matchingDocOrdinal, float predicateBoost) {
throw scoreIsAlwaysConstant();
}

@Override
protected PredicateFinalStep predicateWithFieldLevelBoost(SearchPredicateFactory f, String fieldPath,
float fieldBoost, int matchingDocOrdinal) {
return f.spatial().within().field( fieldPath ).boost( fieldBoost )
.circle( dataSet.values.matchingCenter( matchingDocOrdinal ),
dataSet.values.matchingRadius( matchingDocOrdinal ) );
}

@Override
protected PredicateFinalStep predicateWithFieldLevelBoostAndConstantScore(SearchPredicateFactory f,
String fieldPath, float fieldBoost, int matchingDocOrdinal) {
throw scoreIsAlwaysConstant();
}

@Override
protected PredicateFinalStep predicateWithFieldLevelBoostAndPredicateLevelBoost(SearchPredicateFactory f,
String fieldPath, float fieldBoost, int matchingDocOrdinal, float predicateBoost) {
return f.spatial().within().field( fieldPath ).boost( fieldBoost )
.circle( dataSet.values.matchingCenter( matchingDocOrdinal ),
dataSet.values.matchingRadius( matchingDocOrdinal ) )
.boost( predicateBoost );
}

@Override
protected void assumeConstantScoreSupported() {
throw scoreIsAlwaysConstant();
}

private AssumptionViolatedException scoreIsAlwaysConstant() {
throw new AssumptionViolatedException( "Score is always constant for geo-point fields" );
}
}

public static class InvalidFieldIT extends AbstractPredicateInvalidFieldIT {
private static final SimpleMappedIndex<IndexBinding> index = SimpleMappedIndex.of( IndexBinding::new )
.name( "invalidField" );

public InvalidFieldIT() {
super( index );
}

@Override
protected void tryPredicate(SearchPredicateFactory f, String fieldPath) {
f.spatial().within().field( fieldPath )
// We need this because the backend is not involved before the call to circle()
.circle( GeoPoint.of( 0, 0 ), 1 );
}
}

@RunWith(Parameterized.class)
public static class UnsupportedTypeIT extends AbstractPredicateUnsupportedTypeIT {
private static final List<Object[]> parameters = new ArrayList<>();
static {
for ( FieldTypeDescriptor<?> fieldType : unsupportedFieldTypes ) {
parameters.add( new Object[] { fieldType } );
}
}

private static final SimpleMappedIndex<IndexBinding> index =
SimpleMappedIndex.of( root -> new IndexBinding( root, unsupportedFieldTypes ) )
.name( "unsupportedType" );

@Parameterized.Parameters(name = "{0}")
public static List<Object[]> parameters() {
return parameters;
}

public UnsupportedTypeIT(FieldTypeDescriptor<?> fieldType) {
super( index, fieldType );
}

@Override
protected void tryPredicate(SearchPredicateFactory f, String fieldPath) {
f.spatial().within().field( fieldPath )
// We need this because the backend is not involved before the call to circle()
.circle( GeoPoint.of( 0, 0 ), 1 );
}

@Override
protected String predicateNameInErrorMessage() {
return "Spatial predicates";
}
}

public static class SearchableIT extends AbstractPredicateSearchableIT {
private static final SimpleMappedIndex<SearchableYesIndexBinding> searchableYesIndex =
SimpleMappedIndex.of( root -> new SearchableYesIndexBinding( root, supportedFieldTypes ) )
.name( "searchableYes" );

private static final SimpleMappedIndex<SearchableNoIndexBinding> searchableNoIndex =
SimpleMappedIndex.of( root -> new SearchableNoIndexBinding( root, supportedFieldTypes ) )
.name( "searchableNo" );

public SearchableIT() {
super( searchableYesIndex, searchableNoIndex, supportedFieldType );
}

@Override
protected void tryPredicate(SearchPredicateFactory f, String fieldPath) {
f.spatial().within().field( fieldPath )
// We need this because the backend is not involved before the call to circle()
.circle( GeoPoint.of( 0, 0 ), 1 );
}
}

public static class ArgumentCheckingIT extends AbstractPredicateArgumentCheckingIT {
private static final SimpleMappedIndex<IndexBinding> index =
SimpleMappedIndex.of( root -> new IndexBinding( root, supportedFieldTypes ) )
.name( "argumentChecking" );

public ArgumentCheckingIT() {
super( index, supportedFieldType );
}

@Test
public void nullUnit() {
SearchPredicateFactory f = index.createScope().predicate();

assertThatThrownBy( () -> f.spatial().within().field( fieldPath() ).circle( 0.0, 0.0, 10.0, null ) )
.isInstanceOf( IllegalArgumentException.class )
.hasMessageContainingAll( "must not be null" );
}

@Override
protected void tryPredicateWithNullMatchingParam(SearchPredicateFactory f, String fieldPath) {
f.spatial().within().field( fieldPath ).circle( null, 10.0 );
}
}
}
@@ -0,0 +1,54 @@
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.integrationtest.backend.tck.search.predicate;

import static org.hibernate.search.util.impl.integrationtest.common.assertion.SearchResultAssert.assertThatQuery;

import org.hibernate.search.engine.spatial.DistanceUnit;
import org.hibernate.search.engine.spatial.GeoPoint;

import org.junit.Test;

public class SpatialWithinCirclePredicateSpecificsIT extends AbstractSpatialWithinSearchPredicateIT {

private static final GeoPoint METRO_HOTEL_DE_VILLE = GeoPoint.of( 45.7673396, 4.833743 );
private static final GeoPoint METRO_GARIBALDI = GeoPoint.of( 45.7515926, 4.8514779 );

@Test
public void matchMultipleDocuments() {
assertThatQuery( mainIndex.query()
.where( f -> f.spatial().within()
.field( "geoPoint" )
.circle( METRO_GARIBALDI, 1_500 ) ) )
.hasDocRefHitsAnyOrder( mainIndex.typeName(), CHEZ_MARGOTTE_ID, IMOUTO_ID );

assertThatQuery( mainIndex.query()
.where( f -> f.spatial().within()
.field( "geoPoint" )
.circle( METRO_HOTEL_DE_VILLE, 500 ) ) )
.hasDocRefHitsAnyOrder( mainIndex.typeName(), OURSON_QUI_BOIT_ID );

assertThatQuery( mainIndex.query()
.where( f -> f.spatial().within()
.field( "geoPoint" )
.circle( METRO_GARIBALDI.latitude(), METRO_GARIBALDI.longitude(), 1_500 ) ) )
.hasDocRefHitsAnyOrder( mainIndex.typeName(), CHEZ_MARGOTTE_ID, IMOUTO_ID );

assertThatQuery( mainIndex.query()
.where( f -> f.spatial().within()
.field( "geoPoint" )
.circle( METRO_GARIBALDI.latitude(), METRO_GARIBALDI.longitude(), 1.5, DistanceUnit.KILOMETERS ) ) )
.hasDocRefHitsAnyOrder( mainIndex.typeName(), CHEZ_MARGOTTE_ID, IMOUTO_ID );

assertThatQuery( mainIndex.query()
.where( f -> f.spatial().within()
.field( "geoPoint" )
.circle( METRO_GARIBALDI, 1.5, DistanceUnit.KILOMETERS ) ) )
.hasDocRefHitsAnyOrder( mainIndex.typeName(), CHEZ_MARGOTTE_ID, IMOUTO_ID );
}

}

0 comments on commit 7737e2c

Please sign in to comment.