-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce integration tests to cover the production classloader
- Loading branch information
Showing
8 changed files
with
255 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
The purpose of this module is to run integration tests | ||
on the core state assumptions of a Quarkus application | ||
booted in production mode (on JVM). | ||
|
||
These same tests are not expected to be run in other modes, | ||
and the same assumptions are not expected to hold in | ||
native-image mode either. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This file disables the native profile in the parent pom.xml of this module. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<parent> | ||
<artifactId>quarkus-integration-tests-parent</artifactId> | ||
<groupId>io.quarkus</groupId> | ||
<version>999-SNAPSHOT</version> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<artifactId>production-mode</artifactId> | ||
<name>Quarkus - Integration Tests - Quarkus Production Mode</name> | ||
<description>Integration tests specifically requiring to run Quarkus in prod mode</description> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-resteasy</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-junit5</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.rest-assured</groupId> | ||
<artifactId>rest-assured</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-junit5-internal</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<!-- Minimal test dependencies to *-deployment artifacts for consistent build order --> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-resteasy-deployment</artifactId> | ||
<version>${project.version}</version> | ||
<type>pom</type> | ||
<scope>test</scope> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>*</groupId> | ||
<artifactId>*</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-maven-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>build</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<artifactId>maven-failsafe-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>integration-test</goal> | ||
<goal>verify</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
|
||
</plugins> | ||
</build> | ||
|
||
</project> |
65 changes: 65 additions & 0 deletions
65
...on-tests/production-mode/src/main/java/io/quarkus/it/prodmode/ForkJoinPoolAssertions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package io.quarkus.it.prodmode; | ||
|
||
import java.util.concurrent.CountDownLatch; | ||
import java.util.concurrent.ForkJoinPool; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
/** | ||
* Helper to collect assertions related to the JDK ForkJoinPool | ||
* state. | ||
*/ | ||
public class ForkJoinPoolAssertions { | ||
|
||
/** | ||
* We test which Classloader is being used by each thread | ||
* in the common pool of ForkJoinPool. | ||
* It is expected that a Quarkus application running in production mode | ||
* will have set the io.quarkus.bootstrap.runner.RunnerClassLoader as | ||
* context classloader on each of them, to prevent problems at runtime. | ||
* | ||
* @return true only if all checks are successful. | ||
*/ | ||
static boolean isEachFJThreadUsingQuarkusClassloader() { | ||
AtomicInteger testedOk = new AtomicInteger(); | ||
final int poolParallelism = ForkJoinPool.getCommonPoolParallelism(); | ||
CountDownLatch allDone = new CountDownLatch(poolParallelism); | ||
CountDownLatch taskRelease = new CountDownLatch(1); | ||
if (poolParallelism < 1) { | ||
System.err | ||
.println("Can't test this when ForkJoinPool.getCommonPoolParallelism() has been forced to less than one."); | ||
return false; | ||
} | ||
for (int i = 0; i < poolParallelism; ++i) { | ||
ForkJoinPool.commonPool().execute(new Runnable() { | ||
@Override | ||
public void run() { | ||
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); | ||
final String classLoaderImplementationName = contextClassLoader.getClass().getName(); | ||
if (classLoaderImplementationName.equals(io.quarkus.bootstrap.runner.RunnerClassLoader.class.getName())) { | ||
testedOk.incrementAndGet(); | ||
} else { | ||
System.out.println("Unexpected classloader name used in production: " + classLoaderImplementationName); | ||
} | ||
allDone.countDown(); | ||
try { | ||
taskRelease.await(); | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
}); | ||
} | ||
try { | ||
if (!allDone.await(10, TimeUnit.SECONDS)) { | ||
throw new IllegalStateException("Timed out while trying to scale up the fork join pool"); | ||
} | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
return false; | ||
} finally { | ||
taskRelease.countDown(); | ||
} | ||
return testedOk.get() == poolParallelism; | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
...sts/production-mode/src/main/java/io/quarkus/it/prodmode/ProductionModeTestsEndpoint.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package io.quarkus.it.prodmode; | ||
|
||
import javax.ws.rs.GET; | ||
import javax.ws.rs.Path; | ||
import javax.ws.rs.Produces; | ||
import javax.ws.rs.core.MediaType; | ||
|
||
import io.quarkus.runtime.Quarkus; | ||
|
||
@Path("/production-mode-tests") | ||
public class ProductionModeTestsEndpoint { | ||
|
||
@GET | ||
@Produces(MediaType.TEXT_PLAIN) | ||
public String hello() { | ||
return "hello"; | ||
} | ||
|
||
@GET | ||
@Path("areExpectedSystemPropertiesSet") | ||
@Produces(MediaType.TEXT_PLAIN) | ||
public String areExpectedSystemPropertiesSet() { | ||
if (!"org.jboss.logmanager.LogManager".equals(System.getProperty("java.util.logging.manager"))) { | ||
return "no"; | ||
} | ||
if (!"io.quarkus.bootstrap.forkjoin.QuarkusForkJoinWorkerThreadFactory" | ||
.equals(System.getProperty("java.util.concurrent.ForkJoinPool.common.threadFactory"))) { | ||
return "no"; | ||
} | ||
return "yes"; | ||
} | ||
|
||
@GET | ||
@Path("isForkJoinPoolUsingExpectedClassloader") | ||
@Produces(MediaType.TEXT_PLAIN) | ||
public String isForkJoinPoolUsingExpectedClassloader() { | ||
return ForkJoinPoolAssertions.isEachFJThreadUsingQuarkusClassloader() ? "yes" : "no"; | ||
} | ||
|
||
@GET | ||
@Path("shutdown") | ||
@Produces(MediaType.TEXT_PLAIN) | ||
public String shutdown() { | ||
System.out.println("Terminating Quarkus app!"); | ||
Quarkus.asyncExit(); | ||
return "quitting"; | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
integration-tests/production-mode/src/test/java/io/quarkus/it/prodmode/ProdModeTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package io.quarkus.it.prodmode; | ||
|
||
import static io.restassured.RestAssured.given; | ||
import static org.hamcrest.CoreMatchers.is; | ||
|
||
import org.jboss.shrinkwrap.api.ShrinkWrap; | ||
import org.jboss.shrinkwrap.api.spec.JavaArchive; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.RegisterExtension; | ||
|
||
import io.quarkus.test.QuarkusProdModeTest; | ||
|
||
public class ProdModeTest { | ||
|
||
@RegisterExtension | ||
static final QuarkusProdModeTest config = new QuarkusProdModeTest() | ||
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) | ||
.addClasses(ProductionModeTestsEndpoint.class, ForkJoinPoolAssertions.class)) | ||
.setApplicationName("prod-mode-quarkus") | ||
.setApplicationVersion("0.1-SNAPSHOT") | ||
.setRun(true); | ||
|
||
@Test | ||
public void basicApplicationAliveTest() { | ||
given() | ||
.when().get("/production-mode-tests") | ||
.then() | ||
.statusCode(200) | ||
.body(is("hello")); | ||
} | ||
|
||
@Test | ||
public void areExpectedSystemPropertiesSet() { | ||
given() | ||
.when().get("/production-mode-tests/areExpectedSystemPropertiesSet") | ||
.then() | ||
.statusCode(200) | ||
.body(is("yes")); | ||
} | ||
|
||
@Test | ||
public void isForkJoinPoolUsingExpectedClassloader() { | ||
given() | ||
.when().get("/production-mode-tests/isForkJoinPoolUsingExpectedClassloader") | ||
.then() | ||
.statusCode(200) | ||
.body(is("yes")); | ||
} | ||
|
||
} |