Skip to content

Commit

Permalink
HSEARCH-3099 Validate indexNullAs and test negative cases
Browse files Browse the repository at this point in the history
  • Loading branch information
fax4ever committed Apr 19, 2019
1 parent d1e41e9 commit 1b9df4a
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 1 deletion.
@@ -0,0 +1,70 @@
/*
* 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.engine.cfg.spi;

import java.lang.invoke.MethodHandles;
import java.time.DateTimeException;
import java.time.ZoneId;
import java.util.UUID;

import org.hibernate.search.engine.logging.impl.Log;
import org.hibernate.search.util.common.logging.impl.LoggerFactory;

public final class ValidateUtils {

private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

private ValidateUtils() {
// Private constructor, do not use
}

public static void validateCharacter(String value) {
if ( value != null && value.length() != 1 ) {
throw log.invalidStringForType( value, Character.class, null );
}
}

public static void validateEnum(String value, Class<? extends Enum> enumType) {
if ( value == null ) {
return;
}

try {
Enum.valueOf( enumType, value );
}
catch (IllegalArgumentException ex) {
throw log.invalidStringForEnum( value, enumType, ex );
}
}

public static void validateUUID(String value) {
if ( value == null ) {
return;
}

try {
UUID.fromString( value );
}
catch (IllegalArgumentException ex) {
throw log.invalidStringForType( value, UUID.class, ex );
}
}

public static void validateZoneId(String value) {
if ( value == null ) {
return;
}

try {
ZoneId.of( value );
}
catch (DateTimeException ex) {
throw log.invalidStringForType( value, ZoneId.class, ex );
}
}

}
Expand Up @@ -4,7 +4,6 @@
* 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.engine.logging.impl;

import java.time.format.DateTimeFormatter;
Expand Down Expand Up @@ -275,4 +274,10 @@ SearchException unableToParseTemporal(@FormatWith(SimpleNameClassFormatter.class

@Message(id = ID_OFFSET_2 + 58, value = "Invalid %1$s value: expected either a Number or a String that can be parsed into a %1$s. %2$s")
SearchException invalidNumberPropertyValue(@FormatWith(SimpleNameClassFormatter.class) Class<? extends Number> type, String nestedErrorMessage, @Cause Exception cause);

@Message(id = ID_OFFSET_2 + 59, value = "Invalid '%1$s' value for type '%2$s'.")
SearchException invalidStringForType(String value, @FormatWith(SimpleNameClassFormatter.class) Class<?> type, @Cause Exception cause);

@Message(id = ID_OFFSET_2 + 60, value = "Invalid '%1$s' value for enum '%2$s'.")
SearchException invalidStringForEnum(String value, @FormatWith(ClassFormatter.class) Class<? extends Enum> enumType, @Cause Exception cause);
}
@@ -0,0 +1,70 @@
/*
* 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.mapper.pojo.mapping.definition;

import java.lang.invoke.MethodHandles;
import java.util.Optional;

import org.hibernate.search.integrationtest.mapper.pojo.testsupport.types.PropertyTypeDescriptor;
import org.hibernate.search.integrationtest.mapper.pojo.testsupport.types.expectations.DefaultValueBridgeExpectations;
import org.hibernate.search.integrationtest.mapper.pojo.testsupport.util.rule.JavaBeanMappingSetupHelper;
import org.hibernate.search.util.common.SearchException;
import org.hibernate.search.util.impl.integrationtest.common.rule.BackendMock;
import org.hibernate.search.util.impl.test.SubTest;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class IndexNullAsErrorIT<V, F> {

private static final String FIELD_NAME = DefaultValueBridgeExpectations.TYPE_WITH_VALUE_BRIDGE_FIELD_NAME;
private static final String FIELD_INDEXNULLAS_NAME = DefaultValueBridgeExpectations.TYPE_WITH_VALUE_BRIDGE_FIELD_INDEXNULLAS_NAME;

@Parameterized.Parameters(name = "{0}")
public static Object[] types() {
return PropertyTypeDescriptor.getAll().stream()
// do not test types that do not have a default value bridge
.filter( type -> type.getDefaultValueBridgeExpectations().isPresent() )
// TODO do not test primitive types
.filter( type -> type.getDefaultValueBridgeExpectations().get().isNullTranslatedAsNull() )
.map( type -> new Object[] { type, type.getDefaultValueBridgeExpectations() } )
.toArray();
}

@Rule
public BackendMock backendMock = new BackendMock( "stubBackend" );

@Rule
public JavaBeanMappingSetupHelper setupHelper = new JavaBeanMappingSetupHelper( MethodHandles.lookup() );

private DefaultValueBridgeExpectations<V, F> expectations;

public IndexNullAsErrorIT(PropertyTypeDescriptor<V> typeDescriptor, Optional<DefaultValueBridgeExpectations<V, F>> expectations) {
this.expectations = expectations.get();
}

@Test
public void testParsingException() {
SubTest.expectException( () ->
setupHelper.withBackendMock( backendMock ).withConfiguration( c -> c
.addEntityType( expectations.getTypeWithValueBridge1() )
.programmaticMapping()
.type( expectations.getTypeWithValueBridge1() ).indexed()
.property( FIELD_NAME ).genericField( FIELD_NAME )
.property( FIELD_NAME ).genericField( FIELD_INDEXNULLAS_NAME ).indexNullAs( expectations.getUnparsableNullAsValue() )
).setup()
)
.assertThrown()
.isInstanceOf( SearchException.class )
.hasMessageContaining( "HSEARCH0005" )
.hasMessageContaining( expectations.getTypeWithValueBridge1().getSimpleName() );

}
}
Expand Up @@ -92,6 +92,11 @@ public String getNullAsValueBridge1() {
public String getNullAsValueBridge2() {
return "file:///~calendar";
}

@Override
public String getUnparsableNullAsValue() {
return "http://www.wrong.uri.com?param1=0 param7=0";
}
} );
}

Expand Down
Expand Up @@ -35,4 +35,8 @@ default boolean isNullTranslatedAsNull() {
F getNullAsValueBridge1();

F getNullAsValueBridge2();

default String getUnparsableNullAsValue() {
return "---";
}
}
Expand Up @@ -9,6 +9,7 @@
import org.hibernate.search.engine.backend.types.converter.FromDocumentFieldValueConverter;
import org.hibernate.search.engine.backend.types.converter.runtime.FromDocumentFieldValueConvertContext;
import org.hibernate.search.engine.backend.types.dsl.StandardIndexFieldTypeContext;
import org.hibernate.search.engine.cfg.spi.ValidateUtils;
import org.hibernate.search.mapper.pojo.bridge.ValueBridge;
import org.hibernate.search.mapper.pojo.bridge.binding.ValueBridgeBindingContext;
import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext;
Expand Down Expand Up @@ -40,6 +41,7 @@ public Character cast(Object value) {

@Override
public String parse(String value) {
ValidateUtils.validateCharacter( value );
return value;
}

Expand Down
Expand Up @@ -9,6 +9,7 @@
import org.hibernate.search.engine.backend.types.converter.FromDocumentFieldValueConverter;
import org.hibernate.search.engine.backend.types.converter.runtime.FromDocumentFieldValueConvertContext;
import org.hibernate.search.engine.backend.types.dsl.StandardIndexFieldTypeContext;
import org.hibernate.search.engine.cfg.spi.ValidateUtils;
import org.hibernate.search.mapper.pojo.bridge.ValueBridge;
import org.hibernate.search.mapper.pojo.bridge.binding.ValueBridgeBindingContext;
import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext;
Expand Down Expand Up @@ -43,6 +44,7 @@ public V cast(Object value) {

@Override
public String parse(String value) {
ValidateUtils.validateEnum( value, enumType );
return value;
}

Expand Down
Expand Up @@ -47,6 +47,11 @@ public URI cast(Object value) {

@Override
public String parse(String value) {
if ( value == null ) {
return null;
}

PojoDefaultURIFromDocumentFieldValueConverter.toURI( value );
return value;
}

Expand Down
Expand Up @@ -47,6 +47,11 @@ public URL cast(Object value) {

@Override
public String parse(String value) {
if ( value == null ) {
return null;
}

PojoDefaultURLFromDocumentFieldValueConverter.toURL( value );
return value;
}

Expand Down
Expand Up @@ -54,6 +54,8 @@ public Period cast(Object value) {

@Override
public String parse(String value) {
// using convert to validate
PojoDefaultPeriodFromDocumentFieldValueConverter.INSTANCE.convert( value, null );
return value;
}

Expand Down
Expand Up @@ -11,6 +11,7 @@
import org.hibernate.search.engine.backend.types.converter.FromDocumentFieldValueConverter;
import org.hibernate.search.engine.backend.types.converter.runtime.FromDocumentFieldValueConvertContext;
import org.hibernate.search.engine.backend.types.dsl.StandardIndexFieldTypeContext;
import org.hibernate.search.engine.cfg.spi.ValidateUtils;
import org.hibernate.search.mapper.pojo.bridge.ValueBridge;
import org.hibernate.search.mapper.pojo.bridge.binding.ValueBridgeBindingContext;
import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext;
Expand Down Expand Up @@ -41,6 +42,7 @@ public UUID cast(Object value) {

@Override
public String parse(String value) {
ValidateUtils.validateUUID( value );
return value;
}

Expand Down
Expand Up @@ -11,6 +11,7 @@
import org.hibernate.search.engine.backend.types.converter.FromDocumentFieldValueConverter;
import org.hibernate.search.engine.backend.types.converter.runtime.FromDocumentFieldValueConvertContext;
import org.hibernate.search.engine.backend.types.dsl.StandardIndexFieldTypeContext;
import org.hibernate.search.engine.cfg.spi.ValidateUtils;
import org.hibernate.search.mapper.pojo.bridge.ValueBridge;
import org.hibernate.search.mapper.pojo.bridge.binding.ValueBridgeBindingContext;
import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext;
Expand Down Expand Up @@ -41,6 +42,7 @@ public ZoneId cast(Object value) {

@Override
public String parse(String value) {
ValidateUtils.validateZoneId( value );
return value;
}

Expand Down

0 comments on commit 1b9df4a

Please sign in to comment.