Skip to content

Commit 38c169f

Browse files
DavideDSanne
authored andcommitted
[#1686] Add techempower-postgres-it integration test
1 parent 4059ed7 commit 38c169f

File tree

12 files changed

+854
-0
lines changed

12 files changed

+854
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
buildscript {
2+
repositories {
3+
// Example: ./gradlew build -PenableMavenLocalRepo
4+
if ( project.hasProperty( 'enableMavenLocalRepo' ) ) {
5+
// Useful for local development, it should be disabled otherwise
6+
mavenLocal()
7+
}
8+
mavenCentral()
9+
}
10+
}
11+
12+
description = 'TechEmpower integration tests'
13+
14+
ext {
15+
jacksonDatabindVersion = '2.15.2'
16+
jbossLoggingVersion = '3.5.0.Final'
17+
assertjVersion = '3.24.2'
18+
}
19+
20+
dependencies {
21+
implementation project( ':hibernate-reactive-core' )
22+
implementation "io.vertx:vertx-web:${vertxVersion}"
23+
implementation "io.vertx:vertx-web-client:${vertxVersion}"
24+
25+
runtimeOnly "io.vertx:vertx-pg-client:${vertxVersion}"
26+
// The Pg client requires this dependency
27+
runtimeOnly "com.ongres.scram:client:2.1"
28+
runtimeOnly "com.fasterxml.jackson.core:jackson-databind:${jacksonDatabindVersion}"
29+
30+
// logging
31+
implementation "org.jboss.logging:jboss-logging:${jbossLoggingVersion}"
32+
33+
// Testcontainers
34+
implementation "org.testcontainers:postgresql:${testcontainersVersion}"
35+
36+
// Testing
37+
testImplementation "org.assertj:assertj-core:${assertjVersion}"
38+
testImplementation "io.vertx:vertx-junit5:${vertxVersion}"
39+
}
40+
41+
// Configuration for the tests
42+
tasks.withType( Test ).configureEach {
43+
defaultCharacterEncoding = "UTF-8"
44+
useJUnitPlatform()
45+
testLogging {
46+
showStandardStreams = project.hasProperty( 'showStandardOutput' )
47+
showStackTraces = true
48+
exceptionFormat = 'full'
49+
displayGranularity = 1
50+
events = ['PASSED', 'FAILED', 'SKIPPED']
51+
}
52+
53+
// We need a to use an instance of PostgreSQL with a specific configuration.
54+
// So, for this particular integration-test module, we default to true unless docker is disabled.
55+
systemProperty 'docker', project.properties['docker'] ?: true
56+
systemProperty 'org.hibernate.reactive.common.InternalStateAssertions.ENFORCE', 'true'
57+
58+
if ( project.hasProperty( 'includeTests' ) ) {
59+
// Example: ./gradlew testAll -PincludeTests=DefaultPortTest
60+
filter {
61+
includeTestsMatching project.properties['includeTests'] ?: '*' as String
62+
}
63+
}
64+
}
65+
66+
// Print a summary of the results of the tests (number of failures, successes and skipped)
67+
// This is the same as the one in hibernate-reactive-core
68+
def loggingSummary(db, result, desc) {
69+
if ( !desc.parent ) { // will match the outermost suite
70+
def output = "${db} results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)"
71+
def repeatLength = output.length() + 1
72+
logger.lifecycle '\n' + ('-' * repeatLength) + '\n' + output + '\n' + ('-' * repeatLength)
73+
}
74+
}
75+
76+
test {
77+
doFirst {
78+
systemProperty 'db', 'PostgreSQL'
79+
}
80+
// We only want to test this on Postgres
81+
afterSuite { desc, result ->
82+
loggingSummary( 'PostgreSQL', result, desc )
83+
}
84+
}
85+
86+
def javaMainClass = "org.hibernate.reactive.it.techempower.VertxServer"
87+
jar {
88+
dependsOn = [':hibernate-reactive-core:jar']
89+
archiveFileName = "${project.name}.jar"
90+
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
91+
manifest {
92+
attributes 'Main-Class': javaMainClass
93+
attributes 'Implementation-Version': project.version
94+
}
95+
from {
96+
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
97+
}
98+
}
99+
100+
tasks.register( "startVertx", JavaExec ) {
101+
description = "Starts the Vert.x Server app"
102+
classpath = sourceSets.main.runtimeClasspath
103+
mainClass = javaMainClass
104+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.it.techempower;
7+
8+
import java.util.concurrent.TimeUnit;
9+
10+
import org.hibernate.SessionFactory;
11+
import org.hibernate.boot.registry.StandardServiceRegistry;
12+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
13+
import org.hibernate.cfg.Configuration;
14+
import org.hibernate.reactive.logging.impl.Log;
15+
import org.hibernate.reactive.mutiny.Mutiny;
16+
import org.hibernate.reactive.provider.ReactiveServiceRegistryBuilder;
17+
import org.hibernate.reactive.provider.Settings;
18+
import org.hibernate.reactive.vertx.VertxInstance;
19+
20+
21+
import io.vertx.core.DeploymentOptions;
22+
import io.vertx.core.Vertx;
23+
import io.vertx.core.VertxOptions;
24+
import org.testcontainers.containers.BindMode;
25+
import org.testcontainers.containers.PostgreSQLContainer;
26+
import org.testcontainers.containers.output.OutputFrame;
27+
28+
import static java.lang.invoke.MethodHandles.lookup;
29+
import static org.hibernate.reactive.logging.impl.LoggerFactory.make;
30+
31+
/**
32+
* Make it easier to run benchmarks with external tools like "wrk"
33+
*/
34+
public class VertxServer {
35+
36+
private static final Log LOG = make( Log.class, lookup() );
37+
38+
// These properties are in DatabaseConfiguration in core
39+
public static final boolean USE_DOCKER = isDockerEnabled();
40+
41+
// If not specify, default to enable docker
42+
private static boolean isDockerEnabled() {
43+
String enableDocker = System.getProperty( "docker" );
44+
if ( enableDocker == null ) {
45+
return true;
46+
}
47+
return Boolean.parseBoolean( enableDocker );
48+
}
49+
50+
public static final String IMAGE_NAME = "postgres:15-bullseye";
51+
public static final String USERNAME = "benchmarkdbuser";
52+
public static final String PASSWORD = "benchmarkdbpass";
53+
public static final String DB_NAME = "hello_world";
54+
55+
public static final int VERTICLE_INSTANCES = 10;
56+
57+
private static final String POSGRESQL_CONF_PATH = "/postgresql-min.conf";
58+
59+
public static final PostgreSQLContainer<?> postgresql = new PostgreSQLContainer<>( IMAGE_NAME )
60+
.withUsername( USERNAME )
61+
.withPassword( PASSWORD )
62+
.withDatabaseName( DB_NAME )
63+
.withCommand( "postgres", "-c", "config_file=/ssd/postgresql/postgresql.conf" )
64+
.withEnv( "PG_DATA", "/ssd/postgresql" )
65+
.withClasspathResourceMapping(
66+
POSGRESQL_CONF_PATH,
67+
"/ssd/postgresql/postgresql.conf",
68+
BindMode.READ_ONLY
69+
)
70+
.withReuse( true )
71+
.withLogConsumer( VertxServer::log );
72+
73+
private static void log(OutputFrame outputFrame) {
74+
LOG.info( outputFrame.getUtf8String() );
75+
}
76+
77+
private static Configuration constructConfiguration(boolean enableDocker) {
78+
Configuration configuration = new Configuration();
79+
configuration.addAnnotatedClass( World.class );
80+
81+
configuration.setProperty( Settings.HBM2DDL_AUTO, "create" );
82+
configuration.setProperty( Settings.URL, dbConnectionUrl( enableDocker ) );
83+
configuration.setProperty( Settings.USER, USERNAME );
84+
configuration.setProperty( Settings.PASS, PASSWORD );
85+
86+
//Use JAVA_TOOL_OPTIONS='-Dhibernate.show_sql=true'
87+
configuration.setProperty( Settings.SHOW_SQL, System.getProperty( Settings.SHOW_SQL, "false" ) );
88+
configuration.setProperty( Settings.FORMAT_SQL, System.getProperty( Settings.FORMAT_SQL, "false" ) );
89+
configuration.setProperty( Settings.HIGHLIGHT_SQL, System.getProperty( Settings.HIGHLIGHT_SQL, "true" ) );
90+
return configuration;
91+
}
92+
93+
private static String dbConnectionUrl(boolean enableDocker) {
94+
if ( enableDocker ) {
95+
// Calling start() will start the container (if not already started)
96+
// It is required to call start() before obtaining the JDBC URL because it will contain a randomized port
97+
postgresql.start();
98+
return postgresql.getJdbcUrl();
99+
}
100+
101+
// When we don't use testcontainers we expect a database on the default url
102+
return "postgres://localhost:5432/" + DB_NAME;
103+
}
104+
105+
public static SessionFactory createHibernateSessionFactory(boolean enableDocker, io.vertx.core.Vertx vertx) {
106+
final Configuration configuration = constructConfiguration( enableDocker );
107+
StandardServiceRegistryBuilder builder = new ReactiveServiceRegistryBuilder()
108+
.addService( VertxInstance.class, (VertxInstance) () -> vertx )
109+
.applySettings( configuration.getProperties() );
110+
StandardServiceRegistry registry = builder.build();
111+
return configuration.buildSessionFactory( registry );
112+
}
113+
114+
public static VertxOptions vertxOptions() {
115+
VertxOptions vertxOptions = new VertxOptions();
116+
vertxOptions.setBlockedThreadCheckInterval( 5 );
117+
vertxOptions.setBlockedThreadCheckIntervalUnit( TimeUnit.MINUTES );
118+
return vertxOptions;
119+
}
120+
121+
public static void main(String[] args) {
122+
DeploymentOptions options = new DeploymentOptions();
123+
options.setInstances( VERTICLE_INSTANCES );
124+
125+
Vertx vertx = Vertx.vertx( vertxOptions() );
126+
final Mutiny.SessionFactory sessionFactory = createHibernateSessionFactory( USE_DOCKER, vertx )
127+
.unwrap( Mutiny.SessionFactory.class );
128+
vertx.deployVerticle( () -> new WorldVerticle( () -> sessionFactory ), options )
129+
.onSuccess( s -> {
130+
LOG.info( "✅ Deployment success" );
131+
LOG.info( "💡 Vert.x app started" );
132+
} )
133+
.onFailure( err -> LOG.errorf( "🔥 Deployment failure", err ) );
134+
}
135+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.it.techempower;
7+
8+
import jakarta.persistence.Entity;
9+
import jakarta.persistence.Id;
10+
11+
@Entity
12+
public class World {
13+
14+
@Id
15+
private int id;
16+
private int randomNumber;
17+
18+
public int getId() {
19+
return id;
20+
}
21+
22+
public void setId(int id) {
23+
this.id = id;
24+
}
25+
26+
public int getRandomNumber() {
27+
return randomNumber;
28+
}
29+
30+
public void setRandomNumber(int randomNumber) {
31+
this.randomNumber = randomNumber;
32+
}
33+
34+
@Override
35+
public String toString() {
36+
return id + ":" + randomNumber;
37+
}
38+
}

0 commit comments

Comments
 (0)