Skip to content

Commit

Permalink
Merge pull request quarkusio#21316 from geoand/quarkusio#19080
Browse files Browse the repository at this point in the history
When launching a container via @QuarkusIntegrationTest make network available
  • Loading branch information
geoand authored Nov 10, 2021
2 parents 7d47881 + b6e84c8 commit 68fc74b
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 3 deletions.
41 changes: 41 additions & 0 deletions docs/src/main/asciidoc/getting-started-testing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,47 @@ As a test annotated with `@QuarkusIntegrationTest` tests the result of the build
These tests will **not** work if run in the same phase as `@QuarkusTest` as Quarkus has not yet created the final artifact.
====

=== Launching containers

When `@QuarkusIntegrationTest` results in launching a container (because the application was built with `quarkus.container-image.build` set to `true`), the container is launched on a predictable container network. This facilitates writing integration tests that need to launch services to support the application.
This means that `@QuarkusIntegrationTest` works out of the box with containers launched via link:dev-services[Dev Services], but it also means that it enables using <<quarkus-test-resource,QuarkusTestLifecycleManager>> resources that launch additional containers.
This can be achieved by having your `QuarkusTestLifecycleManager` implement `io.quarkus.test.common.DevServicesContext.ContextAware`. A simple example could be the following:

[source,java]
----
import io.quarkus.test.common.DevServicesContext;
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class CustomResource implements QuarkusTestResourceLifecycleManager, DevServicesContext.ContextAware {
private Optional<String> containerNetworkId;
@Override
public void setIntegrationTestContext(DevServicesContext context) {
containerNetworkId = context.containerNetworkId();
}
@Override
public Map<String, String> start() {
// start a container making sure to call withNetworkMode() with the value of containerNetworkId if present
// return a map containing the configuration the application needs to use the service
return new HashMap<>();
}
@Override
public void stop() {
// close container
}
}
----

`CustomResource` would be activated on a `@QuarkusIntegrationTest` using `@QuarkusTestResource` as is described in the corresponding section of this doc.

=== Executing against a running application

[WARNING]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ interface DevServicesLaunchResult extends AutoCloseable {

String networkId();

boolean manageNetwork();

void close();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,33 @@ public void start() throws IOException {
}
}

if (devServicesLaunchResult.manageNetwork() && (devServicesLaunchResult.networkId() != null)) {
try {
int networkCreateResult = new ProcessBuilder().redirectError(DISCARD).redirectOutput(DISCARD)
.command(DOCKER_BINARY, "network", "create", devServicesLaunchResult.networkId()).start().waitFor();
if (networkCreateResult > 0) {
throw new RuntimeException("Creating container network '" + devServicesLaunchResult.networkId()
+ "' completed unsuccessfully");
}
// do the cleanup in a shutdown hook because there might be more services (launched via QuarkusTestResourceLifecycleManager) connected to the network
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
try {
new ProcessBuilder().redirectError(DISCARD).redirectOutput(DISCARD)
.command(DOCKER_BINARY, "network", "rm", devServicesLaunchResult.networkId()).start()
.waitFor();
} catch (InterruptedException | IOException ignored) {
System.out.println(
"Unable to delete container network '" + devServicesLaunchResult.networkId() + "'");
}
}
}));
} catch (InterruptedException e) {
throw new RuntimeException("Unable to pull container image '" + containerImage + "'", e);
}
}

System.setProperty("test.url", TestHTTPResourceManager.getUri());

if (httpPort == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import javax.enterprise.inject.Alternative;
import javax.inject.Inject;

import org.apache.commons.lang3.RandomStringUtils;
import org.jboss.jandex.Index;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.platform.commons.JUnitException;
Expand Down Expand Up @@ -288,6 +289,7 @@ public void accept(String s, String s2) {
}
}, DevServicesLauncherConfigResultBuildItem.class.getName());

boolean manageNetwork = false;
if (isDockerAppLaunch) {
// obtain the ID of the shared network - this needs to be done after the augmentation has been run
// or else we run into various ClassLoader problems
Expand All @@ -297,11 +299,12 @@ public void accept(String s, String s2) {
Object sharedNetwork = networkClass.getField("SHARED").get(null);
networkId = (String) networkClass.getMethod("getId").invoke(sharedNetwork);
} catch (Exception e) {
networkId = null;
networkId = "quarkus-integration-test-" + RandomStringUtils.random(5, true, false);
manageNetwork = true;
}
}

return new DefaultDevServicesLaunchResult(propertyMap, networkId, curatedApplication);
return new DefaultDevServicesLaunchResult(propertyMap, networkId, manageNetwork, curatedApplication);
}

static void activateLogging() {
Expand All @@ -313,12 +316,14 @@ static void activateLogging() {
static class DefaultDevServicesLaunchResult implements ArtifactLauncher.InitContext.DevServicesLaunchResult {
private final Map<String, String> properties;
private final String networkId;
private final boolean manageNetwork;
private final CuratedApplication curatedApplication;

DefaultDevServicesLaunchResult(Map<String, String> properties, String networkId,
CuratedApplication curatedApplication) {
boolean manageNetwork, CuratedApplication curatedApplication) {
this.properties = properties;
this.networkId = networkId;
this.manageNetwork = manageNetwork;
this.curatedApplication = curatedApplication;
}

Expand All @@ -330,6 +335,11 @@ public String networkId() {
return networkId;
}

@Override
public boolean manageNetwork() {
return manageNetwork;
}

@Override
public void close() {
curatedApplication.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ public String networkId() {
return null;
}

@Override
public boolean manageNetwork() {
return false;
}

@Override
public void close() {

Expand Down

0 comments on commit 68fc74b

Please sign in to comment.