/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.performance.simple;
import static org.assertj.core.api.Assertions.assertThat;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @author Hardy Ferentschik
*/
public class SimpleValidation {
private static final String[] names = {
null,
"Jacob",
"Isabella",
"Ethan",
"Sophia",
"Michael",
"Emma",
"Jayden",
"Olivia",
"William"
};
@State(Scope.Benchmark)
public static class ValidationState {
public volatile Validator validator;
public volatile Random random;
{
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
random = new Random();
}
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(value = 1)
@Threads(50)
@Warmup(iterations = 10)
@Measurement(iterations = 50)
public void testSimpleBeanValidation(ValidationState state, Blackhole bh) {
DriverSetup driverSetup = new DriverSetup( state );
Set<ConstraintViolation<Driver>> violations = state.validator.validate( driverSetup.getDriver() );
assertThat( violations ).hasSize( driverSetup.getExpectedViolationCount() );
bh.consume( violations );
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(value = 1)
@Threads(50)
@Warmup(iterations = 10)
@Measurement(iterations = 50)
public void testSimpleBeanValidationRecreatingValidatorFactory(ValidationState state, Blackhole bh) {
DriverSetup driverSetup = new DriverSetup( state );
Validator localValidator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Driver>> violations = localValidator.validate( driverSetup.getDriver() );
assertThat( violations ).hasSize( driverSetup.getExpectedViolationCount() );
bh.consume( violations );
}
public class Driver {
@NotNull
private String name;
@Min(18)
private int age;
@AssertTrue
private boolean hasDrivingLicense;
public Driver(String name, int age, boolean hasDrivingLicense) {
this.name = name;
this.age = age;
this.hasDrivingLicense = hasDrivingLicense;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "Driver" );
sb.append( "{name='" ).append( name ).append( '\'' );
sb.append( ", age=" ).append( age );
sb.append( ", hasDrivingLicense=" ).append( hasDrivingLicense );
sb.append( '}' );
return sb.toString();
}
}
private class DriverSetup {
private int expectedViolationCount;
private Driver driver;
public DriverSetup(ValidationState state) {
expectedViolationCount = 0;
String name = names[state.random.nextInt( 10 )];
if ( name == null ) {
expectedViolationCount++;
}
int randomAge = state.random.nextInt( 100 );
if ( randomAge < 18 ) {
expectedViolationCount++;
}
int rand = state.random.nextInt( 2 );
boolean hasLicense = rand == 1;
if ( !hasLicense ) {
expectedViolationCount++;
}
driver = new Driver( name, randomAge, hasLicense );
}
public int getExpectedViolationCount() {
return expectedViolationCount;
}
public Driver getDriver() {
return driver;
}
}
}