introduce validators package and add tests

This commit is contained in:
Michael Hoennig 2024-05-10 17:19:29 +02:00
parent 18dd28a7e3
commit cbcef6d354
20 changed files with 331 additions and 57 deletions

View File

@ -17,7 +17,7 @@ import java.util.List;
import java.util.UUID;
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntityValidators.valid;
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.valid;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
@RestController

View File

@ -1,6 +1,8 @@
package net.hostsharing.hsadminng.hs.booking.item;
package net.hostsharing.hsadminng.hs.booking.item.validators;
import lombok.experimental.UtilityClass;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
import jakarta.validation.ValidationException;
@ -34,11 +36,11 @@ public class HsBookingItemEntityValidators {
return validators.get(type);
}
public static Set<? extends Enum<?>> types() {
public static Set<Enum<HsBookingItemType>> types() {
return validators.keySet();
}
static HsBookingItemEntity valid(final HsBookingItemEntity entityToSave) {
public static HsBookingItemEntity valid(final HsBookingItemEntity entityToSave) {
final var violations = HsBookingItemEntityValidators.forType(entityToSave.getType()).validate(entityToSave);
if (!violations.isEmpty()) {
throw new ValidationException(violations.toString());

View File

@ -1,5 +1,7 @@
package net.hostsharing.hsadminng.hs.booking.item;
package net.hostsharing.hsadminng.hs.booking.item.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty;

View File

@ -1,5 +1,7 @@
package net.hostsharing.hsadminng.hs.booking.item;
package net.hostsharing.hsadminng.hs.booking.item.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
import static net.hostsharing.hsadminng.hs.validation.BooleanPropertyValidator.booleanProperty;

View File

@ -1,5 +1,7 @@
package net.hostsharing.hsadminng.hs.booking.item;
package net.hostsharing.hsadminng.hs.booking.item.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;

View File

@ -20,7 +20,7 @@ import java.util.List;
import java.util.UUID;
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntityValidators.valid;
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidators.valid;
@RestController
public class HsHostingAssetController implements HsHostingAssetsApi {

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
import net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidators;
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetPropsApi;
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetTypeResource;
import org.springframework.http.ResponseEntity;

View File

@ -1,5 +1,7 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty;

View File

@ -1,6 +1,8 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import lombok.experimental.UtilityClass;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
import jakarta.validation.ValidationException;
@ -30,16 +32,16 @@ public class HsHostingAssetEntityValidators {
validators.put(type, validator);
}
static HsEntityValidator<HsHostingAssetEntity, HsHostingAssetType> forType(final Enum<HsHostingAssetType> type) {
public static HsEntityValidator<HsHostingAssetEntity, HsHostingAssetType> forType(final Enum<HsHostingAssetType> type) {
return validators.get(type);
}
static Set<? extends Enum<?>> types() {
public static Set<Enum<HsHostingAssetType>> types() {
return validators.keySet();
}
static HsHostingAssetEntity valid(final HsHostingAssetEntity entityToSave) {
public static HsHostingAssetEntity valid(final HsHostingAssetEntity entityToSave) {
final var violations = HsHostingAssetEntityValidators.forType(entityToSave.getType()).validate(entityToSave);
if (!violations.isEmpty()) {
throw new ValidationException(violations.toString());

View File

@ -1,5 +1,7 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty;

View File

@ -1,5 +1,7 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
import java.util.List;

View File

@ -1,34 +0,0 @@
package net.hostsharing.hsadminng.hs.booking.item;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static java.util.Map.entry;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
import static org.assertj.core.api.Assertions.assertThat;
class HsManagedServerBookingItemValidatorUnitTest {
@Test
void validatesDependentProperties() {
// given
final var validator = HsBookingItemEntityValidators.forType(MANAGED_SERVER);
final var mangedWebspaceBookingItemEntity = HsBookingItemEntity.builder()
.type(MANAGED_SERVER)
.resources(Map.ofEntries(
entry("CPUs", 2),
entry("RAM", 25),
entry("SSD", 25),
entry("Traffic", 250),
entry("SLA-EMail", true)
))
.build();
// when
final var result = validator.validate(mangedWebspaceBookingItemEntity);
// then
assertThat(result).containsExactly("'resources.SLA-EMail' is expected to be false because resources.SLA-Platform=BASIC but is true");
}
}

View File

@ -0,0 +1,44 @@
package net.hostsharing.hsadminng.hs.booking.item.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import org.junit.jupiter.api.Test;
import jakarta.validation.ValidationException;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE;
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.valid;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
class HsBookingItemEntityValidatorsUnitTest {
@Test
void validThrowsException() {
// given
final var cloudServerBookingItemEntity = HsBookingItemEntity.builder()
.type(CLOUD_SERVER)
.build();
// when
final var result = catchThrowable( ()-> valid(cloudServerBookingItemEntity) );
// then
assertThat(result).isInstanceOf(ValidationException.class)
.hasMessageContaining(
"'resources.CPUs' is required but missing",
"'resources.RAM' is required but missing",
"'resources.SSD' is required but missing",
"'resources.Traffic' is required but missing");
}
@Test
void listsTypes() {
// when
final var result = HsBookingItemEntityValidators.types();
// then
assertThat(result).containsExactlyInAnyOrder(CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE);
}
}

View File

@ -0,0 +1,51 @@
package net.hostsharing.hsadminng.hs.booking.item.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static java.util.Map.entry;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.forType;
import static org.assertj.core.api.Assertions.assertThat;
class HsCloudServerBookingItemValidatorUnitTest {
@Test
void validatesProperties() {
// given
final var validator = HsBookingItemEntityValidators.forType(CLOUD_SERVER);
final var cloudServerBookingItemEntity = HsBookingItemEntity.builder()
.type(CLOUD_SERVER)
.resources(Map.ofEntries(
entry("CPUs", 2),
entry("RAM", 25),
entry("SSD", 25),
entry("Traffic", 250),
entry("SLA-EMail", true)
))
.build();
// when
final var result = validator.validate(cloudServerBookingItemEntity);
// then
assertThat(result).containsExactly("'resources.SLA-EMail' is not expected but is set to 'true'");
}
@Test
void containsAllValidations() {
// when
final var validator = forType(CLOUD_SERVER);
// then
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
"{type=integer, propertyName=CPUs, required=true, unit=null, min=1, max=32, step=null}",
"{type=integer, propertyName=RAM, required=true, unit=GB, min=1, max=128, step=null}",
"{type=integer, propertyName=SSD, required=true, unit=GB, min=25, max=1000, step=25}",
"{type=integer, propertyName=HDD, required=false, unit=GB, min=0, max=4000, step=250}",
"{type=integer, propertyName=Traffic, required=true, unit=GB, min=250, max=10000, step=250}",
"{type=enumeration, propertyName=SLA-Infrastructure, required=false, values=[BASIC, EXT8H, EXT4H, EXT2H]}");
}
}

View File

@ -0,0 +1,56 @@
package net.hostsharing.hsadminng.hs.booking.item.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static java.util.Map.entry;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.forType;
import static org.assertj.core.api.Assertions.assertThat;
class HsManagedServerBookingItemValidatorUnitTest {
@Test
void validatesProperties() {
// given
final var validator = HsBookingItemEntityValidators.forType(MANAGED_SERVER);
final var mangedServerBookingItemEntity = HsBookingItemEntity.builder()
.type(MANAGED_SERVER)
.resources(Map.ofEntries(
entry("CPUs", 2),
entry("RAM", 25),
entry("SSD", 25),
entry("Traffic", 250),
entry("SLA-EMail", true)
))
.build();
// when
final var result = validator.validate(mangedServerBookingItemEntity);
// then
assertThat(result).containsExactly("'resources.SLA-EMail' is expected to be false because resources.SLA-Platform=BASIC but is true");
}
@Test
void containsAllValidations() {
// when
final var validator = forType(MANAGED_SERVER);
// then
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
"{type=integer, propertyName=CPUs, required=true, unit=null, min=1, max=32, step=null}",
"{type=integer, propertyName=RAM, required=true, unit=GB, min=1, max=128, step=null}",
"{type=integer, propertyName=SSD, required=true, unit=GB, min=25, max=1000, step=25}",
"{type=integer, propertyName=HDD, required=false, unit=GB, min=0, max=4000, step=250}",
"{type=integer, propertyName=Traffic, required=true, unit=GB, min=250, max=10000, step=250}",
"{type=enumeration, propertyName=SLA-Platform, required=false, values=[BASIC, EXT8H, EXT4H, EXT2H]}",
"{type=boolean, propertyName=SLA-EMail, required=false, falseIf={SLA-Platform=BASIC}}",
"{type=boolean, propertyName=SLA-Maria, required=false, falseIf={SLA-Platform=BASIC}}",
"{type=boolean, propertyName=SLA-PgSQL, required=false, falseIf={SLA-Platform=BASIC}}",
"{type=boolean, propertyName=SLA-Office, required=false, falseIf={SLA-Platform=BASIC}}",
"{type=boolean, propertyName=SLA-Web, required=false, falseIf={SLA-Platform=BASIC}}");
}
}

View File

@ -0,0 +1,54 @@
package net.hostsharing.hsadminng.hs.booking.item.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static java.util.Map.entry;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE;
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.forType;
import static org.assertj.core.api.Assertions.assertThat;
class HsManagedWebspaceBookingItemValidatorUnitTest {
@Test
void validatesProperties() {
// given
final var mangedServerBookingItemEntity = HsBookingItemEntity.builder()
.type(MANAGED_WEBSPACE)
.resources(Map.ofEntries(
entry("CPUs", 2),
entry("RAM", 25),
entry("SSD", 25),
entry("Traffic", 250),
entry("SLA-EMail", true)
))
.build();
final var validator = forType(mangedServerBookingItemEntity.getType());
// when
final var result = validator.validate(mangedServerBookingItemEntity);
// then
assertThat(result).containsExactlyInAnyOrder(
"'resources.CPUs' is not expected but is set to '2'",
"'resources.SLA-EMail' is not expected but is set to 'true'",
"'resources.RAM' is not expected but is set to '25'");
}
@Test
void containsAllValidations() {
// when
final var validator = forType(MANAGED_WEBSPACE);
// then
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
"{type=integer, propertyName=SSD, required=true, unit=GB, min=1, max=100, step=1}",
"{type=integer, propertyName=HDD, required=false, unit=GB, min=0, max=250, step=10}",
"{type=integer, propertyName=Traffic, required=true, unit=GB, min=10, max=1000, step=10}",
"{type=enumeration, propertyName=SLA-Platform, required=false, values=[BASIC, EXT24H]}",
"{type=integer, propertyName=Daemons, required=false, unit=null, min=0, max=10, step=null}",
"{type=boolean, propertyName=Online Office Server, required=false, falseIf=null}");
}
}

View File

@ -0,0 +1,55 @@
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static java.util.Map.entry;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER;
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidators.forType;
import static org.assertj.core.api.Assertions.assertThat;
class HsCloudServerHostingAssetValidatorUnitTest {
@Test
void validatesProperties() {
// given
final var cloudServerHostingAssetEntity = HsHostingAssetEntity.builder()
.type(CLOUD_SERVER)
.config(Map.ofEntries(
entry("RAM", 2000),
entry("SSD", 256),
entry("Traffic", "250"),
entry("SLA-Platform", "xxx")
))
.build();
final var validator = forType(cloudServerHostingAssetEntity.getType());
// when
final var result = validator.validate(cloudServerHostingAssetEntity);
// then
assertThat(result).containsExactlyInAnyOrder(
"'config.SLA-Platform' is not expected but is set to 'xxx'",
"'config.CPUs' is required but missing",
"'config.RAM' is expected to be <= 128 but is 2000",
"'config.SSD' is expected to be multiple of 25 but is 256",
"'config.Traffic' is expected to be of type class java.lang.Integer, but is of type 'String'");
}
@Test
void containsAllValidations() {
// when
final var validator = forType(CLOUD_SERVER);
// then
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
"{type=integer, propertyName=CPUs, required=true, unit=null, min=1, max=32, step=null}",
"{type=integer, propertyName=RAM, required=true, unit=GB, min=1, max=128, step=null}",
"{type=integer, propertyName=SSD, required=true, unit=GB, min=25, max=1000, step=25}",
"{type=integer, propertyName=HDD, required=false, unit=GB, min=0, max=4000, step=250}",
"{type=integer, propertyName=Traffic, required=true, unit=GB, min=250, max=10000, step=250}");
}
}

View File

@ -0,0 +1,33 @@
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import org.junit.jupiter.api.Test;
import jakarta.validation.ValidationException;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER;
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidators.valid;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
class HsHostingAssetEntityValidatorsUnitTest {
@Test
void validThrowsException() {
// given
final var cloudServerHostingAssetEntity = HsHostingAssetEntity.builder()
.type(CLOUD_SERVER)
.build();
// when
final var result = catchThrowable( ()-> valid(cloudServerHostingAssetEntity) );
// then
assertThat(result).isInstanceOf(ValidationException.class)
.hasMessageContaining(
"'config.CPUs' is required but missing",
"'config.RAM' is required but missing",
"'config.SSD' is required but missing",
"'config.Traffic' is required but missing");
}
}

View File

@ -1,11 +1,13 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static java.util.Map.entry;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER;
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidators.forType;
import static org.assertj.core.api.Assertions.assertThat;
class HsManagedServerHostingAssetValidatorUnitTest {
@ -13,7 +15,6 @@ class HsManagedServerHostingAssetValidatorUnitTest {
@Test
void validatesProperties() {
// given
final var validator = HsHostingAssetEntityValidators.forType(MANAGED_SERVER);
final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder()
.type(MANAGED_SERVER)
.config(Map.ofEntries(
@ -23,6 +24,7 @@ class HsManagedServerHostingAssetValidatorUnitTest {
entry("SLA-Platform", "xxx")
))
.build();
final var validator = forType(mangedWebspaceHostingAssetEntity.getType());
// when
final var result = validator.validate(mangedWebspaceHostingAssetEntity);

View File

@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import org.junit.jupiter.api.Test;
@ -14,11 +15,6 @@ import static org.assertj.core.api.Assertions.assertThat;
class HsManagedWebspaceHostingAssetValidatorUnitTest {
// just to make sure the class is loaded
static {
new HsManagedWebspaceHostingAssetValidator();
}
final HsBookingItemEntity managedServerBookingItem = HsBookingItemEntity.builder()
.debitor(HsOfficeDebitorEntity.builder().defaultPrefix("abc").build()
)